diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 2fae530cfd2..3dbbad37265 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -98,6 +98,8 @@ static void session_destroy( object_header_t *hdr ) TRACE("%p\n", session); + if (session->unload_event) SetEvent( session->unload_event ); + LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache ) { domain = LIST_ENTRY( item, domain_t, entry ); @@ -199,6 +201,10 @@ static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffe case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: FIXME("WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: 0x%x\n", *(DWORD *)buffer); return TRUE; + case WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: + TRACE("WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT: %p\n", *(HANDLE *)buffer); + session->unload_event = *(HANDLE *)buffer; + return TRUE; default: FIXME("unimplemented option %u\n", option); set_last_error( ERROR_INVALID_PARAMETER ); diff --git a/dlls/winhttp/tests/notification.c b/dlls/winhttp/tests/notification.c index e14af6d03ea..5db8fe384ce 100644 --- a/dlls/winhttp/tests/notification.c +++ b/dlls/winhttp/tests/notification.c @@ -158,9 +158,9 @@ static void setup_test( struct info *info, enum api function, unsigned int line static void test_connection_cache( void ) { - HANDLE ses, con, req; + HANDLE ses, con, req, event; DWORD size, status; - BOOL ret; + BOOL ret, unload = TRUE; struct info info, *context = &info; info.test = cache_test; @@ -171,6 +171,14 @@ static void test_connection_cache( void ) ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 ); ok(ses != NULL, "failed to open session %u\n", GetLastError()); + event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ret = WinHttpSetOption( ses, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT, &event, sizeof(event) ); + if (!ret) + { + win_skip("Unload event not supported\n"); + unload = FALSE; + } + WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 ); ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); @@ -236,15 +244,33 @@ static void test_connection_cache( void ) setup_test( &info, winhttp_close_handle, __LINE__ ); WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); + + if (unload) + { + status = WaitForSingleObject( event, 0 ); + ok(status == WAIT_TIMEOUT, "got %08x\n", status); + } + WinHttpCloseHandle( ses ); Sleep(2000); /* make sure connection is evicted from cache */ + if (unload) + { + status = WaitForSingleObject( event, 0 ); + ok(status == WAIT_OBJECT_0, "got %08x\n", status); + } info.index = 0; ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 ); ok(ses != NULL, "failed to open session %u\n", GetLastError()); + if (unload) + { + ret = WinHttpSetOption( ses, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT, &event, sizeof(event) ); + ok(ret, "failed to set unload option\n"); + } + WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 ); ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); @@ -311,9 +337,23 @@ static void test_connection_cache( void ) done: WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); + + if (unload) + { + status = WaitForSingleObject( event, 0 ); + ok(status == WAIT_TIMEOUT, "got %08x\n", status); + } + WinHttpCloseHandle( ses ); Sleep(2000); /* make sure connection is evicted from cache */ + if (unload) + { + status = WaitForSingleObject( event, 0 ); + ok(status == WAIT_OBJECT_0, "got %08x\n", status); + } + + CloseHandle( event ); } static const struct notification redirect_test[] = @@ -433,9 +473,9 @@ static const struct notification async_test[] = static void test_async( void ) { - HANDLE ses, con, req; + HANDLE ses, con, req, event; DWORD size, status; - BOOL ret; + BOOL ret, unload = TRUE; struct info info, *context = &info; char buffer[1024]; @@ -447,6 +487,14 @@ static void test_async( void ) ses = WinHttpOpen( user_agent, 0, NULL, NULL, WINHTTP_FLAG_ASYNC ); ok(ses != NULL, "failed to open session %u\n", GetLastError()); + event = CreateEventW( NULL, FALSE, FALSE, NULL ); + ret = WinHttpSetOption( ses, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT, &event, sizeof(event) ); + if (!ret) + { + win_skip("Unload event not supported\n"); + unload = FALSE; + } + WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 ); ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); @@ -501,9 +549,22 @@ static void test_async( void ) setup_test( &info, winhttp_close_handle, __LINE__ ); WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); + + if (unload) + { + status = WaitForSingleObject( event, 0 ); + ok(status == WAIT_TIMEOUT, "got %08x\n", status); + } WinHttpCloseHandle( ses ); WaitForSingleObject( info.wait, INFINITE ); + + if (unload) + { + status = WaitForSingleObject( event, 2000 ); + ok(status == WAIT_OBJECT_0, "got %08x\n", status); + } + CloseHandle( event ); CloseHandle( info.wait ); } diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 6a7dd3e439a..b3e28d2c18b 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -110,6 +110,7 @@ typedef struct LPWSTR proxy_username; LPWSTR proxy_password; struct list cookie_cache; + HANDLE unload_event; } session_t; typedef struct