WININET: use pointers internally and refcount all objects

Mike McCormack mike at codeweavers.com
Mon Jul 19 02:03:21 CDT 2004


This patch puts us one step closer to having thread safety in our 
wininet implementation.  All objects are now refcounted, and destroyed 
only when their last reference is removed.  The next step is to lock 
each object when it is being used.

Mike


ChangeLog:
* use pointers internally and refcount all objects
-------------- next part --------------
Index: dlls/wininet/ftp.c
===================================================================
RCS file: /home/wine/wine/dlls/wininet/ftp.c,v
retrieving revision 1.43
diff -u -r1.43 ftp.c
--- dlls/wininet/ftp.c	1 Jun 2004 19:42:43 -0000	1.43
+++ dlls/wininet/ftp.c	19 Jul 2004 05:45:49 -0000
@@ -42,6 +42,7 @@
 # include <unistd.h>
 #endif
 #include <time.h>
+#include <assert.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -115,8 +116,11 @@
 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_CloseFindNextHandle(LPWININETHANDLEHEADER hdr);
 BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam,
-	INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext);
+	INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD dwContext);
 BOOL FTP_SendStore(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, DWORD dwType);
 BOOL FTP_GetDataSocket(LPWININETFTPSESSIONW lpwfs, LPINT nDataSocket);
 BOOL FTP_SendData(LPWININETFTPSESSIONW lpwfs, INT nDataSocket, HANDLE hFile);
@@ -181,12 +185,13 @@
 {
     LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
+    BOOL r = FALSE;
 
     lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
@@ -196,19 +201,25 @@
         struct WORKREQ_FTPPUTFILEW *req = &workRequest.u.FtpPutFileW;
 
         workRequest.asyncall = FTPPUTFILEW;
-	workRequest.handle = hConnect;
+	workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
         req->lpszLocalFile = WININET_strdupW(lpszLocalFile);
         req->lpszNewRemoteFile = WININET_strdupW(lpszNewRemoteFile);
 	req->dwFlags = dwFlags;
 	req->dwContext = dwContext;
 
-	return INTERNET_AsyncCall(&workRequest);
+	r = INTERNET_AsyncCall(&workRequest);
     }
     else
     {
-        return FTP_FtpPutFileW(hConnect, lpszLocalFile,
+        r = FTP_FtpPutFileW(lpwfs, lpszLocalFile,
 	    lpszNewRemoteFile, dwFlags, dwContext);
     }
+
+lend:
+    if( lpwfs )
+        WININET_Release( &lpwfs->hdr );
+
+    return r;
 }
 
 /***********************************************************************
@@ -221,13 +232,12 @@
  *    FALSE on failure
  *
  */
-BOOL WINAPI FTP_FtpPutFileW(HINTERNET hConnect, LPCWSTR lpszLocalFile,
+BOOL WINAPI FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile,
     LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext)
 {
     HANDLE hFile = NULL;
     BOOL bSuccess = FALSE;
     LPWININETAPPINFOW hIC = NULL;
-    LPWININETFTPSESSIONW lpwfs;
     INT nResCode;
 
     TRACE(" lpszLocalFile(%s) lpszNewRemoteFile(%s)\n", debugstr_w(lpszLocalFile), debugstr_w(lpszNewRemoteFile));
@@ -238,12 +248,7 @@
         return FALSE;
     }
 
-    lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
-    if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
-    {
-        INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
-    }
+    assert( WH_HFTPSESSION == lpwfs->hdr.htype);
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -257,7 +262,7 @@
     }
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
-    SendAsyncCallback(hIC, hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
+    SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
 
     if (FTP_SendStore(lpwfs, lpszNewRemoteFile, dwFlags))
     {
@@ -289,7 +294,7 @@
 
         iar.dwResult = (DWORD)bSuccess;
         iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
-        SendAsyncCallback(hIC, hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
 
@@ -336,12 +341,13 @@
 {
     LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
+    BOOL r = FALSE;
 
     lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory));
@@ -353,16 +359,22 @@
         struct WORKREQ_FTPSETCURRENTDIRECTORYW *req;
 
         workRequest.asyncall = FTPSETCURRENTDIRECTORYW;
-	workRequest.handle = hConnect;
+	workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
         req = &workRequest.u.FtpSetCurrentDirectoryW;
         req->lpszDirectory = WININET_strdupW(lpszDirectory);
 
-	return INTERNET_AsyncCall(&workRequest);
+	r = INTERNET_AsyncCall(&workRequest);
     }
     else
     {
-        return FTP_FtpSetCurrentDirectoryW(hConnect, lpszDirectory);
+        r = FTP_FtpSetCurrentDirectoryW(lpwfs, lpszDirectory);
     }
+
+lend:
+    if( lpwfs )
+        WININET_Release( &lpwfs->hdr );
+
+    return r;
 }
 
 
@@ -376,16 +388,14 @@
  *    FALSE on failure
  *
  */
-BOOL WINAPI FTP_FtpSetCurrentDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
+BOOL WINAPI FTP_FtpSetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory)
 {
     INT nResCode;
-    LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
     DWORD bSuccess = FALSE;
 
     TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory));
 
-    lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
@@ -397,7 +407,7 @@
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
     if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_CWD, lpszDirectory,
-        hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext))
+        hIC->lpfnStatusCB, &lpwfs->hdr, lpwfs->hdr.dwContext))
         goto lend;
 
     nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
@@ -417,7 +427,7 @@
 
         iar.dwResult = (DWORD)bSuccess;
         iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR;
-        SendAsyncCallback(hIC, hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
     return bSuccess;
@@ -460,12 +470,13 @@
 {
     LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
+    BOOL r = FALSE;
 
     lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
@@ -475,16 +486,21 @@
         struct WORKREQ_FTPCREATEDIRECTORYW *req;
 
         workRequest.asyncall = FTPCREATEDIRECTORYW;
-	workRequest.handle = hConnect;
+	workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
         req = &workRequest.u.FtpCreateDirectoryW;
         req->lpszDirectory = WININET_strdupW(lpszDirectory);
 
-	return INTERNET_AsyncCall(&workRequest);
+	r = INTERNET_AsyncCall(&workRequest);
     }
     else
     {
-        return FTP_FtpCreateDirectoryW(hConnect, lpszDirectory);
+        r = FTP_FtpCreateDirectoryW(lpwfs, lpszDirectory);
     }
+lend:
+    if( lpwfs )
+        WININET_Release( &lpwfs->hdr );
+
+    return r;
 }
 
 
@@ -498,16 +514,14 @@
  *    FALSE on failure
  *
  */
-BOOL WINAPI FTP_FtpCreateDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory)
+BOOL WINAPI FTP_FtpCreateDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory)
 {
     INT nResCode;
     BOOL bSuccess = FALSE;
     LPWININETAPPINFOW hIC = NULL;
-    LPWININETFTPSESSIONW lpwfs;
 
     TRACE("lpszDirectory(%s)\n", debugstr_w(lpszDirectory));
 
-    lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
@@ -537,7 +551,7 @@
 
         iar.dwResult = (DWORD)bSuccess;
         iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
-        SendAsyncCallback(hIC, hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
 
@@ -589,12 +603,13 @@
 {
     LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
+    HINTERNET r = NULL;
 
     lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
@@ -604,7 +619,7 @@
         struct WORKREQ_FTPFINDFIRSTFILEW *req;
 
         workRequest.asyncall = FTPFINDFIRSTFILEW;
-	workRequest.handle = hConnect;
+	workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
         req = &workRequest.u.FtpFindFirstFileW;
         req->lpszSearchFile = (lpszSearchFile == NULL) ? NULL : WININET_strdupW(lpszSearchFile);
 	req->lpFindFileData = lpFindFileData;
@@ -612,13 +627,18 @@
 	req->dwContext= dwContext;
 
 	INTERNET_AsyncCall(&workRequest);
-	return NULL;
+	r = NULL;
     }
     else
     {
-        return FTP_FtpFindFirstFileW(hConnect, lpszSearchFile, lpFindFileData,
+        r = FTP_FtpFindFirstFileW(lpwfs, lpszSearchFile, lpFindFileData,
             dwFlags, dwContext);
     }
+lend:
+    if( lpwfs )
+        WININET_Release( &lpwfs->hdr );
+
+    return r;
 }
 
 
@@ -632,22 +652,16 @@
  *    NULL on failure
  *
  */
-HINTERNET WINAPI FTP_FtpFindFirstFileW(HINTERNET hConnect,
+HINTERNET WINAPI FTP_FtpFindFirstFileW(LPWININETFTPSESSIONW lpwfs,
     LPCWSTR lpszSearchFile, LPWIN32_FIND_DATAW lpFindFileData, DWORD dwFlags, DWORD dwContext)
 {
     INT nResCode;
     LPWININETAPPINFOW hIC = NULL;
-    LPWININETFTPSESSIONW lpwfs;
     HINTERNET hFindNext = NULL;
 
     TRACE("\n");
 
-    lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hConnect );
-    if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
-    {
-        INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
-    }
+    assert(WH_HFTPSESSION == lpwfs->hdr.htype);
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -663,7 +677,7 @@
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
     if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_LIST, NULL,
-        hIC->lpfnStatusCB, hConnect, lpwfs->hdr.dwContext))
+        hIC->lpfnStatusCB, &lpwfs->hdr, lpwfs->hdr.dwContext))
         goto lend;
 
     nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
@@ -699,13 +713,13 @@
 	{
             iar.dwResult = (DWORD)hFindNext;
             iar.dwError = ERROR_SUCCESS;
-            SendAsyncCallback(hIC, hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
+            SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
                 &iar, sizeof(INTERNET_ASYNC_RESULT));
 	}
 
         iar.dwResult = (DWORD)hFindNext;
         iar.dwError = hFindNext ? ERROR_SUCCESS : INTERNET_GetLastError();
-        SendAsyncCallback(hIC, hConnect, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
 
@@ -756,6 +770,7 @@
 {
     LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
+    BOOL r = FALSE;
 
     TRACE("len(%ld)\n", *lpdwCurrentDirectory);
 
@@ -763,7 +778,7 @@
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
@@ -773,18 +788,24 @@
         struct WORKREQ_FTPGETCURRENTDIRECTORYW *req;
 
         workRequest.asyncall =  FTPGETCURRENTDIRECTORYW;
-	workRequest.handle = hFtpSession;
+	workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
         req = &workRequest.u.FtpGetCurrentDirectoryW;
 	req->lpszDirectory = lpszCurrentDirectory;
 	req->lpdwDirectory = lpdwCurrentDirectory;
 
-	return INTERNET_AsyncCall(&workRequest);
+	r = INTERNET_AsyncCall(&workRequest);
     }
     else
     {
-        return FTP_FtpGetCurrentDirectoryW(hFtpSession, lpszCurrentDirectory,
+        r = FTP_FtpGetCurrentDirectoryW(lpwfs, lpszCurrentDirectory,
             lpdwCurrentDirectory);
     }
+
+lend:
+    if( lpwfs )
+        WININET_Release( &lpwfs->hdr );
+
+    return r;
 }
 
 
@@ -798,17 +819,15 @@
  *    FALSE on failure
  *
  */
-BOOL WINAPI FTP_FtpGetCurrentDirectoryW(HINTERNET hFtpSession, LPWSTR lpszCurrentDirectory,
+BOOL WINAPI FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszCurrentDirectory,
 	LPDWORD lpdwCurrentDirectory)
 {
     INT nResCode;
-    LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
     DWORD bSuccess = FALSE;
 
     TRACE("len(%ld)\n", *lpdwCurrentDirectory);
 
-    lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
@@ -822,7 +841,7 @@
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
     if (!FTP_SendCommand(lpwfs->sndSocket, FTP_CMD_PWD, NULL,
-        hIC->lpfnStatusCB, hFtpSession, lpwfs->hdr.dwContext))
+        hIC->lpfnStatusCB, &lpwfs->hdr, lpwfs->hdr.dwContext))
         goto lend;
 
     nResCode = FTP_ReceiveResponse(lpwfs, lpwfs->hdr.dwContext);
@@ -862,7 +881,7 @@
 
         iar.dwResult = (DWORD)bSuccess;
         iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR;
