Sync wininet with Wine. This fixes the Download! issue.
authorColin Finck <colin@reactos.org>
Sat, 31 May 2008 13:02:59 +0000 (13:02 +0000)
committerColin Finck <colin@reactos.org>
Sat, 31 May 2008 13:02:59 +0000 (13:02 +0000)
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

16 files changed:
reactos/dll/win32/wininet/cookie.c
reactos/dll/win32/wininet/ftp.c
reactos/dll/win32/wininet/http.c
reactos/dll/win32/wininet/internet.c
reactos/dll/win32/wininet/internet.h
reactos/dll/win32/wininet/netconnection.c
reactos/dll/win32/wininet/rsrc.rc
reactos/dll/win32/wininet/urlcache.c
reactos/dll/win32/wininet/utility.c
reactos/dll/win32/wininet/wininet.spec
reactos/dll/win32/wininet/wininet_Da.rc [new file with mode: 0644]
reactos/dll/win32/wininet/wininet_Ru.rc
reactos/dll/win32/wininet/wininet_Si.rc
reactos/dll/win32/wininet/wininet_Sv.rc
reactos/dll/win32/wininet/wininet_ros.diff
reactos/include/psdk/wininet.h

index 2eef2d9..bd22bc6 100644 (file)
@@ -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);
 }
 
 /***********************************************************************
index bec4596..36e9005 100644 (file)
 
 #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,168 +3199,120 @@ 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)
+static void FTPFINDNEXT_Destroy(WININETHANDLEHEADER *hdr)
 {
-    LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) hdr;
+    LPWININETFTPFINDNEXTW lpwfn = (LPWININETFTPFINDNEXTW) hdr;
+    DWORD i;
 
     TRACE("\n");
 
-    WININET_Release(&lpwfs->lpAppInfo->hdr);
+    WININET_Release(&lpwfn->lpFtpSession->hdr);
 
-    HeapFree(GetProcessHeap(), 0, lpwfs->lpszPassword);
-    HeapFree(GetProcessHeap(), 0, lpwfs->lpszUserName);
-    HeapFree(GetProcessHeap(), 0, lpwfs);
-}
+    for (i = 0; i < lpwfn->size; i++)
+    {
+        HeapFree(GetProcessHeap(), 0, lpwfn->lpafp[i].lpszName);
+    }
 
+    HeapFree(GetProcessHeap(), 0, lpwfn->lpafp);
+    HeapFree(GetProcessHeap(), 0, lpwfn);
+}
 
-/***********************************************************************
- *           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)
+static DWORD WINAPI FTPFINDNEXT_FindNextFileProc(WININETFTPFINDNEXTW *find, LPVOID data)
 {
-    BOOL bSuccess = TRUE;
-    LPWIN32_FIND_DATAW lpFindFileData;
+    WIN32_FIND_DATAW *find_data = data;
+    DWORD res = ERROR_SUCCESS;
 
-    TRACE("index(%d) size(%d)\n", lpwh->index, lpwh->size);
+    TRACE("index(%d) size(%d)\n", find->index, find->size);
 
-    assert (lpwh->hdr.htype == WH_HFTPFINDNEXT);
-
-    /* Clear any error information */
-    INTERNET_SetLastError(0);
+    ZeroMemory(find_data, sizeof(WIN32_FIND_DATAW));
 
