From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/name_server.c | 48 +++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 17 deletions(-)
diff --git a/dlls/dplayx/name_server.c b/dlls/dplayx/name_server.c index c1b643ed6da..ddd4ad57e42 100644 --- a/dlls/dplayx/name_server.c +++ b/dlls/dplayx/name_server.c @@ -41,8 +41,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(dplay); /* NS specific structures */ struct NSCacheData { + DPQ_ENTRY(NSCacheData) walkNext; DPQ_ENTRY(NSCacheData) next;
+ LONG ref; + DWORD dwTime; /* Time at which data was last known valid */ LPDPSESSIONDESC2 data;
@@ -55,6 +58,7 @@ struct NSCache { lpNSCacheData present; /* keep track of what is to be looked at when walking */
+ DPQ_HEAD(NSCacheData) walkFirst; DPQ_HEAD(NSCacheData) first;
BOOL bNsIsLocal; @@ -64,7 +68,7 @@ struct NSCache typedef struct NSCache NSCache, *lpNSCache;
/* Function prototypes */ -static DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData ); +static DPQ_DECL_DELETECB( cbReleaseNSNode, lpNSCacheData );
/* Name Server functions * --------------------- @@ -101,7 +105,7 @@ void NS_AddRemoteComputerAsNameServer( LPCVOID lpcNSAddrHdr { TRACE( "Duplicate session entry for %s removed - updated version kept\n", debugstr_guid( &lpCacheNode->data->guidInstance ) ); - cbDeleteNSNodeFromHeap( lpCacheNode ); + cbReleaseNSNode( lpCacheNode ); }
/* Add this to the list */ @@ -133,12 +137,11 @@ void NS_AddRemoteComputerAsNameServer( LPCVOID lpcNSAddrHdr lpCacheNode->data->lpszSessionNameA, len, NULL, NULL ); }
+ lpCacheNode->ref = 1; lpCacheNode->dwTime = timeGetTime();
DPQ_INSERT(lpCache->first, lpCacheNode, next );
- lpCache->present = lpCacheNode; - /* Use this message as an opportunity to weed out any old sessions so * that we don't enum them again */ @@ -159,8 +162,8 @@ LPVOID NS_GetNSAddr( LPVOID lpNSInfo ) * in place. */ #if 1 - if ( lpCache->first.lpQHFirst ) - return lpCache->first.lpQHFirst->lpNSAddrHdr; + if ( lpCache->walkFirst.lpQHFirst ) + return lpCache->walkFirst.lpQHFirst->lpNSAddrHdr;
return NULL; #else @@ -225,9 +228,12 @@ HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid, }
/* Delete a name server node which has been allocated on the heap */ -static DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData ) +static DPQ_DECL_DELETECB( cbReleaseNSNode, lpNSCacheData ) { - /* NOTE: This proc doesn't deal with the walking pointer */ + LONG ref = InterlockedDecrement( &elem->ref ); + + if ( ref ) + return;
/* FIXME: Memory leak on data (contained ptrs) */ free( elem->data ); @@ -246,10 +252,7 @@ void NS_InvalidateSessionCache( LPVOID lpNSInfo ) return; }
- DPQ_DELETEQ( lpCache->first, next, lpNSCacheData, cbDeleteNSNodeFromHeap ); - - /* NULL out the walking pointer */ - lpCache->present = NULL; + DPQ_DELETEQ( lpCache->first, next, lpNSCacheData, cbReleaseNSNode );
lpCache->bNsIsLocal = FALSE;
@@ -267,6 +270,7 @@ BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo ) return FALSE; }
+ DPQ_INIT(lpCache->walkFirst); DPQ_INIT(lpCache->first); lpCache->present = NULL;
@@ -279,12 +283,24 @@ BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo ) void NS_DeleteSessionCache( LPVOID lpNSInfo ) { NS_InvalidateSessionCache( (lpNSCache)lpNSInfo ); + NS_ResetSessionEnumeration( (lpNSCache)lpNSInfo ); }
/* Reinitialize the present pointer for this cache */ void NS_ResetSessionEnumeration( LPVOID lpNSInfo ) { - ((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first.lpQHFirst; + NSCache *cache = (NSCache *) lpNSInfo; + NSCacheData *data; + + DPQ_DELETEQ( cache->walkFirst, walkNext, lpNSCacheData, cbReleaseNSNode ); + + for( data = DPQ_FIRST( cache->first ); data; data = DPQ_NEXT( data->next ) ) + { + InterlockedIncrement( &data->ref ); + DPQ_INSERT( cache->walkFirst, data, walkNext ); + } + + ((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->walkFirst.lpQHFirst; }
LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo ) @@ -292,8 +308,6 @@ LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo ) LPDPSESSIONDESC2 lpSessionDesc; lpNSCache lpCache = (lpNSCache)lpNSInfo;
- /* FIXME: The pointers could disappear when walking if a prune happens */ - /* Test for end of the list */ if( lpCache->present == NULL ) { @@ -303,7 +317,7 @@ LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo ) lpSessionDesc = lpCache->present->data;
/* Advance tracking pointer */ - lpCache->present = lpCache->present->next.lpQNext; + lpCache->present = lpCache->present->walkNext.lpQNext;
return lpSessionDesc; } @@ -345,7 +359,7 @@ void NS_PruneSessionCache( LPVOID lpNSInfo )
lpFirstData = DPQ_FIRST(lpCache->first); DPQ_REMOVE( lpCache->first, DPQ_FIRST(lpCache->first), next ); - cbDeleteNSNodeFromHeap( lpFirstData ); + cbReleaseNSNode( lpFirstData ); }
}
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 854c266aa4f..60d978a6000 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -2474,12 +2474,21 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS return hr; }
- if ( flags & DPENUMSESSIONS_ASYNC ) + if ( !(flags & DPENUMSESSIONS_ASYNC) ) { - /* Enumerate everything presently in the local session cache */ - DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout, - context ); + /* Invalidate the session cache for the interface */ + NS_InvalidateSessionCache( This->dp2->lpNameServerData ); + /* Send the broadcast for session enumeration */ + hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData ); + if ( FAILED( hr ) ) + return hr; + SleepEx( timeout, FALSE ); + }
+ DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout, context ); + + if ( flags & DPENUMSESSIONS_ASYNC ) + { if ( This->dp2->dwEnumSessionLock ) return DPERR_CONNECTING;
@@ -2517,16 +2526,6 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS This->dp2->dwEnumSessionLock--; } } - else - { - /* Invalidate the session cache for the interface */ - NS_InvalidateSessionCache( This->dp2->lpNameServerData ); - /* Send the broadcast for session enumeration */ - hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData ); - SleepEx( timeout, FALSE ); - DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout, - context ); - }
return hr; }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 60d978a6000..fe25b3c94b0 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -2275,11 +2275,6 @@ static void DP_InvokeEnumSessionCallbacks
FIXME( ": not checking for conditions\n" );
- /* Not sure if this should be pruning but it's convenient */ - NS_PruneSessionCache( lpNSInfo ); - - NS_ResetSessionEnumeration( lpNSInfo ); - /* Enumerate all sessions */ /* FIXME: Need to indicate ANSI */ while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL ) @@ -2485,6 +2480,9 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS SleepEx( timeout, FALSE ); }
+ NS_PruneSessionCache( This->dp2->lpNameServerData ); + NS_ResetSessionEnumeration( This->dp2->lpNameServerData ); + DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout, context );
if ( flags & DPENUMSESSIONS_ASYNC )
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index fe25b3c94b0..7f646e5fc31 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -279,11 +279,15 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody,
/* Name server needs to handle this request */ case DPMSGCMD_ENUMSESSIONSREPLY: + EnterCriticalSection( &This->lock ); + /* No reply expected */ NS_AddRemoteComputerAsNameServer( lpcMessageHeader, This->dp2->spData.dwSPHeaderSize, lpcMessageBody, This->dp2->lpNameServerData ); + + LeaveCriticalSection( &This->lock ); break;
case DPMSGCMD_REQUESTNEWPLAYERID: @@ -2471,8 +2475,13 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS
if ( !(flags & DPENUMSESSIONS_ASYNC) ) { + EnterCriticalSection( &This->lock ); + /* Invalidate the session cache for the interface */ NS_InvalidateSessionCache( This->dp2->lpNameServerData ); + + LeaveCriticalSection( &This->lock ); + /* Send the broadcast for session enumeration */ hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData ); if ( FAILED( hr ) ) @@ -2480,9 +2489,13 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS SleepEx( timeout, FALSE ); }
+ EnterCriticalSection( &This->lock ); + NS_PruneSessionCache( This->dp2->lpNameServerData ); NS_ResetSessionEnumeration( This->dp2->lpNameServerData );
+ LeaveCriticalSection( &This->lock ); + DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout, context );
if ( flags & DPENUMSESSIONS_ASYNC )
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 46 ++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 7f646e5fc31..2896677a231 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -2269,7 +2269,7 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *i /* This function should call the registered callback function that the user passed into EnumSessions for each entry available. */ -static void DP_InvokeEnumSessionCallbacks +static BOOL DP_InvokeEnumSessionCallbacks ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2, LPVOID lpNSInfo, DWORD dwTimeout, @@ -2285,13 +2285,11 @@ static void DP_InvokeEnumSessionCallbacks { TRACE( "EnumSessionsCallback2 invoked\n" ); if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) ) - { - return; - } + return FALSE; }
/* Invoke one last time to indicate that there is no more to come */ - lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext ); + return lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext ); }
static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext ) @@ -2473,30 +2471,36 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS return hr; }
- if ( !(flags & DPENUMSESSIONS_ASYNC) ) + for ( ;; ) { - EnterCriticalSection( &This->lock ); + if ( !(flags & DPENUMSESSIONS_ASYNC) ) + { + EnterCriticalSection( &This->lock );
- /* Invalidate the session cache for the interface */ - NS_InvalidateSessionCache( This->dp2->lpNameServerData ); + /* Invalidate the session cache for the interface */ + NS_InvalidateSessionCache( This->dp2->lpNameServerData );
- LeaveCriticalSection( &This->lock ); + LeaveCriticalSection( &This->lock );
- /* Send the broadcast for session enumeration */ - hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData ); - if ( FAILED( hr ) ) - return hr; - SleepEx( timeout, FALSE ); - } + /* Send the broadcast for session enumeration */ + hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, + &This->dp2->spData ); + if ( FAILED( hr ) ) + return hr; + SleepEx( timeout, FALSE ); + }
- EnterCriticalSection( &This->lock ); + EnterCriticalSection( &This->lock );
- NS_PruneSessionCache( This->dp2->lpNameServerData ); - NS_ResetSessionEnumeration( This->dp2->lpNameServerData ); + NS_PruneSessionCache( This->dp2->lpNameServerData ); + NS_ResetSessionEnumeration( This->dp2->lpNameServerData );
- LeaveCriticalSection( &This->lock ); + LeaveCriticalSection( &This->lock );
- DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout, context ); + if ( !DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout, + context ) ) + break; + }
if ( flags & DPENUMSESSIONS_ASYNC ) {
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 2896677a231..9f149879c2b 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -2272,7 +2272,7 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *i static BOOL DP_InvokeEnumSessionCallbacks ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2, LPVOID lpNSInfo, - DWORD dwTimeout, + DWORD *timeout, LPVOID lpContext ) { LPDPSESSIONDESC2 lpSessionDesc; @@ -2284,12 +2284,12 @@ static BOOL DP_InvokeEnumSessionCallbacks while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL ) { TRACE( "EnumSessionsCallback2 invoked\n" ); - if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) ) + if( !lpEnumSessionsCallback2( lpSessionDesc, timeout, 0, lpContext ) ) return FALSE; }
/* Invoke one last time to indicate that there is no more to come */ - return lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext ); + return lpEnumSessionsCallback2( NULL, timeout, DPESC_TIMEDOUT, lpContext ); }
static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext ) @@ -2403,7 +2403,9 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags ) { IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); + DWORD defaultTimeout; void *connection; + DPCAPS caps; DWORD size; HRESULT hr = DP_OK;
@@ -2452,18 +2454,11 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS This->dp2->bSPInitialized = TRUE; }
- - /* Use the service provider default? */ - if ( !timeout ) - { - DPCAPS caps; - caps.dwSize = sizeof( caps ); - - IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 ); - timeout = caps.dwTimeout; - if ( !timeout ) - timeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */ - } + caps.dwSize = sizeof( caps ); + IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 ); + defaultTimeout = caps.dwTimeout; + if ( !defaultTimeout ) + defaultTimeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */
if ( flags & DPENUMSESSIONS_STOPASYNC ) { @@ -2487,7 +2482,7 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS &This->dp2->spData ); if ( FAILED( hr ) ) return hr; - SleepEx( timeout, FALSE ); + SleepEx( timeout ? timeout : defaultTimeout, FALSE ); }
EnterCriticalSection( &This->lock ); @@ -2497,7 +2492,7 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS
LeaveCriticalSection( &This->lock );
- if ( !DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout, + if ( !DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, &timeout, context ) ) break; } @@ -2526,7 +2521,7 @@ static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESS data->lpSpData = &This->dp2->spData; data->requestGuid = sdesc->guidApplication; data->dwEnumSessionFlags = flags; - data->dwTimeout = timeout; + data->dwTimeout = timeout ? timeout : defaultTimeout;
This->dp2->hKillEnumSessionThreadEvent = CreateEventW( NULL, TRUE, FALSE, NULL ); if ( !DuplicateHandle( GetCurrentProcess(), This->dp2->hKillEnumSessionThreadEvent,
This merge request was approved by Alistair Leslie-Hughes.