From 968ab5fd284b69bcc826d7cd20070112bb32e35d Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 2 Feb 2011 22:50:46 +0100 Subject: [PATCH] wininet: Keep handles invalid but reserved in InternetCloseHandle. --- dlls/wininet/internet.c | 90 ++++++++++++++++++----------------------- dlls/wininet/internet.h | 1 + 2 files changed, 41 insertions(+), 50 deletions(-) diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index bdaa992ab9b..b5468675b10 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,51 +231,22 @@ BOOL WININET_Release( object_header_t *info ) if ( info->htype != WH_HINIT ) list_remove( &info->entry ); info->vtbl->Destroy( info ); + + if(info->hInternet) { + UINT_PTR handle = (UINT_PTR)info->hInternet; + + EnterCriticalSection( &WININET_cs ); + + handle_table[handle] = NULL; + if(next_handle > handle) + next_handle = handle; + + LeaveCriticalSection( &WININET_cs ); + } } return TRUE; } -static void invalidate_handle( HINTERNET hinternet ) -{ - UINT_PTR handle = (UINT_PTR) hinternet; - object_header_t *info = NULL, *child, *next; - - 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; - } - } - - 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 ); - } - WININET_Release( info ); - } - - EnterCriticalSection( &WININET_cs ); - - if(next_handle > handle && !handle_table[handle]) - next_handle = handle; - - LeaveCriticalSection( &WININET_cs ); -} - /*********************************************************************** * DllMain [Internal] Initializes the internal 'WININET.DLL'. * @@ -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 8239db2c8d9..d6cd1d2241e 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;