-    lpFindFileData = (LPWIN32_FIND_DATAW) lpvFindData;
-    ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
+    if (find->index < find->size) {
+        FTP_ConvertFileProp(&find->lpafp[find->index], find_data);
+        find->index++;
 
-    if (lpwh->index >= lpwh->size)
-    {
-        INTERNET_SetLastError(ERROR_NO_MORE_FILES);
-        bSuccess = FALSE;
-       goto lend;
+        TRACE("Name: %s\nSize: %d\n", debugstr_w(find_data->cFileName), find_data->nFileSizeLow);
+    }else {
+        res = ERROR_NO_MORE_FILES;
     }
 
-    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)
+    if (find->hdr.dwFlags & INTERNET_FLAG_ASYNC)
     {
         INTERNET_ASYNC_RESULT iar;
 
-        iar.dwResult = (DWORD)bSuccess;
-        iar.dwError = iar.dwError = bSuccess ? ERROR_SUCCESS :
-                                               INTERNET_GetLastError();
+        iar.dwResult = (res == ERROR_SUCCESS);
+        iar.dwError = res;
 
-        INTERNET_SendCallback(&lpwh->hdr, lpwh->hdr.dwContext,
+        INTERNET_SendCallback(&find->hdr, find->hdr.dwContext,
                               INTERNET_STATUS_REQUEST_COMPLETE, &iar,
                               sizeof(INTERNET_ASYNC_RESULT));
     }
 
-    return bSuccess;
+    return res;
 }
 
-
-/***********************************************************************
- *           FTP_CloseFindNextHandle (internal)
- *
- * Deallocate session handle
- *
- * RETURNS
- *   TRUE on success
- *   FALSE on failure
- *
- */
-static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr)
+static void FTPFINDNEXT_AsyncFindNextFileProc(WORKREQUEST *workRequest)
 {
-    LPWININETFTPFINDNEXTW lpwfn = (LPWININETFTPFINDNEXTW) hdr;
-    DWORD i;
+    struct WORKREQ_FTPFINDNEXTW *req = &workRequest->u.FtpFindNextW;
 
-    TRACE("\n");
+    FTPFINDNEXT_FindNextFileProc((WININETFTPFINDNEXTW*)workRequest->hdr, req->lpFindFileData);
+}
 
-    WININET_Release(&lpwfn->lpFtpSession->hdr);
+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");
 
-    for (i = 0; i < lpwfn->size; i++)
-    {
-        HeapFree(GetProcessHeap(), 0, lpwfn->lpafp[i].lpszName);
+        if (*size < sizeof(ULONG))
+            return ERROR_INSUFFICIENT_BUFFER;
+
+        *size = sizeof(DWORD);
+        *(DWORD*)buffer = INTERNET_HANDLE_TYPE_FTP_FIND;
+        return ERROR_SUCCESS;
     }
 
-    HeapFree(GetProcessHeap(), 0, lpwfn->lpafp);
-    HeapFree(GetProcessHeap(), 0, lpwfn);
+    FIXME("Not implemented option %d\n", option);
+    return ERROR_INTERNET_INVALID_OPTION;
 }
 