-        SendAsyncCallback(hIC, hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
 
@@ -909,6 +928,7 @@
 {
     LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
+    HINTERNET r = NULL;
     
     TRACE("(%p,%s,0x%08lx,0x%08lx,0x%08lx)\n", hFtpSession,
         debugstr_w(lpszFileName), fdwAccess, dwFlags, dwContext);
@@ -917,12 +937,12 @@
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     if (lpwfs->download_in_progress != NULL) {
 	INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
-	return FALSE;
+	goto lend;
     }
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
     if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
@@ -931,7 +951,7 @@
         struct WORKREQ_FTPOPENFILEW *req;
 
         workRequest.asyncall = FTPOPENFILEW;
-	workRequest.handle = hFtpSession;
+	workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
         req = &workRequest.u.FtpOpenFileW;
 	req->lpszFilename = WININET_strdupW(lpszFileName);
 	req->dwAccess = fdwAccess;
@@ -939,12 +959,18 @@
 	req->dwContext = dwContext;
 
 	INTERNET_AsyncCall(&workRequest);
-	return NULL;
+	r = NULL;
     }
     else
     {
-	return FTP_FtpOpenFileW(hFtpSession, lpszFileName, fdwAccess, dwFlags, dwContext);
+	r = FTP_FtpOpenFileW(lpwfs, lpszFileName, fdwAccess, dwFlags, dwContext);
     }
+
+lend:
+    if( lpwfs )
+        WININET_Release( &lpwfs->hdr );
+
+    return r;
 }
 
 
@@ -958,7 +984,7 @@
  *    NULL on failure
  *
  */
-HINTERNET FTP_FtpOpenFileW(HINTERNET hFtpSession,
+HINTERNET FTP_FtpOpenFileW(LPWININETFTPSESSIONW lpwfs,
 	LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
 	DWORD dwContext)
 {
@@ -966,17 +992,11 @@
     BOOL bSuccess = FALSE;
     LPWININETFILE lpwh = NULL;
     LPWININETAPPINFOW hIC = NULL;
-    LPWININETFTPSESSIONW lpwfs;
     HINTERNET handle = NULL;
 
     TRACE("\n");
 
-    lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
-    if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
-    {
-        INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
-    }
+    assert (WH_HFTPSESSION == lpwfs->hdr.htype);
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -996,14 +1016,19 @@
     if (bSuccess && FTP_GetDataSocket(lpwfs, &nDataSocket))
     {
         lpwh = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETFILE));
-        handle = WININET_AllocHandle( &lpwh->hdr );
         lpwh->hdr.htype = WH_HFILE;
         lpwh->hdr.dwFlags = dwFlags;
         lpwh->hdr.dwContext = dwContext;
-        lpwh->hdr.lpwhparent = &lpwfs->hdr;
+        lpwh->hdr.lpwhparent = WININET_AddRef( &lpwfs->hdr );
+        lpwh->hdr.dwRefCount = 1;
+        lpwh->hdr.destroy = FTP_CloseFileTransferHandle;
         lpwh->nDataSocket = nDataSocket;
 	lpwh->session_deleted = FALSE;
 	
+        handle = WININET_AllocHandle( &lpwh->hdr );
+        if( !handle )
+            goto lend;
+
 	/* Indicate that a download is currently in progress */
 	lpwfs->download_in_progress = lpwh;
     }
@@ -1020,16 +1045,20 @@
 	{
             iar.dwResult = (DWORD)handle;
             iar.dwError = ERROR_SUCCESS;
-            SendAsyncCallback(hIC, hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
+            SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_HANDLE_CREATED,
                 &iar, sizeof(INTERNET_ASYNC_RESULT));
 	}
 
         iar.dwResult = (DWORD)bSuccess;
         iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
-        SendAsyncCallback(hIC, hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
 
+lend:
+    if( lpwh )
+        WININET_Release( &lpwh->hdr );
+
     return handle;
 }
 
@@ -1078,17 +1107,18 @@
 {
     LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
+    BOOL r = FALSE;
 
     lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hInternet );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     if (lpwfs->download_in_progress != NULL) {
 	INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
-	return FALSE;
+        goto lend;
     }
     
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
@@ -1098,7 +1128,7 @@
         struct WORKREQ_FTPGETFILEW *req;
 
         workRequest.asyncall = FTPGETFILEW;
-	workRequest.handle = hInternet;
+	workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
         req = &workRequest.u.FtpGetFileW;
         req->lpszRemoteFile = WININET_strdupW(lpszRemoteFile);
         req->lpszNewFile = WININET_strdupW(lpszNewFile);
@@ -1107,13 +1137,19 @@
 	req->dwFlags = dwInternetFlags;
 	req->dwContext = dwContext;
 
-	return INTERNET_AsyncCall(&workRequest);
+	r = INTERNET_AsyncCall(&workRequest);
     }
     else
     {
-        return FTP_FtpGetFileW(hInternet, lpszRemoteFile, lpszNewFile,
+        r = FTP_FtpGetFileW(lpwfs, lpszRemoteFile, lpszNewFile,
            fFailIfExists, dwLocalFlagsAttribute, dwInternetFlags, dwContext);
     }
+
+lend:
+    if( lpwfs )
+        WININET_Release( &lpwfs->hdr );
+
+    return r;
 }
 
 
@@ -1127,7 +1163,7 @@
  *    FALSE on failure
  *
  */
-BOOL WINAPI FTP_FtpGetFileW(HINTERNET hInternet, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
+BOOL WINAPI FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
 	BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
 	DWORD dwContext)
 {
@@ -1135,16 +1171,10 @@
     BOOL bSuccess = FALSE;
     HANDLE hFile;
     LPWININETAPPINFOW hIC = NULL;
-    LPWININETFTPSESSIONW lpwfs;
 
     TRACE("lpszRemoteFile(%s) lpszNewFile(%s)\n", debugstr_w(lpszRemoteFile), debugstr_w(lpszNewFile));
 
-    lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hInternet );
-    if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
-    {
-        INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
-    }
+    assert (WH_HFTPSESSION == lpwfs->hdr.htype);
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -1195,7 +1225,7 @@
 
         iar.dwResult = (DWORD)bSuccess;
         iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
-        SendAsyncCallback(hIC, hInternet, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
 
@@ -1238,12 +1268,13 @@
 {
     LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
+    BOOL r = FALSE;
 
     lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
@@ -1253,16 +1284,22 @@
         struct WORKREQ_FTPDELETEFILEW *req;
 
         workRequest.asyncall = FTPDELETEFILEW;
-	workRequest.handle = hFtpSession;
+	workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
         req = &workRequest.u.FtpDeleteFileW;
         req->lpszFilename = WININET_strdupW(lpszFileName);
 
-	return INTERNET_AsyncCall(&workRequest);
+	r = INTERNET_AsyncCall(&workRequest);
     }
     else
     {
-        return FTP_FtpDeleteFileW(hFtpSession, lpszFileName);
+        r = FTP_FtpDeleteFileW(hFtpSession, lpszFileName);
     }
+
+lend:
+    if( lpwfs )
+        WININET_Release( &lpwfs->hdr );
+
+    return r;
 }
 
 /***********************************************************************
@@ -1275,21 +1312,15 @@
  *    FALSE on failure
  *
  */
