-- v2: dplayx: Parse SUPERENUMPLAYERSREPLY and add players to the session.
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 49b80f4d4b8..cc8829aac6f 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -1358,7 +1358,7 @@ DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
}
-static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName, +static HRESULT DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName, void *data, DWORD dataSize, DWORD dwFlags, HANDLE hEvent, BOOL bAnsi ) { lpPlayerData lpPData; @@ -1369,9 +1369,7 @@ static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME * /* Allocate the storage for the player and associate it with list element */ lpPData = calloc( 1, sizeof( *lpPData ) ); if( lpPData == NULL ) - { - return NULL; - } + return DPERR_OUTOFMEMORY;
/* Set the desired player ID */ lpPData->dpid = *lpid; @@ -1404,7 +1402,7 @@ static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME * CloseHandle( lpPData->hEvent ); DP_DeleteDPNameStruct( &lpPData->name ); free( lpPData ); - return NULL; + return DPERR_OUTOFMEMORY; }
lpPData->uRef = 1; @@ -1420,7 +1418,7 @@ static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME * if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER ) This->dp2->lpSessionDesc->dwCurrentPlayers++;
- return lpPData; + return DP_OK; }
/* Delete the contents of the DPNAME struct */ @@ -1562,7 +1560,6 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID * BOOL bAnsi ) { HRESULT hr = DP_OK; - lpPlayerData lpPData; DWORD dwCreateFlags = 0;
TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n", @@ -1650,10 +1647,10 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *
/* We pass creation flags, so we can distinguish sysplayers and not count them in the current player total */ - lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, lpData, dwDataSize, dwCreateFlags, - hEvent, bAnsi ); - if( !lpPData ) - return DPERR_CANTADDPLAYER; + hr = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, lpData, dwDataSize, dwCreateFlags, + hEvent, bAnsi ); + if( FAILED( hr ) ) + return hr;
/* Let the SP know that we've created this player */ if( This->dp2->spData.lpCB->CreatePlayer )
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 116 +++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 45 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index cc8829aac6f..e9611b5b8eb 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -1358,11 +1358,67 @@ DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
}
-static HRESULT DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName, +static HRESULT DP_CreateSPPlayer( IDirectPlayImpl *This, DPID dpid, DWORD flags, void *msgHeader ) +{ + HRESULT hr; + + /* Let the SP know that we've created this player */ + if( This->dp2->spData.lpCB->CreatePlayer ) + { + DPSP_CREATEPLAYERDATA data; + + data.idPlayer = dpid; + data.dwFlags = flags; + data.lpSPMessageHeader = msgHeader; + data.lpISP = This->dp2->spData.lpISP; + + TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n", dpid, flags, + msgHeader ); + + hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data ); + if( FAILED( hr ) ) + { + ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString( hr ) ); + return hr; + } + } + + /* Now let the SP know that this player is a member of the system group */ + if( This->dp2->spData.lpCB->AddPlayerToGroup ) + { + DPSP_ADDPLAYERTOGROUPDATA data; + + data.idPlayer = dpid; + data.idGroup = DPID_SYSTEM_GROUP; + data.lpISP = This->dp2->spData.lpISP; + + TRACE( "Calling SP AddPlayerToGroup (sys group)\n" ); + + hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data ); + if( FAILED( hr ) ) + { + ERR( "Failed to add player to sys group with sp: %s\n", DPLAYX_HresultToString( hr ) ); + if ( This->dp2->spData.lpCB->DeletePlayer ) + { + DPSP_DELETEPLAYERDATA data; + data.idPlayer = dpid; + data.dwFlags = 0; + data.lpISP = This->dp2->spData.lpISP; + This->dp2->spData.lpCB->DeletePlayer( &data ); + } + return hr; + } + } + + return DP_OK; +} + +static HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName, void *data, DWORD dataSize, DWORD dwFlags, HANDLE hEvent, BOOL bAnsi ) { lpPlayerData lpPData; lpPlayerList lpPList; + HRESULT hr;
TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
@@ -1413,6 +1469,19 @@ static HRESULT DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpNam
DP_SetPlayerData( lpPData, DPSET_REMOTE, data, dataSize );
+ hr = DP_CreateSPPlayer( This, *lpid, dwFlags, msgHeader ); + if ( FAILED( hr ) ) + { + free( lpPData->lpRemoteData ); + DPQ_REMOVE( This->dp2->lpSysGroup->players, lpPList, players ); + free( lpPList ); + free( lpPData->lpSPPlayerData ); + CloseHandle( lpPData->hEvent ); + DP_DeleteDPNameStruct( &lpPData->name ); + free( lpPData ); + return hr; + } + TRACE( "Created player id 0x%08lx\n", *lpid );
if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER ) @@ -1647,54 +1716,11 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *
/* We pass creation flags, so we can distinguish sysplayers and not count them in the current player total */ - hr = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, lpData, dwDataSize, dwCreateFlags, + hr = DP_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, lpData, dwDataSize, dwCreateFlags, hEvent, bAnsi ); if( FAILED( hr ) ) return hr;
- /* Let the SP know that we've created this player */ - if( This->dp2->spData.lpCB->CreatePlayer ) - { - DPSP_CREATEPLAYERDATA data; - - data.idPlayer = *lpidPlayer; - data.dwFlags = dwCreateFlags; - data.lpSPMessageHeader = lpMsgHdr; - data.lpISP = This->dp2->spData.lpISP; - - TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n", - *lpidPlayer, data.dwFlags, data.lpSPMessageHeader ); - - hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data ); - } - - if( FAILED(hr) ) - { - ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) ); - return hr; - } - - /* Now let the SP know that this player is a member of the system group */ - if( This->dp2->spData.lpCB->AddPlayerToGroup ) - { - DPSP_ADDPLAYERTOGROUPDATA data; - - data.idPlayer = *lpidPlayer; - data.idGroup = DPID_SYSTEM_GROUP; - data.lpISP = This->dp2->spData.lpISP; - - TRACE( "Calling SP AddPlayerToGroup (sys group)\n" ); - - hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data ); - } - - if( FAILED(hr) ) - { - ERR( "Failed to add player to sys group with sp: %s\n", - DPLAYX_HresultToString(hr) ); - return hr; - } - #if 1 if( !This->dp2->bHostInterface ) {
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index e9611b5b8eb..35a215ac7af 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -1414,7 +1414,8 @@ static HRESULT DP_CreateSPPlayer( IDirectPlayImpl *This, DPID dpid, DWORD flags, }
static HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName, - void *data, DWORD dataSize, DWORD dwFlags, HANDLE hEvent, BOOL bAnsi ) + void *data, DWORD dataSize, void *spData, DWORD spDataSize, DWORD dwFlags, HANDLE hEvent, + BOOL bAnsi ) { lpPlayerData lpPData; lpPlayerList lpPList; @@ -1469,6 +1470,20 @@ static HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lp
DP_SetPlayerData( lpPData, DPSET_REMOTE, data, dataSize );
+ hr = IDirectPlaySP_SetSPPlayerData( This->dp2->spData.lpISP, *lpid, spData, spDataSize, + DPSET_REMOTE ); + if ( FAILED( hr ) ) + { + free( lpPData->lpRemoteData ); + DPQ_REMOVE( This->dp2->lpSysGroup->players, lpPList, players ); + free( lpPList ); + free( lpPData->lpSPPlayerData ); + CloseHandle( lpPData->hEvent ); + DP_DeleteDPNameStruct( &lpPData->name ); + free( lpPData ); + return hr; + } + hr = DP_CreateSPPlayer( This, *lpid, dwFlags, msgHeader ); if ( FAILED( hr ) ) { @@ -1716,8 +1731,8 @@ static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *
/* We pass creation flags, so we can distinguish sysplayers and not count them in the current player total */ - hr = DP_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, lpData, dwDataSize, dwCreateFlags, - hEvent, bAnsi ); + hr = DP_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, lpData, dwDataSize, NULL, 0, + dwCreateFlags, hEvent, bAnsi ); if( FAILED( hr ) ) return hr;
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 4 ++-- dlls/dplayx/dplay_global.h | 2 +- dlls/dplayx/dplayx_messages.c | 28 ++++++++++++++++++---------- dlls/dplayx/dplayx_messages.h | 3 ++- 4 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 35a215ac7af..057003ec8d9 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -385,13 +385,13 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody, case DPMSGCMD_GETNAMETABLEREPLY: case DPMSGCMD_NEWPLAYERIDREPLY: case DPMSGCMD_SUPERENUMPLAYERSREPLY: - DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); + DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize, lpcMessageHeader ); break;
case DPMSGCMD_JUSTENVELOPE: TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] ); NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 ); - DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); + DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize, lpcMessageHeader );
case DPMSGCMD_FORWARDADDPLAYER: TRACE( "Sending message to self to get my addr\n" ); diff --git a/dlls/dplayx/dplay_global.h b/dlls/dplayx/dplay_global.h index 6536d9e3f9c..cc3385569ec 100644 --- a/dlls/dplayx/dplay_global.h +++ b/dlls/dplayx/dplay_global.h @@ -48,7 +48,7 @@ typedef struct tagDP_MSG_REPLY_STRUCT DWORD expectedReplyCount; LPVOID lpReplyMsg; DWORD dwMsgBodySize; - /* FIXME: Is the message header required as well? */ + void *replyMsgHeader; } DP_MSG_REPLY_STRUCT, *LPDP_MSG_REPLY_STRUCT;
typedef struct tagDP_MSG_REPLY_STRUCT_LIST diff --git a/dlls/dplayx/dplayx_messages.c b/dlls/dplayx/dplayx_messages.c index 8fe2d6c3010..8df2cf4e7a4 100644 --- a/dlls/dplayx/dplayx_messages.c +++ b/dlls/dplayx/dplayx_messages.c @@ -47,7 +47,7 @@ typedef struct tagMSGTHREADINFO static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext ); static HRESULT DP_MSG_ExpectReply( IDirectPlayImpl *This, DPSP_SENDEXDATA *data, DWORD dwWaitTime, WORD *replyCommandIds, DWORD replyCommandIdCount, void **lplpReplyMsg, - DWORD *lpdwMsgBodySize ); + DWORD *lpdwMsgBodySize, void **replyMsgHeader );
/* Create the message reception thread to allow the application to receive @@ -209,12 +209,13 @@ void DP_MSG_UnlinkReplyStruct( IDirectPlayImpl *This, DP_MSG_REPLY_STRUCT_LIST *
static void DP_MSG_CleanReplyStruct( LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList, - LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize ) + LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize, void **replyMsgHeader ) { CloseHandle( lpReplyStructList->replyExpected.hReceipt );
*lplpReplyMsg = lpReplyStructList->replyExpected.lpReplyMsg; *lpdwMsgBodySize = lpReplyStructList->replyExpected.dwMsgBodySize; + *replyMsgHeader = lpReplyStructList->replyExpected.replyMsgHeader; }
DWORD DP_MSG_ComputeMessageSize( SGBUFFER *buffers, DWORD bufferCount ) @@ -229,6 +230,7 @@ DWORD DP_MSG_ComputeMessageSize( SGBUFFER *buffers, DWORD bufferCount ) HRESULT DP_MSG_SendRequestPlayerId( IDirectPlayImpl *This, DWORD dwFlags, DPID *lpdpidAllocatedId ) { LPVOID lpMsg; + void *msgHeader; DPMSG_REQUESTNEWPLAYERID msgBody; DWORD dwMsgSize; HRESULT hr = DP_OK; @@ -264,7 +266,7 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlayImpl *This, DWORD dwFlags, DPID * msgBody.dwFlags );
hr = DP_MSG_ExpectReply( This, &data, DPMSG_DEFAULT_WAIT_TIME, &replyCommand, 1, - &lpMsg, &dwMsgSize ); + &lpMsg, &dwMsgSize, &msgHeader ); }
/* Need to examine the data and extract the new player id */ @@ -286,6 +288,7 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlayImpl *This, DWORD dwFlags, DPID * * for several different messages? */
+ free( msgHeader ); free( lpMsg ); }
@@ -301,6 +304,7 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer ) void *spPlayerData; DWORD spPlayerDataSize; const WCHAR *password = L""; + void *msgHeader; HRESULT hr;
hr = IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, dpidServer, @@ -362,7 +366,7 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer ) hr = DP_MSG_ExpectReply( This, &data, DPMSG_WAIT_60_SECS, replyCommands, ARRAYSIZE( replyCommands ), - &lpMsg, &dwMsgSize ); + &lpMsg, &dwMsgSize, &msgHeader ); }
/* Need to examine the data and extract the new player id */ @@ -382,7 +386,7 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer ) */ static HRESULT DP_MSG_ExpectReply( IDirectPlayImpl *This, DPSP_SENDEXDATA *lpData, DWORD dwWaitTime, WORD *replyCommandIds, DWORD replyCommandIdCount, void **lplpReplyMsg, - DWORD *lpdwMsgBodySize ) + DWORD *lpdwMsgBodySize, void **replyMsgHeader ) { HRESULT hr; HANDLE hMsgReceipt; @@ -400,7 +404,7 @@ static HRESULT DP_MSG_ExpectReply( IDirectPlayImpl *This, DPSP_SENDEXDATA *lpDat { ERR( "Send failed: %s\n", DPLAYX_HresultToString( hr ) ); DP_MSG_UnlinkReplyStruct( This, &replyStructList ); - DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize ); + DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize, replyMsgHeader ); return hr; }
@@ -412,12 +416,12 @@ static HRESULT DP_MSG_ExpectReply( IDirectPlayImpl *This, DPSP_SENDEXDATA *lpDat { ERR( "Wait failed 0x%08lx\n", dwWaitReturn ); DP_MSG_UnlinkReplyStruct( This, &replyStructList ); - DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize ); + DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize, replyMsgHeader ); return DPERR_TIMEOUT; }
/* Clean Up */ - DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize ); + DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize, replyMsgHeader ); return DP_OK; }
@@ -426,7 +430,7 @@ static HRESULT DP_MSG_ExpectReply( IDirectPlayImpl *This, DPSP_SENDEXDATA *lpDat * indicate that a copy is taken. Silly really. */ void DP_MSG_ReplyReceived( IDirectPlayImpl *This, WORD wCommandId, const void *lpcMsgBody, - DWORD dwMsgBodySize ) + DWORD dwMsgBodySize, const void *msgHeader ) { LPDP_MSG_REPLY_STRUCT_LIST lpReplyList;
@@ -446,8 +450,11 @@ void DP_MSG_ReplyReceived( IDirectPlayImpl *This, WORD wCommandId, const void *l { lpReplyList->replyExpected.dwMsgBodySize = dwMsgBodySize; lpReplyList->replyExpected.lpReplyMsg = malloc( dwMsgBodySize ); + lpReplyList->replyExpected.replyMsgHeader = malloc( This->dp2->spData.dwSPHeaderSize ); CopyMemory( lpReplyList->replyExpected.lpReplyMsg, lpcMsgBody, dwMsgBodySize ); + CopyMemory( lpReplyList->replyExpected.replyMsgHeader, + msgHeader, This->dp2->spData.dwSPHeaderSize );
/* Signal the thread which sent the message that it has a reply */ SetEvent( lpReplyList->replyExpected.hReceipt ); @@ -462,6 +469,7 @@ void DP_MSG_ReplyReceived( IDirectPlayImpl *This, WORD wCommandId, const void *l void DP_MSG_ToSelf( IDirectPlayImpl *This, DPID dpidSelf ) { LPVOID lpMsg; + void *msgHeader; DPMSG_SENDENVELOPE msgBody; DWORD dwMsgSize;
@@ -492,7 +500,7 @@ void DP_MSG_ToSelf( IDirectPlayImpl *This, DPID dpidSelf ) DP_MSG_ExpectReply( This, &data, DPMSG_WAIT_5_SECS, &replyCommand, 1, - &lpMsg, &dwMsgSize ); + &lpMsg, &dwMsgSize, &msgHeader ); } }
diff --git a/dlls/dplayx/dplayx_messages.h b/dlls/dplayx/dplayx_messages.h index f14ed1f4371..09526085d5a 100644 --- a/dlls/dplayx/dplayx_messages.h +++ b/dlls/dplayx/dplayx_messages.h @@ -36,7 +36,8 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlayImpl *This, DWORD dwFlags, HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer );
void DP_MSG_ReplyReceived( IDirectPlayImpl *This, WORD wCommandId, - LPCVOID lpMsgBody, DWORD dwMsgBodySize ); + LPCVOID lpMsgBody, DWORD dwMsgBodySize, + const void *msgHeader ); void DP_MSG_ErrorReceived( IDirectPlayImpl *This, WORD wCommandId, LPCVOID lpMsgBody, DWORD dwMsgBodySize ); void DP_MSG_ToSelf( IDirectPlayImpl *This, DPID dpidSelf );
From: Anton Baskanov baskanov@gmail.com
--- dlls/dplayx/dplay.c | 2 +- dlls/dplayx/dplay_global.h | 3 + dlls/dplayx/dplayx_messages.c | 214 +++++++++++++++++++++++++++++++++- dlls/dplayx/dplayx_messages.h | 46 ++++++++ dlls/dplayx/tests/dplayx.c | 16 +-- 5 files changed, 271 insertions(+), 10 deletions(-)
diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 057003ec8d9..5f0ba3bdcb3 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -1413,7 +1413,7 @@ static HRESULT DP_CreateSPPlayer( IDirectPlayImpl *This, DPID dpid, DWORD flags, return DP_OK; }
-static HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName, +HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName, void *data, DWORD dataSize, void *spData, DWORD spDataSize, DWORD dwFlags, HANDLE hEvent, BOOL bAnsi ) { diff --git a/dlls/dplayx/dplay_global.h b/dlls/dplayx/dplay_global.h index cc3385569ec..b946c078ec6 100644 --- a/dlls/dplayx/dplay_global.h +++ b/dlls/dplayx/dplay_global.h @@ -201,6 +201,9 @@ HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpMessageBody, DWORD dwMessageBodySize, const void *lpMessageHeader, WORD wCommandId, WORD wVersion, void **lplpReply, DWORD *lpdwMsgSize ); DPSESSIONDESC2 *DP_DuplicateSessionDesc( const DPSESSIONDESC2 *src, BOOL dstAnsi, BOOL srcAnsi ); +HRESULT DP_CreatePlayer( IDirectPlayImpl *This, void *msgHeader, DPID *lpid, DPNAME *lpName, + void *data, DWORD dataSize, void *spData, DWORD spDataSize, DWORD dwFlags, + HANDLE hEvent, BOOL bAnsi );
/* DP SP external interfaces into DirectPlay */ extern HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData ); diff --git a/dlls/dplayx/dplayx_messages.c b/dlls/dplayx/dplayx_messages.c index 8df2cf4e7a4..371caebb893 100644 --- a/dlls/dplayx/dplayx_messages.c +++ b/dlls/dplayx/dplayx_messages.c @@ -295,6 +295,160 @@ HRESULT DP_MSG_SendRequestPlayerId( IDirectPlayImpl *This, DWORD dwFlags, DPID * return hr; }
+static HRESULT DP_MSG_ReadString( char *data, DWORD *inoutOffset, DWORD maxSize, WCHAR **string ) +{ + DWORD offset = *inoutOffset; + DWORD maxLength; + DWORD length; + + if( maxSize - offset < sizeof( WCHAR ) ) + return DPERR_GENERIC; + + maxLength = (maxSize - offset) / sizeof( WCHAR ); + length = wcsnlen( (WCHAR *) &data[ offset ], maxLength ); + if( length == maxLength ) + return DPERR_GENERIC; + + *string = (WCHAR *) &data[ offset ]; + *inoutOffset = offset + (length + 1) * sizeof( WCHAR ); + + return DP_OK; +} + +static HRESULT DP_MSG_ReadInteger( char *data, DWORD *inoutOffset, DWORD maxSize, DWORD size, + DWORD *value ) +{ + DWORD offset = *inoutOffset; + + switch ( size ) + { + case 0: + *value = 0; + break; + case 1: + if( maxSize - offset < 1 ) + return DPERR_GENERIC; + *value = *(BYTE *) &data[ offset ]; + *inoutOffset = offset + 1; + break; + case 2: + if( maxSize - offset < 2 ) + return DPERR_GENERIC; + *value = *(WORD *) &data[ offset ]; + *inoutOffset = offset + 2; + break; + case 3: + if( maxSize - offset < 4 ) + return DPERR_GENERIC; + *value = *(DWORD *) &data[ offset ]; + *inoutOffset = offset + 4; + break; + } + + return DP_OK; +} + +static HRESULT DP_MSG_ReadSuperPackedPlayer( char *data, DWORD *inoutOffset, DWORD maxSize, + DPPLAYERINFO *playerInfo ) +{ + DPLAYI_SUPERPACKEDPLAYER *packedPlayer; + DWORD offset = *inoutOffset; + HRESULT hr; + + memset( playerInfo, 0, sizeof( DPPLAYERINFO ) ); + + if( maxSize - offset < sizeof( DPLAYI_SUPERPACKEDPLAYER ) ) + return DPERR_GENERIC; + packedPlayer = (DPLAYI_SUPERPACKEDPLAYER *) &data[ offset ]; + offset += sizeof( DPLAYI_SUPERPACKEDPLAYER ); + + playerInfo->flags = packedPlayer->flags; + playerInfo->id = packedPlayer->id; + playerInfo->versionOrSystemPlayerId = packedPlayer->versionOrSystemPlayerId; + + if( packedPlayer->infoMask & DPLAYI_SUPERPACKEDPLAYER_SHORT_NAME_PRESENT ) + { + hr = DP_MSG_ReadString( data, &offset, maxSize, &playerInfo->name.lpszShortName ); + if ( FAILED( hr ) ) + return hr; + } + + if( packedPlayer->infoMask & DPLAYI_SUPERPACKEDPLAYER_LONG_NAME_PRESENT ) + { + hr = DP_MSG_ReadString( data, &offset, maxSize, &playerInfo->name.lpszLongName ); + if ( FAILED( hr ) ) + return hr; + } + + hr = DP_MSG_ReadInteger( data, &offset, maxSize, + DPLAYI_SUPERPACKEDPLAYER_PLAYER_DATA_LENGTH_SIZE( packedPlayer->infoMask ), + &playerInfo->playerDataLength ); + if ( FAILED( hr ) ) + return hr; + + if( playerInfo->playerDataLength ) + { + if( maxSize - offset < playerInfo->playerDataLength ) + return DPERR_GENERIC; + playerInfo->playerData = &data[ offset ]; + offset += playerInfo->playerDataLength; + } + + hr = DP_MSG_ReadInteger( data, &offset, maxSize, + DPLAYI_SUPERPACKEDPLAYER_SP_DATA_LENGTH_SIZE( packedPlayer->infoMask ), + &playerInfo->spDataLength ); + if ( FAILED( hr ) ) + return hr; + + if( playerInfo->spDataLength ) + { + if( maxSize - offset < playerInfo->spDataLength ) + return DPERR_GENERIC; + playerInfo->spData = &data[ offset ]; + offset += playerInfo->spDataLength; + } + + hr = DP_MSG_ReadInteger( data, &offset, maxSize, + DPLAYI_SUPERPACKEDPLAYER_PLAYER_COUNT_SIZE( packedPlayer->infoMask ), + &playerInfo->playerCount ); + if ( FAILED( hr ) ) + return hr; + + if( playerInfo->playerCount ) + { + if( maxSize - offset < playerInfo->playerCount * sizeof( DPID ) ) + return DPERR_GENERIC; + playerInfo->playerIds = (DPID *) &data[ offset ]; + offset += playerInfo->playerCount * sizeof( DPID ); + } + + if( packedPlayer->infoMask & DPLAYI_SUPERPACKEDPLAYER_PARENT_ID_PRESENT ) + { + if( maxSize - offset < sizeof( DPID ) ) + return DPERR_GENERIC; + playerInfo->parentId = *(DPID *) &data[ offset ]; + offset += sizeof( DPID ); + } + + hr = DP_MSG_ReadInteger( data, &offset, maxSize, + DPLAYI_SUPERPACKEDPLAYER_SHORTCUT_COUNT_SIZE( packedPlayer->infoMask ), + &playerInfo->shortcutCount ); + if ( FAILED( hr ) ) + return hr; + + if( playerInfo->shortcutCount ) + { + if( maxSize - offset < playerInfo->shortcutCount * sizeof( DPID ) ) + return DPERR_GENERIC; + playerInfo->shortcutIds = (DPID *) &data[ offset ]; + offset += playerInfo->shortcutCount * sizeof( DPID ); + } + + *inoutOffset = offset; + + return S_OK; +} + HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer ) { LPVOID lpMsg; @@ -372,7 +526,65 @@ HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlayImpl *This, DPID dpidServer ) /* Need to examine the data and extract the new player id */ if( lpMsg != NULL ) { - FIXME( "Name Table reply received: stub\n" ); + DPMSG_SENDENVELOPE *envelope; + + if( dwMsgSize < sizeof( DPMSG_SENDENVELOPE ) ) + { + free( msgHeader ); + free( lpMsg ); + return DPERR_GENERIC; + } + envelope = (DPMSG_SENDENVELOPE *) lpMsg; + + if( envelope->wCommandId == DPMSGCMD_SUPERENUMPLAYERSREPLY ) + { + DPSP_MSG_SUPERENUMPLAYERSREPLY *enumPlayersReply; + DWORD offset; + int i; + + if( dwMsgSize < sizeof( DPSP_MSG_SUPERENUMPLAYERSREPLY ) ) + { + free( msgHeader ); + free( lpMsg ); + return DPERR_GENERIC; + } + enumPlayersReply = (DPSP_MSG_SUPERENUMPLAYERSREPLY *) envelope; + + offset = enumPlayersReply->packedOffset; + for( i = 0; i < enumPlayersReply->playerCount; ++i ) + { + DPPLAYERINFO playerInfo; + + hr = DP_MSG_ReadSuperPackedPlayer( (char *) enumPlayersReply, &offset, dwMsgSize, + &playerInfo ); + if( FAILED( hr ) ) + { + free( msgHeader ); + free( lpMsg ); + return hr; + } + + if ( playerInfo.id == dpidServer ) + continue; + + hr = DP_CreatePlayer( This, msgHeader, &playerInfo.id, &playerInfo.name, + playerInfo.playerData, playerInfo.playerDataLength, playerInfo.spData, + playerInfo.spDataLength, playerInfo.flags & ~DPLAYI_PLAYER_PLAYERLOCAL, NULL, + FALSE ); + if( FAILED( hr ) ) + { + free( msgHeader ); + free( lpMsg ); + return hr; + } + } + } + else if( envelope->wCommandId == DPMSGCMD_GETNAMETABLEREPLY ) + { + FIXME( "Name Table reply received: stub\n" ); + } + free( msgHeader ); + free( lpMsg ); }
return hr; diff --git a/dlls/dplayx/dplayx_messages.h b/dlls/dplayx/dplayx_messages.h index 09526085d5a..09a0ffb03d9 100644 --- a/dlls/dplayx/dplayx_messages.h +++ b/dlls/dplayx/dplayx_messages.h @@ -28,6 +28,23 @@
#include "dplay_global.h"
+typedef struct +{ + DWORD flags; + DPID id; + DWORD versionOrSystemPlayerId; + DPNAME name; + DWORD playerDataLength; + void *playerData; + DWORD spDataLength; + void *spData; + DWORD playerCount; + DPID *playerIds; + DPID parentId; + DWORD shortcutCount; + DPID *shortcutIds; +} DPPLAYERINFO; + DWORD CreateLobbyMessageReceptionThread( HANDLE hNotifyEvent, HANDLE hStart, HANDLE hDeath, HANDLE hConnRead );
@@ -221,6 +238,35 @@ typedef struct tagDPMSG_FORWARDADDPLAYERNACK } DPMSG_FORWARDADDPLAYERNACK, *LPDPMSG_FORWARDADDPLAYERNACK; typedef const DPMSG_FORWARDADDPLAYERNACK* LPCDPMSG_FORWARDADDPLAYERNACK;
+typedef struct +{ + DWORD size; + DWORD flags; + DPID id; + DWORD infoMask; + DWORD versionOrSystemPlayerId; +} DPLAYI_SUPERPACKEDPLAYER; + +#define DPLAYI_SUPERPACKEDPLAYER_SHORT_NAME_PRESENT 0x001 +#define DPLAYI_SUPERPACKEDPLAYER_LONG_NAME_PRESENT 0x002 +#define DPLAYI_SUPERPACKEDPLAYER_SP_DATA_LENGTH_SIZE( mask ) (((mask) >> 2) & 0x3) +#define DPLAYI_SUPERPACKEDPLAYER_PLAYER_DATA_LENGTH_SIZE( mask ) (((mask) >> 4) & 0x3) +#define DPLAYI_SUPERPACKEDPLAYER_PLAYER_COUNT_SIZE( mask ) (((mask) >> 6) & 0x3) +#define DPLAYI_SUPERPACKEDPLAYER_PARENT_ID_PRESENT 0x100 +#define DPLAYI_SUPERPACKEDPLAYER_SHORTCUT_COUNT_SIZE( mask ) (((mask) >> 9) & 0x3) + +typedef struct +{ + DPMSG_SENDENVELOPE envelope; + DWORD playerCount; + DWORD groupCount; + DWORD packedOffset; + DWORD shortcutCount; + DWORD descriptionOffset; + DWORD nameOffset; + DWORD passwordOffset; +} DPSP_MSG_SUPERENUMPLAYERSREPLY; + #include "poppack.h"
#endif diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c index 1c2b9bcbd19..dcf0e4f2c4d 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -2029,8 +2029,8 @@ static BOOL CALLBACK checkPlayerListCallback( DPID dpid, DWORD playerType, const playerType ); if ( player->expectedShortName ) { - ok_( __FILE__, data->line )( name->lpszShortNameA && !strcmp( name->lpszShortNameA, player->expectedShortName ), - "got short name %s.\n", wine_dbgstr_a( name->lpszShortNameA ) ); + todo_wine ok_( __FILE__, data->line )( name->lpszShortNameA && !strcmp( name->lpszShortNameA, player->expectedShortName ), + "got short name %s.\n", wine_dbgstr_a( name->lpszShortNameA ) ); } else { @@ -2039,8 +2039,8 @@ static BOOL CALLBACK checkPlayerListCallback( DPID dpid, DWORD playerType, const } if ( player->expectedLongName ) { - ok_( __FILE__, data->line )( name->lpszLongNameA && !strcmp( name->lpszLongNameA, player->expectedLongName ), - "got long name %s.\n", wine_dbgstr_a( name->lpszLongNameA ) ); + todo_wine ok_( __FILE__, data->line )( name->lpszLongNameA && !strcmp( name->lpszLongNameA, player->expectedLongName ), + "got long name %s.\n", wine_dbgstr_a( name->lpszLongNameA ) ); } else { @@ -2053,8 +2053,8 @@ static BOOL CALLBACK checkPlayerListCallback( DPID dpid, DWORD playerType, const playerDataSize = sizeof( playerData ); hr = IDirectPlayX_GetPlayerData( data->dp, dpid, playerData, &playerDataSize, DPGET_REMOTE ); ok_( __FILE__, data->line )( hr == DP_OK, "GetPlayerData() returned %#lx.\n", hr ); - ok_( __FILE__, data->line )( playerDataSize == player->expectedPlayerDataSize, - "got player data size %lu.\n", playerDataSize ); + todo_wine ok_( __FILE__, data->line )( playerDataSize == player->expectedPlayerDataSize, + "got player data size %lu.\n", playerDataSize ); ok_( __FILE__, data->line )( !memcmp( playerData, player->expectedPlayerData, player->expectedPlayerDataSize ), "player data doesn't match.\n" );
@@ -2085,8 +2085,8 @@ static void checkPlayerList_( int line, IDirectPlay4 *dp, ExpectedPlayer *expect
hr = IDirectPlayX_EnumPlayers( dp, NULL, checkPlayerListCallback, &data, 0 ); ok_( __FILE__, line )( hr == DP_OK, "EnumPlayers() returned %#lx.\n", hr ); - todo_wine ok_( __FILE__, line )( data.actualPlayerCount == data.expectedPlayerCount, "got player count %d.\n", - data.actualPlayerCount ); + ok_( __FILE__, line )( data.actualPlayerCount == data.expectedPlayerCount, "got player count %d.\n", + data.actualPlayerCount ); }
#define check_Open( dp, dpsd, serverDpsd, requestExpected, port, expectedPassword, expectedHr ) check_Open_( __LINE__, dp, dpsd, serverDpsd, requestExpected, port, expectedPassword, expectedHr )
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=148788
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
dplayx: dplayx.c:2893: Test failed: select() returned 1. dplayx.c:2302: Test failed: got flags 0.
=== debian11b (64 bit WoW report) ===
mf: mf.c:5383: Test failed: got hr 0x800c0008 mf.c:5383: Test failed: got hr 0x800c0008
qmgr: job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:783: Test failed: unexpected state: 4 job.c:508: Test failed: Failed to get error: 0x8020000f job.c:802: Test failed: BITS job timed out job.c:834: Test failed: got 0x00200017
v2: - Fix bound checks in `DP_MSG_ReadString()`.
This merge request was approved by Alistair Leslie-Hughes.