-/***********************************************************************
- *           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 FTPFINDNEXT_FindNextFileW(WININETHANDLEHEADER *hdr, void *data)
 {
-    LPWININETFTPFILE lpwh = (LPWININETFTPFILE) hdr;
-    LPWININETFTPSESSIONW lpwfs = lpwh->lpFtpSession;
-    INT nResCode;
-
-    TRACE("\n");
+    WININETFTPFINDNEXTW *find = (WININETFTPFINDNEXTW*)hdr;
 
-    WININET_Release(&lpwh->lpFtpSession->hdr);
+    if (find->lpFtpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+    {
+        WORKREQUEST workRequest;
+        struct WORKREQ_FTPFINDNEXTW *req;
 
-    if (!lpwh->session_deleted)
-        lpwfs->download_in_progress = NULL;
+        workRequest.asyncproc = FTPFINDNEXT_AsyncFindNextFileProc;
+        workRequest.hdr = WININET_AddRef( &find->hdr );
+        req = &workRequest.u.FtpFindNextW;
+        req->lpFindFileData = data;
 
-    if (lpwh->nDataSocket != -1)
-        closesocket(lpwh->nDataSocket);
+       INTERNET_AsyncCall(&workRequest);
 
-    nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
-    if (nResCode > 0 && nResCode != 226) WARN("server reports failed transfer\n");
+        return ERROR_SUCCESS;
+    }
 
-    HeapFree(GetProcessHeap(), 0, lpwh);
+    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;
 
index 5e73714..3ae7ac3 100644 (file)
@@ -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++;
+        acceptTypesCount = 0;
+        types = lpszAcceptTypes;
+        while (*types)
+        {
+            /* 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;
-        while (lpszAcceptTypes[acceptTypesCount] && *lpszAcceptTypes[acceptTypesCount])
-        {
-            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++;
+        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;
+        if (pAuthInfo->auth_data_len)
+        {
+            /* 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));
+            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;
+            /* 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_REPLACE | HTTP_ADDHDR_FLAG_REQ);
+        TRACE("Inserting authorization: %s\n", debugstr_w(authorization));
 
-    HeapFree(GetProcessHeap(), 0, authorization);
+        HTTP_ProcessHeader(lpwhr, header, authorization, HTTP_ADDHDR_FLAG_REQ | HTTP_ADDHDR_FLAG_REPLACE);
 
+        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,24 +1975,14 @@ 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 (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 );
+    if (lpwhs->nHostPort == INTERNET_INVALID_PORT_NUMBER)
+        lpwhs->nHostPort = (dwFlags & INTERNET_FLAG_SECURE ?
+                        INTERNET_DEFAULT_HTTPS_PORT :
+                        INTERNET_DEFAULT_HTTP_PORT);
 
-        HTTP_HttpAddRequestHeadersW(lpwhr, agent_header, strlenW(agent_header),
-                               HTTP_ADDREQ_FLAG_ADD);
-        HeapFree(GetProcessHeap(), 0, agent_header);
-    }
+    if (NULL != hIC->lpszProxy && hIC->lpszProxy[0] != 0)
+        HTTP_DealWithProxy( hIC, lpwhs, lpwhr );
 
     Host = HTTP_GetHeader(lpwhr,szHost);
 
@@ -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;
+
+            if (!HTTP_ResolveName(lpwhr))
+                return FALSE;
 
-        NETCON_close(&lpwhr->netConnection);
+            NETCON_close(&lpwhr->netConnection);
 
-        if (!NETCON_init(&lpwhr->netConnection,lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE))
-            return FALSE;
+            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,59 +3698,44 @@ 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 );
 
-    /* regenerate raw headers */
-    while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
-    {
-        cchMaxRawHeaders *= 2;
-        lpszRawHeaders = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
-    }
-    memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
-    cchRawHeaders += (buflen-1);
-    memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
-    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 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;
 
-    /* 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) );
 
-    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);
 
@@ -3066,6 +3745,22 @@ static INT HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr)
     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)
+    {
+        cchMaxRawHeaders *= 2;
+        lpszRawHeaders = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
+    }
+    memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
+    cchRawHeaders += (buflen-1);
+    memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
+    cchRawHeaders += sizeof(szCrLf)/sizeof(szCrLf[0])-1;
+    lpszRawHeaders[cchRawHeaders] = '\0';
+
     /* 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;
 }
 
 /***********************************************************************
index b0357a2..2301d9c 100644 (file)
 #ifdef HAVE_SYS_SOCKET_H
 # include <sys/socket.h>
 #endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
 #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;
-}
 
-/***********************************************************************
- *           INTERNET_CloseHandle (internal)
- *
- * Close internet handle
- *
- * RETURNS
- *    Void
- *
- */
-static VOID INTERNET_CloseHandle(LPWININETHANDLEHEADER hdr)
-{
-    LPWININETAPPINFOW lpwai = (LPWININETAPPINFOW) hdr;
+    WININET_Release(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);
+    if(res != ERROR_SUCCESS)
+        SetLastError(res);
+    return res == ERROR_SUCCESS;
 }
 