-BOOL FTP_FtpDeleteFileW(HINTERNET hFtpSession, LPCWSTR lpszFileName)
+BOOL FTP_FtpDeleteFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszFileName)
 {
     INT nResCode;
     BOOL bSuccess = FALSE;
     LPWININETAPPINFOW hIC = NULL;
-    LPWININETFTPSESSIONW lpwfs;
 
-    TRACE("0x%08lx\n", (ULONG) hFtpSession);
+    TRACE("%p\n", lpwfs);
 
-    lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
-    if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
-    {
-        INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
-    }
+    assert (WH_HFTPSESSION == lpwfs->hdr.htype);
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -1313,7 +1344,7 @@
 
         iar.dwResult = (DWORD)bSuccess;
         iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
-        SendAsyncCallback(hIC, hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
 
@@ -1356,12 +1387,13 @@
 {
     LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
+    BOOL r = FALSE;
 
     lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
@@ -1371,16 +1403,22 @@
         struct WORKREQ_FTPREMOVEDIRECTORYW *req;
 
         workRequest.asyncall = FTPREMOVEDIRECTORYW;
-	workRequest.handle = hFtpSession;
+	workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
         req = &workRequest.u.FtpRemoveDirectoryW;
         req->lpszDirectory = WININET_strdupW(lpszDirectory);
 
-	return INTERNET_AsyncCall(&workRequest);
+	r = INTERNET_AsyncCall(&workRequest);
     }
     else
     {
-        return FTP_FtpRemoveDirectoryW(hFtpSession, lpszDirectory);
+        r = FTP_FtpRemoveDirectoryW(lpwfs, lpszDirectory);
     }
+
+lend:
+    if( lpwfs )
+        WININET_Release( &lpwfs->hdr );
+
+    return r;
 }
 
 /***********************************************************************
@@ -1393,21 +1431,15 @@
  *    FALSE on failure
  *
  */
-BOOL FTP_FtpRemoveDirectoryW(HINTERNET hFtpSession, LPCWSTR lpszDirectory)
+BOOL FTP_FtpRemoveDirectoryW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszDirectory)
 {
     INT nResCode;
     BOOL bSuccess = FALSE;
     LPWININETAPPINFOW hIC = NULL;
-    LPWININETFTPSESSIONW lpwfs;
 
     TRACE("\n");
 
-    lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
-    if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
-    {
-        INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
-    }
+    assert (WH_HFTPSESSION == lpwfs->hdr.htype);
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -1432,7 +1464,7 @@
 
         iar.dwResult = (DWORD)bSuccess;
         iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
-        SendAsyncCallback(hIC, hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
 
@@ -1478,12 +1510,13 @@
 {
     LPWININETFTPSESSIONW lpwfs;
     LPWININETAPPINFOW hIC = NULL;
+    BOOL r = FALSE;
 
     lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
     if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
@@ -1493,17 +1526,23 @@
         struct WORKREQ_FTPRENAMEFILEW *req;
 
         workRequest.asyncall = FTPRENAMEFILEW;
-	workRequest.handle = hFtpSession;
+	workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
         req = &workRequest.u.FtpRenameFileW;
         req->lpszSrcFile = WININET_strdupW(lpszSrc);
         req->lpszDestFile = WININET_strdupW(lpszDest);
 
-	return INTERNET_AsyncCall(&workRequest);
+	r = INTERNET_AsyncCall(&workRequest);
     }
     else
     {
-        return FTP_FtpRenameFileW(hFtpSession, lpszSrc, lpszDest);
+        r = FTP_FtpRenameFileW(hFtpSession, lpszSrc, lpszDest);
     }
+
+lend:
+    if( lpwfs )
+        WININET_Release( &lpwfs->hdr );
+
+    return r;
 }
 
 /***********************************************************************
@@ -1516,21 +1555,16 @@
  *    FALSE on failure
  *
  */
-BOOL FTP_FtpRenameFileW(HINTERNET hFtpSession, LPCWSTR lpszSrc, LPCWSTR lpszDest)
+BOOL FTP_FtpRenameFileW( LPWININETFTPSESSIONW lpwfs,
+                         LPCWSTR lpszSrc, LPCWSTR lpszDest)
 {
     INT nResCode;
     BOOL bSuccess = FALSE;
     LPWININETAPPINFOW hIC = NULL;
-    LPWININETFTPSESSIONW lpwfs;
 
     TRACE("\n");
 
-    lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
-    if (NULL == lpwfs || WH_HFTPSESSION != lpwfs->hdr.htype)
-    {
-        INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
-    }
+    assert (WH_HFTPSESSION == lpwfs->hdr.htype);
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -1560,7 +1594,7 @@
 
         iar.dwResult = (DWORD)bSuccess;
         iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
-        SendAsyncCallback(hIC, hFtpSession, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
 
@@ -1579,7 +1613,7 @@
  *
  */
 
-HINTERNET FTP_Connect(HINTERNET hInternet, LPCWSTR lpszServerName,
+HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
 	INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
 	LPCWSTR lpszPassword, DWORD dwFlags, DWORD dwContext,
 	DWORD dwInternalFlags)
@@ -1589,18 +1623,15 @@
     struct sockaddr_in socketAddr;
     struct hostent *phe = NULL;
     INT nsocket = -1, sock_namelen;
-    LPWININETAPPINFOW hIC = NULL;
     BOOL bSuccess = FALSE;
     LPWININETFTPSESSIONW lpwfs = NULL;
     HINTERNET handle = NULL;
 
-    TRACE("0x%08lx  Server(%s) Port(%d) User(%s) Paswd(%s)\n",
-	    (ULONG) hInternet, debugstr_w(lpszServerName),
+    TRACE("%p  Server(%s) Port(%d) User(%s) Paswd(%s)\n",
+	    hIC, debugstr_w(lpszServerName),
 	    nServerPort, debugstr_w(lpszUserName), debugstr_w(lpszPassword));
 
-    hIC = (LPWININETAPPINFOW) WININET_GetObject( hInternet );
-    if ( (hIC == NULL) || (hIC->hdr.htype != WH_HINIT) )
-        goto lerror;
+    assert( hIC->hdr.htype != WH_HINIT );
 
     if (NULL == lpszUserName && NULL != lpszPassword)
     {
@@ -1615,23 +1646,26 @@
         goto lerror;
     }
 
-    handle = WININET_AllocHandle( &lpwfs->hdr );
-    if( !handle )
-    {
-        ERR("Failed to alloc handle\n");
-        INTERNET_SetLastError(ERROR_OUTOFMEMORY);
-        goto lerror;
-    }
-
     if (nServerPort == INTERNET_INVALID_PORT_NUMBER)
 	nServerPort = INTERNET_DEFAULT_FTP_PORT;
 
     lpwfs->hdr.htype = WH_HFTPSESSION;
-    lpwfs->hdr.lpwhparent = &hIC->hdr;
+    lpwfs->hdr.lpwhparent = WININET_AddRef( &hIC->hdr );
     lpwfs->hdr.dwFlags = dwFlags;
     lpwfs->hdr.dwContext = dwContext;
     lpwfs->hdr.dwInternalFlags = dwInternalFlags;
+    lpwfs->hdr.dwRefCount = 1;
+    lpwfs->hdr.destroy = FTP_CloseSessionHandle;
     lpwfs->download_in_progress = NULL;
+
+    handle = WININET_AllocHandle( &lpwfs->hdr );
+    if( !handle )
+    {
+        ERR("Failed to alloc handle\n");
+        INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+        goto lerror;
+    }
+
     if(hIC->lpszProxy && hIC->dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
         if(strchrW(hIC->lpszProxy, ' '))
             FIXME("Several proxies not implemented.\n");
@@ -1655,12 +1689,12 @@
         iar.dwResult = (DWORD)handle;
         iar.dwError = ERROR_SUCCESS;
 
-        SendAsyncCallback(hIC, hInternet, dwContext,
+        SendAsyncCallback(hIC, &hIC->hdr, dwContext,
                       INTERNET_STATUS_HANDLE_CREATED, &iar,
                       sizeof(INTERNET_ASYNC_RESULT));
     }
         
-    SendAsyncCallback(hIC, hInternet, dwContext, INTERNET_STATUS_RESOLVING_NAME,
+    SendAsyncCallback(hIC, &hIC->hdr, dwContext, INTERNET_STATUS_RESOLVING_NAME,
         (LPWSTR) lpszServerName, strlenW(lpszServerName));
 
     if (!GetAddress(lpszServerName, nServerPort, &phe, &socketAddr))
@@ -1669,7 +1703,7 @@
         goto lerror;
     }
 
-    SendAsyncCallback(hIC, hInternet, dwContext, INTERNET_STATUS_NAME_RESOLVED,
+    SendAsyncCallback(hIC, &hIC->hdr, dwContext, INTERNET_STATUS_NAME_RESOLVED,
         (LPWSTR) lpszServerName, strlenW(lpszServerName));
 
     nsocket = socket(AF_INET,SOCK_STREAM,0);
@@ -1679,7 +1713,7 @@
         goto lerror;
     }
 
-    SendAsyncCallback(hIC, hInternet, dwContext, INTERNET_STATUS_CONNECTING_TO_SERVER,
+    SendAsyncCallback(hIC, &hIC->hdr, dwContext, INTERNET_STATUS_CONNECTING_TO_SERVER,
         &socketAddr, sizeof(struct sockaddr_in));
 
     if (connect(nsocket, (struct sockaddr *)&socketAddr, sizeof(socketAddr)) < 0)
@@ -1691,7 +1725,7 @@
     {
         TRACE("Connected to server\n");
 	lpwfs->sndSocket = nsocket;
-        SendAsyncCallback(hIC, hInternet, dwContext, INTERNET_STATUS_CONNECTED_TO_SERVER,
+        SendAsyncCallback(hIC, &hIC->hdr, dwContext, INTERNET_STATUS_CONNECTED_TO_SERVER,
             &socketAddr, sizeof(struct sockaddr_in));
 
 	sock_namelen = sizeof(lpwfs->socketAddress);
@@ -1722,7 +1756,7 @@
 
         iar.dwResult = (DWORD)lpwfs;
         iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
-        SendAsyncCallback(hIC, hInternet, dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
+        SendAsyncCallback(hIC, &hIC->hdr, dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
             &iar, sizeof(INTERNET_ASYNC_RESULT));
     }
 
@@ -1784,7 +1818,7 @@
  *
  */
 BOOL FTP_SendCommandA(INT nSocket, FTP_COMMAND ftpCmd, LPCSTR lpszParam,
-	INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext)
+	INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD dwContext)
 {
     	DWORD len;
 	CHAR *buf;
@@ -1795,7 +1829,14 @@
 	TRACE("%d: (%s) %d\n", ftpCmd, lpszParam, nSocket);
 
 	if (lpfnStatusCB)
-		lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
+        {
+             HINTERNET hHandle = WININET_FindHandle( hdr );
+	     if( hHandle )
+             {
+                 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
+                 WININET_Release( hdr );
+             }
+        }
 
 	dwParamLen = lpszParam?strlen(lpszParam)+1:0;
 	len = dwParamLen + strlen(szFtpCommands[ftpCmd]) + strlen(szCRLF);
@@ -1817,8 +1858,15 @@
 	HeapFree(GetProcessHeap(), 0, (LPVOID)buf);
 
 	if (lpfnStatusCB)
-		lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_REQUEST_SENT,
-			&nBytesSent, sizeof(DWORD));
+        {
+             HINTERNET hHandle = WININET_FindHandle( hdr );
+	     if( hHandle )
+             {
+                 lpfnStatusCB(hHandle, dwContext, INTERNET_STATUS_REQUEST_SENT,
+                              &nBytesSent, sizeof(DWORD));
+                 WININET_Release( hdr );
+             }
+        }
 
 	TRACE("Sent %ld bytes\n", nBytesSent);
 	return (nRC != -1);
@@ -1835,11 +1883,11 @@
  *
  */
 BOOL FTP_SendCommand(INT nSocket, FTP_COMMAND ftpCmd, LPCWSTR lpszParam,
-	INTERNET_STATUS_CALLBACK lpfnStatusCB, HINTERNET hHandle, DWORD dwContext)
+	INTERNET_STATUS_CALLBACK lpfnStatusCB, LPWININETHANDLEHEADER hdr, DWORD dwContext)
 {
     BOOL ret;
     LPSTR lpszParamA = lpszParam?WININET_strdup_WtoA(lpszParam):NULL;
-    ret = FTP_SendCommandA(nSocket, ftpCmd, lpszParamA, lpfnStatusCB, hHandle, dwContext);
+    ret = FTP_SendCommandA(nSocket, ftpCmd, lpszParamA, lpfnStatusCB, hdr, dwContext);
     HeapFree(GetProcessHeap(), 0, lpszParamA);
     return ret;
 }
@@ -1862,13 +1910,11 @@
     char firstprefix[5];
     BOOL multiline = FALSE;
     LPWININETAPPINFOW hIC = NULL;
-    HINTERNET hHandle;
 
     TRACE("socket(%d) \n", lpwfs->sndSocket);
 
-    hHandle = WININET_FindHandle(&lpwfs->hdr);
     hIC = (LPWININETAPPINFOW) lpwfs->hdr.lpwhparent;
-    SendAsyncCallback(hIC, hHandle, dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+    SendAsyncCallback(hIC, &lpwfs->hdr, dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
 
     while(1)
     {
@@ -1901,7 +1947,7 @@
     {
         rc = atoi(lpszResponse);
 
-        SendAsyncCallback(hIC, hHandle, dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
+        SendAsyncCallback(hIC, &lpwfs->hdr, dwContext, INTERNET_STATUS_RESPONSE_RECEIVED,
 		    &nRecv, sizeof(DWORD));
     }
 
@@ -2543,8 +2589,10 @@
  *   FALSE on failure
  *
  */
-BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONW lpwfs)
+static void FTP_CloseSessionHandle(LPWININETHANDLEHEADER hdr)
 {
+    LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) hdr;
+
     TRACE("\n");
 
     if (lpwfs->download_in_progress != NULL)
@@ -2563,8 +2611,6 @@
         HeapFree(GetProcessHeap(), 0, lpwfs->lpszUserName);
 
     HeapFree(GetProcessHeap(), 0, lpwfs);
-
-    return TRUE;
 }
 
 
@@ -2578,8 +2624,9 @@
  *   FALSE on failure
  *
  */
-BOOL FTP_CloseFindNextHandle(LPWININETFINDNEXTW lpwfn)
+static void FTP_CloseFindNextHandle(LPWININETHANDLEHEADER hdr)
 {
+    LPWININETFINDNEXTW lpwfn = (LPWININETFINDNEXTW) hdr;
     INT i;
 
     TRACE("\n");
@@ -2592,8 +2639,6 @@
 
     HeapFree(GetProcessHeap(), 0, lpwfn->lpafp);
     HeapFree(GetProcessHeap(), 0, lpwfn);
-
-    return TRUE;
 }
 
 /***********************************************************************
@@ -2602,16 +2647,12 @@
  * Closes the file transfer handle. This also 'cleans' the data queue of
  * the 'transfer conplete' message (this is a bit of a hack though :-/ )
  *
- * RETURNS
- *   TRUE on success
- *   FALSE on failure
- *
  */
-BOOL FTP_CloseFileTransferHandle(LPWININETFILE lpwh)
+static void FTP_CloseFileTransferHandle(LPWININETHANDLEHEADER hdr)
 {
+    LPWININETFILE lpwh = (LPWININETFILE) hdr;
     LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) lpwh->hdr.lpwhparent;
     INT nResCode;
-    HINTERNET handle;
 
     TRACE("\n");
 
@@ -2629,16 +2670,6 @@
         close(lpwh->nDataSocket);
 
     HeapFree(GetProcessHeap(), 0, lpwh);
-
-    /* If this handle was opened with InternetOpenUrl, we need to close the parent to prevent
-       a memory leek
-     */
-    if(lpwfs->hdr.dwInternalFlags & INET_OPENURL)
-    {
-        handle = WININET_FindHandle( &lpwfs->hdr );
-        InternetCloseHandle(handle);
-    }
-    return TRUE;
 }
 
 /***********************************************************************
@@ -2669,20 +2700,21 @@
         lpwfn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETFINDNEXTW));
         if (lpwfn)
         {
+            lpwfn->hdr.htype = WH_HFINDNEXT;
+            lpwfn->hdr.lpwhparent = WININET_AddRef( &lpwfs->hdr );
+            lpwfn->hdr.dwContext = dwContext;
+            lpwfn->hdr.dwRefCount = 1;
+            lpwfn->hdr.destroy = FTP_CloseFindNextHandle;
+            lpwfn->index = 1; /* Next index is 1 since we return index 0 */
+            lpwfn->size = dwSize;
+            lpwfn->lpafp = lpafp;
+
             handle = WININET_AllocHandle( &lpwfn->hdr );
-            if( handle )
-            {
-                lpwfn->hdr.htype = WH_HFINDNEXT;
-                lpwfn->hdr.lpwhparent = (LPWININETHANDLEHEADER)lpwfs;
-	        lpwfn->hdr.dwContext = dwContext;
-                lpwfn->index = 1; /* Next index is 1 since we return index 0 */
-                lpwfn->size = dwSize;
-                lpwfn->lpafp = lpafp;
-            }
-            else
-                HeapFree( GetProcessHeap(), 0, lpwfn );
         }
     }
+
+    if( lpwfn )
+        WININET_Release( &lpwfn->hdr );
 
     TRACE("Matched %ld files\n", dwSize);
     return handle;
Index: dlls/wininet/http.c
===================================================================
RCS file: /home/wine/wine/dlls/wininet/http.c,v
retrieving revision 1.68
diff -u -r1.68 http.c
--- dlls/wininet/http.c	16 Jul 2004 19:15:40 -0000	1.68
+++ dlls/wininet/http.c	19 Jul 2004 05:45:49 -0000
@@ -40,6 +40,7 @@
 #include <errno.h>
 #include <string.h>
 #include <time.h>
+#include <assert.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -81,6 +82,8 @@
 #define HTTP_ADDHDR_FLAG_REQ				0x02000000
 
 
+static void HTTP_CloseHTTPRequestHandle(LPWININETHANDLEHEADER hdr);
+static void HTTP_CloseHTTPSessionHandle(LPWININETHANDLEHEADER hdr);
 BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr);
 int HTTP_WriteDataToStream(LPWININETHTTPREQW lpwhr,
 	void *Buffer, int BytesToWrite);
@@ -170,9 +173,12 @@
     if (NULL == lpwhr ||  lpwhr->hdr.htype != WH_HHTTPREQ)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return bSuccess;
+        goto lend;
     }
     bSuccess = HTTP_HttpAddRequestHeadersW( lpwhr, lpszHeader, dwHeaderLength, dwModifier );
+lend:
+    if( lpwhr )
+        WININET_Release( &lpwhr->hdr );
 
     return bSuccess;
 }
@@ -278,7 +284,7 @@
     if (NULL == lpwhs ||  lpwhs->hdr.htype != WH_HHTTPSESSION)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return NULL;
+	goto lend;
     }
     hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
 
@@ -288,40 +294,13 @@
      * if this call was asynchronous then how would you get the
      * necessary HINTERNET pointer returned by this function.
      *
-     * I am leaving this here just in case I am wrong
-     *
-     * if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
      */
-    if (0)
-    {
-        WORKREQUEST workRequest;
-        struct WORKREQ_HTTPOPENREQUESTW *req;
-
-	workRequest.asyncall = HTTPOPENREQUESTW;
-	workRequest.handle = hHttpSession;
-        req = &workRequest.u.HttpOpenRequestW;
-	req->lpszVerb = WININET_strdupW(lpszVerb);
-	req->lpszObjectName = WININET_strdupW(lpszObjectName);
-        if (lpszVersion)
-            req->lpszVersion = WININET_strdupW(lpszVersion);
-        else
-            req->lpszVersion = 0;
-        if (lpszReferrer)
-            req->lpszReferrer = WININET_strdupW(lpszReferrer);
-        else
-            req->lpszReferrer = 0;
-	req->lpszAcceptTypes = lpszAcceptTypes;
-	req->dwFlags = dwFlags;
-	req->dwContext = dwContext;
-
-        INTERNET_AsyncCall(&workRequest);
-    }
-    else
-    {
-        handle = HTTP_HttpOpenRequestW(hHttpSession, lpszVerb, lpszObjectName,
-                                              lpszVersion, lpszReferrer, lpszAcceptTypes,
-                                              dwFlags, dwContext);
-    }
+    handle = HTTP_HttpOpenRequestW(lpwhs, lpszVerb, lpszObjectName,
+                                   lpszVersion, lpszReferrer, lpszAcceptTypes,
+                                   dwFlags, dwContext);
+lend:
+    if( lpwhs )
+        WININET_Release( &lpwhs->hdr );
     TRACE("returning %p\n", handle);
     return handle;
 }
