Jacek Caban : wininet: Keep handles invalid but reserved in InternetCloseHandle.

Alexandre Julliard julliard at winehq.org
Thu Feb 3 12:00:22 CST 2011


Module: wine
Branch: master
Commit: 968ab5fd284b69bcc826d7cd20070112bb32e35d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=968ab5fd284b69bcc826d7cd20070112bb32e35d

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Feb  2 22:50:46 2011 +0100

wininet: Keep handles invalid but reserved in InternetCloseHandle.

---

 dlls/wininet/internet.c |   80 ++++++++++++++++++++--------------------------
 dlls/wininet/internet.h |    1 +
 2 files changed, 36 insertions(+), 45 deletions(-)

diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c
index bdaa992..b546867 100644
--- a/dlls/wininet/internet.c
+++ b/dlls/wininet/internet.c
@@ -161,6 +161,7 @@ DWORD alloc_handle( object_header_t *info, HINTERNET *ret )
     LeaveCriticalSection( &WININET_cs );
 
     info->hInternet = *ret = (HINTERNET)handle;
+    info->valid_handle = res == ERROR_SUCCESS;
     return res;
 }
 
@@ -178,7 +179,7 @@ object_header_t *get_handle_object( HINTERNET hinternet )
 
     EnterCriticalSection( &WININET_cs );
 
-    if(handle > 0 && handle < handle_table_size && handle_table[handle])
+    if(handle > 0 && handle < handle_table_size && handle_table[handle] && handle_table[handle]->valid_handle)
         info = WININET_AddRef(handle_table[handle]);
 
     LeaveCriticalSection( &WININET_cs );
@@ -188,12 +189,31 @@ object_header_t *get_handle_object( HINTERNET hinternet )
     return info;
 }
 
+static void invalidate_handle(object_header_t *info)
+{
+    object_header_t *child, *next;
+
+    if(!info->valid_handle)
+        return;
+    info->valid_handle = FALSE;
+
+    /* Free all children as native does */
+    LIST_FOR_EACH_ENTRY_SAFE( child, next, &info->children, object_header_t, entry )
+    {
+        TRACE("invalidating child handle %p for parent %p\n", child->hInternet, info);
+        invalidate_handle( child );
+    }
+
+    WININET_Release(info);
+}
+
 BOOL WININET_Release( object_header_t *info )
 {
     ULONG refs = InterlockedDecrement(&info->refs);
     TRACE( "object %p refcount = %d\n", info, refs );
     if( !refs )
     {
+        invalidate_handle(info);
         if ( info->vtbl->CloseConnection )
         {
             TRACE( "closing connection %p\n", info);
@@ -211,49 +231,20 @@ BOOL WININET_Release( object_header_t *info )
         if ( info->htype != WH_HINIT )
             list_remove( &info->entry );
         info->vtbl->Destroy( info );
-    }
-    return TRUE;
-}
 
-static void invalidate_handle( HINTERNET hinternet )
-{
-    UINT_PTR handle = (UINT_PTR) hinternet;
-    object_header_t *info = NULL, *child, *next;
+        if(info->hInternet) {
+            UINT_PTR handle = (UINT_PTR)info->hInternet;
 
-    EnterCriticalSection( &WININET_cs );
+            EnterCriticalSection( &WININET_cs );
 
-    if(handle && handle < handle_table_size)
-    {
-        if(handle_table[handle]) {
-            info = handle_table[handle];
-            TRACE( "destroying handle %ld for object %p\n", handle+1, info);
             handle_table[handle] = NULL;
-        }
-    }
+            if(next_handle > handle)
+                next_handle = handle;
 
-    LeaveCriticalSection( &WININET_cs );
-
-    /* As on native when the equivalent of WININET_Release is called, the handle
-     * is already invalid, but if a new handle is created at this time it does
-     * not yet get assigned the freed handle number */
-    if( info )
-    {
-        /* Free all children as native does */
-        LIST_FOR_EACH_ENTRY_SAFE( child, next, &info->children, object_header_t, entry )
-        {
-            TRACE( "freeing child handle %ld for parent handle %ld\n",
-                   (UINT_PTR)child->hInternet, handle+1);
-            invalidate_handle( child->hInternet );
+            LeaveCriticalSection( &WININET_cs );
         }
-        WININET_Release( info );
     }
-
-    EnterCriticalSection( &WININET_cs );
-
-    if(next_handle > handle && !handle_table[handle])
-        next_handle = handle;
-
-    LeaveCriticalSection( &WININET_cs );
+    return TRUE;
 }
 
 /***********************************************************************
@@ -1277,19 +1268,18 @@ BOOL WINAPI InternetFindNextFileW(HINTERNET hFind, LPVOID lpvFindData)
  */
 BOOL WINAPI InternetCloseHandle(HINTERNET hInternet)
 {
-    object_header_t *lpwh;
+    object_header_t *obj;
     
-    TRACE("%p\n",hInternet);
+    TRACE("%p\n", hInternet);
 
-    lpwh = get_handle_object( hInternet );
-    if (NULL == lpwh)
-    {
-        INTERNET_SetLastError(ERROR_INVALID_HANDLE);
+    obj = get_handle_object( hInternet );
+    if (!obj) {
+        SetLastError(ERROR_INVALID_HANDLE);
         return FALSE;
     }
 
-    WININET_Release( lpwh );
-    invalidate_handle( hInternet );
+    invalidate_handle(obj);
+    WININET_Release(obj);
 
     return TRUE;
 }
diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h
index 8239db2..d6cd1d2 100644
--- a/dlls/wininet/internet.h
+++ b/dlls/wininet/internet.h
@@ -204,6 +204,7 @@ struct _object_header_t
     WH_TYPE htype;
     const object_vtbl_t *vtbl;
     HINTERNET hInternet;
+    BOOL valid_handle;
     DWORD  dwFlags;
     DWORD_PTR dwContext;
     DWORD  dwError;




More information about the wine-cvs mailing list