-
 /***********************************************************************
  *           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)
-        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;
+    TRACE("(%p %p %d %p)\n", hFile, lpBuffer, dwNumOfBytesToWrite, lpdwNumOfBytesWritten);
 
-        default:
-            break;
+    lpwh = WININET_GetObject( hFile );
+    if (!lpwh) {
+        WARN("Invalid handle\n");
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
     }
 
-    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;
-
-        if (lpwh->htype == WH_HHTTPREQ)
-            NETCON_query_data_available(&((LPWININETHTTPREQW)lpwh)->netConnection,
-                                        &dwDataAvailable);
+    WININET_Release(hdr);
 
-        if (!dwDataAvailable)
-        {
-            WORKREQUEST workRequest;
-            struct WORKREQ_INTERNETREADFILEEXA *req;
+    TRACE("-- %s (%u, bytes read: %d)\n", res == ERROR_SUCCESS ? "TRUE": "FALSE",
+          res, lpBuffersOut->dwBufferLength);
 
-            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;
+                    strcpyW(lpBuffer, ai->lpszAgent);
+                    bSuccess = TRUE;
                 }
-                else
+            }
+            else
+            {
+                required = WideCharToMultiByte(CP_ACP, 0, ai->lpszAgent, -1, NULL, 0, NULL, NULL);
+                if (*lpdwBufferLength < required)
+                    INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
+                else if (lpBuffer)
                 {
-                    sizeRequired = (lstrlenW(url)+1) * sizeof(WCHAR);
-                    if (*lpdwBufferLength < sizeRequired)
-                        INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
-                    else
-                    {
-                        strcpyW(lpBuffer, url);
-                        bSuccess = TRUE;
-                    }
-                    *lpdwBufferLength = sizeRequired;
+                    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;
 }
 
 
index 0f283e1..5d4d7e8 100644 (file)
@@ -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
 #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);
index 8d9d026..45dc40d 100644 (file)
 #include "config.h"
 #include "wine/port.h"
 
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
 #ifdef HAVE_SYS_TIME_H
 # include <sys/time.h>
 #endif
 #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;
 }
index d284d72..c160c47 100644 (file)
@@ -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"
index 7dfb20a..6e76893 100644 (file)
@@ -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);
+    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 (URLCache_FindHash(pHeader, achUrl, &pHashEntry))
+    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;
-}
+    URLCacheFindEntryHandle *pEntryHandle;
 
-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;
+    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);
 
index 70336d4..2597268 100644 (file)
@@ -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;
 }
index 19e6551..dfbc38c 100644 (file)
 @ 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 (file)
index 0000000..515dcab
--- /dev/null
@@ -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"
+}
index 05d706b..d75985b 100644 (file)
@@ -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 "Ñåòåâîå ïîäêëþ÷åíèå"
+}
index af33339..93ac9e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003 Rok Mandeljc <rok.mandeljc@gimb.org>
+ * 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
  * 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\9enega gesla"
+CAPTION "Vnos omrežnega gesla"
 FONT 8, "MS Shell Dlg"
 {
- LTEXT "Vnesite uporabni\9ako ime in geslo:", -1, 40, 6, 150, 15
- LTEXT "Proxy", -1, 40, 26, 50, 10
- LTEXT "Realm", -1, 40, 46, 50, 10
- LTEXT "Uporabni\9ako 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\9aè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)
index 422b2c8..6d71f2e 100644 (file)
@@ -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
index 1a26b9f..b326c85 100644 (file)
@@ -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"
- #include "wine/unicode.h"
-+#define CP_UNIXCP CP_THREAD_ACP
- WINE_DEFAULT_DEBUG_CHANNEL(wininet);
+-        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 @@
  
-Index: netconnection.c
-===================================================================
---- netconnection.c    (revision 30893)
-+++ netconnection.c    (working copy)
-@@ -58,6 +58,8 @@
- #include "internet.h"
+ 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();
+     TRACE("\n");
+-    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 @@
-       <library>ntdll</library>
-       <library>secur32</library>
-       <library>crypt32</library>
-+      <library>ws2_32</library>
-       <file>cookie.c</file>
-       <file>dialogs.c</file>
-       <file>ftp.c</file>
-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"
index 4aae40a..de1aae3 100644 (file)
@@ -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
 }