@@ -611,50 +590,45 @@
  *    NULL 	 on failure
  *
  */
-HINTERNET WINAPI HTTP_HttpOpenRequestW(HINTERNET hHttpSession,
+HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs,
 	LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
 	LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
 	DWORD dwFlags, DWORD dwContext)
 {
-    LPWININETHTTPSESSIONW lpwhs;
     LPWININETAPPINFOW hIC = NULL;
     LPWININETHTTPREQW lpwhr;
     LPWSTR lpszCookies;
     LPWSTR lpszUrl = NULL;
     DWORD nCookieSize;
-    HINTERNET handle;
+    HINTERNET handle = NULL;
     static const WCHAR szUrlForm[] = {'h','t','t','p',':','/','/','%','s',0};
     DWORD len;
 
     TRACE("--> \n");
 
-    lpwhs = (LPWININETHTTPSESSIONW) WININET_GetObject( hHttpSession );
-    if (NULL == lpwhs ||  lpwhs->hdr.htype != WH_HHTTPSESSION)
-    {
-        INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return NULL;
-    }
-
+    assert( lpwhs->hdr.htype == WH_HHTTPSESSION );
     hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
 
     lpwhr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETHTTPREQW));
     if (NULL == lpwhr)
     {
         INTERNET_SetLastError(ERROR_OUTOFMEMORY);
-        return NULL;
+        goto lend;
     }
+    lpwhr->hdr.htype = WH_HHTTPREQ;
+    lpwhr->hdr.lpwhparent = WININET_AddRef( &lpwhs->hdr );
+    lpwhr->hdr.dwFlags = dwFlags;
+    lpwhr->hdr.dwContext = dwContext;
+    lpwhr->hdr.dwRefCount = 1;
+    lpwhr->hdr.destroy = HTTP_CloseHTTPRequestHandle;
+
     handle = WININET_AllocHandle( &lpwhr->hdr );
     if (NULL == handle)
     {
         INTERNET_SetLastError(ERROR_OUTOFMEMORY);
-        HeapFree( GetProcessHeap(), 0, lpwhr );
-        return NULL;
+        goto lend;
     }
 
-    lpwhr->hdr.htype = WH_HHTTPREQ;
-    lpwhr->hdr.lpwhparent = &lpwhs->hdr;
-    lpwhr->hdr.dwFlags = dwFlags;
-    lpwhr->hdr.dwContext = dwContext;
     NETCON_init(&lpwhr->netConnection, dwFlags & INTERNET_FLAG_SECURE);
 
     if (NULL != lpszObjectName && strlenW(lpszObjectName)) {
@@ -756,7 +730,7 @@
         iar.dwResult = (DWORD)handle;
         iar.dwError = ERROR_SUCCESS;
 
-        SendAsyncCallback(hIC, hHttpSession, dwContext,
+        SendAsyncCallback(hIC, &lpwhs->hdr, dwContext,
                       INTERNET_STATUS_HANDLE_CREATED, &iar,
                       sizeof(INTERNET_ASYNC_RESULT));
     }
@@ -768,7 +742,7 @@
     /*
      * According to my tests. The name is not resolved until a request is Opened
      */
-    SendAsyncCallback(hIC, hHttpSession, dwContext,
+    SendAsyncCallback(hIC, &lpwhs->hdr, dwContext,
                       INTERNET_STATUS_RESOLVING_NAME,
                       lpwhs->lpszServerName,
                       strlenW(lpwhs->lpszServerName)+1);
@@ -776,15 +750,21 @@
                     &lpwhs->phostent, &lpwhs->socketAddress))
     {
         INTERNET_SetLastError(ERROR_INTERNET_NAME_NOT_RESOLVED);
-        return NULL;
+        InternetCloseHandle( handle );
+        handle = NULL;
+        goto lend;
     }
 
-    SendAsyncCallback(hIC, hHttpSession, lpwhr->hdr.dwContext,
+    SendAsyncCallback(hIC, &lpwhs->hdr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_NAME_RESOLVED,
                       &(lpwhs->socketAddress),
                       sizeof(struct sockaddr_in));
 
-    TRACE("<-- %p\n", handle);
+lend:
+    if( lpwhr )
+        WININET_Release( &lpwhr->hdr );
+
+    TRACE("<-- %p (%p)\n", handle, lpwhr);
     return handle;
 }
 
@@ -1167,12 +1147,16 @@
     if (NULL == lpwhr ||  lpwhr->hdr.htype != WH_HHTTPREQ)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+	goto lend;
     }
 
     bSuccess = HTTP_HttpQueryInfoW( lpwhr, dwInfoLevel,
 	                            lpBuffer, lpdwBufferLength, lpdwIndex);
 
+lend:
+    if( lpwhr )
+         WININET_Release( &lpwhr->hdr );
+
     TRACE("%d <--\n", bSuccess);
     return bSuccess;
 }
@@ -1248,6 +1232,7 @@
     LPWININETHTTPREQW lpwhr;
     LPWININETHTTPSESSIONW lpwhs = NULL;
     LPWININETAPPINFOW hIC = NULL;
+    BOOL r;
 
     TRACE("%p, %p (%s), %li, %p, %li)\n", hHttpRequest,
             lpszHeaders, debugstr_w(lpszHeaders), dwHeaderLength, lpOptional, dwOptionalLength);
@@ -1256,21 +1241,24 @@
     if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+	r = FALSE;
+        goto lend;
     }
 
     lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
     if (NULL == lpwhs ||  lpwhs->hdr.htype != WH_HHTTPSESSION)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+	r = FALSE;
+        goto lend;
     }
 
     hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
     if (NULL == hIC ||  hIC->hdr.htype != WH_HINIT)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
+	r = FALSE;
+        goto lend;
     }
 
     if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
@@ -1279,7 +1267,7 @@
         struct WORKREQ_HTTPSENDREQUESTW *req;
 
         workRequest.asyncall = HTTPSENDREQUESTW;
-        workRequest.handle = hHttpRequest;
+	workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
         req = &workRequest.u.HttpSendRequestW;
         if (lpszHeaders)
             req->lpszHeader = WININET_strdupW(lpszHeaders);
@@ -1294,13 +1282,17 @@
          * This is from windows.
          */
         SetLastError(ERROR_IO_PENDING);
-        return 0;
+        r = FALSE;
     }
     else
     {
-	return HTTP_HttpSendRequestW(hHttpRequest, lpszHeaders,
+	r = HTTP_HttpSendRequestW(lpwhr, lpszHeaders,
 		dwHeaderLength, lpOptional, dwOptionalLength);
     }
+lend:
+    if( lpwhr )
+        WININET_Release( &lpwhr->hdr );
+    return r;
 }
 
 /***********************************************************************
@@ -1340,7 +1332,6 @@
     LPWININETHTTPSESSIONW lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
     LPWININETAPPINFOW hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
     WCHAR path[2048];
-    HINTERNET handle;
 
     if(lpszUrl[0]=='/')
     {
@@ -1405,7 +1396,7 @@
             HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName);
         lpwhr->lpszHostName=WININET_strdupW(hostName);
 
-        SendAsyncCallback(hIC, lpwhs, lpwhr->hdr.dwContext,
+        SendAsyncCallback(hIC, &lpwhs->hdr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_RESOLVING_NAME,
                       lpwhs->lpszServerName,
                       strlenW(lpwhs->lpszServerName)+1);
@@ -1417,7 +1408,7 @@
             return FALSE;
         }
 
-        SendAsyncCallback(hIC, lpwhs, lpwhr->hdr.dwContext,
+        SendAsyncCallback(hIC, &lpwhs->hdr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_NAME_RESOLVED,
                       &(lpwhs->socketAddress),
                       sizeof(struct sockaddr_in));
@@ -1445,8 +1436,7 @@
         }
     }
 
-    handle = WININET_FindHandle( &lpwhr->hdr );
-    return HttpSendRequestW(handle, lpszHeaders, dwHeaderLength, lpOptional, dwOptionalLength);
+    return HTTP_HttpSendRequestW(lpwhr, lpszHeaders, dwHeaderLength, lpOptional, dwOptionalLength);
 }
 
 /***********************************************************************
@@ -1482,7 +1472,7 @@
  *    FALSE on failure
  *
  */
-BOOL WINAPI HTTP_HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
+BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
 	DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
 {
     INT cnt;
@@ -1490,21 +1480,14 @@
     BOOL bSuccess = FALSE;
     LPWSTR requestString = NULL;
     INT responseLen;
-    LPWININETHTTPREQW lpwhr;
     LPWININETHTTPSESSIONW lpwhs = NULL;
     LPWININETAPPINFOW hIC = NULL;
     BOOL loop_next = FALSE;
     int CustHeaderIndex;
 
-    TRACE("--> 0x%08lx\n", (ULONG)hHttpRequest);
+    TRACE("--> %p\n", lpwhr);
 
-    /* Verify our tree of internet handles */
-    lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hHttpRequest );
-    if (NULL == lpwhr ||  lpwhr->hdr.htype != WH_HHTTPREQ)
-    {
-        INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-	return FALSE;
-    }
+    assert(lpwhr->hdr.htype == WH_HHTTPREQ);
 
     lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
     if (NULL == lpwhs ||  lpwhs->hdr.htype != WH_HHTTPSESSION)
@@ -1644,7 +1627,7 @@
         if (!HTTP_OpenConnection(lpwhr))
             goto lend;
 
