1 /* Direct Play 2,3,4 Implementation 2 * 3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #define COBJMACROS 21 22 #include <stdarg.h> 23 #include <string.h> 24 25 #define NONAMELESSUNION 26 27 #include "windef.h" 28 #include "winerror.h" 29 #include "winbase.h" 30 #include "winnt.h" 31 #include "winreg.h" 32 #include "winnls.h" 33 #include "wine/debug.h" 34 35 #include "dplayx_global.h" 36 #include "name_server.h" 37 #include "dplayx_queue.h" 38 #include "wine/dplaysp.h" 39 #include "dplay_global.h" 40 41 WINE_DEFAULT_DEBUG_CHANNEL(dplay); 42 43 /* FIXME: Should this be externed? */ 44 extern HRESULT DPL_CreateCompoundAddress 45 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount, 46 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface ); 47 48 49 /* Local function prototypes */ 50 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid ); 51 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi ); 52 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags, 53 LPVOID lpData, DWORD dwDataSize ); 54 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName ); 55 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId, 56 DWORD dwPlayerType, 57 LPCDPNAME lpName, 58 DWORD dwFlags, 59 LPVOID lpContext ); 60 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid ); 61 62 /* Helper methods for player/group interfaces */ 63 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc, 64 DWORD dwFlags, BOOL bInitial, BOOL bAnsi ); 65 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize, 66 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID ); 67 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf, 68 LPDWORD lpdwBufSize ); 69 70 static DPID DP_GetRemoteNextObjectId(void); 71 72 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi ); 73 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc, 74 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi ); 75 76 77 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */ 78 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported 79 we don't have to change much */ 80 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */ 81 82 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */ 83 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN ) 84 85 /* Strip out all dwFlags values for CREATEPLAYER msg */ 86 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0 87 88 static LONG kludgePlayerGroupId = 1000; 89 90 91 static inline IDirectPlayImpl *impl_from_IDirectPlay( IDirectPlay *iface ) 92 { 93 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay_iface ); 94 } 95 96 static inline IDirectPlayImpl *impl_from_IDirectPlay2( IDirectPlay2 *iface ) 97 { 98 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2_iface ); 99 } 100 101 static inline IDirectPlayImpl *impl_from_IDirectPlay2A( IDirectPlay2A *iface ) 102 { 103 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2A_iface ); 104 } 105 106 static inline IDirectPlayImpl *impl_from_IDirectPlay3A( IDirectPlay3A *iface ) 107 { 108 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3A_iface ); 109 } 110 111 static inline IDirectPlayImpl *impl_from_IDirectPlay3( IDirectPlay3 *iface ) 112 { 113 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3_iface ); 114 } 115 116 static inline IDirectPlayImpl *impl_from_IDirectPlay4A( IDirectPlay4A *iface ) 117 { 118 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4A_iface ); 119 } 120 121 static inline IDirectPlayImpl *impl_from_IDirectPlay4( IDirectPlay4 *iface ) 122 { 123 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4_iface ); 124 } 125 126 static BOOL DP_CreateDirectPlay2( LPVOID lpDP ) 127 { 128 IDirectPlayImpl *This = lpDP; 129 130 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) ); 131 if ( This->dp2 == NULL ) 132 { 133 return FALSE; 134 } 135 136 This->dp2->bConnectionOpen = FALSE; 137 138 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE; 139 This->dp2->dwEnumSessionLock = 0; 140 141 This->dp2->bHostInterface = FALSE; 142 143 DPQ_INIT(This->dp2->receiveMsgs); 144 DPQ_INIT(This->dp2->sendMsgs); 145 DPQ_INIT(This->dp2->repliesExpected); 146 147 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) ) 148 { 149 /* FIXME: Memory leak */ 150 return FALSE; 151 } 152 153 /* Provide an initial session desc with nothing in it */ 154 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(), 155 HEAP_ZERO_MEMORY, 156 sizeof( *This->dp2->lpSessionDesc ) ); 157 if( This->dp2->lpSessionDesc == NULL ) 158 { 159 /* FIXME: Memory leak */ 160 return FALSE; 161 } 162 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc ); 163 164 /* We are emulating a dp 6 implementation */ 165 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION; 166 167 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 168 sizeof( *This->dp2->spData.lpCB ) ); 169 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB ); 170 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION; 171 172 /* This is the pointer to the service provider */ 173 if ( FAILED( dplaysp_create( &IID_IDirectPlaySP, (void**)&This->dp2->spData.lpISP, This ) ) ) 174 { 175 /* FIXME: Memory leak */ 176 return FALSE; 177 } 178 179 /* Setup lobby provider information */ 180 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION; 181 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 182 sizeof( *This->dp2->dplspData.lpCB ) ); 183 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB ); 184 185 if( FAILED( dplobbysp_create( &IID_IDPLobbySP, (void**)&This->dp2->dplspData.lpISP, This ) ) 186 ) 187 { 188 /* FIXME: Memory leak */ 189 return FALSE; 190 } 191 192 return TRUE; 193 } 194 195 /* Definition of the global function in dplayx_queue.h. # 196 * FIXME: Would it be better to have a dplayx_queue.c for this function? */ 197 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID ) 198 { 199 HeapFree( GetProcessHeap(), 0, elem ); 200 } 201 202 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP ) 203 { 204 IDirectPlayImpl *This = lpDP; 205 206 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE ) 207 { 208 TerminateThread( This->dp2->hEnumSessionThread, 0 ); 209 CloseHandle( This->dp2->hEnumSessionThread ); 210 } 211 212 /* Finish with the SP - have it shutdown */ 213 if( This->dp2->spData.lpCB->ShutdownEx ) 214 { 215 DPSP_SHUTDOWNDATA data; 216 217 TRACE( "Calling SP ShutdownEx\n" ); 218 219 data.lpISP = This->dp2->spData.lpISP; 220 221 (*This->dp2->spData.lpCB->ShutdownEx)( &data ); 222 } 223 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */ 224 { 225 TRACE( "Calling obsolete SP Shutdown\n" ); 226 (*This->dp2->spData.lpCB->Shutdown)(); 227 } 228 229 /* Unload the SP (if it exists) */ 230 if( This->dp2->hServiceProvider != 0 ) 231 { 232 FreeLibrary( This->dp2->hServiceProvider ); 233 } 234 235 /* Unload the Lobby Provider (if it exists) */ 236 if( This->dp2->hDPLobbyProvider != 0 ) 237 { 238 FreeLibrary( This->dp2->hDPLobbyProvider ); 239 } 240 241 /* FIXME: Need to delete receive and send msgs queue contents */ 242 243 NS_DeleteSessionCache( This->dp2->lpNameServerData ); 244 245 HeapFree( GetProcessHeap(), 0, This->dp2->dplspData.lpCB); 246 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc ); 247 248 IDirectPlaySP_Release( This->dp2->spData.lpISP ); 249 250 /* Delete the contents */ 251 HeapFree( GetProcessHeap(), 0, This->dp2 ); 252 253 return TRUE; 254 } 255 256 static void dplay_destroy(IDirectPlayImpl *obj) 257 { 258 DP_DestroyDirectPlay2( obj ); 259 obj->lock.DebugInfo->Spare[0] = 0; 260 DeleteCriticalSection( &obj->lock ); 261 HeapFree( GetProcessHeap(), 0, obj ); 262 } 263 264 static inline DPID DP_NextObjectId(void) 265 { 266 return (DPID)InterlockedIncrement( &kludgePlayerGroupId ); 267 } 268 269 /* *lplpReply will be non NULL iff there is something to reply */ 270 HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody, 271 DWORD dwMessageBodySize, const void *lpcMessageHeader, WORD wCommandId, WORD wVersion, 272 void **lplpReply, DWORD *lpdwMsgSize ) 273 { 274 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n", 275 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId, 276 wVersion ); 277 278 switch( wCommandId ) 279 { 280 /* Name server needs to handle this request */ 281 case DPMSGCMD_ENUMSESSIONSREQUEST: 282 /* Reply expected */ 283 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This ); 284 break; 285 286 /* Name server needs to handle this request */ 287 case DPMSGCMD_ENUMSESSIONSREPLY: 288 /* No reply expected */ 289 NS_AddRemoteComputerAsNameServer( lpcMessageHeader, 290 This->dp2->spData.dwSPHeaderSize, 291 lpcMessageBody, 292 This->dp2->lpNameServerData ); 293 break; 294 295 case DPMSGCMD_REQUESTNEWPLAYERID: 296 { 297 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = lpcMessageBody; 298 299 LPDPMSG_NEWPLAYERIDREPLY lpReply; 300 301 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply ); 302 303 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize ); 304 305 FIXME( "Ignoring dwFlags 0x%08x in request msg\n", 306 lpcMsg->dwFlags ); 307 308 /* Setup the reply */ 309 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) + 310 This->dp2->spData.dwSPHeaderSize ); 311 312 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG; 313 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY; 314 lpReply->envelope.wVersion = DPMSGVER_DP6; 315 316 lpReply->dpidNewPlayerId = DP_NextObjectId(); 317 318 TRACE( "Allocating new playerid 0x%08x from remote request\n", 319 lpReply->dpidNewPlayerId ); 320 break; 321 } 322 323 case DPMSGCMD_GETNAMETABLEREPLY: 324 case DPMSGCMD_NEWPLAYERIDREPLY: 325 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); 326 break; 327 328 case DPMSGCMD_JUSTENVELOPE: 329 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] ); 330 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 ); 331 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); 332 333 case DPMSGCMD_FORWARDADDPLAYER: 334 TRACE( "Sending message to self to get my addr\n" ); 335 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */ 336 break; 337 338 case DPMSGCMD_FORWARDADDPLAYERNACK: 339 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize ); 340 break; 341 342 default: 343 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId ); 344 DebugBreak(); 345 break; 346 } 347 348 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */ 349 350 return DP_OK; 351 } 352 353 354 static HRESULT WINAPI IDirectPlayImpl_QueryInterface( IDirectPlay *iface, REFIID riid, void **ppv ) 355 { 356 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 357 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv ); 358 } 359 360 static ULONG WINAPI IDirectPlayImpl_AddRef( IDirectPlay *iface ) 361 { 362 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 363 ULONG ref = InterlockedIncrement( &This->ref ); 364 365 TRACE( "(%p) ref=%d\n", This, ref ); 366 367 if ( ref == 1 ) 368 InterlockedIncrement( &This->numIfaces ); 369 370 return ref; 371 } 372 373 static ULONG WINAPI IDirectPlayImpl_Release( IDirectPlay *iface ) 374 { 375 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 376 ULONG ref = InterlockedDecrement( &This->ref ); 377 378 TRACE( "(%p) ref=%d\n", This, ref ); 379 380 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 381 dplay_destroy( This ); 382 383 return ref; 384 } 385 386 static HRESULT WINAPI IDirectPlayImpl_AddPlayerToGroup( IDirectPlay *iface, DPID group, 387 DPID player ) 388 { 389 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 390 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player ); 391 return E_NOTIMPL; 392 } 393 394 static HRESULT WINAPI IDirectPlayImpl_Close( IDirectPlay *iface ) 395 { 396 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 397 FIXME( "(%p): stub\n", This ); 398 return E_NOTIMPL; 399 } 400 401 static HRESULT WINAPI IDirectPlayImpl_CreatePlayer( IDirectPlay *iface, DPID *player, 402 LPSTR name, LPSTR fullname, HANDLE *event ) 403 { 404 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 405 FIXME( "(%p)->(%p,%s,%s,%p): stub\n", This, player, debugstr_a( name ), debugstr_a( fullname ), 406 event ); 407 return E_NOTIMPL; 408 } 409 410 static HRESULT WINAPI IDirectPlayImpl_CreateGroup( IDirectPlay *iface, DPID *group, LPSTR name, 411 LPSTR fullname ) 412 { 413 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 414 FIXME( "(%p)->(%p,%s,%s): stub\n", This, group, debugstr_a( name ), debugstr_a( fullname ) ); 415 return E_NOTIMPL; 416 } 417 418 static HRESULT WINAPI IDirectPlayImpl_DeletePlayerFromGroup( IDirectPlay *iface, DPID group, 419 DPID player ) 420 { 421 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 422 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player ); 423 return E_NOTIMPL; 424 } 425 426 static HRESULT WINAPI IDirectPlayImpl_DestroyPlayer( IDirectPlay *iface, DPID player ) 427 { 428 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 429 FIXME( "(%p)->(0x%08x): stub\n", This, player ); 430 return E_NOTIMPL; 431 } 432 433 static HRESULT WINAPI IDirectPlayImpl_DestroyGroup( IDirectPlay *iface, DPID group ) 434 { 435 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 436 FIXME( "(%p)->(0x%08x): stub\n", This, group ); 437 return E_NOTIMPL; 438 } 439 440 static HRESULT WINAPI IDirectPlayImpl_EnableNewPlayers( IDirectPlay *iface, BOOL enable ) 441 { 442 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 443 FIXME( "(%p)->(%d): stub\n", This, enable ); 444 return E_NOTIMPL; 445 } 446 447 static HRESULT WINAPI IDirectPlayImpl_EnumGroupPlayers( IDirectPlay *iface, DPID group, 448 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags ) 449 { 450 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 451 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, group, enumplayercb, context, flags ); 452 return E_NOTIMPL; 453 } 454 455 static HRESULT WINAPI IDirectPlayImpl_EnumGroups( IDirectPlay *iface, DWORD session, 456 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags ) 457 { 458 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 459 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags ); 460 return E_NOTIMPL; 461 } 462 463 static HRESULT WINAPI IDirectPlayImpl_EnumPlayers( IDirectPlay *iface, DWORD session, 464 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags ) 465 { 466 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 467 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags ); 468 return E_NOTIMPL; 469 } 470 471 static HRESULT WINAPI IDirectPlayImpl_EnumSessions( IDirectPlay *iface, DPSESSIONDESC *sdesc, 472 DWORD timeout, LPDPENUMSESSIONSCALLBACK enumsessioncb, void *context, DWORD flags ) 473 { 474 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 475 FIXME( "(%p)->(%p,%u,%p,%p,0x%08x): stub\n", This, sdesc, timeout, enumsessioncb, context, 476 flags ); 477 return E_NOTIMPL; 478 } 479 480 static HRESULT WINAPI IDirectPlayImpl_GetCaps( IDirectPlay *iface, DPCAPS *caps ) 481 { 482 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 483 FIXME( "(%p)->(%p): stub\n", This, caps ); 484 return E_NOTIMPL; 485 } 486 487 static HRESULT WINAPI IDirectPlayImpl_GetMessageCount( IDirectPlay *iface, DPID player, 488 DWORD *count ) 489 { 490 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 491 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, count ); 492 return E_NOTIMPL; 493 } 494 495 static HRESULT WINAPI IDirectPlayImpl_GetPlayerCaps( IDirectPlay *iface, DPID player, DPCAPS *caps ) 496 { 497 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 498 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, caps ); 499 return E_NOTIMPL; 500 } 501 502 static HRESULT WINAPI IDirectPlayImpl_GetPlayerName( IDirectPlay *iface, DPID player, LPSTR name, 503 DWORD *size_name, LPSTR fullname, DWORD *size_fullname ) 504 { 505 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 506 FIXME( "(%p)->(0x%08x,%p,%p,%p,%p): stub\n", This, player, name, size_name, fullname, 507 size_fullname ); 508 return E_NOTIMPL; 509 } 510 511 static HRESULT WINAPI IDirectPlayImpl_Initialize( IDirectPlay *iface, GUID *guid ) 512 { 513 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 514 FIXME( "(%p)->(%p): stub\n", This, guid ); 515 return E_NOTIMPL; 516 } 517 518 static HRESULT WINAPI IDirectPlayImpl_Open( IDirectPlay *iface, DPSESSIONDESC *sdesc ) 519 { 520 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 521 FIXME( "(%p)->(%p): stub\n", This, sdesc ); 522 return E_NOTIMPL; 523 } 524 525 static HRESULT WINAPI IDirectPlayImpl_Receive( IDirectPlay *iface, DPID *from, DPID *to, 526 DWORD flags, void *data, DWORD *size ) 527 { 528 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 529 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p): stub\n", This, from, to, flags, data, size ); 530 return E_NOTIMPL; 531 } 532 533 static HRESULT WINAPI IDirectPlayImpl_SaveSession( IDirectPlay *iface, LPSTR reserved ) 534 { 535 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 536 FIXME( "(%p)->(%p): stub\n", This, reserved ); 537 return E_NOTIMPL; 538 } 539 540 static HRESULT WINAPI IDirectPlayImpl_Send( IDirectPlay *iface, DPID from, DPID to, DWORD flags, 541 void *data, DWORD size ) 542 { 543 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 544 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%u): stub\n", This, from, to, flags, data, size ); 545 return E_NOTIMPL; 546 } 547 548 static HRESULT WINAPI IDirectPlayImpl_SetPlayerName( IDirectPlay *iface, DPID player, LPSTR name, 549 LPSTR fullname ) 550 { 551 IDirectPlayImpl *This = impl_from_IDirectPlay( iface ); 552 FIXME( "(%p)->(0x%08x,%s,%s): stub\n", This, player, debugstr_a( name ), 553 debugstr_a ( fullname ) ); 554 return E_NOTIMPL; 555 } 556 557 static const IDirectPlayVtbl dp_vt = 558 { 559 IDirectPlayImpl_QueryInterface, 560 IDirectPlayImpl_AddRef, 561 IDirectPlayImpl_Release, 562 IDirectPlayImpl_AddPlayerToGroup, 563 IDirectPlayImpl_Close, 564 IDirectPlayImpl_CreatePlayer, 565 IDirectPlayImpl_CreateGroup, 566 IDirectPlayImpl_DeletePlayerFromGroup, 567 IDirectPlayImpl_DestroyPlayer, 568 IDirectPlayImpl_DestroyGroup, 569 IDirectPlayImpl_EnableNewPlayers, 570 IDirectPlayImpl_EnumGroupPlayers, 571 IDirectPlayImpl_EnumGroups, 572 IDirectPlayImpl_EnumPlayers, 573 IDirectPlayImpl_EnumSessions, 574 IDirectPlayImpl_GetCaps, 575 IDirectPlayImpl_GetMessageCount, 576 IDirectPlayImpl_GetPlayerCaps, 577 IDirectPlayImpl_GetPlayerName, 578 IDirectPlayImpl_Initialize, 579 IDirectPlayImpl_Open, 580 IDirectPlayImpl_Receive, 581 IDirectPlayImpl_SaveSession, 582 IDirectPlayImpl_Send, 583 IDirectPlayImpl_SetPlayerName, 584 }; 585 586 587 static HRESULT WINAPI IDirectPlay2AImpl_QueryInterface( IDirectPlay2A *iface, REFIID riid, 588 void **ppv ) 589 { 590 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 591 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv ); 592 } 593 594 static HRESULT WINAPI IDirectPlay2Impl_QueryInterface( IDirectPlay2 *iface, REFIID riid, 595 void **ppv ) 596 { 597 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 598 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv ); 599 } 600 601 static HRESULT WINAPI IDirectPlay3AImpl_QueryInterface( IDirectPlay3A *iface, REFIID riid, 602 void **ppv ) 603 { 604 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 605 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv ); 606 } 607 608 static HRESULT WINAPI IDirectPlay3Impl_QueryInterface( IDirectPlay3 *iface, REFIID riid, 609 void **ppv ) 610 { 611 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 612 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv ); 613 } 614 615 static HRESULT WINAPI IDirectPlay4AImpl_QueryInterface( IDirectPlay4A *iface, REFIID riid, 616 void **ppv ) 617 { 618 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 619 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv ); 620 } 621 622 static HRESULT WINAPI IDirectPlay4Impl_QueryInterface( IDirectPlay4 *iface, REFIID riid, 623 void **ppv ) 624 { 625 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 626 627 if ( IsEqualGUID( &IID_IUnknown, riid ) ) 628 { 629 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv ); 630 *ppv = &This->IDirectPlay_iface; 631 } 632 else if ( IsEqualGUID( &IID_IDirectPlay, riid ) ) 633 { 634 TRACE( "(%p)->(IID_IDirectPlay %p)\n", This, ppv ); 635 *ppv = &This->IDirectPlay_iface; 636 } 637 else if ( IsEqualGUID( &IID_IDirectPlay2A, riid ) ) 638 { 639 TRACE( "(%p)->(IID_IDirectPlay2A %p)\n", This, ppv ); 640 *ppv = &This->IDirectPlay2A_iface; 641 } 642 else if ( IsEqualGUID( &IID_IDirectPlay2, riid ) ) 643 { 644 TRACE( "(%p)->(IID_IDirectPlay2 %p)\n", This, ppv ); 645 *ppv = &This->IDirectPlay2_iface; 646 } 647 else if ( IsEqualGUID( &IID_IDirectPlay3A, riid ) ) 648 { 649 TRACE( "(%p)->(IID_IDirectPlay3A %p)\n", This, ppv ); 650 *ppv = &This->IDirectPlay3A_iface; 651 } 652 else if ( IsEqualGUID( &IID_IDirectPlay3, riid ) ) 653 { 654 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv ); 655 *ppv = &This->IDirectPlay3_iface; 656 } 657 else if ( IsEqualGUID( &IID_IDirectPlay4A, riid ) ) 658 { 659 TRACE( "(%p)->(IID_IDirectPlay4A %p)\n", This, ppv ); 660 *ppv = &This->IDirectPlay4A_iface; 661 } 662 else if ( IsEqualGUID( &IID_IDirectPlay4, riid ) ) 663 { 664 TRACE( "(%p)->(IID_IDirectPlay4 %p)\n", This, ppv ); 665 *ppv = &This->IDirectPlay4_iface; 666 } 667 else 668 { 669 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 670 *ppv = NULL; 671 return E_NOINTERFACE; 672 } 673 674 IUnknown_AddRef((IUnknown*)*ppv); 675 return S_OK; 676 } 677 678 static ULONG WINAPI IDirectPlay2AImpl_AddRef( IDirectPlay2A *iface ) 679 { 680 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 681 ULONG ref = InterlockedIncrement( &This->ref2A ); 682 683 TRACE( "(%p) ref2A=%d\n", This, ref ); 684 685 if ( ref == 1 ) 686 InterlockedIncrement( &This->numIfaces ); 687 688 return ref; 689 } 690 691 static ULONG WINAPI IDirectPlay2Impl_AddRef( IDirectPlay2 *iface ) 692 { 693 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 694 ULONG ref = InterlockedIncrement( &This->ref2 ); 695 696 TRACE( "(%p) ref2=%d\n", This, ref ); 697 698 if ( ref == 1 ) 699 InterlockedIncrement( &This->numIfaces ); 700 701 return ref; 702 } 703 704 static ULONG WINAPI IDirectPlay3AImpl_AddRef( IDirectPlay3A *iface ) 705 { 706 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 707 ULONG ref = InterlockedIncrement( &This->ref3A ); 708 709 TRACE( "(%p) ref3A=%d\n", This, ref ); 710 711 if ( ref == 1 ) 712 InterlockedIncrement( &This->numIfaces ); 713 714 return ref; 715 } 716 717 static ULONG WINAPI IDirectPlay3Impl_AddRef( IDirectPlay3 *iface ) 718 { 719 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 720 ULONG ref = InterlockedIncrement( &This->ref3 ); 721 722 TRACE( "(%p) ref3=%d\n", This, ref ); 723 724 if ( ref == 1 ) 725 InterlockedIncrement( &This->numIfaces ); 726 727 return ref; 728 } 729 730 static ULONG WINAPI IDirectPlay4AImpl_AddRef(IDirectPlay4A *iface) 731 { 732 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 733 ULONG ref = InterlockedIncrement( &This->ref4A ); 734 735 TRACE( "(%p) ref4A=%d\n", This, ref ); 736 737 if ( ref == 1 ) 738 InterlockedIncrement( &This->numIfaces ); 739 740 return ref; 741 } 742 743 static ULONG WINAPI IDirectPlay4Impl_AddRef(IDirectPlay4 *iface) 744 { 745 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 746 ULONG ref = InterlockedIncrement( &This->ref4 ); 747 748 TRACE( "(%p) ref4=%d\n", This, ref ); 749 750 if ( ref == 1 ) 751 InterlockedIncrement( &This->numIfaces ); 752 753 return ref; 754 } 755 756 static ULONG WINAPI IDirectPlay2AImpl_Release( IDirectPlay2A *iface ) 757 { 758 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 759 ULONG ref = InterlockedDecrement( &This->ref2A ); 760 761 TRACE( "(%p) ref2A=%d\n", This, ref ); 762 763 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 764 dplay_destroy( This ); 765 766 return ref; 767 } 768 769 static ULONG WINAPI IDirectPlay2Impl_Release( IDirectPlay2 *iface ) 770 { 771 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 772 ULONG ref = InterlockedDecrement( &This->ref2 ); 773 774 TRACE( "(%p) ref2=%d\n", This, ref ); 775 776 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 777 dplay_destroy( This ); 778 779 return ref; 780 } 781 782 static ULONG WINAPI IDirectPlay3AImpl_Release( IDirectPlay3A *iface ) 783 { 784 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 785 ULONG ref = InterlockedDecrement( &This->ref3A ); 786 787 TRACE( "(%p) ref3A=%d\n", This, ref ); 788 789 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 790 dplay_destroy( This ); 791 792 return ref; 793 } 794 795 static ULONG WINAPI IDirectPlay3Impl_Release( IDirectPlay3 *iface ) 796 { 797 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 798 ULONG ref = InterlockedDecrement( &This->ref3 ); 799 800 TRACE( "(%p) ref3=%d\n", This, ref ); 801 802 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 803 dplay_destroy( This ); 804 805 return ref; 806 } 807 808 static ULONG WINAPI IDirectPlay4AImpl_Release(IDirectPlay4A *iface) 809 { 810 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 811 ULONG ref = InterlockedDecrement( &This->ref4A ); 812 813 TRACE( "(%p) ref4A=%d\n", This, ref ); 814 815 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 816 dplay_destroy( This ); 817 818 return ref; 819 } 820 821 static ULONG WINAPI IDirectPlay4Impl_Release(IDirectPlay4 *iface) 822 { 823 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 824 ULONG ref = InterlockedDecrement( &This->ref4 ); 825 826 TRACE( "(%p) ref4=%d\n", This, ref ); 827 828 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 829 dplay_destroy( This ); 830 831 return ref; 832 } 833 834 static HRESULT WINAPI IDirectPlay2AImpl_AddPlayerToGroup( IDirectPlay2A *iface, DPID group, 835 DPID player ) 836 { 837 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 838 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4A_iface, group, player ); 839 } 840 841 static HRESULT WINAPI IDirectPlay2Impl_AddPlayerToGroup( IDirectPlay2 *iface, DPID group, 842 DPID player ) 843 { 844 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 845 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player ); 846 } 847 848 static HRESULT WINAPI IDirectPlay3AImpl_AddPlayerToGroup( IDirectPlay3A *iface, DPID group, 849 DPID player ) 850 { 851 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 852 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player ); 853 } 854 855 static HRESULT WINAPI IDirectPlay3Impl_AddPlayerToGroup( IDirectPlay3 *iface, DPID group, 856 DPID player ) 857 { 858 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 859 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player ); 860 } 861 862 static HRESULT WINAPI IDirectPlay4AImpl_AddPlayerToGroup( IDirectPlay4A *iface, DPID group, 863 DPID player ) 864 { 865 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 866 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player ); 867 } 868 869 static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group, 870 DPID player ) 871 { 872 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 873 lpGroupData gdata; 874 lpPlayerList plist; 875 lpPlayerList newplist; 876 877 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player ); 878 879 if ( This->dp2->connectionInitialized == NO_PROVIDER ) 880 return DPERR_UNINITIALIZED; 881 882 /* Find the group */ 883 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL ) 884 return DPERR_INVALIDGROUP; 885 886 /* Find the player */ 887 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL ) 888 return DPERR_INVALIDPLAYER; 889 890 /* Create a player list (ie "shortcut" ) */ 891 newplist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *newplist ) ); 892 if ( !newplist ) 893 return DPERR_CANTADDPLAYER; 894 895 /* Add the shortcut */ 896 plist->lpPData->uRef++; 897 newplist->lpPData = plist->lpPData; 898 899 /* Add the player to the list of players for this group */ 900 DPQ_INSERT(gdata->players, newplist, players); 901 902 /* Let the SP know that we've added a player to the group */ 903 if ( This->dp2->spData.lpCB->AddPlayerToGroup ) 904 { 905 DPSP_ADDPLAYERTOGROUPDATA data; 906 907 TRACE( "Calling SP AddPlayerToGroup\n" ); 908 909 data.idPlayer = player; 910 data.idGroup = group; 911 data.lpISP = This->dp2->spData.lpISP; 912 913 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data ); 914 } 915 916 /* Inform all other peers of the addition of player to the group. If there are 917 * no peers keep this event quiet. 918 * Also, if this event was the result of another machine sending it to us, 919 * don't bother rebroadcasting it. 920 */ 921 if ( This->dp2->lpSessionDesc && 922 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) 923 { 924 DPMSG_ADDPLAYERTOGROUP msg; 925 msg.dwType = DPSYS_ADDPLAYERTOGROUP; 926 927 msg.dpIdGroup = group; 928 msg.dpIdPlayer = player; 929 930 /* FIXME: Correct to just use send effectively? */ 931 /* FIXME: Should size include data w/ message or just message "header" */ 932 /* FIXME: Check return code */ 933 IDirectPlayX_SendEx( iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ), 934 0, 0, NULL, NULL ); 935 } 936 937 return DP_OK; 938 } 939 940 static HRESULT WINAPI IDirectPlay2AImpl_Close( IDirectPlay2A *iface ) 941 { 942 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 943 return IDirectPlayX_Close( &This->IDirectPlay4A_iface ); 944 } 945 946 static HRESULT WINAPI IDirectPlay2Impl_Close( IDirectPlay2 *iface ) 947 { 948 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 949 return IDirectPlayX_Close( &This->IDirectPlay4_iface ); 950 } 951 952 static HRESULT WINAPI IDirectPlay3AImpl_Close( IDirectPlay3A *iface ) 953 { 954 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 955 return IDirectPlayX_Close( &This->IDirectPlay4_iface ); 956 } 957 958 static HRESULT WINAPI IDirectPlay3Impl_Close( IDirectPlay3 *iface ) 959 { 960 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 961 return IDirectPlayX_Close( &This->IDirectPlay4_iface ); 962 } 963 964 static HRESULT WINAPI IDirectPlay4AImpl_Close( IDirectPlay4A *iface ) 965 { 966 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 967 return IDirectPlayX_Close( &This->IDirectPlay4_iface); 968 } 969 970 static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface ) 971 { 972 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 973 HRESULT hr = DP_OK; 974 975 TRACE( "(%p)\n", This ); 976 977 /* FIXME: Need to find a new host I assume (how?) */ 978 /* FIXME: Need to destroy all local groups */ 979 /* FIXME: Need to migrate all remotely visible players to the new host */ 980 981 /* Invoke the SP callback to inform of session close */ 982 if( This->dp2->spData.lpCB->CloseEx ) 983 { 984 DPSP_CLOSEDATA data; 985 986 TRACE( "Calling SP CloseEx\n" ); 987 data.lpISP = This->dp2->spData.lpISP; 988 hr = (*This->dp2->spData.lpCB->CloseEx)( &data ); 989 } 990 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */ 991 { 992 TRACE( "Calling SP Close (obsolete interface)\n" ); 993 hr = (*This->dp2->spData.lpCB->Close)(); 994 } 995 996 return hr; 997 } 998 999 static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, const DPNAME *lpName, 1000 DWORD dwFlags, DPID idParent, BOOL bAnsi ) 1001 { 1002 lpGroupData lpGData; 1003 1004 /* Allocate the new space and add to end of high level group list */ 1005 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) ); 1006 1007 if( lpGData == NULL ) 1008 { 1009 return NULL; 1010 } 1011 1012 DPQ_INIT(lpGData->groups); 1013 DPQ_INIT(lpGData->players); 1014 1015 /* Set the desired player ID - no sanity checking to see if it exists */ 1016 lpGData->dpid = *lpid; 1017 1018 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi ); 1019 1020 /* FIXME: Should we check that the parent exists? */ 1021 lpGData->parent = idParent; 1022 1023 /* FIXME: Should we validate the dwFlags? */ 1024 lpGData->dwFlags = dwFlags; 1025 1026 TRACE( "Created group id 0x%08x\n", *lpid ); 1027 1028 return lpGData; 1029 } 1030 1031 /* This method assumes that all links to it are already deleted */ 1032 static void DP_DeleteGroup( IDirectPlayImpl *This, DPID dpid ) 1033 { 1034 lpGroupList lpGList; 1035 1036 TRACE( "(%p)->(0x%08x)\n", This, dpid ); 1037 1038 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList ); 1039 1040 if( lpGList == NULL ) 1041 { 1042 ERR( "DPID 0x%08x not found\n", dpid ); 1043 return; 1044 } 1045 1046 if( --(lpGList->lpGData->uRef) ) 1047 { 1048 FIXME( "Why is this not the last reference to group?\n" ); 1049 DebugBreak(); 1050 } 1051 1052 /* Delete player */ 1053 DP_DeleteDPNameStruct( &lpGList->lpGData->name ); 1054 HeapFree( GetProcessHeap(), 0, lpGList->lpGData ); 1055 1056 /* Remove and Delete Player List object */ 1057 HeapFree( GetProcessHeap(), 0, lpGList ); 1058 1059 } 1060 1061 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid ) 1062 { 1063 lpGroupList lpGroups; 1064 1065 TRACE( "(%p)->(0x%08x)\n", This, dpid ); 1066 1067 if( dpid == DPID_SYSTEM_GROUP ) 1068 { 1069 return This->dp2->lpSysGroup; 1070 } 1071 else 1072 { 1073 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups ); 1074 } 1075 1076 if( lpGroups == NULL ) 1077 { 1078 return NULL; 1079 } 1080 1081 return lpGroups->lpGData; 1082 } 1083 1084 static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup, 1085 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi ) 1086 { 1087 lpGroupData lpGData; 1088 1089 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n", 1090 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize, 1091 dwFlags, bAnsi ); 1092 1093 if( This->dp2->connectionInitialized == NO_PROVIDER ) 1094 { 1095 return DPERR_UNINITIALIZED; 1096 } 1097 1098 /* If the name is not specified, we must provide one */ 1099 if( DPID_UNKNOWN == *lpidGroup ) 1100 { 1101 /* If we are the name server, we decide on the group ids. If not, we 1102 * must ask for one before attempting a creation. 1103 */ 1104 if( This->dp2->bHostInterface ) 1105 { 1106 *lpidGroup = DP_NextObjectId(); 1107 } 1108 else 1109 { 1110 *lpidGroup = DP_GetRemoteNextObjectId(); 1111 } 1112 } 1113 1114 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags, 1115 DPID_NOPARENT_GROUP, bAnsi ); 1116 1117 if( lpGData == NULL ) 1118 { 1119 return DPERR_CANTADDPLAYER; /* yes player not group */ 1120 } 1121 1122 if( DPID_SYSTEM_GROUP == *lpidGroup ) 1123 { 1124 This->dp2->lpSysGroup = lpGData; 1125 TRACE( "Inserting system group\n" ); 1126 } 1127 else 1128 { 1129 /* Insert into the system group */ 1130 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) ); 1131 lpGroup->lpGData = lpGData; 1132 1133 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups ); 1134 } 1135 1136 /* Something is now referencing this data */ 1137 lpGData->uRef++; 1138 1139 /* Set all the important stuff for the group */ 1140 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize ); 1141 1142 /* FIXME: We should only create the system group if GetCaps returns 1143 * DPCAPS_GROUPOPTIMIZED. 1144 */ 1145 1146 /* Let the SP know that we've created this group */ 1147 if( This->dp2->spData.lpCB->CreateGroup ) 1148 { 1149 DPSP_CREATEGROUPDATA data; 1150 DWORD dwCreateFlags = 0; 1151 1152 TRACE( "Calling SP CreateGroup\n" ); 1153 1154 if( *lpidGroup == DPID_NOPARENT_GROUP ) 1155 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP; 1156 1157 if( lpMsgHdr == NULL ) 1158 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL; 1159 1160 if( dwFlags & DPGROUP_HIDDEN ) 1161 dwCreateFlags |= DPLAYI_GROUP_HIDDEN; 1162 1163 data.idGroup = *lpidGroup; 1164 data.dwFlags = dwCreateFlags; 1165 data.lpSPMessageHeader = lpMsgHdr; 1166 data.lpISP = This->dp2->spData.lpISP; 1167 1168 (*This->dp2->spData.lpCB->CreateGroup)( &data ); 1169 } 1170 1171 /* Inform all other peers of the creation of a new group. If there are 1172 * no peers keep this event quiet. 1173 * Also if this message was sent to us, don't rebroadcast. 1174 */ 1175 if( ( lpMsgHdr == NULL ) && 1176 This->dp2->lpSessionDesc && 1177 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) 1178 { 1179 DPMSG_CREATEPLAYERORGROUP msg; 1180 msg.dwType = DPSYS_CREATEPLAYERORGROUP; 1181 1182 msg.dwPlayerType = DPPLAYERTYPE_GROUP; 1183 msg.dpId = *lpidGroup; 1184 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */ 1185 msg.lpData = lpData; 1186 msg.dwDataSize = dwDataSize; 1187 msg.dpnName = *lpGroupName; 1188 msg.dpIdParent = DPID_NOPARENT_GROUP; 1189 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags ); 1190 1191 /* FIXME: Correct to just use send effectively? */ 1192 /* FIXME: Should size include data w/ message or just message "header" */ 1193 /* FIXME: Check return code */ 1194 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, 1195 sizeof( msg ), 0, 0, NULL, NULL ); 1196 } 1197 1198 return DP_OK; 1199 } 1200 1201 static HRESULT WINAPI IDirectPlay2AImpl_CreateGroup( IDirectPlay2A *iface, DPID *lpidGroup, 1202 DPNAME *name, void *data, DWORD size, DWORD flags ) 1203 { 1204 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 1205 return IDirectPlayX_CreateGroup( &This->IDirectPlay4A_iface, lpidGroup, name, data, size, 1206 flags ); 1207 } 1208 1209 static HRESULT WINAPI IDirectPlay2Impl_CreateGroup( IDirectPlay2 *iface, DPID *lpidGroup, 1210 DPNAME *name, void *data, DWORD size, DWORD flags ) 1211 { 1212 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 1213 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size, 1214 flags ); 1215 } 1216 1217 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroup( IDirectPlay3A *iface, DPID *group, 1218 DPNAME *name, void *data, DWORD size, DWORD flags ) 1219 { 1220 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 1221 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, group, name, data, size, 1222 flags ); 1223 } 1224 1225 static HRESULT WINAPI IDirectPlay3Impl_CreateGroup( IDirectPlay3 *iface, DPID *lpidGroup, 1226 DPNAME *name, void *data, DWORD size, DWORD flags ) 1227 { 1228 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 1229 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size, 1230 flags ); 1231 } 1232 1233 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroup( IDirectPlay4A *iface, DPID *lpidGroup, 1234 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags ) 1235 { 1236 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 1237 1238 *lpidGroup = DPID_UNKNOWN; 1239 1240 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags, 1241 TRUE ); 1242 } 1243 1244 static HRESULT WINAPI IDirectPlay4Impl_CreateGroup( IDirectPlay4 *iface, DPID *lpidGroup, 1245 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags ) 1246 { 1247 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 1248 1249 *lpidGroup = DPID_UNKNOWN; 1250 1251 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags, 1252 FALSE ); 1253 } 1254 1255 1256 static void 1257 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags, 1258 LPVOID lpData, DWORD dwDataSize ) 1259 { 1260 /* Clear out the data with this player */ 1261 if( dwFlags & DPSET_LOCAL ) 1262 { 1263 if ( lpGData->dwLocalDataSize != 0 ) 1264 { 1265 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData ); 1266 lpGData->lpLocalData = NULL; 1267 lpGData->dwLocalDataSize = 0; 1268 } 1269 } 1270 else 1271 { 1272 if( lpGData->dwRemoteDataSize != 0 ) 1273 { 1274 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData ); 1275 lpGData->lpRemoteData = NULL; 1276 lpGData->dwRemoteDataSize = 0; 1277 } 1278 } 1279 1280 /* Reallocate for new data */ 1281 if( lpData != NULL ) 1282 { 1283 if( dwFlags & DPSET_LOCAL ) 1284 { 1285 lpGData->lpLocalData = lpData; 1286 lpGData->dwLocalDataSize = dwDataSize; 1287 } 1288 else 1289 { 1290 lpGData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize ); 1291 CopyMemory( lpGData->lpRemoteData, lpData, dwDataSize ); 1292 lpGData->dwRemoteDataSize = dwDataSize; 1293 } 1294 } 1295 1296 } 1297 1298 /* This function will just create the storage for the new player. */ 1299 static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName, 1300 DWORD dwFlags, HANDLE hEvent, BOOL bAnsi ) 1301 { 1302 lpPlayerData lpPData; 1303 1304 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi ); 1305 1306 /* Allocate the storage for the player and associate it with list element */ 1307 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) ); 1308 if( lpPData == NULL ) 1309 { 1310 return NULL; 1311 } 1312 1313 /* Set the desired player ID */ 1314 lpPData->dpid = *lpid; 1315 1316 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi ); 1317 1318 lpPData->dwFlags = dwFlags; 1319 1320 /* If we were given an event handle, duplicate it */ 1321 if( hEvent != 0 ) 1322 { 1323 if( !DuplicateHandle( GetCurrentProcess(), hEvent, 1324 GetCurrentProcess(), &lpPData->hEvent, 1325 0, FALSE, DUPLICATE_SAME_ACCESS ) 1326 ) 1327 { 1328 /* FIXME: Memory leak */ 1329 ERR( "Can't duplicate player msg handle %p\n", hEvent ); 1330 } 1331 } 1332 1333 /* Initialize the SP data section */ 1334 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData(); 1335 1336 TRACE( "Created player id 0x%08x\n", *lpid ); 1337 1338 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER ) 1339 This->dp2->lpSessionDesc->dwCurrentPlayers++; 1340 1341 return lpPData; 1342 } 1343 1344 /* Delete the contents of the DPNAME struct */ 1345 static void 1346 DP_DeleteDPNameStruct( LPDPNAME lpDPName ) 1347 { 1348 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA ); 1349 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA ); 1350 } 1351 1352 /* This method assumes that all links to it are already deleted */ 1353 static void DP_DeletePlayer( IDirectPlayImpl *This, DPID dpid ) 1354 { 1355 lpPlayerList lpPList; 1356 1357 TRACE( "(%p)->(0x%08x)\n", This, dpid ); 1358 1359 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList ); 1360 1361 if( lpPList == NULL ) 1362 { 1363 ERR( "DPID 0x%08x not found\n", dpid ); 1364 return; 1365 } 1366 1367 /* Verify that this is the last reference to the data */ 1368 if( --(lpPList->lpPData->uRef) ) 1369 { 1370 FIXME( "Why is this not the last reference to player?\n" ); 1371 DebugBreak(); 1372 } 1373 1374 /* Delete player */ 1375 DP_DeleteDPNameStruct( &lpPList->lpPData->name ); 1376 1377 CloseHandle( lpPList->lpPData->hEvent ); 1378 HeapFree( GetProcessHeap(), 0, lpPList->lpPData ); 1379 1380 /* Delete Player List object */ 1381 HeapFree( GetProcessHeap(), 0, lpPList ); 1382 } 1383 1384 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid ) 1385 { 1386 lpPlayerList lpPlayers; 1387 1388 TRACE( "(%p)->(0x%08x)\n", This, dpid ); 1389 1390 if(This->dp2->lpSysGroup == NULL) 1391 return NULL; 1392 1393 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers ); 1394 1395 return lpPlayers; 1396 } 1397 1398 /* Basic area for Dst must already be allocated */ 1399 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi ) 1400 { 1401 if( lpSrc == NULL ) 1402 { 1403 ZeroMemory( lpDst, sizeof( *lpDst ) ); 1404 lpDst->dwSize = sizeof( *lpDst ); 1405 return TRUE; 1406 } 1407 1408 if( lpSrc->dwSize != sizeof( *lpSrc) ) 1409 { 1410 return FALSE; 1411 } 1412 1413 /* Delete any existing pointers */ 1414 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA ); 1415 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA ); 1416 1417 /* Copy as required */ 1418 CopyMemory( lpDst, lpSrc, lpSrc->dwSize ); 1419 1420 if( bAnsi ) 1421 { 1422 if( lpSrc->u1.lpszShortNameA ) 1423 { 1424 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0, 1425 strlen(lpSrc->u1.lpszShortNameA)+1 ); 1426 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA ); 1427 } 1428 if( lpSrc->u2.lpszLongNameA ) 1429 { 1430 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0, 1431 strlen(lpSrc->u2.lpszLongNameA)+1 ); 1432 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA ); 1433 } 1434 } 1435 else 1436 { 1437 if( lpSrc->u1.lpszShortNameA ) 1438 { 1439 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0, 1440 (lstrlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) ); 1441 lstrcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName ); 1442 } 1443 if( lpSrc->u2.lpszLongNameA ) 1444 { 1445 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0, 1446 (lstrlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) ); 1447 lstrcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName ); 1448 } 1449 } 1450 1451 return TRUE; 1452 } 1453 1454 static void 1455 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags, 1456 LPVOID lpData, DWORD dwDataSize ) 1457 { 1458 /* Clear out the data with this player */ 1459 if( dwFlags & DPSET_LOCAL ) 1460 { 1461 if ( lpPData->dwLocalDataSize != 0 ) 1462 { 1463 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData ); 1464 lpPData->lpLocalData = NULL; 1465 lpPData->dwLocalDataSize = 0; 1466 } 1467 } 1468 else 1469 { 1470 if( lpPData->dwRemoteDataSize != 0 ) 1471 { 1472 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData ); 1473 lpPData->lpRemoteData = NULL; 1474 lpPData->dwRemoteDataSize = 0; 1475 } 1476 } 1477 1478 /* Reallocate for new data */ 1479 if( lpData != NULL ) 1480 { 1481 1482 if( dwFlags & DPSET_LOCAL ) 1483 { 1484 lpPData->lpLocalData = lpData; 1485 lpPData->dwLocalDataSize = dwDataSize; 1486 } 1487 else 1488 { 1489 lpPData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize ); 1490 CopyMemory( lpPData->lpRemoteData, lpData, dwDataSize ); 1491 lpPData->dwRemoteDataSize = dwDataSize; 1492 } 1493 } 1494 1495 } 1496 1497 /* Note: lpMsgHdr is NULL for local creation, non NULL for remote creation */ 1498 static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidPlayer, 1499 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags, 1500 BOOL bAnsi ) 1501 { 1502 HRESULT hr = DP_OK; 1503 lpPlayerData lpPData; 1504 lpPlayerList lpPList; 1505 DWORD dwCreateFlags = 0; 1506 1507 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n", 1508 This, lpidPlayer, lpPlayerName, hEvent, lpData, 1509 dwDataSize, dwFlags, bAnsi ); 1510 if( This->dp2->connectionInitialized == NO_PROVIDER ) 1511 { 1512 return DPERR_UNINITIALIZED; 1513 } 1514 1515 if( dwFlags == 0 ) 1516 { 1517 dwFlags = DPPLAYER_SPECTATOR; 1518 } 1519 1520 if( lpidPlayer == NULL ) 1521 { 1522 return DPERR_INVALIDPARAMS; 1523 } 1524 1525 1526 /* Determine the creation flags for the player. These will be passed 1527 * to the name server if requesting a player id and to the SP when 1528 * informing it of the player creation 1529 */ 1530 { 1531 if( dwFlags & DPPLAYER_SERVERPLAYER ) 1532 { 1533 if( *lpidPlayer == DPID_SERVERPLAYER ) 1534 { 1535 /* Server player for the host interface */ 1536 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER; 1537 } 1538 else if( *lpidPlayer == DPID_NAME_SERVER ) 1539 { 1540 /* Name server - master of everything */ 1541 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER); 1542 } 1543 else 1544 { 1545 /* Server player for a non host interface */ 1546 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER; 1547 } 1548 } 1549 1550 if( lpMsgHdr == NULL ) 1551 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL; 1552 } 1553 1554 /* Verify we know how to handle all the flags */ 1555 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) || 1556 ( dwFlags & DPPLAYER_SPECTATOR ) 1557 ) 1558 ) 1559 { 1560 /* Assume non fatal failure */ 1561 ERR( "unknown dwFlags = 0x%08x\n", dwFlags ); 1562 } 1563 1564 /* If the name is not specified, we must provide one */ 1565 if( *lpidPlayer == DPID_UNKNOWN ) 1566 { 1567 /* If we are the session master, we dish out the group/player ids */ 1568 if( This->dp2->bHostInterface ) 1569 { 1570 *lpidPlayer = DP_NextObjectId(); 1571 } 1572 else 1573 { 1574 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer ); 1575 1576 if( FAILED(hr) ) 1577 { 1578 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) ); 1579 return hr; 1580 } 1581 } 1582 } 1583 else 1584 { 1585 /* FIXME: Would be nice to perhaps verify that we don't already have 1586 * this player. 1587 */ 1588 } 1589 1590 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current 1591 player total */ 1592 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags, 1593 hEvent, bAnsi ); 1594 /* Create the list object and link it in */ 1595 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) ); 1596 if( !lpPData || !lpPList ) 1597 { 1598 HeapFree( GetProcessHeap(), 0, lpPData ); 1599 HeapFree( GetProcessHeap(), 0, lpPList ); 1600 return DPERR_CANTADDPLAYER; 1601 } 1602 1603 lpPData->uRef = 1; 1604 lpPList->lpPData = lpPData; 1605 1606 /* Add the player to the system group */ 1607 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players ); 1608 1609 /* Update the information and send it to all players in the session */ 1610 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize ); 1611 1612 /* Let the SP know that we've created this player */ 1613 if( This->dp2->spData.lpCB->CreatePlayer ) 1614 { 1615 DPSP_CREATEPLAYERDATA data; 1616 1617 data.idPlayer = *lpidPlayer; 1618 data.dwFlags = dwCreateFlags; 1619 data.lpSPMessageHeader = lpMsgHdr; 1620 data.lpISP = This->dp2->spData.lpISP; 1621 1622 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n", 1623 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader ); 1624 1625 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data ); 1626 } 1627 1628 if( FAILED(hr) ) 1629 { 1630 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) ); 1631 return hr; 1632 } 1633 1634 /* Now let the SP know that this player is a member of the system group */ 1635 if( This->dp2->spData.lpCB->AddPlayerToGroup ) 1636 { 1637 DPSP_ADDPLAYERTOGROUPDATA data; 1638 1639 data.idPlayer = *lpidPlayer; 1640 data.idGroup = DPID_SYSTEM_GROUP; 1641 data.lpISP = This->dp2->spData.lpISP; 1642 1643 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" ); 1644 1645 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data ); 1646 } 1647 1648 if( FAILED(hr) ) 1649 { 1650 ERR( "Failed to add player to sys group with sp: %s\n", 1651 DPLAYX_HresultToString(hr) ); 1652 return hr; 1653 } 1654 1655 #if 1 1656 if( !This->dp2->bHostInterface ) 1657 { 1658 /* Let the name server know about the creation of this player */ 1659 /* FIXME: Is this only to be done for the creation of a server player or 1660 * is this used for regular players? If only for server players, move 1661 * this call to DP_SecureOpen(...); 1662 */ 1663 #if 0 1664 TRACE( "Sending message to self to get my addr\n" ); 1665 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */ 1666 #endif 1667 1668 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer); 1669 } 1670 #else 1671 /* Inform all other peers of the creation of a new player. If there are 1672 * no peers keep this quiet. 1673 * Also, if this was a remote event, no need to rebroadcast it. 1674 */ 1675 if( ( lpMsgHdr == NULL ) && 1676 This->dp2->lpSessionDesc && 1677 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) 1678 { 1679 DPMSG_CREATEPLAYERORGROUP msg; 1680 msg.dwType = DPSYS_CREATEPLAYERORGROUP; 1681 1682 msg.dwPlayerType = DPPLAYERTYPE_PLAYER; 1683 msg.dpId = *lpidPlayer; 1684 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */ 1685 msg.lpData = lpData; 1686 msg.dwDataSize = dwDataSize; 1687 msg.dpnName = *lpPlayerName; 1688 msg.dpIdParent = DPID_NOPARENT_GROUP; 1689 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags ); 1690 1691 /* FIXME: Correct to just use send effectively? */ 1692 /* FIXME: Should size include data w/ message or just message "header" */ 1693 /* FIXME: Check return code */ 1694 hr = IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, 1695 &msg, sizeof( msg ), 0, 0, NULL, NULL ); 1696 } 1697 #endif 1698 1699 return hr; 1700 } 1701 1702 static HRESULT WINAPI IDirectPlay2AImpl_CreatePlayer( IDirectPlay2A *iface, DPID *lpidPlayer, 1703 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags ) 1704 { 1705 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 1706 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4A_iface, lpidPlayer, name, event, data, 1707 size, flags ); 1708 } 1709 1710 static HRESULT WINAPI IDirectPlay2Impl_CreatePlayer( IDirectPlay2 *iface, DPID *lpidPlayer, 1711 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags ) 1712 { 1713 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 1714 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data, 1715 size, flags ); 1716 } 1717 1718 static HRESULT WINAPI IDirectPlay3AImpl_CreatePlayer( IDirectPlay3A *iface, DPID *lpidPlayer, 1719 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags ) 1720 { 1721 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 1722 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data, 1723 size, flags ); 1724 } 1725 1726 static HRESULT WINAPI IDirectPlay3Impl_CreatePlayer( IDirectPlay3 *iface, DPID *lpidPlayer, 1727 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags ) 1728 { 1729 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 1730 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data, 1731 size, flags ); 1732 } 1733 1734 static HRESULT WINAPI IDirectPlay4AImpl_CreatePlayer( IDirectPlay4A *iface, DPID *lpidPlayer, 1735 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags ) 1736 { 1737 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 1738 1739 if( lpidPlayer == NULL ) 1740 { 1741 return DPERR_INVALIDPARAMS; 1742 } 1743 1744 if( dwFlags & DPPLAYER_SERVERPLAYER ) 1745 { 1746 *lpidPlayer = DPID_SERVERPLAYER; 1747 } 1748 else 1749 { 1750 *lpidPlayer = DPID_UNKNOWN; 1751 } 1752 1753 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent, 1754 lpData, dwDataSize, dwFlags, TRUE ); 1755 } 1756 1757 static HRESULT WINAPI IDirectPlay4Impl_CreatePlayer( IDirectPlay4 *iface, DPID *lpidPlayer, 1758 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags ) 1759 { 1760 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 1761 1762 if( lpidPlayer == NULL ) 1763 { 1764 return DPERR_INVALIDPARAMS; 1765 } 1766 1767 if( dwFlags & DPPLAYER_SERVERPLAYER ) 1768 { 1769 *lpidPlayer = DPID_SERVERPLAYER; 1770 } 1771 else 1772 { 1773 *lpidPlayer = DPID_UNKNOWN; 1774 } 1775 1776 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent, 1777 lpData, dwDataSize, dwFlags, FALSE ); 1778 } 1779 1780 static DPID DP_GetRemoteNextObjectId(void) 1781 { 1782 FIXME( ":stub\n" ); 1783 1784 /* Hack solution */ 1785 return DP_NextObjectId(); 1786 } 1787 1788 static HRESULT WINAPI IDirectPlay2AImpl_DeletePlayerFromGroup( IDirectPlay2A *iface, DPID group, 1789 DPID player ) 1790 { 1791 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 1792 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4A_iface, group, player ); 1793 } 1794 1795 static HRESULT WINAPI IDirectPlay2Impl_DeletePlayerFromGroup( IDirectPlay2 *iface, DPID group, 1796 DPID player ) 1797 { 1798 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 1799 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player ); 1800 } 1801 1802 static HRESULT WINAPI IDirectPlay3AImpl_DeletePlayerFromGroup( IDirectPlay3A *iface, DPID group, 1803 DPID player ) 1804 { 1805 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 1806 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player ); 1807 } 1808 1809 static HRESULT WINAPI IDirectPlay3Impl_DeletePlayerFromGroup( IDirectPlay3 *iface, DPID group, 1810 DPID player ) 1811 { 1812 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 1813 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player ); 1814 } 1815 1816 static HRESULT WINAPI IDirectPlay4AImpl_DeletePlayerFromGroup( IDirectPlay4A *iface, DPID group, 1817 DPID player ) 1818 { 1819 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 1820 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player ); 1821 } 1822 1823 static HRESULT WINAPI IDirectPlay4Impl_DeletePlayerFromGroup( IDirectPlay4 *iface, DPID group, 1824 DPID player ) 1825 { 1826 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 1827 HRESULT hr = DP_OK; 1828 1829 lpGroupData gdata; 1830 lpPlayerList plist; 1831 1832 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player ); 1833 1834 /* Find the group */ 1835 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL ) 1836 return DPERR_INVALIDGROUP; 1837 1838 /* Find the player */ 1839 if ( DP_FindPlayer( This, player ) == NULL ) 1840 return DPERR_INVALIDPLAYER; 1841 1842 /* Remove the player shortcut from the group */ 1843 DPQ_REMOVE_ENTRY( gdata->players, players, lpPData->dpid, ==, player, plist ); 1844 1845 if ( !plist ) 1846 return DPERR_INVALIDPLAYER; 1847 1848 /* One less reference */ 1849 plist->lpPData->uRef--; 1850 1851 /* Delete the Player List element */ 1852 HeapFree( GetProcessHeap(), 0, plist ); 1853 1854 /* Inform the SP if they care */ 1855 if ( This->dp2->spData.lpCB->RemovePlayerFromGroup ) 1856 { 1857 DPSP_REMOVEPLAYERFROMGROUPDATA data; 1858 1859 TRACE( "Calling SP RemovePlayerFromGroup\n" ); 1860 data.idPlayer = player; 1861 data.idGroup = group; 1862 data.lpISP = This->dp2->spData.lpISP; 1863 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data ); 1864 } 1865 1866 /* Need to send a DELETEPLAYERFROMGROUP message */ 1867 FIXME( "Need to send a message\n" ); 1868 1869 return hr; 1870 } 1871 1872 typedef struct _DPRGOPContext 1873 { 1874 IDirectPlayImpl *This; 1875 BOOL bAnsi; 1876 DPID idGroup; 1877 } DPRGOPContext, *lpDPRGOPContext; 1878 1879 static BOOL CALLBACK 1880 cbRemoveGroupOrPlayer( 1881 DPID dpId, 1882 DWORD dwPlayerType, 1883 LPCDPNAME lpName, 1884 DWORD dwFlags, 1885 LPVOID lpContext ) 1886 { 1887 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext; 1888 1889 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n", 1890 dpId, dwPlayerType, lpCtxt->idGroup ); 1891 1892 if( dwPlayerType == DPPLAYERTYPE_GROUP ) 1893 { 1894 if ( FAILED( IDirectPlayX_DeleteGroupFromGroup( &lpCtxt->This->IDirectPlay4_iface, 1895 lpCtxt->idGroup, dpId ) ) ) 1896 ERR( "Unable to delete group 0x%08x from group 0x%08x\n", dpId, lpCtxt->idGroup ); 1897 } 1898 else if ( FAILED( IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface, 1899 lpCtxt->idGroup, dpId ) ) ) 1900 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n", dpId, lpCtxt->idGroup ); 1901 1902 return TRUE; /* Continue enumeration */ 1903 } 1904 1905 static HRESULT DP_IF_DestroyGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idGroup, BOOL bAnsi ) 1906 { 1907 lpGroupData lpGData; 1908 DPRGOPContext context; 1909 1910 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n", 1911 This, lpMsgHdr, idGroup, bAnsi ); 1912 1913 /* Find the group */ 1914 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 1915 { 1916 return DPERR_INVALIDPLAYER; /* yes player */ 1917 } 1918 1919 context.This = This; 1920 context.bAnsi = bAnsi; 1921 context.idGroup = idGroup; 1922 1923 /* Remove all players that this group has */ 1924 IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer, 1925 &context, 0 ); 1926 1927 /* Remove all links to groups that this group has since this is dp3 */ 1928 IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer, 1929 (void*)&context, 0 ); 1930 1931 /* Remove this group from the parent group - if it has one */ 1932 if( ( idGroup != DPID_SYSTEM_GROUP ) && ( lpGData->parent != DPID_SYSTEM_GROUP ) ) 1933 IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, lpGData->parent, idGroup ); 1934 1935 /* Now delete this group data and list from the system group */ 1936 DP_DeleteGroup( This, idGroup ); 1937 1938 /* Let the SP know that we've destroyed this group */ 1939 if( This->dp2->spData.lpCB->DeleteGroup ) 1940 { 1941 DPSP_DELETEGROUPDATA data; 1942 1943 FIXME( "data.dwFlags is incorrect\n" ); 1944 1945 data.idGroup = idGroup; 1946 data.dwFlags = 0; 1947 data.lpISP = This->dp2->spData.lpISP; 1948 1949 (*This->dp2->spData.lpCB->DeleteGroup)( &data ); 1950 } 1951 1952 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" ); 1953 1954 return DP_OK; 1955 } 1956 1957 static HRESULT WINAPI IDirectPlay2AImpl_DestroyGroup( IDirectPlay2A *iface, DPID group ) 1958 { 1959 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 1960 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4A_iface, group ); 1961 } 1962 1963 static HRESULT WINAPI IDirectPlay2Impl_DestroyGroup( IDirectPlay2 *iface, DPID group ) 1964 { 1965 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 1966 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group ); 1967 } 1968 1969 static HRESULT WINAPI IDirectPlay3AImpl_DestroyGroup( IDirectPlay3A *iface, DPID group ) 1970 { 1971 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 1972 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group ); 1973 } 1974 1975 static HRESULT WINAPI IDirectPlay3Impl_DestroyGroup( IDirectPlay3 *iface, DPID group ) 1976 { 1977 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 1978 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group ); 1979 } 1980 1981 static HRESULT WINAPI IDirectPlay4AImpl_DestroyGroup( IDirectPlay4A *iface, DPID idGroup ) 1982 { 1983 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 1984 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE ); 1985 } 1986 1987 static HRESULT WINAPI IDirectPlay4Impl_DestroyGroup( IDirectPlay4 *iface, DPID idGroup ) 1988 { 1989 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 1990 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE ); 1991 } 1992 1993 typedef struct _DPFAGContext 1994 { 1995 IDirectPlayImpl *This; 1996 DPID idPlayer; 1997 BOOL bAnsi; 1998 } DPFAGContext, *lpDPFAGContext; 1999 2000 static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID idPlayer, 2001 BOOL bAnsi ) 2002 { 2003 DPFAGContext cbContext; 2004 2005 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n", 2006 This, lpMsgHdr, idPlayer, bAnsi ); 2007 2008 if( This->dp2->connectionInitialized == NO_PROVIDER ) 2009 { 2010 return DPERR_UNINITIALIZED; 2011 } 2012 2013 if( DP_FindPlayer( This, idPlayer ) == NULL ) 2014 { 2015 return DPERR_INVALIDPLAYER; 2016 } 2017 2018 /* FIXME: If the player is remote, we must be the host to delete this */ 2019 2020 cbContext.This = This; 2021 cbContext.idPlayer = idPlayer; 2022 cbContext.bAnsi = bAnsi; 2023 2024 /* Find each group and call DeletePlayerFromGroup if the player is a 2025 member of the group */ 2026 IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, NULL, cbDeletePlayerFromAllGroups, &cbContext, 2027 DPENUMGROUPS_ALL ); 2028 2029 /* Now delete player and player list from the sys group */ 2030 DP_DeletePlayer( This, idPlayer ); 2031 2032 /* Let the SP know that we've destroyed this group */ 2033 if( This->dp2->spData.lpCB->DeletePlayer ) 2034 { 2035 DPSP_DELETEPLAYERDATA data; 2036 2037 FIXME( "data.dwFlags is incorrect\n" ); 2038 2039 data.idPlayer = idPlayer; 2040 data.dwFlags = 0; 2041 data.lpISP = This->dp2->spData.lpISP; 2042 2043 (*This->dp2->spData.lpCB->DeletePlayer)( &data ); 2044 } 2045 2046 FIXME( "Send a DELETEPLAYERORGROUP msg\n" ); 2047 2048 return DP_OK; 2049 } 2050 2051 static BOOL CALLBACK 2052 cbDeletePlayerFromAllGroups( 2053 DPID dpId, 2054 DWORD dwPlayerType, 2055 LPCDPNAME lpName, 2056 DWORD dwFlags, 2057 LPVOID lpContext ) 2058 { 2059 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext; 2060 2061 if( dwPlayerType == DPPLAYERTYPE_GROUP ) 2062 { 2063 IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, lpCtxt->idPlayer ); 2064 2065 /* Enumerate all groups in this group since this will normally only 2066 * be called for top level groups 2067 */ 2068 IDirectPlayX_EnumGroupsInGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, NULL, 2069 cbDeletePlayerFromAllGroups, lpContext, DPENUMGROUPS_ALL); 2070 2071 } 2072 else 2073 { 2074 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType ); 2075 } 2076 2077 return TRUE; 2078 } 2079 2080 static HRESULT WINAPI IDirectPlay2AImpl_DestroyPlayer( IDirectPlay2A *iface, DPID player ) 2081 { 2082 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2083 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4A_iface, player ); 2084 } 2085 2086 static HRESULT WINAPI IDirectPlay2Impl_DestroyPlayer( IDirectPlay2 *iface, DPID player ) 2087 { 2088 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2089 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player ); 2090 } 2091 2092 static HRESULT WINAPI IDirectPlay3AImpl_DestroyPlayer( IDirectPlay3A *iface, DPID player ) 2093 { 2094 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2095 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player ); 2096 } 2097 2098 static HRESULT WINAPI IDirectPlay3Impl_DestroyPlayer( IDirectPlay3 *iface, DPID player ) 2099 { 2100 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2101 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player ); 2102 } 2103 2104 static HRESULT WINAPI IDirectPlay4AImpl_DestroyPlayer( IDirectPlay4A *iface, DPID idPlayer ) 2105 { 2106 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 2107 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE ); 2108 } 2109 2110 static HRESULT WINAPI IDirectPlay4Impl_DestroyPlayer( IDirectPlay4 *iface, DPID idPlayer ) 2111 { 2112 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 2113 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE ); 2114 } 2115 2116 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroupPlayers( IDirectPlay2A *iface, DPID group, 2117 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2118 { 2119 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2120 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4A_iface, group, instance, 2121 enumplayercb, context, flags ); 2122 } 2123 2124 static HRESULT WINAPI IDirectPlay2Impl_EnumGroupPlayers( IDirectPlay2 *iface, DPID group, 2125 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2126 { 2127 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2128 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, 2129 enumplayercb, context, flags ); 2130 } 2131 2132 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupPlayers( IDirectPlay3A *iface, DPID group, 2133 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2134 { 2135 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2136 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, 2137 enumplayercb, context, flags ); 2138 } 2139 2140 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupPlayers( IDirectPlay3 *iface, DPID group, 2141 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2142 { 2143 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2144 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, 2145 enumplayercb, context, flags ); 2146 } 2147 2148 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupPlayers( IDirectPlay4A *iface, DPID group, 2149 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2150 { 2151 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 2152 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, enumplayercb, 2153 context, flags ); 2154 } 2155 2156 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupPlayers( IDirectPlay4 *iface, DPID group, 2157 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2158 { 2159 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 2160 lpGroupData gdata; 2161 lpPlayerList plist; 2162 2163 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb, 2164 context, flags ); 2165 2166 if ( This->dp2->connectionInitialized == NO_PROVIDER ) 2167 return DPERR_UNINITIALIZED; 2168 2169 /* Find the group */ 2170 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL ) 2171 return DPERR_INVALIDGROUP; 2172 2173 if ( DPQ_IS_EMPTY( gdata->players ) ) 2174 return DP_OK; 2175 2176 /* Walk the players in this group */ 2177 for( plist = DPQ_FIRST( gdata->players ); ; plist = DPQ_NEXT( plist->players ) ) 2178 { 2179 /* We do not enum the name server or app server as they are of no 2180 * consequence to the end user. 2181 */ 2182 if ( ( plist->lpPData->dpid != DPID_NAME_SERVER ) && 2183 ( plist->lpPData->dpid != DPID_SERVERPLAYER ) ) 2184 { 2185 /* FIXME: Need to add stuff for flags checking */ 2186 if ( !enumplayercb( plist->lpPData->dpid, DPPLAYERTYPE_PLAYER, 2187 &plist->lpPData->name, plist->lpPData->dwFlags, context ) ) 2188 /* User requested break */ 2189 return DP_OK; 2190 } 2191 2192 if ( DPQ_IS_ENDOFLIST( plist->players ) ) 2193 break; 2194 } 2195 return DP_OK; 2196 } 2197 2198 /* NOTE: This only enumerates top level groups (created with CreateGroup) */ 2199 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroups( IDirectPlay2A *iface, GUID *instance, 2200 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2201 { 2202 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2203 return IDirectPlayX_EnumGroups( &This->IDirectPlay4A_iface, instance, enumplayercb, context, 2204 flags ); 2205 } 2206 2207 static HRESULT WINAPI IDirectPlay2Impl_EnumGroups( IDirectPlay2 *iface, GUID *instance, 2208 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2209 { 2210 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2211 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context, 2212 flags ); 2213 } 2214 2215 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroups( IDirectPlay3A *iface, GUID *instance, 2216 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2217 { 2218 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2219 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context, 2220 flags ); 2221 } 2222 2223 static HRESULT WINAPI IDirectPlay3Impl_EnumGroups( IDirectPlay3 *iface, GUID *instance, 2224 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2225 { 2226 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2227 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context, 2228 flags ); 2229 } 2230 2231 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroups( IDirectPlay4A *iface, GUID *instance, 2232 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2233 { 2234 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb, 2235 context, flags ); 2236 } 2237 2238 static HRESULT WINAPI IDirectPlay4Impl_EnumGroups ( IDirectPlay4 *iface, GUID *instance, 2239 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2240 { 2241 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb, 2242 context, flags ); 2243 } 2244 2245 static HRESULT WINAPI IDirectPlay2AImpl_EnumPlayers( IDirectPlay2A *iface, GUID *instance, 2246 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2247 { 2248 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2249 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4A_iface, instance, enumplayercb, context, 2250 flags ); 2251 } 2252 2253 static HRESULT WINAPI IDirectPlay2Impl_EnumPlayers( IDirectPlay2 *iface, GUID *instance, 2254 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2255 { 2256 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2257 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context, 2258 flags ); 2259 } 2260 2261 static HRESULT WINAPI IDirectPlay3AImpl_EnumPlayers( IDirectPlay3A *iface, GUID *instance, 2262 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2263 { 2264 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2265 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context, 2266 flags ); 2267 } 2268 2269 static HRESULT WINAPI IDirectPlay3Impl_EnumPlayers( IDirectPlay3 *iface, GUID *instance, 2270 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2271 { 2272 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2273 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context, 2274 flags ); 2275 } 2276 2277 static HRESULT WINAPI IDirectPlay4AImpl_EnumPlayers( IDirectPlay4A *iface, GUID *instance, 2278 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2279 { 2280 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb, 2281 context, flags ); 2282 } 2283 2284 static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *instance, 2285 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 2286 { 2287 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb, 2288 context, flags ); 2289 } 2290 2291 /* This function should call the registered callback function that the user 2292 passed into EnumSessions for each entry available. 2293 */ 2294 static void DP_InvokeEnumSessionCallbacks 2295 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2, 2296 LPVOID lpNSInfo, 2297 DWORD dwTimeout, 2298 LPVOID lpContext ) 2299 { 2300 LPDPSESSIONDESC2 lpSessionDesc; 2301 2302 FIXME( ": not checking for conditions\n" ); 2303 2304 /* Not sure if this should be pruning but it's convenient */ 2305 NS_PruneSessionCache( lpNSInfo ); 2306 2307 NS_ResetSessionEnumeration( lpNSInfo ); 2308 2309 /* Enumerate all sessions */ 2310 /* FIXME: Need to indicate ANSI */ 2311 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL ) 2312 { 2313 TRACE( "EnumSessionsCallback2 invoked\n" ); 2314 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) ) 2315 { 2316 return; 2317 } 2318 } 2319 2320 /* Invoke one last time to indicate that there is no more to come */ 2321 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext ); 2322 } 2323 2324 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext ) 2325 { 2326 EnumSessionAsyncCallbackData* data = lpContext; 2327 HANDLE hSuicideRequest = data->hSuicideRequest; 2328 DWORD dwTimeout = data->dwTimeout; 2329 2330 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout ); 2331 2332 for( ;; ) 2333 { 2334 HRESULT hr; 2335 2336 /* Sleep up to dwTimeout waiting for request to terminate thread */ 2337 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 ) 2338 { 2339 TRACE( "Thread terminating on terminate request\n" ); 2340 break; 2341 } 2342 2343 /* Now resend the enum request */ 2344 hr = NS_SendSessionRequestBroadcast( &data->requestGuid, 2345 data->dwEnumSessionFlags, 2346 data->lpSpData ); 2347 2348 if( FAILED(hr) ) 2349 { 2350 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) ); 2351 /* FIXME: Should we kill this thread? How to inform the main thread? */ 2352 } 2353 2354 } 2355 2356 TRACE( "Thread terminating\n" ); 2357 2358 /* Clean up the thread data */ 2359 CloseHandle( hSuicideRequest ); 2360 HeapFree( GetProcessHeap(), 0, lpContext ); 2361 2362 /* FIXME: Need to have some notification to main app thread that this is 2363 * dead. It would serve two purposes. 1) allow sync on termination 2364 * so that we don't actually send something to ourselves when we 2365 * become name server (race condition) and 2) so that if we die 2366 * abnormally something else will be able to tell. 2367 */ 2368 2369 return 1; 2370 } 2371 2372 static void DP_KillEnumSessionThread( IDirectPlayImpl *This ) 2373 { 2374 /* Does a thread exist? If so we were doing an async enum session */ 2375 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE ) 2376 { 2377 TRACE( "Killing EnumSession thread %p\n", 2378 This->dp2->hEnumSessionThread ); 2379 2380 /* Request that the thread kill itself nicely */ 2381 SetEvent( This->dp2->hKillEnumSessionThreadEvent ); 2382 CloseHandle( This->dp2->hKillEnumSessionThreadEvent ); 2383 2384 /* We no longer need to know about the thread */ 2385 CloseHandle( This->dp2->hEnumSessionThread ); 2386 2387 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE; 2388 } 2389 } 2390 2391 static HRESULT WINAPI IDirectPlay2AImpl_EnumSessions( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc, 2392 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags ) 2393 { 2394 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2395 return IDirectPlayX_EnumSessions( &This->IDirectPlay4A_iface, sdesc, timeout, enumsessioncb, 2396 context, flags ); 2397 } 2398 2399 static HRESULT WINAPI IDirectPlay2Impl_EnumSessions( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc, 2400 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags ) 2401 { 2402 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2403 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb, 2404 context, flags ); 2405 } 2406 2407 static HRESULT WINAPI IDirectPlay3AImpl_EnumSessions( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc, 2408 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags ) 2409 { 2410 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2411 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb, 2412 context, flags ); 2413 } 2414 2415 static HRESULT WINAPI IDirectPlay3Impl_EnumSessions( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc, 2416 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags ) 2417 { 2418 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2419 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb, 2420 context, flags ); 2421 } 2422 2423 static HRESULT WINAPI IDirectPlay4AImpl_EnumSessions( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc, 2424 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags ) 2425 { 2426 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 2427 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb, 2428 context, flags ); 2429 } 2430 2431 static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc, 2432 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags ) 2433 { 2434 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 2435 void *connection; 2436 DWORD size; 2437 HRESULT hr = DP_OK; 2438 2439 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x)\n", This, sdesc, timeout, enumsessioncb, 2440 context, flags ); 2441 2442 if ( This->dp2->connectionInitialized == NO_PROVIDER ) 2443 return DPERR_UNINITIALIZED; 2444 2445 /* Can't enumerate if the interface is already open */ 2446 if ( This->dp2->bConnectionOpen ) 2447 return DPERR_GENERIC; 2448 2449 /* The loading of a lobby provider _seems_ to require a backdoor loading 2450 * of the service provider to also associate with this DP object. This is 2451 * because the app doesn't seem to have to call EnumConnections and 2452 * InitializeConnection for the SP before calling this method. As such 2453 * we'll do their dirty work for them with a quick hack so as to always 2454 * load the TCP/IP service provider. 2455 * 2456 * The correct solution would seem to involve creating a dialog box which 2457 * contains the possible SPs. These dialog boxes most likely follow SDK 2458 * examples. 2459 */ 2460 if ( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized ) 2461 { 2462 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" ); 2463 2464 if ( !DP_BuildSPCompoundAddr( (GUID*)&DPSPGUID_TCPIP, &connection, &size ) ) 2465 { 2466 ERR( "Can't build compound addr\n" ); 2467 return DPERR_GENERIC; 2468 } 2469 2470 hr = IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, 0 ); 2471 if ( FAILED(hr) ) 2472 return hr; 2473 2474 HeapFree( GetProcessHeap(), 0, connection ); 2475 This->dp2->bSPInitialized = TRUE; 2476 } 2477 2478 2479 /* Use the service provider default? */ 2480 if ( !timeout ) 2481 { 2482 DPCAPS caps; 2483 caps.dwSize = sizeof( caps ); 2484 2485 IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 ); 2486 timeout = caps.dwTimeout; 2487 if ( !timeout ) 2488 timeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */ 2489 } 2490 2491 if ( flags & DPENUMSESSIONS_STOPASYNC ) 2492 { 2493 DP_KillEnumSessionThread( This ); 2494 return hr; 2495 } 2496 2497 if ( flags & DPENUMSESSIONS_ASYNC ) 2498 { 2499 /* Enumerate everything presently in the local session cache */ 2500 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout, 2501 context ); 2502 2503 if ( This->dp2->dwEnumSessionLock ) 2504 return DPERR_CONNECTING; 2505 2506 /* See if we've already created a thread to service this interface */ 2507 if ( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE ) 2508 { 2509 DWORD tid; 2510 This->dp2->dwEnumSessionLock++; 2511 2512 /* Send the first enum request inline since the user may cancel a dialog 2513 * if one is presented. Also, may also have a connecting return code. 2514 */ 2515 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, 2516 &This->dp2->spData ); 2517 2518 if ( SUCCEEDED(hr) ) 2519 { 2520 EnumSessionAsyncCallbackData* data = HeapAlloc( GetProcessHeap(), 2521 HEAP_ZERO_MEMORY, sizeof( *data ) ); 2522 /* FIXME: need to kill the thread on object deletion */ 2523 data->lpSpData = &This->dp2->spData; 2524 data->requestGuid = sdesc->guidApplication; 2525 data->dwEnumSessionFlags = flags; 2526 data->dwTimeout = timeout; 2527 2528 This->dp2->hKillEnumSessionThreadEvent = CreateEventW( NULL, TRUE, FALSE, NULL ); 2529 if ( !DuplicateHandle( GetCurrentProcess(), This->dp2->hKillEnumSessionThreadEvent, 2530 GetCurrentProcess(), &data->hSuicideRequest, 0, FALSE, 2531 DUPLICATE_SAME_ACCESS ) ) 2532 ERR( "Can't duplicate thread killing handle\n" ); 2533 2534 TRACE( ": creating EnumSessionsRequest thread\n" ); 2535 This->dp2->hEnumSessionThread = CreateThread( NULL, 0, 2536 DP_EnumSessionsSendAsyncRequestThread, data, 0, &tid ); 2537 } 2538 This->dp2->dwEnumSessionLock--; 2539 } 2540 } 2541 else 2542 { 2543 /* Invalidate the session cache for the interface */ 2544 NS_InvalidateSessionCache( This->dp2->lpNameServerData ); 2545 /* Send the broadcast for session enumeration */ 2546 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData ); 2547 SleepEx( timeout, FALSE ); 2548 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout, 2549 context ); 2550 } 2551 2552 return hr; 2553 } 2554 2555 static HRESULT WINAPI IDirectPlay2AImpl_GetCaps( IDirectPlay2A *iface, DPCAPS *caps, DWORD flags ) 2556 { 2557 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2558 return IDirectPlayX_GetCaps( &This->IDirectPlay4A_iface, caps, flags ); 2559 } 2560 2561 static HRESULT WINAPI IDirectPlay2Impl_GetCaps( IDirectPlay2 *iface, DPCAPS *caps, DWORD flags ) 2562 { 2563 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2564 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags ); 2565 } 2566 2567 static HRESULT WINAPI IDirectPlay3AImpl_GetCaps( IDirectPlay3A *iface, DPCAPS *caps, DWORD flags ) 2568 { 2569 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2570 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags ); 2571 } 2572 2573 static HRESULT WINAPI IDirectPlay3Impl_GetCaps( IDirectPlay3 *iface, DPCAPS *caps, DWORD flags ) 2574 { 2575 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2576 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags ); 2577 } 2578 2579 static HRESULT WINAPI IDirectPlay4AImpl_GetCaps( IDirectPlay4A *iface, DPCAPS *caps, DWORD flags ) 2580 { 2581 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags ); 2582 } 2583 2584 static HRESULT WINAPI IDirectPlay4Impl_GetCaps( IDirectPlay4 *iface, DPCAPS *caps, DWORD flags ) 2585 { 2586 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags ); 2587 } 2588 2589 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupData( IDirectPlay2A *iface, DPID group, void *data, 2590 DWORD *size, DWORD flags ) 2591 { 2592 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2593 return IDirectPlayX_GetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags ); 2594 } 2595 2596 static HRESULT WINAPI IDirectPlay2Impl_GetGroupData( IDirectPlay2 *iface, DPID group, void *data, 2597 DWORD *size, DWORD flags ) 2598 { 2599 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2600 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags ); 2601 } 2602 2603 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupData( IDirectPlay3A *iface, DPID group, void *data, 2604 DWORD *size, DWORD flags ) 2605 { 2606 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2607 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags ); 2608 } 2609 2610 static HRESULT WINAPI IDirectPlay3Impl_GetGroupData( IDirectPlay3 *iface, DPID group, void *data, 2611 DWORD *size, DWORD flags ) 2612 { 2613 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2614 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags ); 2615 } 2616 2617 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupData( IDirectPlay4A *iface, DPID group, 2618 void *data, DWORD *size, DWORD flags ) 2619 { 2620 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 2621 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags ); 2622 } 2623 2624 static HRESULT WINAPI IDirectPlay4Impl_GetGroupData( IDirectPlay4 *iface, DPID group, 2625 void *data, DWORD *size, DWORD flags ) 2626 { 2627 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 2628 lpGroupData gdata; 2629 DWORD bufsize; 2630 void *src; 2631 2632 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, group, data, size, flags ); 2633 2634 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL ) 2635 return DPERR_INVALIDGROUP; 2636 2637 /* How much buffer is required? */ 2638 if ( flags & DPSET_LOCAL ) 2639 { 2640 bufsize = gdata->dwLocalDataSize; 2641 src = gdata->lpLocalData; 2642 } 2643 else 2644 { 2645 bufsize = gdata->dwRemoteDataSize; 2646 src = gdata->lpRemoteData; 2647 } 2648 2649 /* Is the user requesting to know how big a buffer is required? */ 2650 if ( !data || *size < bufsize ) 2651 { 2652 *size = bufsize; 2653 return DPERR_BUFFERTOOSMALL; 2654 } 2655 2656 CopyMemory( data, src, bufsize ); 2657 2658 return DP_OK; 2659 } 2660 2661 static HRESULT DP_IF_GetGroupName( IDirectPlayImpl *This, DPID idGroup, void *lpData, 2662 DWORD *lpdwDataSize, BOOL bAnsi ) 2663 { 2664 lpGroupData lpGData; 2665 LPDPNAME lpName = lpData; 2666 DWORD dwRequiredDataSize; 2667 2668 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n", 2669 This, idGroup, lpData, lpdwDataSize, bAnsi ); 2670 2671 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 2672 { 2673 return DPERR_INVALIDGROUP; 2674 } 2675 2676 dwRequiredDataSize = lpGData->name.dwSize; 2677 2678 if( lpGData->name.u1.lpszShortNameA ) 2679 { 2680 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1; 2681 } 2682 2683 if( lpGData->name.u2.lpszLongNameA ) 2684 { 2685 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1; 2686 } 2687 2688 if( ( lpData == NULL ) || 2689 ( *lpdwDataSize < dwRequiredDataSize ) 2690 ) 2691 { 2692 *lpdwDataSize = dwRequiredDataSize; 2693 return DPERR_BUFFERTOOSMALL; 2694 } 2695 2696 /* Copy the structure */ 2697 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize ); 2698 2699 if( lpGData->name.u1.lpszShortNameA ) 2700 { 2701 strcpy( ((char*)lpName)+lpGData->name.dwSize, 2702 lpGData->name.u1.lpszShortNameA ); 2703 } 2704 else 2705 { 2706 lpName->u1.lpszShortNameA = NULL; 2707 } 2708 2709 if( lpGData->name.u1.lpszShortNameA ) 2710 { 2711 strcpy( ((char*)lpName)+lpGData->name.dwSize, 2712 lpGData->name.u2.lpszLongNameA ); 2713 } 2714 else 2715 { 2716 lpName->u2.lpszLongNameA = NULL; 2717 } 2718 2719 return DP_OK; 2720 } 2721 2722 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupName( IDirectPlay2A *iface, DPID group, void *data, 2723 DWORD *size ) 2724 { 2725 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2726 return IDirectPlayX_GetGroupName( &This->IDirectPlay4A_iface, group, data, size ); 2727 } 2728 2729 static HRESULT WINAPI IDirectPlay2Impl_GetGroupName( IDirectPlay2 *iface, DPID group, void *data, 2730 DWORD *size ) 2731 { 2732 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2733 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size ); 2734 } 2735 2736 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupName( IDirectPlay3A *iface, DPID group, void *data, 2737 DWORD *size ) 2738 { 2739 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2740 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size ); 2741 } 2742 2743 static HRESULT WINAPI IDirectPlay3Impl_GetGroupName( IDirectPlay3 *iface, DPID group, void *data, 2744 DWORD *size ) 2745 { 2746 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2747 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size ); 2748 } 2749 2750 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupName( IDirectPlay4A *iface, DPID idGroup, 2751 void *lpData, DWORD *lpdwDataSize ) 2752 { 2753 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 2754 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE ); 2755 } 2756 2757 static HRESULT WINAPI IDirectPlay4Impl_GetGroupName( IDirectPlay4 *iface, DPID idGroup, 2758 void *lpData, DWORD *lpdwDataSize ) 2759 { 2760 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 2761 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE ); 2762 } 2763 2764 static HRESULT WINAPI IDirectPlay2AImpl_GetMessageCount( IDirectPlay2A *iface, DPID player, 2765 DWORD *count ) 2766 { 2767 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2768 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4A_iface, player, count ); 2769 } 2770 2771 static HRESULT WINAPI IDirectPlay2Impl_GetMessageCount( IDirectPlay2 *iface, DPID player, 2772 DWORD *count ) 2773 { 2774 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2775 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count ); 2776 } 2777 2778 static HRESULT WINAPI IDirectPlay3AImpl_GetMessageCount( IDirectPlay3A *iface, DPID player, 2779 DWORD *count ) 2780 { 2781 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2782 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count ); 2783 } 2784 2785 static HRESULT WINAPI IDirectPlay3Impl_GetMessageCount( IDirectPlay3 *iface, DPID player, 2786 DWORD *count ) 2787 { 2788 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2789 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count ); 2790 } 2791 2792 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageCount( IDirectPlay4A *iface, DPID player, 2793 DWORD *count ) 2794 { 2795 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL ); 2796 } 2797 2798 static HRESULT WINAPI IDirectPlay4Impl_GetMessageCount( IDirectPlay4 *iface, DPID player, 2799 DWORD *count ) 2800 { 2801 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL ); 2802 } 2803 2804 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerAddress( IDirectPlay2A *iface, DPID player, 2805 void *data, DWORD *size ) 2806 { 2807 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2808 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4A_iface, player, data, size ); 2809 } 2810 2811 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerAddress( IDirectPlay2 *iface, DPID player, 2812 void *data, DWORD *size ) 2813 { 2814 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2815 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size ); 2816 } 2817 2818 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAddress( IDirectPlay3A *iface, DPID player, 2819 void *data, DWORD *size ) 2820 { 2821 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2822 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size ); 2823 } 2824 2825 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAddress( IDirectPlay3 *iface, DPID player, 2826 void *data, DWORD *size ) 2827 { 2828 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2829 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size ); 2830 } 2831 2832 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAddress( IDirectPlay4A *iface, DPID player, 2833 void *data, DWORD *size ) 2834 { 2835 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 2836 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size ); 2837 return DP_OK; 2838 } 2839 2840 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAddress( IDirectPlay4 *iface, DPID player, 2841 void *data, DWORD *size ) 2842 { 2843 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 2844 FIXME( "(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size ); 2845 return DP_OK; 2846 } 2847 2848 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerCaps( IDirectPlay2A *iface, DPID player, 2849 DPCAPS *caps, DWORD flags ) 2850 { 2851 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2852 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4A_iface, player, caps, flags ); 2853 } 2854 2855 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerCaps( IDirectPlay2 *iface, DPID player, 2856 DPCAPS *caps, DWORD flags ) 2857 { 2858 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2859 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags ); 2860 } 2861 2862 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerCaps( IDirectPlay3A *iface, DPID player, 2863 DPCAPS *caps, DWORD flags ) 2864 { 2865 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2866 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags ); 2867 } 2868 2869 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerCaps( IDirectPlay3 *iface, DPID player, 2870 DPCAPS *caps, DWORD flags ) 2871 { 2872 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2873 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags ); 2874 } 2875 2876 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerCaps( IDirectPlay4A *iface, DPID player, 2877 DPCAPS *caps, DWORD flags ) 2878 { 2879 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 2880 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags ); 2881 } 2882 2883 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerCaps( IDirectPlay4 *iface, DPID player, 2884 DPCAPS *caps, DWORD flags ) 2885 { 2886 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 2887 DPSP_GETCAPSDATA data; 2888 2889 TRACE( "(%p)->(0x%08x,%p,0x%08x)\n", This, player, caps, flags); 2890 2891 if ( !caps ) 2892 return DPERR_INVALIDPARAMS; 2893 2894 if ( This->dp2->connectionInitialized == NO_PROVIDER ) 2895 return DPERR_UNINITIALIZED; 2896 2897 if( caps->dwSize != sizeof(DPCAPS) ) 2898 return DPERR_INVALIDPARAMS; 2899 2900 /* Query the service provider */ 2901 data.idPlayer = player; 2902 data.dwFlags = flags; 2903 data.lpCaps = caps; 2904 data.lpISP = This->dp2->spData.lpISP; 2905 2906 return (*This->dp2->spData.lpCB->GetCaps)( &data ); 2907 } 2908 2909 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerData( IDirectPlay2A *iface, DPID player, 2910 void *data, DWORD *size, DWORD flags ) 2911 { 2912 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 2913 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags ); 2914 } 2915 2916 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerData( IDirectPlay2 *iface, DPID player, 2917 void *data, DWORD *size, DWORD flags ) 2918 { 2919 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 2920 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags ); 2921 } 2922 2923 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerData( IDirectPlay3A *iface, DPID player, 2924 void *data, DWORD *size, DWORD flags ) 2925 { 2926 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 2927 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags ); 2928 } 2929 2930 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerData( IDirectPlay3 *iface, DPID player, 2931 void *data, DWORD *size, DWORD flags ) 2932 { 2933 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 2934 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags ); 2935 } 2936 2937 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerData( IDirectPlay4A *iface, DPID player, 2938 void *data, DWORD *size, DWORD flags ) 2939 { 2940 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 2941 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags ); 2942 } 2943 2944 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID player, 2945 void *data, DWORD *size, DWORD flags ) 2946 { 2947 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 2948 lpPlayerList plist; 2949 DWORD bufsize; 2950 void *src; 2951 2952 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, player, data, size, flags ); 2953 2954 if ( This->dp2->connectionInitialized == NO_PROVIDER ) 2955 return DPERR_UNINITIALIZED; 2956 2957 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL ) 2958 return DPERR_INVALIDPLAYER; 2959 2960 if ( flags & DPSET_LOCAL ) 2961 { 2962 bufsize = plist->lpPData->dwLocalDataSize; 2963 src = plist->lpPData->lpLocalData; 2964 } 2965 else 2966 { 2967 bufsize = plist->lpPData->dwRemoteDataSize; 2968 src = plist->lpPData->lpRemoteData; 2969 } 2970 2971 /* Is the user requesting to know how big a buffer is required? */ 2972 if ( !data || *size < bufsize ) 2973 { 2974 *size = bufsize; 2975 return DPERR_BUFFERTOOSMALL; 2976 } 2977 2978 CopyMemory( data, src, bufsize ); 2979 2980 return DP_OK; 2981 } 2982 2983 static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void *lpData, 2984 DWORD *lpdwDataSize, BOOL bAnsi ) 2985 { 2986 lpPlayerList lpPList; 2987 LPDPNAME lpName = lpData; 2988 DWORD dwRequiredDataSize; 2989 2990 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n", 2991 This, idPlayer, lpData, lpdwDataSize, bAnsi ); 2992 2993 if( This->dp2->connectionInitialized == NO_PROVIDER ) 2994 { 2995 return DPERR_UNINITIALIZED; 2996 } 2997 2998 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL ) 2999 { 3000 return DPERR_INVALIDPLAYER; 3001 } 3002 3003 dwRequiredDataSize = lpPList->lpPData->name.dwSize; 3004 3005 if( lpPList->lpPData->name.u1.lpszShortNameA ) 3006 { 3007 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1; 3008 } 3009 3010 if( lpPList->lpPData->name.u2.lpszLongNameA ) 3011 { 3012 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1; 3013 } 3014 3015 if( ( lpData == NULL ) || 3016 ( *lpdwDataSize < dwRequiredDataSize ) 3017 ) 3018 { 3019 *lpdwDataSize = dwRequiredDataSize; 3020 return DPERR_BUFFERTOOSMALL; 3021 } 3022 3023 /* Copy the structure */ 3024 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize ); 3025 3026 if( lpPList->lpPData->name.u1.lpszShortNameA ) 3027 { 3028 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize, 3029 lpPList->lpPData->name.u1.lpszShortNameA ); 3030 } 3031 else 3032 { 3033 lpName->u1.lpszShortNameA = NULL; 3034 } 3035 3036 if( lpPList->lpPData->name.u1.lpszShortNameA ) 3037 { 3038 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize, 3039 lpPList->lpPData->name.u2.lpszLongNameA ); 3040 } 3041 else 3042 { 3043 lpName->u2.lpszLongNameA = NULL; 3044 } 3045 3046 return DP_OK; 3047 } 3048 3049 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerName( IDirectPlay2A *iface, DPID player, 3050 void *data, DWORD *size ) 3051 { 3052 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3053 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4A_iface, player, data, size ); 3054 } 3055 3056 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerName( IDirectPlay2 *iface, DPID player, 3057 void *data, DWORD *size ) 3058 { 3059 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3060 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size ); 3061 } 3062 3063 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerName( IDirectPlay3A *iface, DPID player, 3064 void *data, DWORD *size ) 3065 { 3066 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3067 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size ); 3068 } 3069 3070 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerName( IDirectPlay3 *iface, DPID player, 3071 void *data, DWORD *size ) 3072 { 3073 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3074 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size ); 3075 } 3076 3077 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerName( IDirectPlay4A *iface, DPID idPlayer, 3078 void *lpData, DWORD *lpdwDataSize ) 3079 { 3080 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 3081 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE ); 3082 } 3083 3084 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerName( IDirectPlay4 *iface, DPID idPlayer, 3085 void *lpData, DWORD *lpdwDataSize ) 3086 { 3087 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 3088 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE ); 3089 } 3090 3091 static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lpdwDataSize, 3092 BOOL bAnsi ) 3093 { 3094 DWORD dwRequiredSize; 3095 3096 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi ); 3097 3098 if( This->dp2->connectionInitialized == NO_PROVIDER ) 3099 { 3100 return DPERR_UNINITIALIZED; 3101 } 3102 3103 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) ) 3104 { 3105 return DPERR_INVALIDPARAMS; 3106 } 3107 3108 /* FIXME: Get from This->dp2->lpSessionDesc */ 3109 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi ); 3110 3111 if ( ( lpData == NULL ) || 3112 ( *lpdwDataSize < dwRequiredSize ) 3113 ) 3114 { 3115 *lpdwDataSize = dwRequiredSize; 3116 return DPERR_BUFFERTOOSMALL; 3117 } 3118 3119 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi ); 3120 3121 return DP_OK; 3122 } 3123 3124 static HRESULT WINAPI IDirectPlay2AImpl_GetSessionDesc( IDirectPlay2A *iface, void *data, 3125 DWORD *size ) 3126 { 3127 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3128 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4A_iface, data, size ); 3129 } 3130 3131 static HRESULT WINAPI IDirectPlay2Impl_GetSessionDesc( IDirectPlay2 *iface, void *data, 3132 DWORD *size ) 3133 { 3134 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3135 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size ); 3136 } 3137 3138 static HRESULT WINAPI IDirectPlay3AImpl_GetSessionDesc( IDirectPlay3A *iface, void *data, 3139 DWORD *size ) 3140 { 3141 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3142 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size ); 3143 } 3144 3145 static HRESULT WINAPI IDirectPlay3Impl_GetSessionDesc( IDirectPlay3 *iface, void *data, 3146 DWORD *size ) 3147 { 3148 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3149 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size ); 3150 } 3151 3152 static HRESULT WINAPI IDirectPlay4AImpl_GetSessionDesc( IDirectPlay4A *iface, void *lpData, 3153 DWORD *lpdwDataSize ) 3154 { 3155 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 3156 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE ); 3157 } 3158 3159 static HRESULT WINAPI IDirectPlay4Impl_GetSessionDesc( IDirectPlay4 *iface, void *lpData, 3160 DWORD *lpdwDataSize ) 3161 { 3162 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 3163 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE ); 3164 } 3165 3166 static HRESULT WINAPI IDirectPlay2AImpl_Initialize( IDirectPlay2A *iface, GUID *guid ) 3167 { 3168 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3169 return IDirectPlayX_Initialize( &This->IDirectPlay4A_iface, guid ); 3170 } 3171 3172 static HRESULT WINAPI IDirectPlay2Impl_Initialize( IDirectPlay2 *iface, GUID *guid ) 3173 { 3174 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3175 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid ); 3176 } 3177 3178 static HRESULT WINAPI IDirectPlay3AImpl_Initialize( IDirectPlay3A *iface, GUID *guid ) 3179 { 3180 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3181 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid ); 3182 } 3183 3184 static HRESULT WINAPI IDirectPlay3Impl_Initialize( IDirectPlay3 *iface, GUID *guid ) 3185 { 3186 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3187 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid ); 3188 } 3189 3190 /* Intended only for COM compatibility. Always returns an error. */ 3191 static HRESULT WINAPI IDirectPlay4AImpl_Initialize( IDirectPlay4A *iface, GUID *guid ) 3192 { 3193 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 3194 TRACE("(%p)->(%p): no-op\n", This, guid ); 3195 return DPERR_ALREADYINITIALIZED; 3196 } 3197 3198 static HRESULT WINAPI IDirectPlay4Impl_Initialize( IDirectPlay4 *iface, GUID *guid ) 3199 { 3200 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 3201 TRACE( "(%p)->(%p): no-op\n", This, guid ); 3202 return DPERR_ALREADYINITIALIZED; 3203 } 3204 3205 3206 static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, DWORD dwFlags, 3207 const DPSECURITYDESC *lpSecurity, const DPCREDENTIALS *lpCredentials, BOOL bAnsi ) 3208 { 3209 HRESULT hr = DP_OK; 3210 3211 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n", 3212 This, lpsd, dwFlags, lpSecurity, lpCredentials ); 3213 3214 if( This->dp2->connectionInitialized == NO_PROVIDER ) 3215 { 3216 return DPERR_UNINITIALIZED; 3217 } 3218 3219 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) ) 3220 { 3221 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize ); 3222 return DPERR_INVALIDPARAMS; 3223 } 3224 3225 if( This->dp2->bConnectionOpen ) 3226 { 3227 TRACE( ": rejecting already open connection.\n" ); 3228 return DPERR_ALREADYINITIALIZED; 3229 } 3230 3231 /* If we're enumerating, kill the thread */ 3232 DP_KillEnumSessionThread( This ); 3233 3234 if( dwFlags & DPOPEN_CREATE ) 3235 { 3236 /* Rightoo - this computer is the host and the local computer needs to be 3237 the name server so that others can join this session */ 3238 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData ); 3239 3240 This->dp2->bHostInterface = TRUE; 3241 3242 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi ); 3243 if( FAILED( hr ) ) 3244 { 3245 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) ); 3246 return hr; 3247 } 3248 } 3249 3250 /* Invoke the conditional callback for the service provider */ 3251 if( This->dp2->spData.lpCB->Open ) 3252 { 3253 DPSP_OPENDATA data; 3254 3255 FIXME( "Not all data fields are correct. Need new parameter\n" ); 3256 3257 data.bCreate = (dwFlags & DPOPEN_CREATE ) != 0; 3258 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL 3259 : NS_GetNSAddr( This->dp2->lpNameServerData ); 3260 data.lpISP = This->dp2->spData.lpISP; 3261 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) != 0; 3262 data.dwOpenFlags = dwFlags; 3263 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags; 3264 3265 hr = (*This->dp2->spData.lpCB->Open)(&data); 3266 if( FAILED( hr ) ) 3267 { 3268 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) ); 3269 return hr; 3270 } 3271 } 3272 3273 { 3274 /* Create the system group of which everything is a part of */ 3275 DPID systemGroup = DPID_SYSTEM_GROUP; 3276 3277 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL, 3278 NULL, 0, 0, TRUE ); 3279 3280 } 3281 3282 if( dwFlags & DPOPEN_JOIN ) 3283 { 3284 DPID dpidServerId = DPID_UNKNOWN; 3285 3286 /* Create the server player for this interface. This way we can receive 3287 * messages for this session. 3288 */ 3289 /* FIXME: I suppose that we should be setting an event for a receive 3290 * type of thing. That way the messaging thread could know to wake 3291 * up. DPlay would then trigger the hEvent for the player the 3292 * message is directed to. 3293 */ 3294 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL, 3295 0, 3296 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi ); 3297 3298 } 3299 else if( dwFlags & DPOPEN_CREATE ) 3300 { 3301 DPID dpidNameServerId = DPID_NAME_SERVER; 3302 3303 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL, 3304 0, DPPLAYER_SERVERPLAYER, bAnsi ); 3305 } 3306 3307 if( FAILED(hr) ) 3308 { 3309 ERR( "Couldn't create name server/system player: %s\n", 3310 DPLAYX_HresultToString(hr) ); 3311 } 3312 3313 return hr; 3314 } 3315 3316 static HRESULT WINAPI IDirectPlay2AImpl_Open( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc, 3317 DWORD flags ) 3318 { 3319 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3320 return IDirectPlayX_Open( &This->IDirectPlay4A_iface, sdesc, flags ); 3321 } 3322 3323 static HRESULT WINAPI IDirectPlay2Impl_Open( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc, 3324 DWORD flags ) 3325 { 3326 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3327 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags ); 3328 } 3329 3330 static HRESULT WINAPI IDirectPlay3AImpl_Open( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc, 3331 DWORD flags ) 3332 { 3333 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3334 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags ); 3335 } 3336 3337 static HRESULT WINAPI IDirectPlay3Impl_Open( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc, 3338 DWORD flags ) 3339 { 3340 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3341 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags ); 3342 } 3343 3344 static HRESULT WINAPI IDirectPlay4AImpl_Open( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc, 3345 DWORD flags ) 3346 { 3347 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL ); 3348 } 3349 3350 static HRESULT WINAPI IDirectPlay4Impl_Open( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc, 3351 DWORD flags ) 3352 { 3353 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL ); 3354 } 3355 3356 static HRESULT DP_IF_Receive( IDirectPlayImpl *This, DPID *lpidFrom, DPID *lpidTo, DWORD dwFlags, 3357 void *lpData, DWORD *lpdwDataSize, BOOL bAnsi ) 3358 { 3359 LPDPMSG lpMsg = NULL; 3360 3361 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n", 3362 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi ); 3363 3364 if( This->dp2->connectionInitialized == NO_PROVIDER ) 3365 { 3366 return DPERR_UNINITIALIZED; 3367 } 3368 3369 if( dwFlags == 0 ) 3370 { 3371 dwFlags = DPRECEIVE_ALL; 3372 } 3373 3374 /* If the lpData is NULL, we must be peeking the message */ 3375 if( ( lpData == NULL ) && 3376 !( dwFlags & DPRECEIVE_PEEK ) 3377 ) 3378 { 3379 return DPERR_INVALIDPARAMS; 3380 } 3381 3382 if( dwFlags & DPRECEIVE_ALL ) 3383 { 3384 lpMsg = This->dp2->receiveMsgs.lpQHFirst; 3385 3386 if( !( dwFlags & DPRECEIVE_PEEK ) ) 3387 { 3388 FIXME( "Remove from queue\n" ); 3389 } 3390 } 3391 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) || 3392 ( dwFlags & DPRECEIVE_FROMPLAYER ) 3393 ) 3394 { 3395 FIXME( "Find matching message 0x%08x\n", dwFlags ); 3396 } 3397 else 3398 { 3399 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags ); 3400 } 3401 3402 if( lpMsg == NULL ) 3403 { 3404 return DPERR_NOMESSAGES; 3405 } 3406 3407 /* Copy into the provided buffer */ 3408 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize ); 3409 3410 return DP_OK; 3411 } 3412 3413 static HRESULT WINAPI IDirectPlay2AImpl_Receive( IDirectPlay2A *iface, DPID *from, DPID *to, 3414 DWORD flags, void *data, DWORD *size ) 3415 { 3416 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3417 return IDirectPlayX_Receive( &This->IDirectPlay4A_iface, from, to, flags, data, size ); 3418 } 3419 3420 static HRESULT WINAPI IDirectPlay2Impl_Receive( IDirectPlay2 *iface, DPID *from, DPID *to, 3421 DWORD flags, void *data, DWORD *size ) 3422 { 3423 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3424 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size ); 3425 } 3426 3427 static HRESULT WINAPI IDirectPlay3AImpl_Receive( IDirectPlay3A *iface, DPID *from, DPID *to, 3428 DWORD flags, void *data, DWORD *size ) 3429 { 3430 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3431 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size ); 3432 } 3433 3434 static HRESULT WINAPI IDirectPlay3Impl_Receive( IDirectPlay3 *iface, DPID *from, DPID *to, 3435 DWORD flags, void *data, DWORD *size ) 3436 { 3437 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3438 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size ); 3439 } 3440 3441 static HRESULT WINAPI IDirectPlay4AImpl_Receive( IDirectPlay4A *iface, DPID *lpidFrom, 3442 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize ) 3443 { 3444 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 3445 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, TRUE ); 3446 } 3447 3448 static HRESULT WINAPI IDirectPlay4Impl_Receive( IDirectPlay4 *iface, DPID *lpidFrom, 3449 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize ) 3450 { 3451 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 3452 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, FALSE ); 3453 } 3454 3455 static HRESULT WINAPI IDirectPlay2AImpl_Send( IDirectPlay2A *iface, DPID from, DPID to, 3456 DWORD flags, void *data, DWORD size ) 3457 { 3458 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3459 return IDirectPlayX_Send( &This->IDirectPlay4A_iface, from, to, flags, data, size ); 3460 } 3461 3462 static HRESULT WINAPI IDirectPlay2Impl_Send( IDirectPlay2 *iface, DPID from, DPID to, 3463 DWORD flags, void *data, DWORD size ) 3464 { 3465 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3466 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size ); 3467 } 3468 3469 static HRESULT WINAPI IDirectPlay3AImpl_Send( IDirectPlay3A *iface, DPID from, DPID to, 3470 DWORD flags, void *data, DWORD size ) 3471 { 3472 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3473 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size ); 3474 } 3475 3476 static HRESULT WINAPI IDirectPlay3Impl_Send( IDirectPlay3 *iface, DPID from, DPID to, 3477 DWORD flags, void *data, DWORD size ) 3478 { 3479 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3480 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size ); 3481 } 3482 3483 static HRESULT WINAPI IDirectPlay4AImpl_Send( IDirectPlay4A *iface, DPID from, DPID to, 3484 DWORD flags, void *data, DWORD size ) 3485 { 3486 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL ); 3487 } 3488 3489 static HRESULT WINAPI IDirectPlay4Impl_Send( IDirectPlay4 *iface, DPID from, DPID to, 3490 DWORD flags, void *data, DWORD size ) 3491 { 3492 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL ); 3493 } 3494 3495 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupData( IDirectPlay2A *iface, DPID group, void *data, 3496 DWORD size, DWORD flags ) 3497 { 3498 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3499 return IDirectPlayX_SetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags ); 3500 } 3501 3502 static HRESULT WINAPI IDirectPlay2Impl_SetGroupData( IDirectPlay2 *iface, DPID group, void *data, 3503 DWORD size, DWORD flags ) 3504 { 3505 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3506 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags ); 3507 } 3508 3509 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupData( IDirectPlay3A *iface, DPID group, void *data, 3510 DWORD size, DWORD flags ) 3511 { 3512 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3513 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags ); 3514 } 3515 3516 static HRESULT WINAPI IDirectPlay3Impl_SetGroupData( IDirectPlay3 *iface, DPID group, void *data, 3517 DWORD size, DWORD flags ) 3518 { 3519 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3520 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags ); 3521 } 3522 3523 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupData( IDirectPlay4A *iface, DPID group, void *data, 3524 DWORD size, DWORD flags ) 3525 { 3526 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 3527 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags ); 3528 } 3529 3530 static HRESULT WINAPI IDirectPlay4Impl_SetGroupData( IDirectPlay4 *iface, DPID group, void *data, 3531 DWORD size, DWORD flags ) 3532 { 3533 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 3534 lpGroupData gdata; 3535 3536 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, group, data, size, flags ); 3537 3538 /* Parameter check */ 3539 if ( !data && size ) 3540 return DPERR_INVALIDPARAMS; 3541 3542 /* Find the pointer to the data for this player */ 3543 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL ) 3544 return DPERR_INVALIDOBJECT; 3545 3546 if ( !(flags & DPSET_LOCAL) ) 3547 { 3548 FIXME( "Was this group created by this interface?\n" ); 3549 /* FIXME: If this is a remote update need to allow it but not 3550 * send a message. 3551 */ 3552 } 3553 3554 DP_SetGroupData( gdata, flags, data, size ); 3555 3556 /* FIXME: Only send a message if this group is local to the session otherwise 3557 * it will have been rejected above 3558 */ 3559 if ( !(flags & DPSET_LOCAL) ) 3560 FIXME( "Send msg?\n" ); 3561 3562 return DP_OK; 3563 } 3564 3565 static HRESULT DP_IF_SetGroupName( IDirectPlayImpl *This, DPID idGroup, DPNAME *lpGroupName, 3566 DWORD dwFlags, BOOL bAnsi ) 3567 { 3568 lpGroupData lpGData; 3569 3570 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup, 3571 lpGroupName, dwFlags, bAnsi ); 3572 3573 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL ) 3574 { 3575 return DPERR_INVALIDGROUP; 3576 } 3577 3578 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi ); 3579 3580 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */ 3581 FIXME( "Message not sent and dwFlags ignored\n" ); 3582 3583 return DP_OK; 3584 } 3585 3586 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupName( IDirectPlay2A *iface, DPID group, 3587 DPNAME *name, DWORD flags ) 3588 { 3589 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3590 return IDirectPlayX_SetGroupName( &This->IDirectPlay4A_iface, group, name, flags ); 3591 } 3592 3593 static HRESULT WINAPI IDirectPlay2Impl_SetGroupName( IDirectPlay2 *iface, DPID group, 3594 DPNAME *name, DWORD flags ) 3595 { 3596 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3597 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags ); 3598 } 3599 3600 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupName( IDirectPlay3A *iface, DPID group, 3601 DPNAME *name, DWORD flags ) 3602 { 3603 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3604 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags ); 3605 } 3606 3607 static HRESULT WINAPI IDirectPlay3Impl_SetGroupName( IDirectPlay3 *iface, DPID group, 3608 DPNAME *name, DWORD flags ) 3609 { 3610 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3611 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags ); 3612 } 3613 3614 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupName( IDirectPlay4A *iface, DPID idGroup, 3615 DPNAME *lpGroupName, DWORD dwFlags ) 3616 { 3617 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 3618 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE ); 3619 } 3620 3621 static HRESULT WINAPI IDirectPlay4Impl_SetGroupName( IDirectPlay4 *iface, DPID idGroup, 3622 DPNAME *lpGroupName, DWORD dwFlags ) 3623 { 3624 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 3625 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE ); 3626 } 3627 3628 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerData( IDirectPlay2A *iface, DPID player, 3629 void *data, DWORD size, DWORD flags ) 3630 { 3631 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3632 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags ); 3633 } 3634 3635 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerData( IDirectPlay2 *iface, DPID player, 3636 void *data, DWORD size, DWORD flags ) 3637 { 3638 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3639 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags ); 3640 } 3641 3642 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerData( IDirectPlay3A *iface, DPID player, 3643 void *data, DWORD size, DWORD flags ) 3644 { 3645 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3646 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags ); 3647 } 3648 3649 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerData( IDirectPlay3 *iface, DPID player, 3650 void *data, DWORD size, DWORD flags ) 3651 { 3652 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3653 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags ); 3654 } 3655 3656 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerData( IDirectPlay4A *iface, DPID player, 3657 void *data, DWORD size, DWORD flags ) 3658 { 3659 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 3660 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags ); 3661 } 3662 3663 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerData( IDirectPlay4 *iface, DPID player, 3664 void *data, DWORD size, DWORD flags ) 3665 { 3666 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 3667 lpPlayerList plist; 3668 3669 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, player, data, size, flags ); 3670 3671 if ( This->dp2->connectionInitialized == NO_PROVIDER ) 3672 return DPERR_UNINITIALIZED; 3673 3674 /* Parameter check */ 3675 if ( !data && size ) 3676 return DPERR_INVALIDPARAMS; 3677 3678 /* Find the pointer to the data for this player */ 3679 if ( (plist = DP_FindPlayer( This, player )) == NULL ) 3680 return DPERR_INVALIDPLAYER; 3681 3682 if ( !(flags & DPSET_LOCAL) ) 3683 { 3684 FIXME( "Was this group created by this interface?\n" ); 3685 /* FIXME: If this is a remote update need to allow it but not 3686 * send a message. 3687 */ 3688 } 3689 3690 DP_SetPlayerData( plist->lpPData, flags, data, size ); 3691 3692 if ( !(flags & DPSET_LOCAL) ) 3693 FIXME( "Send msg?\n" ); 3694 3695 return DP_OK; 3696 } 3697 3698 static HRESULT DP_IF_SetPlayerName( IDirectPlayImpl *This, DPID idPlayer, DPNAME *lpPlayerName, 3699 DWORD dwFlags, BOOL bAnsi ) 3700 { 3701 lpPlayerList lpPList; 3702 3703 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", 3704 This, idPlayer, lpPlayerName, dwFlags, bAnsi ); 3705 3706 if( This->dp2->connectionInitialized == NO_PROVIDER ) 3707 { 3708 return DPERR_UNINITIALIZED; 3709 } 3710 3711 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL ) 3712 { 3713 return DPERR_INVALIDGROUP; 3714 } 3715 3716 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi ); 3717 3718 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */ 3719 FIXME( "Message not sent and dwFlags ignored\n" ); 3720 3721 return DP_OK; 3722 } 3723 3724 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerName( IDirectPlay2A *iface, DPID player, 3725 DPNAME *name, DWORD flags ) 3726 { 3727 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3728 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4A_iface, player, name, flags ); 3729 } 3730 3731 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerName( IDirectPlay2 *iface, DPID player, 3732 DPNAME *name, DWORD flags ) 3733 { 3734 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3735 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags ); 3736 } 3737 3738 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerName( IDirectPlay3A *iface, DPID player, 3739 DPNAME *name, DWORD flags ) 3740 { 3741 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3742 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags ); 3743 } 3744 3745 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerName( IDirectPlay3 *iface, DPID player, 3746 DPNAME *name, DWORD flags ) 3747 { 3748 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3749 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags ); 3750 } 3751 3752 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerName( IDirectPlay4A *iface, DPID idPlayer, 3753 DPNAME *lpPlayerName, DWORD dwFlags ) 3754 { 3755 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 3756 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE ); 3757 } 3758 3759 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerName( IDirectPlay4 *iface, DPID idPlayer, 3760 DPNAME *lpPlayerName, DWORD dwFlags ) 3761 { 3762 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 3763 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE ); 3764 } 3765 3766 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc, 3767 DWORD dwFlags, BOOL bInitial, BOOL bAnsi ) 3768 { 3769 DWORD dwRequiredSize; 3770 LPDPSESSIONDESC2 lpTempSessDesc; 3771 3772 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n", 3773 This, lpSessDesc, dwFlags, bInitial, bAnsi ); 3774 3775 if( This->dp2->connectionInitialized == NO_PROVIDER ) 3776 { 3777 return DPERR_UNINITIALIZED; 3778 } 3779 3780 if( dwFlags ) 3781 { 3782 return DPERR_INVALIDPARAMS; 3783 } 3784 3785 /* Only the host is allowed to update the session desc */ 3786 if( !This->dp2->bHostInterface ) 3787 { 3788 return DPERR_ACCESSDENIED; 3789 } 3790 3791 /* FIXME: Copy into This->dp2->lpSessionDesc */ 3792 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi ); 3793 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize ); 3794 3795 if( lpTempSessDesc == NULL ) 3796 { 3797 return DPERR_OUTOFMEMORY; 3798 } 3799 3800 /* Free the old */ 3801 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc ); 3802 3803 This->dp2->lpSessionDesc = lpTempSessDesc; 3804 /* Set the new */ 3805 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi ); 3806 if( bInitial ) 3807 { 3808 /*Initializing session GUID*/ 3809 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) ); 3810 } 3811 /* If this is an external invocation of the interface, we should be 3812 * letting everyone know that things have changed. Otherwise this is 3813 * just an initialization and it doesn't need to be propagated. 3814 */ 3815 if( !bInitial ) 3816 { 3817 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" ); 3818 } 3819 3820 return DP_OK; 3821 } 3822 3823 static HRESULT WINAPI IDirectPlay2AImpl_SetSessionDesc( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc, 3824 DWORD flags ) 3825 { 3826 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface ); 3827 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4A_iface, sdesc, flags ); 3828 } 3829 3830 static HRESULT WINAPI IDirectPlay2Impl_SetSessionDesc( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc, 3831 DWORD flags ) 3832 { 3833 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface ); 3834 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags ); 3835 } 3836 3837 static HRESULT WINAPI IDirectPlay3AImpl_SetSessionDesc( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc, 3838 DWORD flags ) 3839 { 3840 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3841 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags ); 3842 } 3843 3844 static HRESULT WINAPI IDirectPlay3Impl_SetSessionDesc( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc, 3845 DWORD flags ) 3846 { 3847 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3848 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags ); 3849 } 3850 3851 static HRESULT WINAPI IDirectPlay4AImpl_SetSessionDesc( IDirectPlay4A *iface, 3852 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags ) 3853 { 3854 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 3855 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE ); 3856 } 3857 3858 static HRESULT WINAPI IDirectPlay4Impl_SetSessionDesc( IDirectPlay4 *iface, 3859 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags ) 3860 { 3861 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 3862 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE ); 3863 } 3864 3865 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */ 3866 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi ) 3867 { 3868 DWORD dwSize = 0; 3869 3870 if( lpSessDesc == NULL ) 3871 { 3872 /* Hmmm..don't need any size? */ 3873 ERR( "NULL lpSessDesc\n" ); 3874 return dwSize; 3875 } 3876 3877 dwSize += sizeof( *lpSessDesc ); 3878 3879 if( bAnsi ) 3880 { 3881 if( lpSessDesc->u1.lpszSessionNameA ) 3882 { 3883 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1; 3884 } 3885 3886 if( lpSessDesc->u2.lpszPasswordA ) 3887 { 3888 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1; 3889 } 3890 } 3891 else /* UNICODE */ 3892 { 3893 if( lpSessDesc->u1.lpszSessionName ) 3894 { 3895 dwSize += sizeof( WCHAR ) * 3896 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 ); 3897 } 3898 3899 if( lpSessDesc->u2.lpszPassword ) 3900 { 3901 dwSize += sizeof( WCHAR ) * 3902 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 ); 3903 } 3904 } 3905 3906 return dwSize; 3907 } 3908 3909 /* Assumes that contiguous buffers are already allocated. */ 3910 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest, 3911 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi ) 3912 { 3913 BYTE* lpStartOfFreeSpace; 3914 3915 if( lpSessionDest == NULL ) 3916 { 3917 ERR( "NULL lpSessionDest\n" ); 3918 return; 3919 } 3920 3921 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) ); 3922 3923 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc ); 3924 3925 if( bAnsi ) 3926 { 3927 if( lpSessionSrc->u1.lpszSessionNameA ) 3928 { 3929 lstrcpyA( (LPSTR)lpStartOfFreeSpace, 3930 lpSessionDest->u1.lpszSessionNameA ); 3931 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace; 3932 lpStartOfFreeSpace += 3933 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1; 3934 } 3935 3936 if( lpSessionSrc->u2.lpszPasswordA ) 3937 { 3938 lstrcpyA( (LPSTR)lpStartOfFreeSpace, 3939 lpSessionDest->u2.lpszPasswordA ); 3940 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace; 3941 } 3942 } 3943 else /* UNICODE */ 3944 { 3945 if( lpSessionSrc->u1.lpszSessionName ) 3946 { 3947 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, 3948 lpSessionDest->u1.lpszSessionName ); 3949 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace; 3950 lpStartOfFreeSpace += sizeof(WCHAR) * 3951 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 ); 3952 } 3953 3954 if( lpSessionSrc->u2.lpszPassword ) 3955 { 3956 lstrcpyW( (LPWSTR)lpStartOfFreeSpace, 3957 lpSessionDest->u2.lpszPassword ); 3958 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace; 3959 } 3960 } 3961 } 3962 3963 static HRESULT WINAPI IDirectPlay3AImpl_AddGroupToGroup( IDirectPlay3A *iface, DPID parent, 3964 DPID group ) 3965 { 3966 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 3967 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4A_iface, parent, group ); 3968 } 3969 3970 static HRESULT WINAPI IDirectPlay3Impl_AddGroupToGroup( IDirectPlay3 *iface, DPID parent, 3971 DPID group ) 3972 { 3973 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 3974 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group ); 3975 } 3976 3977 static HRESULT WINAPI IDirectPlay4AImpl_AddGroupToGroup( IDirectPlay4A *iface, DPID parent, 3978 DPID group ) 3979 { 3980 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 3981 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group ); 3982 } 3983 3984 static HRESULT WINAPI IDirectPlay4Impl_AddGroupToGroup( IDirectPlay4 *iface, DPID parent, 3985 DPID group ) 3986 { 3987 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 3988 lpGroupData gdata; 3989 lpGroupList glist; 3990 3991 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, parent, group ); 3992 3993 if ( This->dp2->connectionInitialized == NO_PROVIDER ) 3994 return DPERR_UNINITIALIZED; 3995 3996 if ( !DP_FindAnyGroup(This, parent ) ) 3997 return DPERR_INVALIDGROUP; 3998 3999 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL ) 4000 return DPERR_INVALIDGROUP; 4001 4002 /* Create a player list (ie "shortcut" ) */ 4003 glist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *glist ) ); 4004 if ( !glist ) 4005 return DPERR_CANTADDPLAYER; 4006 4007 /* Add the shortcut */ 4008 gdata->uRef++; 4009 glist->lpGData = gdata; 4010 4011 /* Add the player to the list of players for this group */ 4012 DPQ_INSERT( gdata->groups, glist, groups ); 4013 4014 /* Send a ADDGROUPTOGROUP message */ 4015 FIXME( "Not sending message\n" ); 4016 4017 return DP_OK; 4018 } 4019 4020 static HRESULT DP_IF_CreateGroupInGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idParentGroup, 4021 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, 4022 BOOL bAnsi ) 4023 { 4024 lpGroupData lpGParentData; 4025 lpGroupList lpGList; 4026 lpGroupData lpGData; 4027 4028 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n", 4029 This, idParentGroup, lpidGroup, lpGroupName, lpData, 4030 dwDataSize, dwFlags, bAnsi ); 4031 4032 if( This->dp2->connectionInitialized == NO_PROVIDER ) 4033 { 4034 return DPERR_UNINITIALIZED; 4035 } 4036 4037 /* Verify that the specified parent is valid */ 4038 if( ( lpGParentData = DP_FindAnyGroup(This, idParentGroup ) ) == NULL ) 4039 return DPERR_INVALIDGROUP; 4040 4041 lpGData = DP_CreateGroup(This, lpidGroup, lpGroupName, dwFlags, idParentGroup, bAnsi ); 4042 4043 if( lpGData == NULL ) 4044 { 4045 return DPERR_CANTADDPLAYER; /* yes player not group */ 4046 } 4047 4048 /* Something else is referencing this data */ 4049 lpGData->uRef++; 4050 4051 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize ); 4052 4053 /* The list has now been inserted into the interface group list. We now 4054 need to put a "shortcut" to this group in the parent group */ 4055 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) ); 4056 if( lpGList == NULL ) 4057 { 4058 FIXME( "Memory leak\n" ); 4059 return DPERR_CANTADDPLAYER; /* yes player not group */ 4060 } 4061 4062 lpGList->lpGData = lpGData; 4063 4064 DPQ_INSERT( lpGParentData->groups, lpGList, groups ); 4065 4066 /* Let the SP know that we've created this group */ 4067 if( This->dp2->spData.lpCB->CreateGroup ) 4068 { 4069 DPSP_CREATEGROUPDATA data; 4070 4071 TRACE( "Calling SP CreateGroup\n" ); 4072 4073 data.idGroup = *lpidGroup; 4074 data.dwFlags = dwFlags; 4075 data.lpSPMessageHeader = lpMsgHdr; 4076 data.lpISP = This->dp2->spData.lpISP; 4077 4078 (*This->dp2->spData.lpCB->CreateGroup)( &data ); 4079 } 4080 4081 /* Inform all other peers of the creation of a new group. If there are 4082 * no peers keep this quiet. 4083 */ 4084 if( This->dp2->lpSessionDesc && 4085 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) ) 4086 { 4087 DPMSG_CREATEPLAYERORGROUP msg; 4088 4089 msg.dwType = DPSYS_CREATEPLAYERORGROUP; 4090 msg.dwPlayerType = DPPLAYERTYPE_GROUP; 4091 msg.dpId = *lpidGroup; 4092 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */ 4093 msg.lpData = lpData; 4094 msg.dwDataSize = dwDataSize; 4095 msg.dpnName = *lpGroupName; 4096 4097 /* FIXME: Correct to just use send effectively? */ 4098 /* FIXME: Should size include data w/ message or just message "header" */ 4099 /* FIXME: Check return code */ 4100 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, 4101 sizeof( msg ), 0, 0, NULL, NULL ); 4102 } 4103 4104 return DP_OK; 4105 } 4106 4107 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroupInGroup( IDirectPlay3A *iface, DPID parent, 4108 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags ) 4109 { 4110 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 4111 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4A_iface, parent, group, name, 4112 data, size, flags ); 4113 } 4114 4115 static HRESULT WINAPI IDirectPlay3Impl_CreateGroupInGroup( IDirectPlay3 *iface, DPID parent, 4116 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags ) 4117 { 4118 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 4119 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4_iface, parent, group, name, 4120 data, size, flags ); 4121 } 4122 4123 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroupInGroup( IDirectPlay4A *iface, 4124 DPID idParentGroup, DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, 4125 DWORD dwFlags ) 4126 { 4127 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 4128 4129 *lpidGroup = DPID_UNKNOWN; 4130 4131 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData, 4132 dwDataSize, dwFlags, TRUE ); 4133 } 4134 4135 static HRESULT WINAPI IDirectPlay4Impl_CreateGroupInGroup( IDirectPlay4 *iface, DPID idParentGroup, 4136 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags ) 4137 { 4138 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 4139 4140 *lpidGroup = DPID_UNKNOWN; 4141 4142 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData, 4143 dwDataSize, dwFlags, FALSE ); 4144 } 4145 4146 static HRESULT WINAPI IDirectPlay3AImpl_DeleteGroupFromGroup( IDirectPlay3A *iface, DPID parent, 4147 DPID group ) 4148 { 4149 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 4150 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4A_iface, parent, group ); 4151 } 4152 4153 static HRESULT WINAPI IDirectPlay3Impl_DeleteGroupFromGroup( IDirectPlay3 *iface, DPID parent, 4154 DPID group ) 4155 { 4156 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 4157 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group ); 4158 } 4159 4160 static HRESULT WINAPI IDirectPlay4AImpl_DeleteGroupFromGroup( IDirectPlay4A *iface, DPID parent, 4161 DPID group ) 4162 { 4163 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 4164 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group ); 4165 } 4166 4167 static HRESULT WINAPI IDirectPlay4Impl_DeleteGroupFromGroup( IDirectPlay4 *iface, DPID parent, 4168 DPID group ) 4169 { 4170 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 4171 lpGroupList glist; 4172 lpGroupData parentdata; 4173 4174 TRACE("(%p)->(0x%08x,0x%08x)\n", This, parent, group ); 4175 4176 /* Is the parent group valid? */ 4177 if ( ( parentdata = DP_FindAnyGroup(This, parent ) ) == NULL ) 4178 return DPERR_INVALIDGROUP; 4179 4180 /* Remove the group from the parent group queue */ 4181 DPQ_REMOVE_ENTRY( parentdata->groups, groups, lpGData->dpid, ==, group, glist ); 4182 4183 if ( glist == NULL ) 4184 return DPERR_INVALIDGROUP; 4185 4186 /* Decrement the ref count */ 4187 glist->lpGData->uRef--; 4188 4189 /* Free up the list item */ 4190 HeapFree( GetProcessHeap(), 0, glist ); 4191 4192 /* Should send a DELETEGROUPFROMGROUP message */ 4193 FIXME( "message not sent\n" ); 4194 4195 return DP_OK; 4196 } 4197 4198 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf, 4199 LPDWORD lpdwBufSize ) 4200 { 4201 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress; 4202 HRESULT hr; 4203 4204 dpCompoundAddress.dwDataSize = sizeof( GUID ); 4205 dpCompoundAddress.guidDataType = DPAID_ServiceProvider; 4206 dpCompoundAddress.lpData = lpcSpGuid; 4207 4208 *lplpAddrBuf = NULL; 4209 *lpdwBufSize = 0; 4210 4211 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf, 4212 lpdwBufSize, TRUE ); 4213 4214 if( hr != DPERR_BUFFERTOOSMALL ) 4215 { 4216 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) ); 4217 return FALSE; 4218 } 4219 4220 /* Now allocate the buffer */ 4221 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 4222 *lpdwBufSize ); 4223 4224 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf, 4225 lpdwBufSize, TRUE ); 4226 if( FAILED(hr) ) 4227 { 4228 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) ); 4229 return FALSE; 4230 } 4231 4232 return TRUE; 4233 } 4234 4235 static HRESULT WINAPI IDirectPlay3AImpl_EnumConnections( IDirectPlay3A *iface, 4236 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags ) 4237 { 4238 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 4239 return IDirectPlayX_EnumConnections( &This->IDirectPlay4A_iface, application, enumcb, context, 4240 flags ); 4241 } 4242 4243 static HRESULT WINAPI IDirectPlay3Impl_EnumConnections( IDirectPlay3 *iface, 4244 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags ) 4245 { 4246 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 4247 return IDirectPlayX_EnumConnections( &This->IDirectPlay4_iface, application, enumcb, context, 4248 flags ); 4249 } 4250 4251 static HRESULT WINAPI IDirectPlay4AImpl_EnumConnections( IDirectPlay4A *iface, 4252 const GUID *lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, void *lpContext, 4253 DWORD dwFlags ) 4254 { 4255 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 4256 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags ); 4257 4258 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */ 4259 if( dwFlags == 0 ) 4260 { 4261 dwFlags = DPCONNECTION_DIRECTPLAY; 4262 } 4263 4264 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) || 4265 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) ) 4266 ) 4267 { 4268 return DPERR_INVALIDFLAGS; 4269 } 4270 4271 if( !lpEnumCallback ) 4272 { 4273 return DPERR_INVALIDPARAMS; 4274 } 4275 4276 /* Enumerate DirectPlay service providers */ 4277 if( dwFlags & DPCONNECTION_DIRECTPLAY ) 4278 { 4279 HKEY hkResult; 4280 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers"; 4281 LPCSTR guidDataSubKey = "Guid"; 4282 char subKeyName[51]; 4283 DWORD dwIndex, sizeOfSubKeyName=50; 4284 FILETIME filetime; 4285 4286 /* Need to loop over the service providers in the registry */ 4287 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey, 4288 0, KEY_READ, &hkResult ) != ERROR_SUCCESS ) 4289 { 4290 /* Hmmm. Does this mean that there are no service providers? */ 4291 ERR(": no service providers?\n"); 4292 return DP_OK; 4293 } 4294 4295 4296 /* Traverse all the service providers we have available */ 4297 for( dwIndex=0; 4298 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 4299 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; 4300 ++dwIndex, sizeOfSubKeyName=51 ) 4301 { 4302 4303 HKEY hkServiceProvider; 4304 GUID serviceProviderGUID; 4305 DWORD returnTypeGUID, sizeOfReturnBuffer = 50; 4306 char returnBuffer[51]; 4307 WCHAR buff[51]; 4308 DPNAME dpName; 4309 BOOL bBuildPass; 4310 4311 LPVOID lpAddressBuffer = NULL; 4312 DWORD dwAddressBufferSize = 0; 4313 4314 TRACE(" this time through: %s\n", subKeyName ); 4315 4316 /* Get a handle for this particular service provider */ 4317 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ, 4318 &hkServiceProvider ) != ERROR_SUCCESS ) 4319 { 4320 ERR(": what the heck is going on?\n" ); 4321 continue; 4322 } 4323 4324 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey, 4325 NULL, &returnTypeGUID, (LPBYTE)returnBuffer, 4326 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 4327 { 4328 ERR(": missing GUID registry data members\n" ); 4329 RegCloseKey(hkServiceProvider); 4330 continue; 4331 } 4332 RegCloseKey(hkServiceProvider); 4333 4334 /* FIXME: Check return types to ensure we're interpreting data right */ 4335 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, ARRAY_SIZE( buff )); 4336 CLSIDFromString( buff, &serviceProviderGUID ); 4337 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */ 4338 4339 /* Fill in the DPNAME struct for the service provider */ 4340 dpName.dwSize = sizeof( dpName ); 4341 dpName.dwFlags = 0; 4342 dpName.u1.lpszShortNameA = subKeyName; 4343 dpName.u2.lpszLongNameA = NULL; 4344 4345 /* Create the compound address for the service provider. 4346 * NOTE: This is a gruesome architectural scar right now. DP 4347 * uses DPL and DPL uses DP. Nasty stuff. This may be why the 4348 * native dll just gets around this little bit by allocating an 4349 * 80 byte buffer which isn't even filled with a valid compound 4350 * address. Oh well. Creating a proper compound address is the 4351 * way to go anyways despite this method taking slightly more 4352 * heap space and realtime :) */ 4353 4354 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID, 4355 &lpAddressBuffer, 4356 &dwAddressBufferSize ); 4357 if( !bBuildPass ) 4358 { 4359 ERR( "Can't build compound addr\n" ); 4360 return DPERR_GENERIC; 4361 } 4362 4363 /* The enumeration will return FALSE if we are not to continue */ 4364 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize, 4365 &dpName, dwFlags, lpContext ) ) 4366 { 4367 HeapFree( GetProcessHeap(), 0, lpAddressBuffer ); 4368 return DP_OK; 4369 } 4370 HeapFree( GetProcessHeap(), 0, lpAddressBuffer ); 4371 } 4372 } 4373 4374 /* Enumerate DirectPlayLobby service providers */ 4375 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) 4376 { 4377 HKEY hkResult; 4378 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers"; 4379 LPCSTR guidDataSubKey = "Guid"; 4380 char subKeyName[51]; 4381 DWORD dwIndex, sizeOfSubKeyName=50; 4382 FILETIME filetime; 4383 4384 /* Need to loop over the service providers in the registry */ 4385 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey, 4386 0, KEY_READ, &hkResult ) != ERROR_SUCCESS ) 4387 { 4388 TRACE("No Lobby Providers have been registered.\n"); 4389 return DP_OK; 4390 } 4391 4392 4393 /* Traverse all the lobby providers we have available */ 4394 for( dwIndex=0; 4395 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 4396 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; 4397 ++dwIndex, sizeOfSubKeyName=51 ) 4398 { 4399 4400 HKEY hkServiceProvider; 4401 GUID serviceProviderGUID; 4402 DWORD returnTypeGUID, sizeOfReturnBuffer = 50; 4403 char returnBuffer[51]; 4404 WCHAR buff[51]; 4405 DPNAME dpName; 4406 HRESULT hr; 4407 4408 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress; 4409 LPVOID lpAddressBuffer = NULL; 4410 DWORD dwAddressBufferSize = 0; 4411 4412 TRACE(" this time through: %s\n", subKeyName ); 4413 4414 /* Get a handle for this particular service provider */ 4415 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ, 4416 &hkServiceProvider ) != ERROR_SUCCESS ) 4417 { 4418 ERR(": what the heck is going on?\n" ); 4419 continue; 4420 } 4421 4422 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey, 4423 NULL, &returnTypeGUID, (LPBYTE)returnBuffer, 4424 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 4425 { 4426 ERR(": missing GUID registry data members\n" ); 4427 RegCloseKey(hkServiceProvider); 4428 continue; 4429 } 4430 RegCloseKey(hkServiceProvider); 4431 4432 /* FIXME: Check return types to ensure we're interpreting data right */ 4433 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, ARRAY_SIZE( buff )); 4434 CLSIDFromString( buff, &serviceProviderGUID ); 4435 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */ 4436 4437 /* Fill in the DPNAME struct for the service provider */ 4438 dpName.dwSize = sizeof( dpName ); 4439 dpName.dwFlags = 0; 4440 dpName.u1.lpszShortNameA = subKeyName; 4441 dpName.u2.lpszLongNameA = NULL; 4442 4443 /* Create the compound address for the service provider. 4444 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP 4445 nast stuff. This may be why the native dll just gets around this little bit by 4446 allocating an 80 byte buffer which isn't even a filled with a valid compound 4447 address. Oh well. Creating a proper compound address is the way to go anyways 4448 despite this method taking slightly more heap space and realtime :) */ 4449 4450 dpCompoundAddress.guidDataType = DPAID_LobbyProvider; 4451 dpCompoundAddress.dwDataSize = sizeof( GUID ); 4452 dpCompoundAddress.lpData = &serviceProviderGUID; 4453 4454 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer, 4455 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL ) 4456 { 4457 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) ); 4458 return hr; 4459 } 4460 4461 /* Now allocate the buffer */ 4462 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize ); 4463 4464 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer, 4465 &dwAddressBufferSize, TRUE ) ) != DP_OK ) 4466 { 4467 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) ); 4468 HeapFree( GetProcessHeap(), 0, lpAddressBuffer ); 4469 return hr; 4470 } 4471 4472 /* The enumeration will return FALSE if we are not to continue */ 4473 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize, 4474 &dpName, dwFlags, lpContext ) ) 4475 { 4476 HeapFree( GetProcessHeap(), 0, lpAddressBuffer ); 4477 return DP_OK; 4478 } 4479 HeapFree( GetProcessHeap(), 0, lpAddressBuffer ); 4480 } 4481 } 4482 4483 return DP_OK; 4484 } 4485 4486 static HRESULT WINAPI IDirectPlay4Impl_EnumConnections( IDirectPlay4 *iface, 4487 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags ) 4488 { 4489 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 4490 return IDirectPlayX_EnumConnections( &This->IDirectPlay4A_iface, application, enumcb, context, 4491 flags ); 4492 } 4493 4494 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupsInGroup( IDirectPlay3A *iface, DPID group, 4495 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 4496 { 4497 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 4498 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4A_iface, group, instance, 4499 enumplayercb, context, flags ); 4500 } 4501 4502 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupsInGroup( IDirectPlay3 *iface, DPID group, 4503 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 4504 { 4505 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 4506 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance, 4507 enumplayercb, context, flags ); 4508 } 4509 4510 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupsInGroup( IDirectPlay4A *iface, DPID group, 4511 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 4512 { 4513 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 4514 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance, 4515 enumplayercb, context, flags ); 4516 } 4517 4518 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupsInGroup( IDirectPlay4 *iface, DPID group, 4519 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags ) 4520 { 4521 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 4522 lpGroupList glist; 4523 lpGroupData gdata; 4524 4525 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb, 4526 context, flags ); 4527 4528 if ( This->dp2->connectionInitialized == NO_PROVIDER ) 4529 return DPERR_UNINITIALIZED; 4530 4531 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL ) 4532 return DPERR_INVALIDGROUP; 4533 4534 if ( DPQ_IS_EMPTY( gdata->groups ) ) 4535 return DP_OK; 4536 4537 4538 for( glist = DPQ_FIRST( gdata->groups ); ; glist = DPQ_NEXT( glist->groups ) ) 4539 { 4540 /* FIXME: Should check flags for match here */ 4541 if ( !(*enumplayercb)( glist->lpGData->dpid, DPPLAYERTYPE_GROUP, &glist->lpGData->name, 4542 flags, context ) ) 4543 return DP_OK; /* User requested break */ 4544 4545 if ( DPQ_IS_ENDOFLIST( glist->groups ) ) 4546 break; 4547 } 4548 4549 return DP_OK; 4550 } 4551 4552 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupConnectionSettings( IDirectPlay3A *iface, 4553 DWORD flags, DPID group, void *data, DWORD *size ) 4554 { 4555 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 4556 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group, 4557 data, size ); 4558 } 4559 4560 static HRESULT WINAPI IDirectPlay3Impl_GetGroupConnectionSettings( IDirectPlay3 *iface, 4561 DWORD flags, DPID group, void *data, DWORD *size ) 4562 { 4563 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 4564 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group, 4565 data, size ); 4566 } 4567 4568 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupConnectionSettings( IDirectPlay4A *iface, 4569 DWORD flags, DPID group, void *data, DWORD *size ) 4570 { 4571 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 4572 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size ); 4573 return DP_OK; 4574 } 4575 4576 static HRESULT WINAPI IDirectPlay4Impl_GetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags, 4577 DPID group, void *data, DWORD *size ) 4578 { 4579 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 4580 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size ); 4581 return DP_OK; 4582 } 4583 4584 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress( 4585 REFGUID guidDataType, 4586 DWORD dwDataSize, 4587 LPCVOID lpData, 4588 LPVOID lpContext ) 4589 { 4590 /* Looking for the GUID of the provider to load */ 4591 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) || 4592 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) ) 4593 ) 4594 { 4595 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n", 4596 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize ); 4597 4598 if( dwDataSize != sizeof( GUID ) ) 4599 { 4600 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize ); 4601 } 4602 4603 memcpy( lpContext, lpData, dwDataSize ); 4604 4605 /* There shouldn't be more than 1 GUID/compound address */ 4606 return FALSE; 4607 } 4608 4609 /* Still waiting for what we want */ 4610 return TRUE; 4611 } 4612 4613 4614 /* Find and perform a LoadLibrary on the requested SP or LP GUID */ 4615 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp ) 4616 { 4617 UINT i; 4618 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers"; 4619 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers"; 4620 LPCSTR guidDataSubKey = "Guid"; 4621 LPCSTR majVerDataSubKey = "dwReserved1"; 4622 LPCSTR minVerDataSubKey = "dwReserved2"; 4623 LPCSTR pathSubKey = "Path"; 4624 4625 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) ); 4626 4627 /* FIXME: Cloned code with a quick hack. */ 4628 for( i=0; i<2; i++ ) 4629 { 4630 HKEY hkResult; 4631 LPCSTR searchSubKey; 4632 char subKeyName[51]; 4633 DWORD dwIndex, sizeOfSubKeyName=50; 4634 FILETIME filetime; 4635 4636 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey ); 4637 *lpbIsDpSp = (i == 0); 4638 4639 4640 /* Need to loop over the service providers in the registry */ 4641 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey, 4642 0, KEY_READ, &hkResult ) != ERROR_SUCCESS ) 4643 { 4644 /* Hmmm. Does this mean that there are no service providers? */ 4645 ERR(": no service providers?\n"); 4646 return 0; 4647 } 4648 4649 /* Traverse all the service providers we have available */ 4650 for( dwIndex=0; 4651 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 4652 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; 4653 ++dwIndex, sizeOfSubKeyName=51 ) 4654 { 4655 4656 HKEY hkServiceProvider; 4657 GUID serviceProviderGUID; 4658 DWORD returnType, sizeOfReturnBuffer = 255; 4659 char returnBuffer[256]; 4660 WCHAR buff[51]; 4661 DWORD dwTemp, len; 4662 4663 TRACE(" this time through: %s\n", subKeyName ); 4664 4665 /* Get a handle for this particular service provider */ 4666 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ, 4667 &hkServiceProvider ) != ERROR_SUCCESS ) 4668 { 4669 ERR(": what the heck is going on?\n" ); 4670 continue; 4671 } 4672 4673 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey, 4674 NULL, &returnType, (LPBYTE)returnBuffer, 4675 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 4676 { 4677 ERR(": missing GUID registry data members\n" ); 4678 continue; 4679 } 4680 4681 /* FIXME: Check return types to ensure we're interpreting data right */ 4682 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, ARRAY_SIZE( buff )); 4683 CLSIDFromString( buff, &serviceProviderGUID ); 4684 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */ 4685 4686 /* Determine if this is the Service Provider that the user asked for */ 4687 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) ) 4688 { 4689 continue; 4690 } 4691 4692 if( i == 0 ) /* DP SP */ 4693 { 4694 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 ); 4695 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); 4696 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len ); 4697 } 4698 4699 sizeOfReturnBuffer = 255; 4700 4701 /* Get dwReserved1 */ 4702 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey, 4703 NULL, &returnType, (LPBYTE)returnBuffer, 4704 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 4705 { 4706 ERR(": missing dwReserved1 registry data members\n") ; 4707 continue; 4708 } 4709 4710 if( i == 0 ) 4711 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) ); 4712 4713 sizeOfReturnBuffer = 255; 4714 4715 /* Get dwReserved2 */ 4716 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey, 4717 NULL, &returnType, (LPBYTE)returnBuffer, 4718 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 4719 { 4720 ERR(": missing dwReserved1 registry data members\n") ; 4721 continue; 4722 } 4723 4724 if( i == 0 ) 4725 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) ); 4726 4727 sizeOfReturnBuffer = 255; 4728 4729 /* Get the path for this service provider */ 4730 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey, 4731 NULL, NULL, (LPBYTE)returnBuffer, 4732 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS ) 4733 { 4734 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp ); 4735 continue; 4736 } 4737 4738 TRACE( "Loading %s\n", returnBuffer ); 4739 return LoadLibraryA( returnBuffer ); 4740 } 4741 } 4742 4743 return 0; 4744 } 4745 4746 static HRESULT DP_InitializeDPSP( IDirectPlayImpl *This, HMODULE hServiceProvider ) 4747 { 4748 HRESULT hr; 4749 LPDPSP_SPINIT SPInit; 4750 4751 /* Initialize the service provider by calling SPInit */ 4752 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" ); 4753 4754 if( SPInit == NULL ) 4755 { 4756 ERR( "Service provider doesn't provide SPInit interface?\n" ); 4757 FreeLibrary( hServiceProvider ); 4758 return DPERR_UNAVAILABLE; 4759 } 4760 4761 TRACE( "Calling SPInit (DP SP entry point)\n" ); 4762 4763 hr = (*SPInit)( &This->dp2->spData ); 4764 4765 if( FAILED(hr) ) 4766 { 4767 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) ); 4768 FreeLibrary( hServiceProvider ); 4769 return hr; 4770 } 4771 4772 /* FIXME: Need to verify the sanity of the returned callback table 4773 * using IsBadCodePtr */ 4774 This->dp2->bSPInitialized = TRUE; 4775 4776 /* This interface is now initialized as a DP object */ 4777 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER; 4778 4779 /* Store the handle of the module so that we can unload it later */ 4780 This->dp2->hServiceProvider = hServiceProvider; 4781 4782 return hr; 4783 } 4784 4785 static HRESULT DP_InitializeDPLSP( IDirectPlayImpl *This, HMODULE hLobbyProvider ) 4786 { 4787 HRESULT hr; 4788 LPSP_INIT DPLSPInit; 4789 4790 /* Initialize the service provider by calling SPInit */ 4791 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" ); 4792 4793 if( DPLSPInit == NULL ) 4794 { 4795 ERR( "Service provider doesn't provide DPLSPInit interface?\n" ); 4796 FreeLibrary( hLobbyProvider ); 4797 return DPERR_UNAVAILABLE; 4798 } 4799 4800 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" ); 4801 4802 hr = (*DPLSPInit)( &This->dp2->dplspData ); 4803 4804 if( FAILED(hr) ) 4805 { 4806 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) ); 4807 FreeLibrary( hLobbyProvider ); 4808 return hr; 4809 } 4810 4811 /* FIXME: Need to verify the sanity of the returned callback table 4812 * using IsBadCodePtr */ 4813 4814 This->dp2->bDPLSPInitialized = TRUE; 4815 4816 /* This interface is now initialized as a lobby object */ 4817 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER; 4818 4819 /* Store the handle of the module so that we can unload it later */ 4820 This->dp2->hDPLobbyProvider = hLobbyProvider; 4821 4822 return hr; 4823 } 4824 4825 static HRESULT WINAPI IDirectPlay3AImpl_InitializeConnection( IDirectPlay3A *iface, 4826 void *connection, DWORD flags ) 4827 { 4828 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 4829 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4A_iface, connection, flags ); 4830 } 4831 4832 static HRESULT WINAPI IDirectPlay3Impl_InitializeConnection( IDirectPlay3 *iface, 4833 void *connection, DWORD flags ) 4834 { 4835 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 4836 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags ); 4837 } 4838 4839 static HRESULT WINAPI IDirectPlay4AImpl_InitializeConnection( IDirectPlay4A *iface, 4840 void *connection, DWORD flags ) 4841 { 4842 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 4843 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags ); 4844 } 4845 4846 static HRESULT WINAPI IDirectPlay4Impl_InitializeConnection( IDirectPlay4 *iface, 4847 void *connection, DWORD flags ) 4848 { 4849 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 4850 HMODULE servprov; 4851 GUID sp; 4852 const DWORD size = 80; /* FIXME: Need to calculate it correctly */ 4853 BOOL is_dp_sp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */ 4854 HRESULT hr; 4855 4856 TRACE( "(%p)->(%p,0x%08x)\n", This, connection, flags ); 4857 4858 if ( !connection ) 4859 return DPERR_INVALIDPARAMS; 4860 4861 if ( flags ) 4862 return DPERR_INVALIDFLAGS; 4863 4864 if ( This->dp2->connectionInitialized != NO_PROVIDER ) 4865 return DPERR_ALREADYINITIALIZED; 4866 4867 /* Find out what the requested SP is and how large this buffer is */ 4868 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, connection, size, &sp ); 4869 4870 if ( FAILED(hr) ) 4871 { 4872 ERR( "Invalid compound address?\n" ); 4873 return DPERR_UNAVAILABLE; 4874 } 4875 4876 /* Load the service provider */ 4877 servprov = DP_LoadSP( &sp, &This->dp2->spData, &is_dp_sp ); 4878 4879 if ( !servprov ) 4880 { 4881 ERR( "Unable to load service provider %s\n", debugstr_guid(&sp) ); 4882 return DPERR_UNAVAILABLE; 4883 } 4884 4885 if ( is_dp_sp ) 4886 { 4887 /* Fill in what we can of the Service Provider required information. 4888 * The rest was be done in DP_LoadSP 4889 */ 4890 This->dp2->spData.lpAddress = connection; 4891 This->dp2->spData.dwAddressSize = size; 4892 This->dp2->spData.lpGuid = &sp; 4893 hr = DP_InitializeDPSP( This, servprov ); 4894 } 4895 else 4896 { 4897 This->dp2->dplspData.lpAddress = connection; 4898 hr = DP_InitializeDPLSP( This, servprov ); 4899 } 4900 4901 if ( FAILED(hr) ) 4902 return hr; 4903 4904 return DP_OK; 4905 } 4906 4907 static HRESULT WINAPI IDirectPlay3AImpl_SecureOpen( IDirectPlay3A *iface, 4908 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security, 4909 const DPCREDENTIALS *credentials ) 4910 { 4911 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 4912 return IDirectPlayX_SecureOpen( &This->IDirectPlay4A_iface, sdesc, flags, security, 4913 credentials ); 4914 } 4915 4916 static HRESULT WINAPI IDirectPlay3Impl_SecureOpen( IDirectPlay3 *iface, 4917 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security, 4918 const DPCREDENTIALS *credentials ) 4919 { 4920 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 4921 return IDirectPlayX_SecureOpen( &This->IDirectPlay4_iface, sdesc, flags, security, 4922 credentials ); 4923 } 4924 4925 static HRESULT WINAPI IDirectPlay4AImpl_SecureOpen( IDirectPlay4A *iface, 4926 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity, 4927 const DPCREDENTIALS *lpCredentials ) 4928 { 4929 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 4930 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE ); 4931 } 4932 4933 static HRESULT WINAPI IDirectPlay4Impl_SecureOpen( IDirectPlay4 *iface, 4934 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity, 4935 const DPCREDENTIALS *lpCredentials ) 4936 { 4937 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 4938 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE ); 4939 } 4940 4941 static HRESULT WINAPI IDirectPlay3AImpl_SendChatMessage( IDirectPlay3A *iface, DPID from, DPID to, 4942 DWORD flags, DPCHAT *chatmsg ) 4943 { 4944 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 4945 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4A_iface, from, to, flags, chatmsg ); 4946 } 4947 4948 static HRESULT WINAPI IDirectPlay3Impl_SendChatMessage( IDirectPlay3 *iface, DPID from, DPID to, 4949 DWORD flags, DPCHAT *chatmsg ) 4950 { 4951 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 4952 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4_iface, from, to, flags, chatmsg ); 4953 } 4954 4955 static HRESULT WINAPI IDirectPlay4AImpl_SendChatMessage( IDirectPlay4A *iface, DPID from, 4956 DPID to, DWORD flags, DPCHAT *chatmsg ) 4957 { 4958 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 4959 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg ); 4960 return DP_OK; 4961 } 4962 4963 static HRESULT WINAPI IDirectPlay4Impl_SendChatMessage( IDirectPlay4 *iface, DPID from, DPID to, 4964 DWORD flags, DPCHAT *chatmsg ) 4965 { 4966 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 4967 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg ); 4968 return DP_OK; 4969 } 4970 4971 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupConnectionSettings( IDirectPlay3A *iface, 4972 DWORD flags, DPID group, DPLCONNECTION *connection ) 4973 { 4974 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 4975 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group, 4976 connection ); 4977 } 4978 4979 static HRESULT WINAPI IDirectPlay3Impl_SetGroupConnectionSettings( IDirectPlay3 *iface, 4980 DWORD flags, DPID group, DPLCONNECTION *connection ) 4981 { 4982 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 4983 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group, 4984 connection ); 4985 } 4986 4987 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupConnectionSettings( IDirectPlay4A *iface, 4988 DWORD flags, DPID group, DPLCONNECTION *connection ) 4989 { 4990 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 4991 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection ); 4992 return DP_OK; 4993 } 4994 4995 static HRESULT WINAPI IDirectPlay4Impl_SetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags, 4996 DPID group, DPLCONNECTION *connection ) 4997 { 4998 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 4999 FIXME( "(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection ); 5000 return DP_OK; 5001 } 5002 5003 static HRESULT WINAPI IDirectPlay3AImpl_StartSession( IDirectPlay3A *iface, DWORD flags, 5004 DPID group ) 5005 { 5006 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 5007 return IDirectPlayX_StartSession( &This->IDirectPlay4A_iface, flags, group ); 5008 } 5009 5010 static HRESULT WINAPI IDirectPlay3Impl_StartSession( IDirectPlay3 *iface, DWORD flags, 5011 DPID group ) 5012 { 5013 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 5014 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group ); 5015 } 5016 5017 static HRESULT WINAPI IDirectPlay4AImpl_StartSession( IDirectPlay4A *iface, DWORD flags, 5018 DPID group ) 5019 { 5020 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5021 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group ); 5022 } 5023 5024 static HRESULT WINAPI IDirectPlay4Impl_StartSession( IDirectPlay4 *iface, DWORD flags, DPID group ) 5025 { 5026 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5027 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, flags, group ); 5028 return DP_OK; 5029 } 5030 5031 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupFlags( IDirectPlay3A *iface, DPID group, 5032 DWORD *flags ) 5033 { 5034 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 5035 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4A_iface, group, flags ); 5036 } 5037 5038 static HRESULT WINAPI IDirectPlay3Impl_GetGroupFlags( IDirectPlay3 *iface, DPID group, 5039 DWORD *flags ) 5040 { 5041 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 5042 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags ); 5043 } 5044 5045 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupFlags( IDirectPlay4A *iface, DPID group, 5046 DWORD *flags ) 5047 { 5048 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5049 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags ); 5050 } 5051 5052 static HRESULT WINAPI IDirectPlay4Impl_GetGroupFlags( IDirectPlay4 *iface, DPID group, 5053 DWORD *flags ) 5054 { 5055 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5056 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, flags ); 5057 return DP_OK; 5058 } 5059 5060 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupParent( IDirectPlay3A *iface, DPID group, 5061 DPID *parent ) 5062 { 5063 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 5064 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4A_iface, group, parent ); 5065 } 5066 5067 static HRESULT WINAPI IDirectPlay3Impl_GetGroupParent( IDirectPlay3 *iface, DPID group, 5068 DPID *parent ) 5069 { 5070 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 5071 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent ); 5072 } 5073 5074 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupParent( IDirectPlay4A *iface, DPID group, 5075 DPID *parent ) 5076 { 5077 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5078 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent ); 5079 } 5080 5081 static HRESULT WINAPI IDirectPlay4Impl_GetGroupParent( IDirectPlay4 *iface, DPID group, 5082 DPID *parent ) 5083 { 5084 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5085 lpGroupData gdata; 5086 5087 TRACE( "(%p)->(0x%08x,%p)\n", This, group, parent ); 5088 5089 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL ) 5090 return DPERR_INVALIDGROUP; 5091 5092 *parent = gdata->dpid; 5093 5094 return DP_OK; 5095 } 5096 5097 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAccount( IDirectPlay3A *iface, DPID player, 5098 DWORD flags, void *data, DWORD *size ) 5099 { 5100 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 5101 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4A_iface, player, flags, data, size ); 5102 } 5103 5104 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAccount( IDirectPlay3 *iface, DPID player, 5105 DWORD flags, void *data, DWORD *size ) 5106 { 5107 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 5108 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4_iface, player, flags, data, size ); 5109 } 5110 5111 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAccount( IDirectPlay4A *iface, DPID player, 5112 DWORD flags, void *data, DWORD *size ) 5113 { 5114 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5115 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size ); 5116 return DP_OK; 5117 } 5118 5119 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAccount( IDirectPlay4 *iface, DPID player, 5120 DWORD flags, void *data, DWORD *size ) 5121 { 5122 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5123 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size ); 5124 return DP_OK; 5125 } 5126 5127 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerFlags( IDirectPlay3A *iface, DPID player, 5128 DWORD *flags ) 5129 { 5130 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface ); 5131 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4A_iface, player, flags ); 5132 } 5133 5134 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerFlags( IDirectPlay3 *iface, DPID player, 5135 DWORD *flags ) 5136 { 5137 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface ); 5138 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags ); 5139 } 5140 5141 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerFlags( IDirectPlay4A *iface, DPID player, 5142 DWORD *flags ) 5143 { 5144 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5145 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags ); 5146 } 5147 5148 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerFlags( IDirectPlay4 *iface, DPID player, 5149 DWORD *flags ) 5150 { 5151 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5152 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, flags ); 5153 return DP_OK; 5154 } 5155 5156 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupOwner( IDirectPlay4A *iface, DPID group, 5157 DPID *owner ) 5158 { 5159 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5160 return IDirectPlayX_GetGroupOwner( &This->IDirectPlay4_iface, group, owner ); 5161 } 5162 5163 static HRESULT WINAPI IDirectPlay4Impl_GetGroupOwner( IDirectPlay4 *iface, DPID group, 5164 DPID *owner ) 5165 { 5166 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5167 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, owner ); 5168 return DP_OK; 5169 } 5170 5171 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupOwner( IDirectPlay4A *iface, DPID group, 5172 DPID owner ) 5173 { 5174 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5175 return IDirectPlayX_SetGroupOwner( &This->IDirectPlay4_iface, group, owner ); 5176 } 5177 5178 static HRESULT WINAPI IDirectPlay4Impl_SetGroupOwner( IDirectPlay4 *iface, DPID group , 5179 DPID owner ) 5180 { 5181 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5182 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, owner ); 5183 return DP_OK; 5184 } 5185 5186 static HRESULT WINAPI IDirectPlay4AImpl_SendEx( IDirectPlay4A *iface, DPID from, DPID to, 5187 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context, 5188 DWORD *msgid ) 5189 { 5190 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5191 return IDirectPlayX_SendEx( &This->IDirectPlay4_iface, from, to, flags, data, size, priority, 5192 timeout, context, msgid ); 5193 } 5194 5195 static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, DPID to, 5196 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context, 5197 DWORD *msgid ) 5198 { 5199 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5200 5201 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n", 5202 This, from, to, flags, data, size, priority, timeout, context, msgid ); 5203 5204 if ( This->dp2->connectionInitialized == NO_PROVIDER ) 5205 return DPERR_UNINITIALIZED; 5206 5207 /* FIXME: Add parameter checking */ 5208 /* FIXME: First call to this needs to acquire a message id which will be 5209 * used for multiple sends 5210 */ 5211 5212 /* NOTE: Can't send messages to yourself - this will be trapped in receive */ 5213 5214 /* Verify that the message is being sent from a valid local player. The 5215 * from player may be anonymous DPID_UNKNOWN 5216 */ 5217 if ( from != DPID_UNKNOWN && !DP_FindPlayer( This, from ) ) 5218 { 5219 WARN( "INFO: Invalid from player 0x%08x\n", from ); 5220 return DPERR_INVALIDPLAYER; 5221 } 5222 5223 /* Verify that the message is being sent to a valid player, group or to 5224 * everyone. If it's valid, send it to those players. 5225 */ 5226 if ( to == DPID_ALLPLAYERS ) 5227 { 5228 /* See if SP has the ability to multicast. If so, use it */ 5229 if ( This->dp2->spData.lpCB->SendToGroupEx ) 5230 FIXME( "Use group sendex to group 0\n" ); 5231 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */ 5232 FIXME( "Use obsolete group send to group 0\n" ); 5233 else /* No multicast, multiplicate */ 5234 FIXME( "Send to all players using EnumPlayersInGroup\n" ); 5235 } 5236 else if ( DP_FindPlayer( This, to ) ) 5237 { 5238 /* Have the service provider send this message */ 5239 /* FIXME: Could optimize for local interface sends */ 5240 return DP_SP_SendEx( This, flags, data, size, priority, timeout, context, msgid ); 5241 } 5242 else if ( DP_FindAnyGroup( This, to ) ) 5243 { 5244 /* See if SP has the ability to multicast. If so, use it */ 5245 if ( This->dp2->spData.lpCB->SendToGroupEx ) 5246 FIXME( "Use group sendex\n" ); 5247 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */ 5248 FIXME( "Use obsolete group send to group\n" ); 5249 else /* No multicast, multiplicate */ 5250 FIXME( "Send to all players using EnumPlayersInGroup\n" ); 5251 5252 } 5253 else 5254 return DPERR_INVALIDPLAYER; 5255 5256 /* FIXME: Should return what the send returned */ 5257 return DP_OK; 5258 } 5259 5260 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize, 5261 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID ) 5262 { 5263 LPDPMSG lpMElem; 5264 5265 FIXME( ": stub\n" ); 5266 5267 /* FIXME: This queuing should only be for async messages */ 5268 5269 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) ); 5270 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); 5271 5272 CopyMemory( lpMElem->msg, lpData, dwDataSize ); 5273 5274 /* FIXME: Need to queue based on priority */ 5275 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs ); 5276 5277 return DP_OK; 5278 } 5279 5280 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageQueue( IDirectPlay4A *iface, DPID from, DPID to, 5281 DWORD flags, DWORD *msgs, DWORD *bytes ) 5282 { 5283 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5284 return IDirectPlayX_GetMessageQueue( &This->IDirectPlay4_iface, from, to, flags, msgs, bytes ); 5285 } 5286 5287 static HRESULT WINAPI IDirectPlay4Impl_GetMessageQueue( IDirectPlay4 *iface, DPID from, DPID to, 5288 DWORD flags, DWORD *msgs, DWORD *bytes ) 5289 { 5290 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5291 HRESULT hr = DP_OK; 5292 5293 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n", This, from, to, flags, msgs, bytes ); 5294 5295 /* FIXME: Do we need to do from and to sanity checking here? */ 5296 /* FIXME: What about sends which are not immediate? */ 5297 5298 if ( This->dp2->spData.lpCB->GetMessageQueue ) 5299 { 5300 DPSP_GETMESSAGEQUEUEDATA data; 5301 5302 FIXME( "Calling SP GetMessageQueue - is it right?\n" ); 5303 5304 /* FIXME: None of this is documented :( */ 5305 data.lpISP = This->dp2->spData.lpISP; 5306 data.dwFlags = flags; 5307 data.idFrom = from; 5308 data.idTo = to; 5309 data.lpdwNumMsgs = msgs; 5310 data.lpdwNumBytes = bytes; 5311 5312 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data ); 5313 } 5314 else 5315 FIXME( "No SP for GetMessageQueue - fake some data\n" ); 5316 5317 return hr; 5318 } 5319 5320 static HRESULT dplay_cancelmsg ( IDirectPlayImpl* This, DWORD msgid, DWORD flags, DWORD minprio, 5321 DWORD maxprio ) 5322 { 5323 HRESULT hr = DP_OK; 5324 5325 FIXME( "(%p)->(0x%08x,0x%08x): semi stub\n", This, msgid, flags ); 5326 5327 if ( This->dp2->spData.lpCB->Cancel ) 5328 { 5329 DPSP_CANCELDATA data; 5330 5331 TRACE( "Calling SP Cancel\n" ); 5332 5333 /* FIXME: Undocumented callback */ 5334 5335 data.lpISP = This->dp2->spData.lpISP; 5336 data.dwFlags = flags; 5337 data.lprglpvSPMsgID = NULL; 5338 data.cSPMsgID = msgid; 5339 data.dwMinPriority = minprio; 5340 data.dwMaxPriority = maxprio; 5341 5342 hr = (*This->dp2->spData.lpCB->Cancel)( &data ); 5343 } 5344 else 5345 FIXME( "SP doesn't implement Cancel\n" ); 5346 5347 return hr; 5348 } 5349 5350 static HRESULT WINAPI IDirectPlay4AImpl_CancelMessage( IDirectPlay4A *iface, DWORD msgid, 5351 DWORD flags ) 5352 { 5353 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5354 return IDirectPlayX_CancelMessage( &This->IDirectPlay4_iface, msgid, flags ); 5355 } 5356 5357 static HRESULT WINAPI IDirectPlay4Impl_CancelMessage( IDirectPlay4 *iface, DWORD msgid, 5358 DWORD flags ) 5359 { 5360 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5361 5362 if ( flags != 0 ) 5363 return DPERR_INVALIDFLAGS; 5364 5365 if ( msgid == 0 ) 5366 flags |= DPCANCELSEND_ALL; 5367 5368 return dplay_cancelmsg( This, msgid, flags, 0, 0 ); 5369 } 5370 5371 static HRESULT WINAPI IDirectPlay4AImpl_CancelPriority( IDirectPlay4A *iface, DWORD minprio, 5372 DWORD maxprio, DWORD flags ) 5373 { 5374 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface ); 5375 return IDirectPlayX_CancelPriority( &This->IDirectPlay4_iface, minprio, maxprio, flags ); 5376 } 5377 5378 static HRESULT WINAPI IDirectPlay4Impl_CancelPriority( IDirectPlay4 *iface, DWORD minprio, 5379 DWORD maxprio, DWORD flags ) 5380 { 5381 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface ); 5382 5383 if ( flags != 0 ) 5384 return DPERR_INVALIDFLAGS; 5385 5386 return dplay_cancelmsg( This, 0, DPCANCELSEND_PRIORITY, minprio, maxprio ); 5387 } 5388 5389 static const IDirectPlay2Vtbl dp2_vt = 5390 { 5391 IDirectPlay2Impl_QueryInterface, 5392 IDirectPlay2Impl_AddRef, 5393 IDirectPlay2Impl_Release, 5394 IDirectPlay2Impl_AddPlayerToGroup, 5395 IDirectPlay2Impl_Close, 5396 IDirectPlay2Impl_CreateGroup, 5397 IDirectPlay2Impl_CreatePlayer, 5398 IDirectPlay2Impl_DeletePlayerFromGroup, 5399 IDirectPlay2Impl_DestroyGroup, 5400 IDirectPlay2Impl_DestroyPlayer, 5401 IDirectPlay2Impl_EnumGroupPlayers, 5402 IDirectPlay2Impl_EnumGroups, 5403 IDirectPlay2Impl_EnumPlayers, 5404 IDirectPlay2Impl_EnumSessions, 5405 IDirectPlay2Impl_GetCaps, 5406 IDirectPlay2Impl_GetGroupData, 5407 IDirectPlay2Impl_GetGroupName, 5408 IDirectPlay2Impl_GetMessageCount, 5409 IDirectPlay2Impl_GetPlayerAddress, 5410 IDirectPlay2Impl_GetPlayerCaps, 5411 IDirectPlay2Impl_GetPlayerData, 5412 IDirectPlay2Impl_GetPlayerName, 5413 IDirectPlay2Impl_GetSessionDesc, 5414 IDirectPlay2Impl_Initialize, 5415 IDirectPlay2Impl_Open, 5416 IDirectPlay2Impl_Receive, 5417 IDirectPlay2Impl_Send, 5418 IDirectPlay2Impl_SetGroupData, 5419 IDirectPlay2Impl_SetGroupName, 5420 IDirectPlay2Impl_SetPlayerData, 5421 IDirectPlay2Impl_SetPlayerName, 5422 IDirectPlay2Impl_SetSessionDesc 5423 }; 5424 5425 static const IDirectPlay2Vtbl dp2A_vt = 5426 { 5427 IDirectPlay2AImpl_QueryInterface, 5428 IDirectPlay2AImpl_AddRef, 5429 IDirectPlay2AImpl_Release, 5430 IDirectPlay2AImpl_AddPlayerToGroup, 5431 IDirectPlay2AImpl_Close, 5432 IDirectPlay2AImpl_CreateGroup, 5433 IDirectPlay2AImpl_CreatePlayer, 5434 IDirectPlay2AImpl_DeletePlayerFromGroup, 5435 IDirectPlay2AImpl_DestroyGroup, 5436 IDirectPlay2AImpl_DestroyPlayer, 5437 IDirectPlay2AImpl_EnumGroupPlayers, 5438 IDirectPlay2AImpl_EnumGroups, 5439 IDirectPlay2AImpl_EnumPlayers, 5440 IDirectPlay2AImpl_EnumSessions, 5441 IDirectPlay2AImpl_GetCaps, 5442 IDirectPlay2AImpl_GetGroupData, 5443 IDirectPlay2AImpl_GetGroupName, 5444 IDirectPlay2AImpl_GetMessageCount, 5445 IDirectPlay2AImpl_GetPlayerAddress, 5446 IDirectPlay2AImpl_GetPlayerCaps, 5447 IDirectPlay2AImpl_GetPlayerData, 5448 IDirectPlay2AImpl_GetPlayerName, 5449 IDirectPlay2AImpl_GetSessionDesc, 5450 IDirectPlay2AImpl_Initialize, 5451 IDirectPlay2AImpl_Open, 5452 IDirectPlay2AImpl_Receive, 5453 IDirectPlay2AImpl_Send, 5454 IDirectPlay2AImpl_SetGroupData, 5455 IDirectPlay2AImpl_SetGroupName, 5456 IDirectPlay2AImpl_SetPlayerData, 5457 IDirectPlay2AImpl_SetPlayerName, 5458 IDirectPlay2AImpl_SetSessionDesc 5459 }; 5460 5461 static const IDirectPlay3Vtbl dp3_vt = 5462 { 5463 IDirectPlay3Impl_QueryInterface, 5464 IDirectPlay3Impl_AddRef, 5465 IDirectPlay3Impl_Release, 5466 IDirectPlay3Impl_AddPlayerToGroup, 5467 IDirectPlay3Impl_Close, 5468 IDirectPlay3Impl_CreateGroup, 5469 IDirectPlay3Impl_CreatePlayer, 5470 IDirectPlay3Impl_DeletePlayerFromGroup, 5471 IDirectPlay3Impl_DestroyGroup, 5472 IDirectPlay3Impl_DestroyPlayer, 5473 IDirectPlay3Impl_EnumGroupPlayers, 5474 IDirectPlay3Impl_EnumGroups, 5475 IDirectPlay3Impl_EnumPlayers, 5476 IDirectPlay3Impl_EnumSessions, 5477 IDirectPlay3Impl_GetCaps, 5478 IDirectPlay3Impl_GetGroupData, 5479 IDirectPlay3Impl_GetGroupName, 5480 IDirectPlay3Impl_GetMessageCount, 5481 IDirectPlay3Impl_GetPlayerAddress, 5482 IDirectPlay3Impl_GetPlayerCaps, 5483 IDirectPlay3Impl_GetPlayerData, 5484 IDirectPlay3Impl_GetPlayerName, 5485 IDirectPlay3Impl_GetSessionDesc, 5486 IDirectPlay3Impl_Initialize, 5487 IDirectPlay3Impl_Open, 5488 IDirectPlay3Impl_Receive, 5489 IDirectPlay3Impl_Send, 5490 IDirectPlay3Impl_SetGroupData, 5491 IDirectPlay3Impl_SetGroupName, 5492 IDirectPlay3Impl_SetPlayerData, 5493 IDirectPlay3Impl_SetPlayerName, 5494 IDirectPlay3Impl_SetSessionDesc, 5495 IDirectPlay3Impl_AddGroupToGroup, 5496 IDirectPlay3Impl_CreateGroupInGroup, 5497 IDirectPlay3Impl_DeleteGroupFromGroup, 5498 IDirectPlay3Impl_EnumConnections, 5499 IDirectPlay3Impl_EnumGroupsInGroup, 5500 IDirectPlay3Impl_GetGroupConnectionSettings, 5501 IDirectPlay3Impl_InitializeConnection, 5502 IDirectPlay3Impl_SecureOpen, 5503 IDirectPlay3Impl_SendChatMessage, 5504 IDirectPlay3Impl_SetGroupConnectionSettings, 5505 IDirectPlay3Impl_StartSession, 5506 IDirectPlay3Impl_GetGroupFlags, 5507 IDirectPlay3Impl_GetGroupParent, 5508 IDirectPlay3Impl_GetPlayerAccount, 5509 IDirectPlay3Impl_GetPlayerFlags 5510 }; 5511 5512 static const IDirectPlay3Vtbl dp3A_vt = 5513 { 5514 IDirectPlay3AImpl_QueryInterface, 5515 IDirectPlay3AImpl_AddRef, 5516 IDirectPlay3AImpl_Release, 5517 IDirectPlay3AImpl_AddPlayerToGroup, 5518 IDirectPlay3AImpl_Close, 5519 IDirectPlay3AImpl_CreateGroup, 5520 IDirectPlay3AImpl_CreatePlayer, 5521 IDirectPlay3AImpl_DeletePlayerFromGroup, 5522 IDirectPlay3AImpl_DestroyGroup, 5523 IDirectPlay3AImpl_DestroyPlayer, 5524 IDirectPlay3AImpl_EnumGroupPlayers, 5525 IDirectPlay3AImpl_EnumGroups, 5526 IDirectPlay3AImpl_EnumPlayers, 5527 IDirectPlay3AImpl_EnumSessions, 5528 IDirectPlay3AImpl_GetCaps, 5529 IDirectPlay3AImpl_GetGroupData, 5530 IDirectPlay3AImpl_GetGroupName, 5531 IDirectPlay3AImpl_GetMessageCount, 5532 IDirectPlay3AImpl_GetPlayerAddress, 5533 IDirectPlay3AImpl_GetPlayerCaps, 5534 IDirectPlay3AImpl_GetPlayerData, 5535 IDirectPlay3AImpl_GetPlayerName, 5536 IDirectPlay3AImpl_GetSessionDesc, 5537 IDirectPlay3AImpl_Initialize, 5538 IDirectPlay3AImpl_Open, 5539 IDirectPlay3AImpl_Receive, 5540 IDirectPlay3AImpl_Send, 5541 IDirectPlay3AImpl_SetGroupData, 5542 IDirectPlay3AImpl_SetGroupName, 5543 IDirectPlay3AImpl_SetPlayerData, 5544 IDirectPlay3AImpl_SetPlayerName, 5545 IDirectPlay3AImpl_SetSessionDesc, 5546 IDirectPlay3AImpl_AddGroupToGroup, 5547 IDirectPlay3AImpl_CreateGroupInGroup, 5548 IDirectPlay3AImpl_DeleteGroupFromGroup, 5549 IDirectPlay3AImpl_EnumConnections, 5550 IDirectPlay3AImpl_EnumGroupsInGroup, 5551 IDirectPlay3AImpl_GetGroupConnectionSettings, 5552 IDirectPlay3AImpl_InitializeConnection, 5553 IDirectPlay3AImpl_SecureOpen, 5554 IDirectPlay3AImpl_SendChatMessage, 5555 IDirectPlay3AImpl_SetGroupConnectionSettings, 5556 IDirectPlay3AImpl_StartSession, 5557 IDirectPlay3AImpl_GetGroupFlags, 5558 IDirectPlay3AImpl_GetGroupParent, 5559 IDirectPlay3AImpl_GetPlayerAccount, 5560 IDirectPlay3AImpl_GetPlayerFlags 5561 }; 5562 5563 static const IDirectPlay4Vtbl dp4_vt = 5564 { 5565 IDirectPlay4Impl_QueryInterface, 5566 IDirectPlay4Impl_AddRef, 5567 IDirectPlay4Impl_Release, 5568 IDirectPlay4Impl_AddPlayerToGroup, 5569 IDirectPlay4Impl_Close, 5570 IDirectPlay4Impl_CreateGroup, 5571 IDirectPlay4Impl_CreatePlayer, 5572 IDirectPlay4Impl_DeletePlayerFromGroup, 5573 IDirectPlay4Impl_DestroyGroup, 5574 IDirectPlay4Impl_DestroyPlayer, 5575 IDirectPlay4Impl_EnumGroupPlayers, 5576 IDirectPlay4Impl_EnumGroups, 5577 IDirectPlay4Impl_EnumPlayers, 5578 IDirectPlay4Impl_EnumSessions, 5579 IDirectPlay4Impl_GetCaps, 5580 IDirectPlay4Impl_GetGroupData, 5581 IDirectPlay4Impl_GetGroupName, 5582 IDirectPlay4Impl_GetMessageCount, 5583 IDirectPlay4Impl_GetPlayerAddress, 5584 IDirectPlay4Impl_GetPlayerCaps, 5585 IDirectPlay4Impl_GetPlayerData, 5586 IDirectPlay4Impl_GetPlayerName, 5587 IDirectPlay4Impl_GetSessionDesc, 5588 IDirectPlay4Impl_Initialize, 5589 IDirectPlay4Impl_Open, 5590 IDirectPlay4Impl_Receive, 5591 IDirectPlay4Impl_Send, 5592 IDirectPlay4Impl_SetGroupData, 5593 IDirectPlay4Impl_SetGroupName, 5594 IDirectPlay4Impl_SetPlayerData, 5595 IDirectPlay4Impl_SetPlayerName, 5596 IDirectPlay4Impl_SetSessionDesc, 5597 IDirectPlay4Impl_AddGroupToGroup, 5598 IDirectPlay4Impl_CreateGroupInGroup, 5599 IDirectPlay4Impl_DeleteGroupFromGroup, 5600 IDirectPlay4Impl_EnumConnections, 5601 IDirectPlay4Impl_EnumGroupsInGroup, 5602 IDirectPlay4Impl_GetGroupConnectionSettings, 5603 IDirectPlay4Impl_InitializeConnection, 5604 IDirectPlay4Impl_SecureOpen, 5605 IDirectPlay4Impl_SendChatMessage, 5606 IDirectPlay4Impl_SetGroupConnectionSettings, 5607 IDirectPlay4Impl_StartSession, 5608 IDirectPlay4Impl_GetGroupFlags, 5609 IDirectPlay4Impl_GetGroupParent, 5610 IDirectPlay4Impl_GetPlayerAccount, 5611 IDirectPlay4Impl_GetPlayerFlags, 5612 IDirectPlay4Impl_GetGroupOwner, 5613 IDirectPlay4Impl_SetGroupOwner, 5614 IDirectPlay4Impl_SendEx, 5615 IDirectPlay4Impl_GetMessageQueue, 5616 IDirectPlay4Impl_CancelMessage, 5617 IDirectPlay4Impl_CancelPriority 5618 }; 5619 5620 static const IDirectPlay4Vtbl dp4A_vt = 5621 { 5622 IDirectPlay4AImpl_QueryInterface, 5623 IDirectPlay4AImpl_AddRef, 5624 IDirectPlay4AImpl_Release, 5625 IDirectPlay4AImpl_AddPlayerToGroup, 5626 IDirectPlay4AImpl_Close, 5627 IDirectPlay4AImpl_CreateGroup, 5628 IDirectPlay4AImpl_CreatePlayer, 5629 IDirectPlay4AImpl_DeletePlayerFromGroup, 5630 IDirectPlay4AImpl_DestroyGroup, 5631 IDirectPlay4AImpl_DestroyPlayer, 5632 IDirectPlay4AImpl_EnumGroupPlayers, 5633 IDirectPlay4AImpl_EnumGroups, 5634 IDirectPlay4AImpl_EnumPlayers, 5635 IDirectPlay4AImpl_EnumSessions, 5636 IDirectPlay4AImpl_GetCaps, 5637 IDirectPlay4AImpl_GetGroupData, 5638 IDirectPlay4AImpl_GetGroupName, 5639 IDirectPlay4AImpl_GetMessageCount, 5640 IDirectPlay4AImpl_GetPlayerAddress, 5641 IDirectPlay4AImpl_GetPlayerCaps, 5642 IDirectPlay4AImpl_GetPlayerData, 5643 IDirectPlay4AImpl_GetPlayerName, 5644 IDirectPlay4AImpl_GetSessionDesc, 5645 IDirectPlay4AImpl_Initialize, 5646 IDirectPlay4AImpl_Open, 5647 IDirectPlay4AImpl_Receive, 5648 IDirectPlay4AImpl_Send, 5649 IDirectPlay4AImpl_SetGroupData, 5650 IDirectPlay4AImpl_SetGroupName, 5651 IDirectPlay4AImpl_SetPlayerData, 5652 IDirectPlay4AImpl_SetPlayerName, 5653 IDirectPlay4AImpl_SetSessionDesc, 5654 IDirectPlay4AImpl_AddGroupToGroup, 5655 IDirectPlay4AImpl_CreateGroupInGroup, 5656 IDirectPlay4AImpl_DeleteGroupFromGroup, 5657 IDirectPlay4AImpl_EnumConnections, 5658 IDirectPlay4AImpl_EnumGroupsInGroup, 5659 IDirectPlay4AImpl_GetGroupConnectionSettings, 5660 IDirectPlay4AImpl_InitializeConnection, 5661 IDirectPlay4AImpl_SecureOpen, 5662 IDirectPlay4AImpl_SendChatMessage, 5663 IDirectPlay4AImpl_SetGroupConnectionSettings, 5664 IDirectPlay4AImpl_StartSession, 5665 IDirectPlay4AImpl_GetGroupFlags, 5666 IDirectPlay4AImpl_GetGroupParent, 5667 IDirectPlay4AImpl_GetPlayerAccount, 5668 IDirectPlay4AImpl_GetPlayerFlags, 5669 IDirectPlay4AImpl_GetGroupOwner, 5670 IDirectPlay4AImpl_SetGroupOwner, 5671 IDirectPlay4AImpl_SendEx, 5672 IDirectPlay4AImpl_GetMessageQueue, 5673 IDirectPlay4AImpl_CancelMessage, 5674 IDirectPlay4AImpl_CancelPriority 5675 }; 5676 5677 HRESULT dplay_create( REFIID riid, void **ppv ) 5678 { 5679 IDirectPlayImpl *obj; 5680 HRESULT hr; 5681 5682 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv ); 5683 5684 *ppv = NULL; 5685 obj = HeapAlloc( GetProcessHeap(), 0, sizeof( *obj ) ); 5686 if ( !obj ) 5687 return DPERR_OUTOFMEMORY; 5688 5689 obj->IDirectPlay_iface.lpVtbl = &dp_vt; 5690 obj->IDirectPlay2A_iface.lpVtbl = &dp2A_vt; 5691 obj->IDirectPlay2_iface.lpVtbl = &dp2_vt; 5692 obj->IDirectPlay3A_iface.lpVtbl = &dp3A_vt; 5693 obj->IDirectPlay3_iface.lpVtbl = &dp3_vt; 5694 obj->IDirectPlay4A_iface.lpVtbl = &dp4A_vt; 5695 obj->IDirectPlay4_iface.lpVtbl = &dp4_vt; 5696 obj->numIfaces = 1; 5697 obj->ref = 0; 5698 obj->ref2A = 0; 5699 obj->ref2 = 0; 5700 obj->ref3A = 0; 5701 obj->ref3 = 0; 5702 obj->ref4A = 0; 5703 obj->ref4 = 1; 5704 5705 InitializeCriticalSection( &obj->lock ); 5706 obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayImpl.lock"); 5707 5708 if ( DP_CreateDirectPlay2( obj ) ) 5709 hr = IDirectPlayX_QueryInterface( &obj->IDirectPlay4_iface, riid, ppv ); 5710 else 5711 hr = DPERR_NOMEMORY; 5712 IDirectPlayX_Release( &obj->IDirectPlay4_iface ); 5713 5714 return hr; 5715 } 5716 5717 5718 HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData ) 5719 { 5720 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer ); 5721 5722 if( lpPlayer == NULL ) 5723 { 5724 return DPERR_INVALIDPLAYER; 5725 } 5726 5727 *lplpData = lpPlayer->lpPData->lpSPPlayerData; 5728 5729 return DP_OK; 5730 } 5731 5732 HRESULT DP_SetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void *lpData ) 5733 { 5734 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer ); 5735 5736 if( lpPlayer == NULL ) 5737 { 5738 return DPERR_INVALIDPLAYER; 5739 } 5740 5741 lpPlayer->lpPData->lpSPPlayerData = lpData; 5742 5743 return DP_OK; 5744 } 5745 5746 /*************************************************************************** 5747 * DirectPlayEnumerateAW 5748 * 5749 * The pointer to the structure lpContext will be filled with the 5750 * appropriate data for each service offered by the OS. These services are 5751 * not necessarily available on this particular machine but are defined 5752 * as simple service providers under the "Service Providers" registry key. 5753 * This structure is then passed to lpEnumCallback for each of the different 5754 * services. 5755 * 5756 * This API is useful only for applications written using DirectX3 or 5757 * worse. It is superseded by IDirectPlay3::EnumConnections which also 5758 * gives information on the actual connections. 5759 * 5760 * defn of a service provider: 5761 * A dynamic-link library used by DirectPlay to communicate over a network. 5762 * The service provider contains all the network-specific code required 5763 * to send and receive messages. Online services and network operators can 5764 * supply service providers to use specialized hardware, protocols, communications 5765 * media, and network resources. 5766 * 5767 */ 5768 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA, 5769 LPDPENUMDPCALLBACKW lpEnumCallbackW, 5770 LPVOID lpContext) 5771 { 5772 HKEY hkResult; 5773 static const WCHAR searchSubKey[] = { 5774 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\', 5775 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\', 5776 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\', 5777 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 }; 5778 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 }; 5779 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 }; 5780 5781 DWORD dwIndex; 5782 FILETIME filetime; 5783 5784 char *descriptionA = NULL; 5785 DWORD max_sizeOfDescriptionA = 0; 5786 WCHAR *descriptionW = NULL; 5787 DWORD max_sizeOfDescriptionW = 0; 5788 DWORD sizeOfSubKeyName; 5789 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */ 5790 LONG ret_value; 5791 static GUID *guid_cache; 5792 static int cache_count; 5793 5794 if (!lpEnumCallbackA && !lpEnumCallbackW) 5795 { 5796 return DPERR_INVALIDPARAMS; 5797 } 5798 5799 /* Need to loop over the service providers in the registry */ 5800 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey, 5801 0, KEY_READ, &hkResult) != ERROR_SUCCESS) 5802 { 5803 /* Hmmm. Does this mean that there are no service providers? */ 5804 ERR(": no service provider key in the registry - check your Wine installation !!!\n"); 5805 return DPERR_GENERIC; 5806 } 5807 5808 dwIndex = 0; 5809 do 5810 { 5811 sizeOfSubKeyName = ARRAY_SIZE(subKeyName); 5812 ret_value = RegEnumKeyW(hkResult, dwIndex, subKeyName, sizeOfSubKeyName); 5813 dwIndex++; 5814 } 5815 while (ret_value == ERROR_SUCCESS); 5816 /* The game Swing from bug 37185 expects GUID values to persist after 5817 * the end of the enumeration. */ 5818 if (cache_count < dwIndex) 5819 { 5820 HeapFree(GetProcessHeap(), 0, guid_cache); 5821 guid_cache = HeapAlloc(GetProcessHeap(), 0, sizeof(GUID) * dwIndex); 5822 if (!guid_cache) 5823 { 5824 ERR(": failed to allocate required memory.\n"); 5825 return DPERR_EXCEPTION; 5826 } 5827 cache_count = dwIndex; 5828 } 5829 /* Traverse all the service providers we have available */ 5830 dwIndex = 0; 5831 while (1) 5832 { 5833 HKEY hkServiceProvider; 5834 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ]; 5835 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent); 5836 5837 sizeOfSubKeyName = ARRAY_SIZE(subKeyName); 5838 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 5839 NULL, NULL, NULL, &filetime); 5840 if (ret_value == ERROR_NO_MORE_ITEMS) 5841 break; 5842 else if (ret_value != ERROR_SUCCESS) 5843 { 5844 ERR(": could not enumerate on service provider key.\n"); 5845 return DPERR_EXCEPTION; 5846 } 5847 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName)); 5848 5849 /* Open the key for this service provider */ 5850 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS) 5851 { 5852 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName)); 5853 continue; 5854 } 5855 5856 /* Get the GUID from the registry */ 5857 if (RegQueryValueExW(hkServiceProvider, guidKey, 5858 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS) 5859 { 5860 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName)); 5861 continue; 5862 } 5863 if (sizeOfGuidKeyContent != sizeof(guidKeyContent)) 5864 { 5865 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent)); 5866 continue; 5867 } 5868 CLSIDFromString(guidKeyContent, &guid_cache[dwIndex]); 5869 5870 /* The enumeration will return FALSE if we are not to continue. 5871 * 5872 * Note: on my windows box, major / minor version is 6 / 0 for all service providers 5873 * and have no relation to any of the two dwReserved1 and dwReserved2 keys. 5874 * I think that it simply means that they are in-line with DirectX 6.0 5875 */ 5876 if (lpEnumCallbackA) 5877 { 5878 DWORD sizeOfDescription = 0; 5879 5880 /* Note that this is the A case of this function, so use the A variant to get the description string */ 5881 if (RegQueryValueExA(hkServiceProvider, "DescriptionA", 5882 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS) 5883 { 5884 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName)); 5885 continue; 5886 } 5887 if (sizeOfDescription > max_sizeOfDescriptionA) 5888 { 5889 HeapFree(GetProcessHeap(), 0, descriptionA); 5890 max_sizeOfDescriptionA = sizeOfDescription; 5891 } 5892 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription); 5893 RegQueryValueExA(hkServiceProvider, "DescriptionA", 5894 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription); 5895 5896 if (!lpEnumCallbackA(&guid_cache[dwIndex], descriptionA, 6, 0, lpContext)) 5897 goto end; 5898 } 5899 else 5900 { 5901 DWORD sizeOfDescription = 0; 5902 5903 if (RegQueryValueExW(hkServiceProvider, descW, 5904 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS) 5905 { 5906 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName)); 5907 continue; 5908 } 5909 if (sizeOfDescription > max_sizeOfDescriptionW) 5910 { 5911 HeapFree(GetProcessHeap(), 0, descriptionW); 5912 max_sizeOfDescriptionW = sizeOfDescription; 5913 } 5914 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription); 5915 RegQueryValueExW(hkServiceProvider, descW, 5916 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription); 5917 5918 if (!lpEnumCallbackW(&guid_cache[dwIndex], descriptionW, 6, 0, lpContext)) 5919 goto end; 5920 } 5921 5922 dwIndex++; 5923 } 5924 5925 end: 5926 HeapFree(GetProcessHeap(), 0, descriptionA); 5927 HeapFree(GetProcessHeap(), 0, descriptionW); 5928 5929 return DP_OK; 5930 } 5931 5932 /*************************************************************************** 5933 * DirectPlayEnumerate [DPLAYX.9] 5934 * DirectPlayEnumerateA [DPLAYX.2] 5935 */ 5936 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext ) 5937 { 5938 TRACE("(%p,%p)\n", lpEnumCallback, lpContext); 5939 5940 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext); 5941 } 5942 5943 /*************************************************************************** 5944 * DirectPlayEnumerateW [DPLAYX.3] 5945 */ 5946 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext ) 5947 { 5948 TRACE("(%p,%p)\n", lpEnumCallback, lpContext); 5949 5950 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext); 5951 } 5952 5953 typedef struct tagCreateEnum 5954 { 5955 LPVOID lpConn; 5956 LPCGUID lpGuid; 5957 } CreateEnumData, *lpCreateEnumData; 5958 5959 /* Find and copy the matching connection for the SP guid */ 5960 static BOOL CALLBACK cbDPCreateEnumConnections( 5961 LPCGUID lpguidSP, 5962 LPVOID lpConnection, 5963 DWORD dwConnectionSize, 5964 LPCDPNAME lpName, 5965 DWORD dwFlags, 5966 LPVOID lpContext) 5967 { 5968 lpCreateEnumData lpData = (lpCreateEnumData)lpContext; 5969 5970 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) ) 5971 { 5972 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) ); 5973 5974 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 5975 dwConnectionSize ); 5976 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize ); 5977 5978 /* Found the record that we were looking for */ 5979 return FALSE; 5980 } 5981 5982 /* Haven't found what were looking for yet */ 5983 return TRUE; 5984 } 5985 5986 5987 /*************************************************************************** 5988 * DirectPlayCreate [DPLAYX.1] 5989 * 5990 */ 5991 HRESULT WINAPI DirectPlayCreate 5992 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk ) 5993 { 5994 HRESULT hr; 5995 LPDIRECTPLAY3A lpDP3A; 5996 CreateEnumData cbData; 5997 5998 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk ); 5999 6000 if( pUnk != NULL ) 6001 { 6002 return CLASS_E_NOAGGREGATION; 6003 } 6004 6005 if( (lplpDP == NULL) || (lpGUID == NULL) ) 6006 { 6007 return DPERR_INVALIDPARAMS; 6008 } 6009 6010 if ( dplay_create( &IID_IDirectPlay, (void**)lplpDP ) != DP_OK ) 6011 return DPERR_UNAVAILABLE; 6012 6013 if( IsEqualGUID( &GUID_NULL, lpGUID ) ) 6014 { 6015 /* The GUID_NULL means don't bind a service provider. Just return the 6016 interface as is */ 6017 return DP_OK; 6018 } 6019 6020 /* Bind the desired service provider since lpGUID is non NULL */ 6021 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) ); 6022 6023 /* We're going to use a DP3 interface */ 6024 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A, 6025 (LPVOID*)&lpDP3A ); 6026 if( FAILED(hr) ) 6027 { 6028 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) ); 6029 return hr; 6030 } 6031 6032 cbData.lpConn = NULL; 6033 cbData.lpGuid = lpGUID; 6034 6035 /* We were given a service provider, find info about it... */ 6036 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections, 6037 &cbData, DPCONNECTION_DIRECTPLAY ); 6038 if( ( FAILED(hr) ) || 6039 ( cbData.lpConn == NULL ) 6040 ) 6041 { 6042 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) ); 6043 IDirectPlayX_Release( lpDP3A ); 6044 return DPERR_UNAVAILABLE; 6045 } 6046 6047 /* Initialize the service provider */ 6048 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 ); 6049 if( FAILED(hr) ) 6050 { 6051 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) ); 6052 HeapFree( GetProcessHeap(), 0, cbData.lpConn ); 6053 IDirectPlayX_Release( lpDP3A ); 6054 return hr; 6055 } 6056 6057 /* Release our version of the interface now that we're done with it */ 6058 IDirectPlayX_Release( lpDP3A ); 6059 HeapFree( GetProcessHeap(), 0, cbData.lpConn ); 6060 6061 return DP_OK; 6062 } 6063