-        SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+        SendAsyncCallback(hIC, &lpwhr->hdr, lpwhr->hdr.dwContext,
                           INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
 
         /* send the request as ASCII, tack on the optional data */
@@ -1661,11 +1644,11 @@
         NETCON_send(&lpwhr->netConnection, ascii_req, len, 0, &cnt);
         HeapFree( GetProcessHeap(), 0, ascii_req );
 
-        SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+        SendAsyncCallback(hIC, &lpwhr->hdr, lpwhr->hdr.dwContext,
                           INTERNET_STATUS_REQUEST_SENT,
                           &len,sizeof(DWORD));
 
-        SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+        SendAsyncCallback(hIC, &lpwhr->hdr, lpwhr->hdr.dwContext,
                           INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
 
         if (cnt < 0)
@@ -1675,7 +1658,7 @@
         if (responseLen)
 	    bSuccess = TRUE;
 
-        SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+        SendAsyncCallback(hIC, &lpwhr->hdr, lpwhr->hdr.dwContext,
                           INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen,
                           sizeof(DWORD));
 
@@ -1775,7 +1758,7 @@
             dwIndex=0;
             if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,&dwIndex))
             {
-                SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+                SendAsyncCallback(hIC, &lpwhr->hdr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_REDIRECT, szNewLocation,
                       dwBufferSize);
                 return HTTP_HandleRedirect(lpwhr, szNewLocation, lpszHeaders,
@@ -1791,7 +1774,7 @@
         iar.dwResult = (DWORD)bSuccess;
         iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
 
-        SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext,
+        SendAsyncCallback(hIC, &lpwhr->hdr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_REQUEST_COMPLETE, &iar,
                       sizeof(INTERNET_ASYNC_RESULT));
     }
@@ -1811,21 +1794,18 @@
  *   NULL on failure
  *
  */
-HINTERNET HTTP_Connect(HINTERNET hInternet, LPCWSTR lpszServerName,
+HINTERNET HTTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
 	INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
 	LPCWSTR lpszPassword, DWORD dwFlags, DWORD dwContext,
 	DWORD dwInternalFlags)
 {
     BOOL bSuccess = FALSE;
-    LPWININETAPPINFOW hIC = NULL;
     LPWININETHTTPSESSIONW lpwhs = NULL;
     HINTERNET handle = NULL;
 
     TRACE("-->\n");
 
-    hIC = (LPWININETAPPINFOW) WININET_GetObject( hInternet );
-    if( (hIC == NULL) || (hIC->hdr.htype != WH_HINIT) )
-        goto lerror;
+    assert( hIC->hdr.htype == WH_HINIT );
 
     hIC->hdr.dwContext = dwContext;
     
@@ -1836,14 +1816,6 @@
 	goto lerror;
     }
 
-    handle = WININET_AllocHandle( &lpwhs->hdr );
-    if (NULL == handle)
-    {
-        ERR("Failed to alloc handle\n");
-        INTERNET_SetLastError(ERROR_OUTOFMEMORY);
-	goto lerror;
-    }
-
    /*
     * According to my tests. The name is not resolved until a request is sent
     */
@@ -1852,10 +1824,21 @@
 	nServerPort = INTERNET_DEFAULT_HTTP_PORT;
 
     lpwhs->hdr.htype = WH_HHTTPSESSION;
-    lpwhs->hdr.lpwhparent = &hIC->hdr;
+    lpwhs->hdr.lpwhparent = WININET_AddRef( &hIC->hdr );
     lpwhs->hdr.dwFlags = dwFlags;
     lpwhs->hdr.dwContext = dwContext;
     lpwhs->hdr.dwInternalFlags = dwInternalFlags;
+    lpwhs->hdr.dwRefCount = 1;
+    lpwhs->hdr.destroy = HTTP_CloseHTTPSessionHandle;
+
+    handle = WININET_AllocHandle( &lpwhs->hdr );
+    if (NULL == handle)
+    {
+        ERR("Failed to alloc handle\n");
+        INTERNET_SetLastError(ERROR_OUTOFMEMORY);
+	goto lerror;
+    }
+
     if(hIC->lpszProxy && hIC->dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
         if(strchrW(hIC->lpszProxy, ' '))
             FIXME("Several proxies not implemented.\n");
@@ -1876,7 +1859,7 @@
         iar.dwResult = (DWORD)handle;
         iar.dwError = ERROR_SUCCESS;
 
-        SendAsyncCallback(hIC, hInternet, dwContext,
+        SendAsyncCallback(hIC, &hIC->hdr, dwContext,
                       INTERNET_STATUS_HANDLE_CREATED, &iar,
                       sizeof(INTERNET_ASYNC_RESULT));
     }
@@ -1884,19 +1867,15 @@
     bSuccess = TRUE;
 
 lerror:
-    if (!bSuccess && lpwhs)
-    {
-        HeapFree(GetProcessHeap(), 0, lpwhs);
-        WININET_FreeHandle( handle );
-	lpwhs = NULL;
-    }
+    if( lpwhs )
+        WININET_Release( &lpwhs->hdr );
 
 /*
  * a INTERNET_STATUS_REQUEST_COMPLETE is NOT sent here as per my tests on
  * windows
  */
 
-    TRACE("%p --> %p\n", hInternet, handle);
+    TRACE("%p --> %p (%p)\n", hIC, handle, lpwhs);
     return handle;
 }
 
@@ -1929,7 +1908,7 @@
     lpwhs = (LPWININETHTTPSESSIONW)lpwhr->hdr.lpwhparent;
 
     hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
-    SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext,
+    SendAsyncCallback(hIC, &lpwhr->hdr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_CONNECTING_TO_SERVER,
                       &(lpwhs->socketAddress),
                        sizeof(struct sockaddr_in));
@@ -1948,7 +1927,7 @@
        goto lend;
     }
 
-    SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext,
+    SendAsyncCallback(hIC, &lpwhr->hdr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_CONNECTED_TO_SERVER,
                       &(lpwhs->socketAddress),
                        sizeof(struct sockaddr_in));
@@ -2100,7 +2079,7 @@
  *   TRUE  on success
  *   FALSE on error
  */
-INT stripSpaces(LPCWSTR lpszSrc, LPWSTR lpszStart, INT *len)
+static INT stripSpaces(LPCWSTR lpszSrc, LPWSTR lpszStart, INT *len)
 {
     LPCWSTR lpsztmp;
     INT srclen;
@@ -2411,19 +2390,15 @@
  */
 VOID HTTP_CloseConnection(LPWININETHTTPREQW lpwhr)
 {
-
-
     LPWININETHTTPSESSIONW lpwhs = NULL;
     LPWININETAPPINFOW hIC = NULL;
-    HINTERNET handle;
 
     TRACE("%p\n",lpwhr);
 
-    handle = WININET_FindHandle( &lpwhr->hdr );
     lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
     hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
 
-    SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext,
+    SendAsyncCallback(hIC, &lpwhr->hdr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
 
     if (NETCON_connected(&lpwhr->netConnection))
@@ -2431,7 +2406,7 @@
         NETCON_close(&lpwhr->netConnection);
     }
 
-    SendAsyncCallback(hIC, lpwhr, lpwhr->hdr.dwContext,
+    SendAsyncCallback(hIC, &lpwhr->hdr, lpwhr->hdr.dwContext,
                       INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
 }
 
@@ -2442,26 +2417,16 @@
  * Deallocate request handle
  *
  */
-void HTTP_CloseHTTPRequestHandle(LPWININETHTTPREQW lpwhr)
+static void HTTP_CloseHTTPRequestHandle(LPWININETHANDLEHEADER hdr)
 {
     int i;
-    LPWININETHTTPSESSIONW lpwhs = NULL;
-    LPWININETAPPINFOW hIC = NULL;
-    HINTERNET handle;
+    LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW) hdr;
 
     TRACE("\n");
 
     if (NETCON_connected(&lpwhr->netConnection))
         HTTP_CloseConnection(lpwhr);
 
-    handle = WININET_FindHandle( &lpwhr->hdr );
-    lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
-    hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
-
-    SendAsyncCallback(hIC, handle, lpwhr->hdr.dwContext,
-                      INTERNET_STATUS_HANDLE_CLOSING, lpwhr,
-                      sizeof(HINTERNET));
-
     if (lpwhr->lpszPath)
         HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
     if (lpwhr->lpszVerb)
@@ -2487,15 +2452,6 @@
 
     HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders);
     HeapFree(GetProcessHeap(), 0, lpwhr);
-    
-    /* If this handle was opened with InternetOpenUrl, we need to close the parent to prevent
-       a memory leek
-     */
-    if(lpwhs->hdr.dwInternalFlags & INET_OPENURL)
-    {
-        handle = WININET_FindHandle( &lpwhs->hdr );
-        InternetCloseHandle(handle);
-    }
 }
 
 
@@ -2505,23 +2461,11 @@
  * Deallocate session handle
  *
  */
-void HTTP_CloseHTTPSessionHandle(LPWININETHTTPSESSIONW lpwhs)
+void HTTP_CloseHTTPSessionHandle(LPWININETHANDLEHEADER hdr)
 {
-    LPWININETAPPINFOW hIC = NULL;
-    HINTERNET handle;
+    LPWININETHTTPSESSIONW lpwhs = (LPWININETHTTPSESSIONW) hdr;
 
     TRACE("%p\n", lpwhs);
-
-    hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
-
-    /* Don't send a handle closing callback if this handle was created with InternetOpenUrl */
-    if(!(lpwhs->hdr.dwInternalFlags & INET_OPENURL))
-    {
-        handle = WININET_FindHandle( &lpwhs->hdr );
-        SendAsyncCallback(hIC, handle, lpwhs->hdr.dwContext,
-                          INTERNET_STATUS_HANDLE_CLOSING, lpwhs,
-                          sizeof(HINTERNET));
-    }
 
     if (lpwhs->lpszServerName)
         HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName);
Index: dlls/wininet/internet.c
===================================================================
RCS file: /home/wine/wine/dlls/wininet/internet.c,v
retrieving revision 1.90
diff -u -r1.90 internet.c
--- dlls/wininet/internet.c	4 Jul 2004 00:06:44 -0000	1.90
+++ dlls/wininet/internet.c	19 Jul 2004 05:45:49 -0000
@@ -46,6 +46,7 @@
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
+#include <assert.h>
 
 #include "ntstatus.h"
 #include "windef.h"
@@ -81,10 +82,11 @@
     CHAR   response[MAX_REPLY_LEN];
 } WITHREADERROR, *LPWITHREADERROR;
 
-BOOL WINAPI INTERNET_FindNextFileW(HINTERNET hFind, LPVOID lpvFindData);
-HINTERNET WINAPI INTERNET_InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
-					   LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext);
-VOID INTERNET_ExecuteWork();
+static VOID INTERNET_CloseHandle(LPWININETHANDLEHEADER hdr);
+BOOL WINAPI INTERNET_FindNextFileW(LPWININETFINDNEXTW lpwh, LPVOID lpvFindData);
+HINTERNET WINAPI INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUrl,
+              LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext);
+static VOID INTERNET_ExecuteWork();
 
 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
 DWORD dwNumThreads;
@@ -145,7 +147,7 @@
     handle = WININET_dwNextHandle;
     if( WININET_Handles[handle] )
         ERR("handle isn't free but should be\n");
-    WININET_Handles[handle] = info;
+    WININET_Handles[handle] = WININET_AddRef( info );
 
     while( WININET_Handles[WININET_dwNextHandle] && 
            (WININET_dwNextHandle < WININET_dwMaxHandles ) )
@@ -166,6 +168,7 @@
     {
         if( info == WININET_Handles[i] )
         {
+            WININET_AddRef( info );
             handle = i+1;
             break;
         }
@@ -175,6 +178,13 @@
     return (HINTERNET) handle;
 }
 
+LPWININETHANDLEHEADER WININET_AddRef( LPWININETHANDLEHEADER info )
+{
+    info->dwRefCount++;
+    TRACE("%p -> refcount = %ld\n", info, info->dwRefCount );
+    return info;
+}
+
 LPWININETHANDLEHEADER WININET_GetObject( HINTERNET hinternet )
 {
     LPWININETHANDLEHEADER info = NULL;
@@ -183,7 +193,7 @@
     EnterCriticalSection( &WININET_cs );
 
     if( (handle > 0) && ( handle <= WININET_dwMaxHandles ) )
-        info = WININET_Handles[handle-1];
+        info = WININET_AddRef( WININET_Handles[handle-1] );
 
     LeaveCriticalSection( &WININET_cs );
 
@@ -192,18 +202,33 @@
     return info;
 }
 
+BOOL WININET_Release( LPWININETHANDLEHEADER info )
+{
+    info->dwRefCount--;
+    TRACE( "object %p refcount = %ld\n", info, info->dwRefCount );
+    if( !info->dwRefCount )
+    {
+        TRACE( "destroying object %p\n", info);
+        info->destroy( info );
+    }
+    return TRUE;
+}
+
 BOOL WININET_FreeHandle( HINTERNET hinternet )
 {
     BOOL ret = FALSE;
     UINT handle = (UINT) hinternet;
+    LPWININETHANDLEHEADER info = NULL;
 
     EnterCriticalSection( &WININET_cs );
 
-    if( (handle > 1) && ( handle < WININET_dwMaxHandles ) )
+    if( (handle > 0) && ( handle <= WININET_dwMaxHandles ) )
     {
         handle--;
         if( WININET_Handles[handle] )
         {
+            info = WININET_Handles[handle];
+            TRACE( "destroying handle %d for object %p\n", handle+1, info);
             WININET_Handles[handle] = NULL;
             ret = TRUE;
             if( WININET_dwNextHandle > handle )
@@ -213,6 +238,9 @@
 
     LeaveCriticalSection( &WININET_cs );
 
+    if( info )
+        WININET_Release( info );
+
     return ret;
 }
 
@@ -461,6 +489,8 @@
     lpwai->hdr.htype = WH_HINIT;
     lpwai->hdr.lpwhparent = NULL;
     lpwai->hdr.dwFlags = dwFlags;
+    lpwai->hdr.dwRefCount = 1;
+    lpwai->hdr.destroy = INTERNET_CloseHandle;
     lpwai->dwAccessType = dwAccessType;
     lpwai->lpszProxyUsername = NULL;
     lpwai->lpszProxyPassword = NULL;
@@ -498,8 +528,11 @@
             lstrcpyW( lpwai->lpszProxyBypass, lpszProxyBypass );
     }
 
- lend:
-    TRACE("returning %p\n", (HINTERNET)lpwai);
+lend:
+    if( lpwai )
+        WININET_Release( &lpwai->hdr );
+
+    TRACE("returning %p\n", lpwai);
 
     return handle;
 }
@@ -652,6 +685,7 @@
     LPCWSTR lpszUserName, LPCWSTR lpszPassword,
     DWORD dwService, DWORD dwFlags, DWORD dwContext)
 {
+    LPWININETAPPINFOW hIC;
     HINTERNET rc = (HINTERNET) NULL;
 
     TRACE("(%p, %s, %i, %s, %s, %li, %li, %li)\n", hInternet, debugstr_w(lpszServerName),
@@ -660,16 +694,19 @@
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
+    hIC = (LPWININETAPPINFOW) WININET_GetObject( hInternet );
+    if ( (hIC == NULL) || (hIC->hdr.htype != WH_HINIT) )
+        goto lend;
 
     switch (dwService)
     {
         case INTERNET_SERVICE_FTP:
-            rc = FTP_Connect(hInternet, lpszServerName, nServerPort,
+            rc = FTP_Connect(hIC, lpszServerName, nServerPort,
             lpszUserName, lpszPassword, dwFlags, dwContext, 0);
             break;
 
         case INTERNET_SERVICE_HTTP:
-	    rc = HTTP_Connect(hInternet, lpszServerName, nServerPort,
+	    rc = HTTP_Connect(hIC, lpszServerName, nServerPort,
             lpszUserName, lpszPassword, dwFlags, dwContext, 0);
             break;
 
@@ -677,6 +714,9 @@
         default:
             break;
     }
+lend:
+    if( hIC )
+        WININET_Release( &hIC->hdr );
 
     TRACE("returning %p\n", rc);
     return rc;
@@ -769,15 +809,15 @@
 {
     LPWININETAPPINFOW hIC = NULL;
     LPWININETFINDNEXTW lpwh;
+    BOOL bSuccess = FALSE;
 
     TRACE("\n");
 
     lpwh = (LPWININETFINDNEXTW) WININET_GetObject( hFind );
-
     if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
     {
         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
+        goto lend;
     }
 
     hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
@@ -787,16 +827,20 @@
         struct WORKREQ_INTERNETFINDNEXTW *req;
 
         workRequest.asyncall = INTERNETFINDNEXTW;
-	workRequest.handle = hFind;
+	workRequest.hdr = WININET_AddRef( &lpwh->hdr );
         req = &workRequest.u.InternetFindNextW;
 	req->lpFindFileData = lpvFindData;
 
-	return INTERNET_AsyncCall(&workRequest);
+	bSuccess = INTERNET_AsyncCall(&workRequest);
     }
     else
     {
-        return INTERNET_FindNextFileW(hFind, lpvFindData);
+        bSuccess = INTERNET_FindNextFileW(lpwh, lpvFindData);
     }
+lend:
+    if( lpwh )
+        WININET_Release( &lpwh->hdr );
+    return bSuccess;
 }
 
 /***********************************************************************
@@ -809,21 +853,15 @@
  *    FALSE on failure
  *
  */
-BOOL WINAPI INTERNET_FindNextFileW(HINTERNET hFind, LPVOID lpvFindData)
+BOOL WINAPI INTERNET_FindNextFileW(LPWININETFINDNEXTW lpwh, LPVOID lpvFindData)
 {
     BOOL bSuccess = TRUE;
     LPWININETAPPINFOW hIC = NULL;
     LPWIN32_FIND_DATAW lpFindFileData;
-    LPWININETFINDNEXTW lpwh;
 
     TRACE("\n");
 
-    lpwh = (LPWININETFINDNEXTW) WININET_GetObject( hFind );
-    if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
-    {
-        INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-        return FALSE;
-    }
+    assert (lpwh->hdr.htype == WH_HFINDNEXT);
 
     /* Clear any error information */
     INTERNET_SetLastError(0);
@@ -863,7 +901,7 @@
         iar.dwError = iar.dwError = bSuccess ? ERROR_SUCCESS :
                                                INTERNET_GetLastError();
 
-        SendAsyncCallback(hIC, hFind, lpwh->hdr.dwContext,
+        SendAsyncCallback(hIC, &lpwh->hdr, lpwh->hdr.dwContext,
                       INTERNET_STATUS_REQUEST_COMPLETE, &iar,
                        sizeof(INTERNET_ASYNC_RESULT));
     }
@@ -881,13 +919,11 @@
  *    Void
  *
  */
-VOID INTERNET_CloseHandle(LPWININETAPPINFOW lpwai)
+static VOID INTERNET_CloseHandle(LPWININETHANDLEHEADER hdr)
 {
-    TRACE("%p\n",lpwai);
+    LPWININETAPPINFOW lpwai = (LPWININETAPPINFOW) hdr;
 
-    SendAsyncCallback(lpwai, lpwai, lpwai->hdr.dwContext,
-                      INTERNET_STATUS_HANDLE_CLOSING, lpwai,
-                      sizeof(HINTERNET));
+    TRACE("%p\n",lpwai);
 
     if (lpwai->lpszAgent)
         HeapFree(GetProcessHeap(), 0, lpwai->lpszAgent);
@@ -920,9 +956,9 @@
  */
 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
 {
-    BOOL retval;
-    LPWININETHANDLEHEADER lpwh;
-
+    LPWININETHANDLEHEADER lpwh, parent;
+    LPWININETAPPINFOW hIC;
+    
     TRACE("%p\n",hInternet);
 
     lpwh = WININET_GetObject( hInternet );
@@ -932,46 +968,21 @@
         return FALSE;
     }
 
-	/* Clear any error information */
-	INTERNET_SetLastError(0);
-        retval = FALSE;
-
-	switch (lpwh->htype)
-	{
-	    case WH_HINIT:
-		INTERNET_CloseHandle((LPWININETAPPINFOW) lpwh);
-		retval = TRUE;
-		break;
-
-	    case WH_HHTTPSESSION:
-		HTTP_CloseHTTPSessionHandle((LPWININETHTTPSESSIONW) lpwh);
-		retval = TRUE;
-		break;
-
-	    case WH_HHTTPREQ:
-		HTTP_CloseHTTPRequestHandle((LPWININETHTTPREQW) lpwh);
-		retval = TRUE;
-		break;
-
-	    case WH_HFTPSESSION:
-		retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONW) lpwh);
-		break;
-
-	    case WH_HFINDNEXT:
-		retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTW) lpwh);
-		break;
+    parent = lpwh;
+    while( parent && (parent->htype != WH_HINIT ) )
+        parent = parent->lpwhparent;
+
+    hIC = (LPWININETAPPINFOW) parent;
+    SendAsyncCallback(hIC, lpwh, lpwh->dwContext,
+                      INTERNET_STATUS_HANDLE_CLOSING, hInternet,
+                      sizeof(HINTERNET));
 
-	    case WH_HFILE:
-		retval = FTP_CloseFileTransferHandle((LPWININETFILE) lpwh);
-		break;
-		
-	    default:
-		break;
-	}
-    if( retval )
-        WININET_FreeHandle( hInternet );
+    if( lpwh->lpwhparent )
+        WININET_Release( lpwh->lpwhparent );
+    WININET_FreeHandle( hInternet );
+    WININET_Release( lpwh );
 
-    return retval;
+    return TRUE;
 }
 
 
@@ -1480,21 +1491,22 @@
 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackA(
 	HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
 {
-    INTERNET_STATUS_CALLBACK retVal;
+    INTERNET_STATUS_CALLBACK retVal = INTERNET_INVALID_STATUS_CALLBACK;
     LPWININETAPPINFOW lpwai;
 
     TRACE("0x%08lx\n", (ULONG)hInternet);
     
     lpwai = (LPWININETAPPINFOW)WININET_GetObject(hInternet);
     if (!lpwai)
-        return NULL;
-
-    if (lpwai->hdr.htype != WH_HINIT)
-        return INTERNET_INVALID_STATUS_CALLBACK;
+        return retVal;
 
-    lpwai->hdr.dwInternalFlags &= ~INET_CALLBACKW;
-    retVal = lpwai->lpfnStatusCB;
-    lpwai->lpfnStatusCB = lpfnIntCB;
+    if (lpwai->hdr.htype == WH_HINIT)
+    {
+        lpwai->hdr.dwInternalFlags &= ~INET_CALLBACKW;
+        retVal = lpwai->lpfnStatusCB;
+        lpwai->lpfnStatusCB = lpfnIntCB;
+    }
+    WININET_Release( &lpwai->hdr );
 
     return retVal;
 }
@@ -1513,21 +1525,23 @@
 INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallbackW(
 	HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
 {
-    INTERNET_STATUS_CALLBACK retVal;
+    INTERNET_STATUS_CALLBACK retVal = INTERNET_INVALID_STATUS_CALLBACK;
     LPWININETAPPINFOW lpwai;
 
     TRACE("0x%08lx\n", (ULONG)hInternet);
     
     lpwai = (LPWININETAPPINFOW)WININET_GetObject(hInternet);
     if (!lpwai)
-        return NULL;
+        return retVal;
 
-    if (lpwai->hdr.htype != WH_HINIT)
-        return INTERNET_INVALID_STATUS_CALLBACK;
+    if (lpwai->hdr.htype == WH_HINIT)
+    {
+        lpwai->hdr.dwInternalFlags |= INET_CALLBACKW;
+        retVal = lpwai->lpfnStatusCB;
+        lpwai->lpfnStatusCB = lpfnIntCB;
+    }
 
-    lpwai->hdr.dwInternalFlags |= INET_CALLBACKW;
-    retVal = lpwai->lpfnStatusCB;
-    lpwai->lpfnStatusCB = lpfnIntCB;
+    WININET_Release( &lpwai->hdr );
 
     return retVal;
 }
@@ -1586,6 +1600,7 @@
         retval = (res >= 0);
         *lpdwNumOfBytesWritten = retval ? res : 0;
     }
+    WININET_Release( lpwh );
 
     return retval;
 }
@@ -1608,7 +1623,7 @@
     int nSocket = -1;
     LPWININETHANDLEHEADER lpwh;
 
-    TRACE("\n");
+    TRACE("%p %p %ld %p\n", hFile, lpBuffer, dwNumOfBytesToRead, dwNumOfBytesRead);
 
     lpwh = (LPWININETHANDLEHEADER) WININET_GetObject( hFile );
     if (NULL == lpwh)
@@ -1642,6 +1657,7 @@
         default:
             break;
     }
+    WININET_Release( lpwh );
 
     return retval;
 }
@@ -1778,6 +1794,7 @@
          FIXME("Stub! %ld \n",dwOption);
          break;
     }
+    WININET_Release( lpwhh );
 
     return bSuccess;
 }
@@ -1829,6 +1846,7 @@
                            LPVOID lpBuffer, DWORD dwBufferLength)
 {
     LPWININETHANDLEHEADER lpwhh;
+    BOOL ret = TRUE;
 
     TRACE("0x%08lx\n", dwOption);
 
@@ -1886,8 +1904,10 @@
     default:
         FIXME("Option %ld STUB\n",dwOption);
         INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
+        ret = FALSE;
+        break;
     }
+    WININET_Release( lpwhh );
 
     return TRUE;
 }
@@ -2097,7 +2117,7 @@
  * RETURNS
  *   handle of connection or NULL on failure
  */
-HINTERNET WINAPI INTERNET_InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl,
+HINTERNET WINAPI INTERNET_InternetOpenUrlW(LPWININETAPPINFOW hIC, LPCWSTR lpszUrl,
     LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD dwContext)
 {
     URL_COMPONENTSW urlComponents;
@@ -2105,7 +2125,7 @@
     WCHAR password[1024], path[2048], extra[1024];
     HINTERNET client = NULL, client1 = NULL;
     
-    TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hInternet, debugstr_w(lpszUrl), debugstr_w(lpszHeaders),
+    TRACE("(%p, %s, %s, %08lx, %08lx, %08lx\n", hIC, debugstr_w(lpszUrl), debugstr_w(lpszHeaders),
 	  dwHeadersLength, dwFlags, dwContext);
     
     urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
@@ -2127,7 +2147,7 @@
     case INTERNET_SCHEME_FTP:
 	if(urlComponents.nPort == 0)
 	    urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT;
-	client = FTP_Connect(hInternet, hostName, urlComponents.nPort,
+	client = FTP_Connect(hIC, hostName, urlComponents.nPort,
 			     userName, password, dwFlags, dwContext, INET_OPENURL);
 	if(client == NULL)
 	    break;
@@ -2148,7 +2168,8 @@
 	    else
 		urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
 	}
-	client = HTTP_Connect(hInternet, hostName, urlComponents.nPort,
+        /* FIXME: should use pointers, not handles, as handles are not thread-safe */
+	client = HTTP_Connect(hIC, hostName, urlComponents.nPort,
 			      userName, password, dwFlags, dwContext, INET_OPENURL);
 	if(client == NULL)
 	    break;
@@ -2158,7 +2179,7 @@
 	    break;
 	}
 	HttpAddRequestHeadersW(client1, lpszHeaders, dwHeadersLength, HTTP_ADDREQ_FLAG_ADD);
-	if (!HTTP_HttpSendRequestW(client1, NULL, 0, NULL, 0)) {
+	if (!HttpSendRequestW(client1, NULL, 0, NULL, 0)) {
 	    InternetCloseHandle(client1);
 	    client1 = NULL;
 	    break;
@@ -2204,7 +2225,7 @@
 	struct WORKREQ_INTERNETOPENURLW *req;
 	
 	workRequest.asyncall = INTERNETOPENURLW;
-	workRequest.handle = hInternet;
+	workRequest.hdr = WININET_AddRef( &hIC->hdr );
 	req = &workRequest.u.InternetOpenUrlW;
 	if (lpszUrl)
 	    req->lpszUrl = WININET_strdupW(lpszUrl);
@@ -2224,10 +2245,12 @@
 	 */
 	SetLastError(ERROR_IO_PENDING);
     } else {
-	ret = INTERNET_InternetOpenUrlW(hInternet, lpszUrl, lpszHeaders, dwHeadersLength, dwFlags, dwContext);
+	ret = INTERNET_InternetOpenUrlW(hIC, lpszUrl, lpszHeaders, dwHeadersLength, dwFlags, dwContext);
     }
     
   lend:
+    if( hIC )
+        WININET_Release( &hIC->hdr );
     TRACE(" %p <--\n", ret);
     
     return ret;
@@ -2476,7 +2499,7 @@
  * RETURNS
  *
  */
-VOID INTERNET_ExecuteWork()
+static VOID INTERNET_ExecuteWork()
 {
     WORKREQUEST workRequest;
 
@@ -2485,45 +2508,16 @@
     if (!INTERNET_GetWorkRequest(&workRequest))
         return;
 
-    if (TRACE_ON(wininet)) {
-	static const wininet_flag_info work_request_types[] = {
-#define FE(x) { x, #x }
-	    FE(FTPPUTFILEW),
-	    FE(FTPSETCURRENTDIRECTORYW),
-	    FE(FTPCREATEDIRECTORYW),
-	    FE(FTPFINDFIRSTFILEW),
-	    FE(FTPGETCURRENTDIRECTORYW),
-	    FE(FTPOPENFILEW),
-	    FE(FTPGETFILEW),
-	    FE(FTPDELETEFILEW),
-	    FE(FTPREMOVEDIRECTORYW),
-	    FE(FTPRENAMEFILEW),
-	    FE(INTERNETFINDNEXTW),
-	    FE(HTTPSENDREQUESTW),
-	    FE(HTTPOPENREQUESTW),
-	    FE(SENDCALLBACK),
-	    FE(INTERNETOPENURLW)
-#undef FE
-	};
-	int i;
-	const char *val = "Unknown";
-
-	for (i = 0; i < (sizeof(work_request_types) / sizeof(work_request_types[0])); i++) {
-	    if (work_request_types[i].val == workRequest.asyncall) {
-		val = work_request_types[i].name;
-		break;
-	    }
-	}
-
-	TRACE("Got work %d (%s)\n", workRequest.asyncall, val);
-    }
     switch (workRequest.asyncall)
     {
     case FTPPUTFILEW:
         {
         struct WORKREQ_FTPPUTFILEW *req = &workRequest.u.FtpPutFileW;
+        LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
 
-	FTP_FtpPutFileW(workRequest.handle, req->lpszLocalFile,
+        TRACE("FTPPUTFILEW %p\n", lpwfs);
+
+	FTP_FtpPutFileW(lpwfs, req->lpszLocalFile,
                    req->lpszNewRemoteFile, req->dwFlags, req->dwContext);
 
 	HeapFree(GetProcessHeap(), 0, req->lpszLocalFile);
@@ -2534,9 +2528,12 @@
     case FTPSETCURRENTDIRECTORYW:
         {
         struct WORKREQ_FTPSETCURRENTDIRECTORYW *req;
+        LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
+
+        TRACE("FTPSETCURRENTDIRECTORYW %p\n", lpwfs);
 
         req = &workRequest.u.FtpSetCurrentDirectoryW;
-	FTP_FtpSetCurrentDirectoryW(workRequest.handle, req->lpszDirectory);
+	FTP_FtpSetCurrentDirectoryW(lpwfs, req->lpszDirectory);
 	HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
         }
 	break;
@@ -2544,9 +2541,12 @@
     case FTPCREATEDIRECTORYW:
         {
         struct WORKREQ_FTPCREATEDIRECTORYW *req;
+        LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
+
+        TRACE("FTPCREATEDIRECTORYW %p\n", lpwfs);
 
         req = &workRequest.u.FtpCreateDirectoryW;
-	FTP_FtpCreateDirectoryW(workRequest.handle, req->lpszDirectory);
+	FTP_FtpCreateDirectoryW(lpwfs, req->lpszDirectory);
 	HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
         }
 	break;
@@ -2554,9 +2554,12 @@
     case FTPFINDFIRSTFILEW:
         {
         struct WORKREQ_FTPFINDFIRSTFILEW *req;
+        LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
+
+        TRACE("FTPFINDFIRSTFILEW %p\n", lpwfs);
 
         req = &workRequest.u.FtpFindFirstFileW;
-        FTP_FtpFindFirstFileW(workRequest.handle, req->lpszSearchFile,
+        FTP_FtpFindFirstFileW(lpwfs, req->lpszSearchFile,
            req->lpFindFileData, req->dwFlags, req->dwContext);
 	if (req->lpszSearchFile != NULL)
 	    HeapFree(GetProcessHeap(), 0, req->lpszSearchFile);
@@ -2566,9 +2569,12 @@
     case FTPGETCURRENTDIRECTORYW:
         {
         struct WORKREQ_FTPGETCURRENTDIRECTORYW *req;
+        LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
+
+        TRACE("FTPGETCURRENTDIRECTORYW %p\n", lpwfs);
 
         req = &workRequest.u.FtpGetCurrentDirectoryW;
-        FTP_FtpGetCurrentDirectoryW(workRequest.handle,
+        FTP_FtpGetCurrentDirectoryW(lpwfs,
 		req->lpszDirectory, req->lpdwDirectory);
         }
 	break;
@@ -2576,8 +2582,11 @@
     case FTPOPENFILEW:
         {
         struct WORKREQ_FTPOPENFILEW *req = &workRequest.u.FtpOpenFileW;
+        LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
 
-        FTP_FtpOpenFileW(workRequest.handle, req->lpszFilename,
+        TRACE("FTPOPENFILEW %p\n", lpwfs);
+
+        FTP_FtpOpenFileW(lpwfs, req->lpszFilename,
             req->dwAccess, req->dwFlags, req->dwContext);
         HeapFree(GetProcessHeap(), 0, req->lpszFilename);
         }
@@ -2586,8 +2595,11 @@
     case FTPGETFILEW:
         {
         struct WORKREQ_FTPGETFILEW *req = &workRequest.u.FtpGetFileW;
+        LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
+
+        TRACE("FTPGETFILEW %p\n", lpwfs);
 
-        FTP_FtpGetFileW(workRequest.handle, req->lpszRemoteFile,
+        FTP_FtpGetFileW(lpwfs, req->lpszRemoteFile,
                  req->lpszNewFile, req->fFailIfExists,
                  req->dwLocalFlagsAttribute, req->dwFlags, req->dwContext);
 	HeapFree(GetProcessHeap(), 0, req->lpszRemoteFile);
@@ -2598,8 +2610,11 @@
     case FTPDELETEFILEW:
         {
         struct WORKREQ_FTPDELETEFILEW *req = &workRequest.u.FtpDeleteFileW;
+        LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
+
+        TRACE("FTPDELETEFILEW %p\n", lpwfs);
 
-        FTP_FtpDeleteFileW(workRequest.handle, req->lpszFilename);
+        FTP_FtpDeleteFileW(lpwfs, req->lpszFilename);
 	HeapFree(GetProcessHeap(), 0, req->lpszFilename);
         }
 	break;
@@ -2607,9 +2622,12 @@
     case FTPREMOVEDIRECTORYW:
         {
         struct WORKREQ_FTPREMOVEDIRECTORYW *req;
+        LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
+
+        TRACE("FTPREMOVEDIRECTORYW %p\n", lpwfs);
 
         req = &workRequest.u.FtpRemoveDirectoryW;
-        FTP_FtpRemoveDirectoryW(workRequest.handle, req->lpszDirectory);
+        FTP_FtpRemoveDirectoryW(lpwfs, req->lpszDirectory);
 	HeapFree(GetProcessHeap(), 0, req->lpszDirectory);
         }
 	break;
@@ -2617,8 +2635,11 @@
     case FTPRENAMEFILEW:
         {
         struct WORKREQ_FTPRENAMEFILEW *req = &workRequest.u.FtpRenameFileW;
+        LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest.hdr;
+
+        TRACE("FTPRENAMEFILEW %p\n", lpwfs);
 
-        FTP_FtpRenameFileW(workRequest.handle, req->lpszSrcFile, req->lpszDestFile);
+        FTP_FtpRenameFileW(lpwfs, req->lpszSrcFile, req->lpszDestFile);
 	HeapFree(GetProcessHeap(), 0, req->lpszSrcFile);
 	HeapFree(GetProcessHeap(), 0, req->lpszDestFile);
         }
@@ -2627,17 +2648,23 @@
     case INTERNETFINDNEXTW:
         {
         struct WORKREQ_INTERNETFINDNEXTW *req;
+        LPWININETFINDNEXTW lpwh = (LPWININETFINDNEXTW) workRequest.hdr;
+
+        TRACE("INTERNETFINDNEXTW %p\n", lpwh);
 
         req = &workRequest.u.InternetFindNextW;
-	INTERNET_FindNextFileW(workRequest.handle, req->lpFindFileData);
+	INTERNET_FindNextFileW(lpwh, req->lpFindFileData);
         }
 	break;
 
     case HTTPSENDREQUESTW:
         {
         struct WORKREQ_HTTPSENDREQUESTW *req = &workRequest.u.HttpSendRequestW;
+        LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW) workRequest.hdr;
 
-        HTTP_HttpSendRequestW(workRequest.handle, req->lpszHeader,
+        TRACE("HTTPSENDREQUESTW %p\n", lpwhr);
+
+        HTTP_HttpSendRequestW(lpwhr, req->lpszHeader,
                 req->dwHeaderLength, req->lpOptional, req->dwOptionalLength);
 
         HeapFree(GetProcessHeap(), 0, req->lpszHeader);
@@ -2647,8 +2674,11 @@
     case HTTPOPENREQUESTW:
         {
         struct WORKREQ_HTTPOPENREQUESTW *req = &workRequest.u.HttpOpenRequestW;
+        LPWININETHTTPSESSIONW lpwhs = (LPWININETHTTPSESSIONW) workRequest.hdr;
+
+        TRACE("HTTPOPENREQUESTW %p\n", lpwhs);
 
-        HTTP_HttpOpenRequestW(workRequest.handle, req->lpszVerb,
+        HTTP_HttpOpenRequestW(lpwhs, req->lpszVerb,
             req->lpszObjectName, req->lpszVersion, req->lpszReferrer,
             req->lpszAcceptTypes, req->dwFlags, req->dwContext);
 
@@ -2662,8 +2692,11 @@
     case SENDCALLBACK:
         {
         struct WORKREQ_SENDCALLBACK *req = &workRequest.u.SendCallback;
+        LPWININETAPPINFOW hIC = (LPWININETAPPINFOW) workRequest.hdr;
+
+        TRACE("SENDCALLBACK %p\n", hIC);
 
-        SendAsyncCallbackInt(workRequest.handle, req->hHttpSession,
+        SendAsyncCallbackInt(hIC, req->hdr,
                 req->dwContext, req->dwInternetStatus, req->lpvStatusInfo,
                 req->dwStatusInfoLength);
         }
@@ -2672,14 +2705,18 @@
     case INTERNETOPENURLW:
 	{
 	struct WORKREQ_INTERNETOPENURLW *req = &workRequest.u.InternetOpenUrlW;
+        LPWININETAPPINFOW hIC = (LPWININETAPPINFOW) workRequest.hdr;
 	
-	INTERNET_InternetOpenUrlW(workRequest.handle, req->lpszUrl,
+        TRACE("INTERNETOPENURLW %p\n", hIC);
+
+	INTERNET_InternetOpenUrlW(hIC, req->lpszUrl,
 				  req->lpszHeaders, req->dwHeadersLength, req->dwFlags, req->dwContext);
 	HeapFree(GetProcessHeap(), 0, req->lpszUrl);
 	HeapFree(GetProcessHeap(), 0, req->lpszHeaders);
 	}
 	break;
     }
+    WININET_Release( workRequest.hdr );
 }
 
 
@@ -2772,7 +2809,6 @@
     INT retval = -1;
     char buffer[4048];
 
-
     lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hFile );
     if (NULL == lpwhr)
     {
@@ -2799,6 +2835,7 @@
         FIXME("unsupported file type\n");
         break;
     }
+    WININET_Release( &lpwhr->hdr );
 
     TRACE("<-- %i\n",retval);
     return (retval+1);
Index: dlls/wininet/internet.h
===================================================================
RCS file: /home/wine/wine/dlls/wininet/internet.h,v
retrieving revision 1.25
diff -u -r1.25 internet.h
--- dlls/wininet/internet.h	25 May 2004 04:02:05 -0000	1.25
+++ dlls/wininet/internet.h	19 Jul 2004 05:45:49 -0000
@@ -120,15 +120,22 @@
 #define INET_OPENURL 0x0001
 #define INET_CALLBACKW 0x0002
 
-typedef struct _WININETHANDLEHEADER
+struct _WININETHANDLEHEADER;
+typedef struct _WININETHANDLEHEADER WININETHANDLEHEADER, *LPWININETHANDLEHEADER;
+
+typedef void (*WININET_object_destructor)( LPWININETHANDLEHEADER );
+
+struct _WININETHANDLEHEADER
 {
     WH_TYPE htype;
     DWORD  dwFlags;
     DWORD  dwContext;
     DWORD  dwError;
     DWORD  dwInternalFlags;
+    DWORD  dwRefCount;
+    WININET_object_destructor destroy;
     struct _WININETHANDLEHEADER *lpwhparent;
-} WININETHANDLEHEADER, *LPWININETHANDLEHEADER;
+};
 
 
 typedef struct
@@ -332,7 +339,8 @@
 
 struct WORKREQ_SENDCALLBACK
 {
-    HINTERNET hHttpSession;
+    //HINTERNET hHttpSession;
+    WININETHANDLEHEADER *hdr;
     DWORD     dwContext;
     DWORD     dwInternetStatus;
     LPVOID    lpvStatusInfo;
@@ -352,7 +360,7 @@
 typedef struct WORKREQ
 {
     ASYNC_FUNC asyncall;
-    HINTERNET handle;
+    WININETHANDLEHEADER *hdr;
 
     union {
         struct WORKREQ_FTPPUTFILEW              FtpPutFileW;
@@ -379,17 +387,19 @@
 
 HINTERNET WININET_AllocHandle( LPWININETHANDLEHEADER info );
 LPWININETHANDLEHEADER WININET_GetObject( HINTERNET hinternet );
+LPWININETHANDLEHEADER WININET_AddRef( LPWININETHANDLEHEADER info );
+BOOL WININET_Release( LPWININETHANDLEHEADER info );
 BOOL WININET_FreeHandle( HINTERNET hinternet );
 HINTERNET WININET_FindHandle( LPWININETHANDLEHEADER info );
 
 time_t ConvertTimeString(LPCWSTR asctime);
 
-HINTERNET FTP_Connect(HINTERNET hInterent, LPCWSTR lpszServerName,
+HINTERNET FTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
 	INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
 	LPCWSTR lpszPassword, DWORD dwFlags, DWORD dwContext,
 	DWORD dwInternalFlags);
 
-HINTERNET HTTP_Connect(HINTERNET hInterent, LPCWSTR lpszServerName,
+HINTERNET HTTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName,
 	INTERNET_PORT nServerPort, LPCWSTR lpszUserName,
 	LPCWSTR lpszPassword, DWORD dwFlags, DWORD dwContext,
 	DWORD dwInternalFlags);
@@ -403,41 +413,36 @@
 LPSTR INTERNET_GetResponseBuffer();
 LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen);
 
-BOOL FTP_CloseSessionHandle(LPWININETFTPSESSIONW lpwfs);
-BOOL FTP_CloseFindNextHandle(LPWININETFINDNEXTW lpwfn);
-BOOL FTP_CloseFileTransferHandle(LPWININETFILE lpwfn);
-BOOLAPI FTP_FtpPutFileW(HINTERNET hConnect, LPCWSTR lpszLocalFile,
+BOOLAPI FTP_FtpPutFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszLocalFile,
     LPCWSTR lpszNewRemoteFile, DWORD dwFlags, DWORD dwContext);
-BOOLAPI FTP_FtpSetCurrentDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory);
-BOOLAPI FTP_FtpCreateDirectoryW(HINTERNET hConnect, LPCWSTR lpszDirectory);
-INTERNETAPI HINTERNET WINAPI FTP_FtpFindFirstFileW(HINTERNET hConnect,
+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 dwContext);
-BOOLAPI FTP_FtpGetCurrentDirectoryW(HINTERNET hFtpSession, LPWSTR lpszCurrentDirectory,
+BOOLAPI FTP_FtpGetCurrentDirectoryW(LPWININETFTPSESSIONW lpwfs, LPWSTR lpszCurrentDirectory,
 	LPDWORD lpdwCurrentDirectory);
 BOOL FTP_ConvertFileProp(LPFILEPROPERTIESW lpafp, LPWIN32_FIND_DATAW lpFindFileData);
-BOOL FTP_FtpRenameFileW(HINTERNET hFtpSession, LPCWSTR lpszSrc, LPCWSTR lpszDest);
-BOOL FTP_FtpRemoveDirectoryW(HINTERNET hFtpSession, LPCWSTR lpszDirectory);
-BOOL FTP_FtpDeleteFileW(HINTERNET hFtpSession, LPCWSTR lpszFileName);
-HINTERNET FTP_FtpOpenFileW(HINTERNET hFtpSession, LPCWSTR lpszFileName,
+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 dwContext);
-BOOLAPI FTP_FtpGetFileW(HINTERNET hInternet, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
+BOOLAPI FTP_FtpGetFileW(LPWININETFTPSESSIONW lpwfs, LPCWSTR lpszRemoteFile, LPCWSTR lpszNewFile,
 	BOOL fFailIfExists, DWORD dwLocalFlagsAttribute, DWORD dwInternetFlags,
 	DWORD dwContext);
 
-BOOLAPI HTTP_HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
+BOOLAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
 	DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength);
-INTERNETAPI HINTERNET WINAPI HTTP_HttpOpenRequestW(HINTERNET hHttpSession,
+INTERNETAPI HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs,
 	LPCWSTR lpszVerb, LPCWSTR lpszObjectName, LPCWSTR lpszVersion,
 	LPCWSTR lpszReferrer , LPCWSTR *lpszAcceptTypes,
 	DWORD dwFlags, DWORD dwContext);
-void HTTP_CloseHTTPSessionHandle(LPWININETHTTPSESSIONW lpwhs);
-void HTTP_CloseHTTPRequestHandle(LPWININETHTTPREQW lpwhr);
 
-VOID SendAsyncCallback(LPWININETAPPINFOW hIC, HINTERNET hHttpSession,
+VOID SendAsyncCallback(LPWININETAPPINFOW hIC, LPWININETHANDLEHEADER hdr,
                              DWORD dwContext, DWORD dwInternetStatus, LPVOID
                              lpvStatusInfo , DWORD dwStatusInfoLength);
 
-VOID SendAsyncCallbackInt(LPWININETAPPINFOW hIC, HINTERNET hHttpSession,
+VOID SendAsyncCallbackInt(LPWININETAPPINFOW hIC, LPWININETHANDLEHEADER hdr,
                              DWORD dwContext, DWORD dwInternetStatus, LPVOID
                              lpvStatusInfo , DWORD dwStatusInfoLength);
 
Index: dlls/wininet/utility.c
===================================================================
RCS file: /home/wine/wine/dlls/wininet/utility.c,v
retrieving revision 1.18
diff -u -r1.18 utility.c
--- dlls/wininet/utility.c	14 Jun 2004 16:56:10 -0000	1.18
+++ dlls/wininet/utility.c	19 Jul 2004 05:45:49 -0000
@@ -215,12 +215,14 @@
     return "Unknown";
 }
 
-VOID SendAsyncCallbackInt(LPWININETAPPINFOW hIC, HINTERNET hHttpSession,
+VOID SendAsyncCallbackInt(LPWININETAPPINFOW hIC, LPWININETHANDLEHEADER hdr,
                              DWORD dwContext, DWORD dwInternetStatus, LPVOID
                              lpvStatusInfo, DWORD dwStatusInfoLength)
 {
+    HINTERNET hHttpSession;
     LPVOID lpvNewInfo = NULL;
-    if (! (hIC->lpfnStatusCB))
+
+    if( !hIC->lpfnStatusCB )
         return;
 
     /* the IE5 version of wininet does not
@@ -230,6 +232,10 @@
 
     TRACE("--> Callback %ld (%s)\n",dwInternetStatus, get_callback_name(dwInternetStatus));
 
+    hHttpSession = WININET_FindHandle( hdr );
+    if( !hHttpSession )
+        return;
+
     lpvNewInfo = lpvStatusInfo;
     if(!(hIC->hdr.dwInternalFlags & INET_CALLBACKW)) {
         switch(dwInternetStatus)
@@ -245,11 +251,13 @@
         HeapFree(GetProcessHeap(), 0, lpvNewInfo);
 
     TRACE("<-- Callback %ld (%s)\n",dwInternetStatus, get_callback_name(dwInternetStatus));
+
+    WININET_Release( hdr );
 }
 
 
 
-VOID SendAsyncCallback(LPWININETAPPINFOW hIC, HINTERNET hHttpSession,
+VOID SendAsyncCallback(LPWININETAPPINFOW hIC, LPWININETHANDLEHEADER hdr,
                              DWORD dwContext, DWORD dwInternetStatus, LPVOID
                              lpvStatusInfo,  DWORD dwStatusInfoLength)
 {
@@ -263,9 +271,9 @@
             struct WORKREQ_SENDCALLBACK *req;
 
             workRequest.asyncall = SENDCALLBACK;
-            workRequest.handle = hIC;
+            workRequest.hdr = WININET_AddRef( &hIC->hdr );
             req = &workRequest.u.SendCallback;
-            req->hHttpSession = hHttpSession;
+            req->hdr = hdr;
             req->dwContext = dwContext;
             req->dwInternetStatus = dwInternetStatus;
             req->lpvStatusInfo = lpvStatusInfo;
@@ -274,6 +282,6 @@
             INTERNET_AsyncCall(&workRequest);
         }
         else
-            SendAsyncCallbackInt(hIC, hHttpSession, dwContext, dwInternetStatus,
+            SendAsyncCallbackInt(hIC, hdr, dwContext, dwInternetStatus,
                                   lpvStatusInfo, dwStatusInfoLength);
 }


More information about the wine-patches mailing list