1 /* Direct Play Lobby 2 & 3 Implementation 2 * 3 * Copyright 1998,1999,2000 - 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 #include <stdarg.h> 20 #include <string.h> 21 22 #define COBJMACROS 23 #define NONAMELESSUNION 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "winerror.h" 28 #include "winreg.h" 29 #include "winnls.h" 30 #include "wine/debug.h" 31 32 #include "dplayx_global.h" 33 #include "dplayx_messages.h" 34 #include "dplayx_queue.h" 35 #include "dplobby.h" 36 37 WINE_DEFAULT_DEBUG_CHANNEL(dplay); 38 39 /* Forward declarations for this module helper methods */ 40 HRESULT DPL_CreateCompoundAddress ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount, 41 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface )DECLSPEC_HIDDEN; 42 43 static HRESULT DPL_CreateAddress( REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData, DWORD dwDataSize, 44 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface ); 45 46 47 /***************************************************************************** 48 * IDirectPlayLobby {1,2,3} implementation structure 49 * 50 * The philosophy behind this extra pointer dereference is that I wanted to 51 * have the same structure for all types of objects without having to do 52 * a lot of casting. I also only wanted to implement an interface in the 53 * object it was "released" with IUnknown interface being implemented in the 1 version. 54 * Of course, with these new interfaces comes the data required to keep the state required 55 * by these interfaces. So, basically, the pointers contain the data associated with 56 * a release. If you use the data associated with release 3 in a release 2 object, you'll 57 * get a run time trap, as that won't have any data. 58 * 59 */ 60 struct DPLMSG 61 { 62 DPQ_ENTRY( DPLMSG ) msgs; /* Link to next queued message */ 63 }; 64 typedef struct DPLMSG* LPDPLMSG; 65 66 typedef struct IDirectPlayLobbyImpl 67 { 68 IDirectPlayLobby IDirectPlayLobby_iface; 69 IDirectPlayLobbyA IDirectPlayLobbyA_iface; 70 IDirectPlayLobby2 IDirectPlayLobby2_iface; 71 IDirectPlayLobby2A IDirectPlayLobby2A_iface; 72 IDirectPlayLobby3 IDirectPlayLobby3_iface; 73 IDirectPlayLobby3A IDirectPlayLobby3A_iface; 74 LONG numIfaces; /* "in use interfaces" refcount */ 75 LONG ref, refA, ref2, ref2A, ref3, ref3A; 76 CRITICAL_SECTION lock; 77 HKEY cbkeyhack; 78 DWORD msgtid; 79 DPQ_HEAD( DPLMSG ) msgs; /* List of messages received */ 80 } IDirectPlayLobbyImpl; 81 82 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby( IDirectPlayLobby *iface ) 83 { 84 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby_iface ); 85 } 86 87 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobbyA( IDirectPlayLobbyA *iface ) 88 { 89 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobbyA_iface ); 90 } 91 92 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby2( IDirectPlayLobby2 *iface ) 93 { 94 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby2_iface ); 95 } 96 97 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby2A( IDirectPlayLobby2A *iface ) 98 { 99 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby2A_iface ); 100 } 101 102 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby3( IDirectPlayLobby3 *iface ) 103 { 104 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby3_iface ); 105 } 106 107 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby3A( IDirectPlayLobby3A *iface ) 108 { 109 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby3A_iface ); 110 } 111 112 static void dplobby_destroy(IDirectPlayLobbyImpl *obj) 113 { 114 if ( obj->msgtid ) 115 FIXME( "Should kill the msg thread\n" ); 116 117 DPQ_DELETEQ( obj->msgs, msgs, LPDPLMSG, cbDeleteElemFromHeap ); 118 obj->lock.DebugInfo->Spare[0] = 0; 119 DeleteCriticalSection( &obj->lock ); 120 HeapFree( GetProcessHeap(), 0, obj ); 121 } 122 123 static HRESULT WINAPI IDirectPlayLobbyAImpl_QueryInterface( IDirectPlayLobbyA *iface, REFIID riid, 124 void **ppv ) 125 { 126 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 127 return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv ); 128 } 129 130 static HRESULT WINAPI IDirectPlayLobbyImpl_QueryInterface( IDirectPlayLobby *iface, REFIID riid, 131 void **ppv ) 132 { 133 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 134 return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv ); 135 } 136 137 static HRESULT WINAPI IDirectPlayLobby2AImpl_QueryInterface( IDirectPlayLobby2A *iface, REFIID riid, 138 void **ppv ) 139 { 140 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 141 return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv ); 142 } 143 144 static HRESULT WINAPI IDirectPlayLobby2Impl_QueryInterface( IDirectPlayLobby2 *iface, REFIID riid, 145 void **ppv ) 146 { 147 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 148 return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv ); 149 } 150 151 static HRESULT WINAPI IDirectPlayLobby3AImpl_QueryInterface( IDirectPlayLobby3A *iface, REFIID riid, 152 void **ppv ) 153 { 154 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 155 return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv ); 156 } 157 158 static HRESULT WINAPI IDirectPlayLobby3Impl_QueryInterface( IDirectPlayLobby3 *iface, REFIID riid, 159 void **ppv ) 160 { 161 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 162 163 if ( IsEqualGUID( &IID_IUnknown, riid ) ) 164 { 165 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv ); 166 *ppv = &This->IDirectPlayLobby_iface; 167 } 168 else if ( IsEqualGUID( &IID_IDirectPlayLobby, riid ) ) 169 { 170 TRACE( "(%p)->(IID_IDirectPlayLobby %p)\n", This, ppv ); 171 *ppv = &This->IDirectPlayLobby_iface; 172 } 173 else if ( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) ) 174 { 175 TRACE( "(%p)->(IID_IDirectPlayLobbyA %p)\n", This, ppv ); 176 *ppv = &This->IDirectPlayLobbyA_iface; 177 } 178 else if ( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) ) 179 { 180 TRACE( "(%p)->(IID_IDirectPlayLobby2 %p)\n", This, ppv ); 181 *ppv = &This->IDirectPlayLobby2_iface; 182 } 183 else if ( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) ) 184 { 185 TRACE( "(%p)->(IID_IDirectPlayLobby2A %p)\n", This, ppv ); 186 *ppv = &This->IDirectPlayLobby2A_iface; 187 } 188 else if ( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) ) 189 { 190 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv ); 191 *ppv = &This->IDirectPlayLobby3_iface; 192 } 193 else if ( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) ) 194 { 195 TRACE( "(%p)->(IID_IDirectPlayLobby3A %p)\n", This, ppv ); 196 *ppv = &This->IDirectPlayLobby3A_iface; 197 } 198 else 199 { 200 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 201 *ppv = NULL; 202 return E_NOINTERFACE; 203 } 204 205 IUnknown_AddRef((IUnknown*)*ppv); 206 return S_OK; 207 } 208 209 static ULONG WINAPI IDirectPlayLobbyAImpl_AddRef( IDirectPlayLobbyA *iface ) 210 { 211 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 212 ULONG ref = InterlockedIncrement( &This->refA ); 213 214 TRACE( "(%p) refA=%d\n", This, ref ); 215 216 if ( ref == 1 ) 217 InterlockedIncrement( &This->numIfaces ); 218 219 return ref; 220 } 221 222 static ULONG WINAPI IDirectPlayLobbyImpl_AddRef( IDirectPlayLobby *iface ) 223 { 224 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 225 ULONG ref = InterlockedIncrement( &This->ref ); 226 227 TRACE( "(%p) ref=%d\n", This, ref ); 228 229 if ( ref == 1 ) 230 InterlockedIncrement( &This->numIfaces ); 231 232 return ref; 233 } 234 235 static ULONG WINAPI IDirectPlayLobby2AImpl_AddRef(IDirectPlayLobby2A *iface) 236 { 237 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 238 ULONG ref = InterlockedIncrement( &This->ref2A ); 239 240 TRACE( "(%p) ref2A=%d\n", This, ref ); 241 242 if ( ref == 1 ) 243 InterlockedIncrement( &This->numIfaces ); 244 245 return ref; 246 } 247 248 static ULONG WINAPI IDirectPlayLobby2Impl_AddRef(IDirectPlayLobby2 *iface) 249 { 250 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 251 ULONG ref = InterlockedIncrement( &This->ref2 ); 252 253 TRACE( "(%p) ref2=%d\n", This, ref ); 254 255 if ( ref == 1 ) 256 InterlockedIncrement( &This->numIfaces ); 257 258 return ref; 259 } 260 261 static ULONG WINAPI IDirectPlayLobby3AImpl_AddRef(IDirectPlayLobby3A *iface) 262 { 263 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 264 ULONG ref = InterlockedIncrement( &This->ref3A ); 265 266 TRACE( "(%p) ref3A=%d\n", This, ref ); 267 268 if ( ref == 1 ) 269 InterlockedIncrement( &This->numIfaces ); 270 271 return ref; 272 } 273 274 static ULONG WINAPI IDirectPlayLobby3Impl_AddRef(IDirectPlayLobby3 *iface) 275 { 276 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 277 ULONG ref = InterlockedIncrement( &This->ref3 ); 278 279 TRACE( "(%p) ref3=%d\n", This, ref ); 280 281 if ( ref == 1 ) 282 InterlockedIncrement( &This->numIfaces ); 283 284 return ref; 285 } 286 287 static ULONG WINAPI IDirectPlayLobbyAImpl_Release( IDirectPlayLobbyA *iface ) 288 { 289 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 290 ULONG ref = InterlockedDecrement( &This->refA ); 291 292 TRACE( "(%p) refA=%d\n", This, ref ); 293 294 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 295 dplobby_destroy( This ); 296 297 return ref; 298 } 299 300 static ULONG WINAPI IDirectPlayLobbyImpl_Release( IDirectPlayLobby *iface ) 301 { 302 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 303 ULONG ref = InterlockedDecrement( &This->ref ); 304 305 TRACE( "(%p) ref=%d\n", This, ref ); 306 307 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 308 dplobby_destroy( This ); 309 310 return ref; 311 } 312 313 static ULONG WINAPI IDirectPlayLobby2AImpl_Release(IDirectPlayLobby2A *iface) 314 { 315 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 316 ULONG ref = InterlockedDecrement( &This->ref2A ); 317 318 TRACE( "(%p) ref2A=%d\n", This, ref ); 319 320 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 321 dplobby_destroy( This ); 322 323 return ref; 324 } 325 326 static ULONG WINAPI IDirectPlayLobby2Impl_Release(IDirectPlayLobby2 *iface) 327 { 328 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 329 ULONG ref = InterlockedDecrement( &This->ref2 ); 330 331 TRACE( "(%p) ref2=%d\n", This, ref ); 332 333 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 334 dplobby_destroy( This ); 335 336 return ref; 337 } 338 339 static ULONG WINAPI IDirectPlayLobby3AImpl_Release(IDirectPlayLobby3A *iface) 340 { 341 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 342 ULONG ref = InterlockedDecrement( &This->ref3A ); 343 344 TRACE( "(%p) ref3A=%d\n", This, ref ); 345 346 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 347 dplobby_destroy( This ); 348 349 return ref; 350 } 351 352 static ULONG WINAPI IDirectPlayLobby3Impl_Release(IDirectPlayLobby3 *iface) 353 { 354 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 355 ULONG ref = InterlockedDecrement( &This->ref3 ); 356 357 TRACE( "(%p) ref3=%d\n", This, ref ); 358 359 if ( !ref && !InterlockedDecrement( &This->numIfaces ) ) 360 dplobby_destroy( This ); 361 362 return ref; 363 } 364 365 366 /******************************************************************** 367 * 368 * Connects an application to the session specified by the DPLCONNECTION 369 * structure currently stored with the DirectPlayLobby object. 370 * 371 * Returns an IDirectPlay interface. 372 * 373 */ 374 static HRESULT DPL_ConnectEx( IDirectPlayLobbyImpl *This, DWORD dwFlags, REFIID riid, void **lplpDP, 375 IUnknown* pUnk) 376 { 377 HRESULT hr; 378 DWORD dwOpenFlags = 0; 379 DWORD dwConnSize = 0; 380 LPDPLCONNECTION lpConn; 381 382 FIXME("(%p)->(0x%08x,%p,%p): semi stub\n", This, dwFlags, lplpDP, pUnk ); 383 384 if( pUnk ) 385 { 386 return DPERR_INVALIDPARAMS; 387 } 388 389 /* Backwards compatibility */ 390 if( dwFlags == 0 ) 391 { 392 dwFlags = DPCONNECT_RETURNSTATUS; 393 } 394 395 if ( ( hr = dplay_create( riid, lplpDP ) ) != DP_OK ) 396 { 397 ERR( "error creating interface for %s:%s.\n", 398 debugstr_guid( riid ), DPLAYX_HresultToString( hr ) ); 399 return hr; 400 } 401 402 /* FIXME: Is it safe/correct to use appID of 0? */ 403 hr = IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface, 404 0, NULL, &dwConnSize ); 405 if( hr != DPERR_BUFFERTOOSMALL ) 406 { 407 return hr; 408 } 409 410 lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwConnSize ); 411 412 if( lpConn == NULL ) 413 { 414 return DPERR_NOMEMORY; 415 } 416 417 /* FIXME: Is it safe/correct to use appID of 0? */ 418 hr = IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface, 419 0, lpConn, &dwConnSize ); 420 if( FAILED( hr ) ) 421 { 422 HeapFree( GetProcessHeap(), 0, lpConn ); 423 return hr; 424 } 425 426 #if 0 427 /* - Need to call IDirectPlay::EnumConnections with the service provider to get that good information 428 * - Need to call CreateAddress to create the lpConnection param for IDirectPlay::InitializeConnection 429 * - Call IDirectPlay::InitializeConnection 430 */ 431 432 /* Now initialize the Service Provider */ 433 hr = IDirectPlayX_InitializeConnection( (*(LPDIRECTPLAY2*)lplpDP), 434 #endif 435 436 437 /* Setup flags to pass into DirectPlay::Open */ 438 if( dwFlags & DPCONNECT_RETURNSTATUS ) 439 { 440 dwOpenFlags |= DPOPEN_RETURNSTATUS; 441 } 442 dwOpenFlags |= lpConn->dwFlags; 443 444 hr = IDirectPlayX_Open( (*(LPDIRECTPLAY2*)lplpDP), lpConn->lpSessionDesc, 445 dwOpenFlags ); 446 447 HeapFree( GetProcessHeap(), 0, lpConn ); 448 449 return hr; 450 } 451 452 static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect( IDirectPlayLobbyA *iface, DWORD flags, 453 IDirectPlay2A **dp, IUnknown *unk ) 454 { 455 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 456 return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3A_iface, flags, dp, unk ); 457 } 458 459 static HRESULT WINAPI IDirectPlayLobbyImpl_Connect( IDirectPlayLobby *iface, DWORD flags, 460 IDirectPlay2A **dp, IUnknown *unk ) 461 { 462 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 463 return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3_iface, flags, dp, unk ); 464 } 465 466 static HRESULT WINAPI IDirectPlayLobby2AImpl_Connect( IDirectPlayLobby2A *iface, DWORD flags, 467 IDirectPlay2A **dp, IUnknown *unk ) 468 { 469 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 470 return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3A_iface, flags, dp, unk ); 471 } 472 473 static HRESULT WINAPI IDirectPlayLobby2Impl_Connect( IDirectPlayLobby2 *iface, DWORD flags, 474 IDirectPlay2A **dp, IUnknown *unk ) 475 { 476 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 477 return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3_iface, flags, dp, unk ); 478 } 479 480 static HRESULT WINAPI IDirectPlayLobby3AImpl_Connect( IDirectPlayLobby3A *iface, DWORD flags, 481 IDirectPlay2A **dp, IUnknown *unk) 482 { 483 return IDirectPlayLobby_ConnectEx( iface, flags, &IID_IDirectPlay2A, (void**)dp, unk ); 484 } 485 486 static HRESULT WINAPI IDirectPlayLobby3Impl_Connect( IDirectPlayLobby3 *iface, DWORD flags, 487 IDirectPlay2 **dp, IUnknown *unk) 488 { 489 return IDirectPlayLobby_ConnectEx( iface, flags, &IID_IDirectPlay2A, (void**)dp, unk ); 490 } 491 492 /******************************************************************** 493 * 494 * Creates a DirectPlay Address, given a service provider-specific network 495 * address. 496 * Returns an address contains the globally unique identifier 497 * (GUID) of the service provider and data that the service provider can 498 * interpret as a network address. 499 * 500 * NOTE: It appears that this method is supposed to be really really stupid 501 * with no error checking on the contents. 502 */ 503 static HRESULT WINAPI IDirectPlayLobbyAImpl_CreateAddress( IDirectPlayLobbyA *iface, REFGUID sp, 504 REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize ) 505 { 506 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 507 return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3A_iface, sp, datatype, data, 508 datasize, address, addrsize ); 509 } 510 511 static HRESULT WINAPI IDirectPlayLobbyImpl_CreateAddress( IDirectPlayLobby *iface, REFGUID sp, 512 REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize ) 513 { 514 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 515 return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3_iface, sp, datatype, data, 516 datasize, address, addrsize ); 517 } 518 519 static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateAddress( IDirectPlayLobby2A *iface, REFGUID sp, 520 REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize ) 521 { 522 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 523 return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3A_iface, sp, datatype, data, 524 datasize, address, addrsize ); 525 } 526 527 static HRESULT WINAPI IDirectPlayLobby2Impl_CreateAddress( IDirectPlayLobby2 *iface, REFGUID sp, 528 REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize ) 529 { 530 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 531 return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3_iface, sp, datatype, data, 532 datasize, address, addrsize ); 533 } 534 535 static HRESULT WINAPI IDirectPlayLobby3AImpl_CreateAddress( IDirectPlayLobby3A *iface, 536 REFGUID guidSP, REFGUID guidDataType, const void *lpData, DWORD dwDataSize, void *lpAddress, 537 DWORD *lpdwAddressSize ) 538 { 539 return DPL_CreateAddress( guidSP, guidDataType, lpData, dwDataSize, 540 lpAddress, lpdwAddressSize, TRUE ); 541 } 542 543 static HRESULT WINAPI IDirectPlayLobby3Impl_CreateAddress( IDirectPlayLobby3 *iface, REFGUID guidSP, 544 REFGUID guidDataType, const void *lpData, DWORD dwDataSize, void *lpAddress, 545 DWORD *lpdwAddressSize ) 546 { 547 return DPL_CreateAddress( guidSP, guidDataType, lpData, dwDataSize, 548 lpAddress, lpdwAddressSize, FALSE ); 549 } 550 551 static HRESULT DPL_CreateAddress( 552 REFGUID guidSP, 553 REFGUID guidDataType, 554 LPCVOID lpData, 555 DWORD dwDataSize, 556 LPVOID lpAddress, 557 LPDWORD lpdwAddressSize, 558 BOOL bAnsiInterface ) 559 { 560 const DWORD dwNumAddElements = 2; /* Service Provide & address data type */ 561 DPCOMPOUNDADDRESSELEMENT addressElements[ 2 /* dwNumAddElements */ ]; 562 563 TRACE( "(%p)->(%p,%p,0x%08x,%p,%p,%d)\n", guidSP, guidDataType, lpData, dwDataSize, 564 lpAddress, lpdwAddressSize, bAnsiInterface ); 565 566 addressElements[ 0 ].guidDataType = DPAID_ServiceProvider; 567 addressElements[ 0 ].dwDataSize = sizeof( GUID ); 568 addressElements[ 0 ].lpData = (LPVOID)guidSP; 569 570 addressElements[ 1 ].guidDataType = *guidDataType; 571 addressElements[ 1 ].dwDataSize = dwDataSize; 572 addressElements[ 1 ].lpData = (LPVOID)lpData; 573 574 /* Call CreateCompoundAddress to cut down on code. 575 NOTE: We can do this because we don't support DPL 1 interfaces! */ 576 return DPL_CreateCompoundAddress( addressElements, dwNumAddElements, 577 lpAddress, lpdwAddressSize, bAnsiInterface ); 578 } 579 580 581 582 /******************************************************************** 583 * 584 * Parses out chunks from the DirectPlay Address buffer by calling the 585 * given callback function, with lpContext, for each of the chunks. 586 * 587 */ 588 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddress( IDirectPlayLobbyA *iface, 589 LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context ) 590 { 591 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 592 return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3A_iface, enumaddrcb, address, size, 593 context ); 594 } 595 596 static HRESULT WINAPI IDirectPlayLobbyImpl_EnumAddress( IDirectPlayLobby *iface, 597 LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context ) 598 { 599 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 600 return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3_iface, enumaddrcb, address, size, 601 context ); 602 } 603 604 static HRESULT WINAPI IDirectPlayLobby2AImpl_EnumAddress( IDirectPlayLobby2A *iface, 605 LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context ) 606 { 607 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 608 return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3A_iface, enumaddrcb, address, size, 609 context ); 610 } 611 612 static HRESULT WINAPI IDirectPlayLobby2Impl_EnumAddress( IDirectPlayLobby2 *iface, 613 LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context ) 614 { 615 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 616 return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3_iface, enumaddrcb, address, size, 617 context ); 618 } 619 620 static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumAddress( IDirectPlayLobby3A *iface, 621 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, const void *lpAddress, DWORD dwAddressSize, 622 void *lpContext ) 623 { 624 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 625 626 TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, lpEnumAddressCallback, lpAddress, 627 dwAddressSize, lpContext ); 628 629 return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext ); 630 } 631 632 static HRESULT WINAPI IDirectPlayLobby3Impl_EnumAddress( IDirectPlayLobby3 *iface, 633 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, const void *lpAddress, DWORD dwAddressSize, 634 void *lpContext ) 635 { 636 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 637 638 TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, lpEnumAddressCallback, lpAddress, 639 dwAddressSize, lpContext ); 640 641 return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext ); 642 } 643 644 HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress, 645 DWORD dwAddressSize, LPVOID lpContext ) 646 { 647 DWORD dwTotalSizeEnumerated = 0; 648 649 /* FIXME: First chunk is always the total size chunk - Should we report it? */ 650 651 while ( dwTotalSizeEnumerated < dwAddressSize ) 652 { 653 const DPADDRESS* lpElements = lpAddress; 654 DWORD dwSizeThisEnumeration; 655 656 /* Invoke the enum method. If false is returned, stop enumeration */ 657 if ( !lpEnumAddressCallback( &lpElements->guidDataType, 658 lpElements->dwDataSize, 659 (const BYTE *)lpElements + sizeof( DPADDRESS ), 660 lpContext ) ) 661 { 662 break; 663 } 664 665 dwSizeThisEnumeration = sizeof( DPADDRESS ) + lpElements->dwDataSize; 666 lpAddress = (const BYTE*) lpAddress + dwSizeThisEnumeration; 667 dwTotalSizeEnumerated += dwSizeThisEnumeration; 668 } 669 670 return DP_OK; 671 } 672 673 /******************************************************************** 674 * 675 * Enumerates all the address types that a given service provider needs to 676 * build the DirectPlay Address. 677 * 678 */ 679 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddressTypes( IDirectPlayLobbyA *iface, 680 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags ) 681 { 682 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 683 return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3A_iface, enumaddrtypecb, sp, 684 context, flags ); 685 } 686 687 static HRESULT WINAPI IDirectPlayLobbyImpl_EnumAddressTypes( IDirectPlayLobby *iface, 688 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags ) 689 { 690 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 691 return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3_iface, enumaddrtypecb, sp, 692 context, flags ); 693 } 694 695 static HRESULT WINAPI IDirectPlayLobby2AImpl_EnumAddressTypes( IDirectPlayLobby2A *iface, 696 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags ) 697 { 698 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 699 return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3A_iface, enumaddrtypecb, sp, 700 context, flags ); 701 } 702 703 static HRESULT WINAPI IDirectPlayLobby2Impl_EnumAddressTypes( IDirectPlayLobby2 *iface, 704 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags ) 705 { 706 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 707 return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3_iface, enumaddrtypecb, sp, 708 context, flags ); 709 } 710 711 static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumAddressTypes( IDirectPlayLobby3A *iface, 712 LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback, REFGUID guidSP, void *lpContext, 713 DWORD dwFlags ) 714 { 715 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 716 717 HKEY hkResult; 718 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers"; 719 DWORD dwIndex, sizeOfSubKeyName=50; 720 char subKeyName[51]; 721 FILETIME filetime; 722 723 TRACE(" (%p)->(%p,%p,%p,0x%08x)\n", This, lpEnumAddressTypeCallback, guidSP, lpContext, dwFlags ); 724 725 if( dwFlags != 0 ) 726 { 727 return DPERR_INVALIDPARAMS; 728 } 729 730 if( !lpEnumAddressTypeCallback ) 731 { 732 return DPERR_INVALIDPARAMS; 733 } 734 735 if( guidSP == NULL ) 736 { 737 return DPERR_INVALIDOBJECT; 738 } 739 740 /* Need to loop over the service providers in the registry */ 741 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey, 742 0, KEY_READ, &hkResult ) != ERROR_SUCCESS ) 743 { 744 /* Hmmm. Does this mean that there are no service providers? */ 745 ERR(": no service providers?\n"); 746 return DP_OK; 747 } 748 749 /* Traverse all the service providers we have available */ 750 for( dwIndex=0; 751 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 752 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; 753 ++dwIndex, sizeOfSubKeyName=50 ) 754 { 755 756 HKEY hkServiceProvider, hkServiceProviderAt; 757 GUID serviceProviderGUID; 758 DWORD returnTypeGUID, sizeOfReturnBuffer = 50; 759 char atSubKey[51]; 760 char returnBuffer[51]; 761 WCHAR buff[51]; 762 DWORD dwAtIndex; 763 LPCSTR atKey = "Address Types"; 764 LPCSTR guidDataSubKey = "Guid"; 765 766 TRACE(" this time through: %s\n", subKeyName ); 767 768 /* Get a handle for this particular service provider */ 769 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ, 770 &hkServiceProvider ) != ERROR_SUCCESS ) 771 { 772 ERR(": what the heck is going on?\n" ); 773 continue; 774 } 775 776 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey, 777 NULL, &returnTypeGUID, (LPBYTE)returnBuffer, 778 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 779 { 780 ERR(": missing GUID registry data members\n" ); 781 continue; 782 } 783 784 /* FIXME: Check return types to ensure we're interpreting data right */ 785 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, ARRAY_SIZE( buff )); 786 CLSIDFromString( buff, &serviceProviderGUID ); 787 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */ 788 789 /* Determine if this is the Service Provider that the user asked for */ 790 if( !IsEqualGUID( &serviceProviderGUID, guidSP ) ) 791 { 792 continue; 793 } 794 795 /* Get a handle for this particular service provider */ 796 if( RegOpenKeyExA( hkServiceProvider, atKey, 0, KEY_READ, 797 &hkServiceProviderAt ) != ERROR_SUCCESS ) 798 { 799 TRACE(": No Address Types registry data sub key/members\n" ); 800 break; 801 } 802 803 /* Traverse all the address type we have available */ 804 for( dwAtIndex=0; 805 RegEnumKeyExA( hkServiceProviderAt, dwAtIndex, atSubKey, &sizeOfSubKeyName, 806 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; 807 ++dwAtIndex, sizeOfSubKeyName=50 ) 808 { 809 TRACE( "Found Address Type GUID %s\n", atSubKey ); 810 811 /* FIXME: Check return types to ensure we're interpreting data right */ 812 MultiByteToWideChar( CP_ACP, 0, atSubKey, -1, buff, ARRAY_SIZE( buff )); 813 CLSIDFromString( buff, &serviceProviderGUID ); 814 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */ 815 816 /* The enumeration will return FALSE if we are not to continue */ 817 if( !lpEnumAddressTypeCallback( &serviceProviderGUID, lpContext, 0 ) ) 818 { 819 WARN("lpEnumCallback returning FALSE\n" ); 820 break; /* FIXME: This most likely has to break from the procedure...*/ 821 } 822 823 } 824 825 /* We only enumerate address types for 1 GUID. We've found it, so quit looking */ 826 break; 827 } 828 829 return DP_OK; 830 } 831 832 static HRESULT WINAPI IDirectPlayLobby3Impl_EnumAddressTypes( IDirectPlayLobby3 *iface, 833 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags ) 834 { 835 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 836 return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3A_iface, enumaddrtypecb, sp, 837 context, flags ); 838 } 839 840 /******************************************************************** 841 * 842 * Enumerates what applications are registered with DirectPlay by 843 * invoking the callback function with lpContext. 844 * 845 */ 846 static HRESULT WINAPI IDirectPlayLobby3Impl_EnumLocalApplications( IDirectPlayLobby3 *iface, 847 LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback, void *lpContext, DWORD dwFlags ) 848 { 849 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 850 851 FIXME("(%p)->(%p,%p,0x%08x):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags ); 852 853 return DPERR_OUTOFMEMORY; 854 } 855 856 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumLocalApplications( IDirectPlayLobbyA *iface, 857 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags ) 858 { 859 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 860 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3A_iface, enumlocalappcb, 861 context, flags ); 862 } 863 864 static HRESULT WINAPI IDirectPlayLobbyImpl_EnumLocalApplications( IDirectPlayLobby *iface, 865 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags ) 866 { 867 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 868 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3_iface, enumlocalappcb, 869 context, flags ); 870 } 871 872 static HRESULT WINAPI IDirectPlayLobby2AImpl_EnumLocalApplications( IDirectPlayLobby2A *iface, 873 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags ) 874 { 875 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 876 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3A_iface, enumlocalappcb, 877 context, flags ); 878 } 879 880 static HRESULT WINAPI IDirectPlayLobby2Impl_EnumLocalApplications( IDirectPlayLobby2 *iface, 881 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags ) 882 { 883 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 884 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3_iface, enumlocalappcb, 885 context, flags ); 886 } 887 888 static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumLocalApplications( IDirectPlayLobby3A *iface, 889 LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback, void *lpContext, DWORD dwFlags ) 890 { 891 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 892 893 HKEY hkResult; 894 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Applications"; 895 LPCSTR guidDataSubKey = "Guid"; 896 DWORD dwIndex, sizeOfSubKeyName=50; 897 char subKeyName[51]; 898 FILETIME filetime; 899 900 TRACE("(%p)->(%p,%p,0x%08x)\n", This, lpEnumLocalAppCallback, lpContext, dwFlags ); 901 902 if( dwFlags != 0 ) 903 { 904 return DPERR_INVALIDPARAMS; 905 } 906 907 if( !lpEnumLocalAppCallback ) 908 { 909 return DPERR_INVALIDPARAMS; 910 } 911 912 /* Need to loop over the service providers in the registry */ 913 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey, 914 0, KEY_READ, &hkResult ) != ERROR_SUCCESS ) 915 { 916 /* Hmmm. Does this mean that there are no service providers? */ 917 ERR(": no service providers?\n"); 918 return DP_OK; 919 } 920 921 /* Traverse all registered applications */ 922 for( dwIndex=0; 923 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS; 924 ++dwIndex, sizeOfSubKeyName=50 ) 925 { 926 927 HKEY hkServiceProvider; 928 GUID serviceProviderGUID; 929 DWORD returnTypeGUID, sizeOfReturnBuffer = 50; 930 char returnBuffer[51]; 931 WCHAR buff[51]; 932 DPLAPPINFO dplAppInfo; 933 934 TRACE(" this time through: %s\n", subKeyName ); 935 936 /* Get a handle for this particular service provider */ 937 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ, 938 &hkServiceProvider ) != ERROR_SUCCESS ) 939 { 940 ERR(": what the heck is going on?\n" ); 941 continue; 942 } 943 944 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey, 945 NULL, &returnTypeGUID, (LPBYTE)returnBuffer, 946 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 947 { 948 ERR(": missing GUID registry data members\n" ); 949 continue; 950 } 951 952 /* FIXME: Check return types to ensure we're interpreting data right */ 953 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, ARRAY_SIZE( buff )); 954 CLSIDFromString( buff, &serviceProviderGUID ); 955 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */ 956 957 dplAppInfo.dwSize = sizeof( dplAppInfo ); 958 dplAppInfo.guidApplication = serviceProviderGUID; 959 dplAppInfo.u.lpszAppNameA = subKeyName; 960 961 EnterCriticalSection( &This->lock ); 962 963 memcpy( &This->cbkeyhack, &hkServiceProvider, sizeof( hkServiceProvider ) ); 964 965 if( !lpEnumLocalAppCallback( &dplAppInfo, lpContext, dwFlags ) ) 966 { 967 LeaveCriticalSection( &This->lock ); 968 break; 969 } 970 971 LeaveCriticalSection( &This->lock ); 972 } 973 974 return DP_OK; 975 } 976 977 /******************************************************************** 978 * 979 * Retrieves the DPLCONNECTION structure that contains all the information 980 * needed to start and connect an application. This was generated using 981 * either the RunApplication or SetConnectionSettings methods. 982 * 983 * NOTES: If lpData is NULL then just return lpdwDataSize. This allows 984 * the data structure to be allocated by our caller which can then 985 * call this procedure/method again with a valid data pointer. 986 */ 987 static HRESULT WINAPI IDirectPlayLobbyAImpl_GetConnectionSettings( IDirectPlayLobbyA *iface, 988 DWORD appid, void *data, DWORD *size ) 989 { 990 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 991 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3A_iface, appid, data, 992 size ); 993 } 994 995 static HRESULT WINAPI IDirectPlayLobbyImpl_GetConnectionSettings( IDirectPlayLobby *iface, 996 DWORD appid, void *data, DWORD *size ) 997 { 998 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 999 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface, appid, data, 1000 size ); 1001 } 1002 1003 static HRESULT WINAPI IDirectPlayLobby2AImpl_GetConnectionSettings( IDirectPlayLobby2A *iface, 1004 DWORD appid, void *data, DWORD *size ) 1005 { 1006 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 1007 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3A_iface, appid, data, 1008 size ); 1009 } 1010 1011 static HRESULT WINAPI IDirectPlayLobby2Impl_GetConnectionSettings( IDirectPlayLobby2 *iface, 1012 DWORD appid, void *data, DWORD *size ) 1013 { 1014 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 1015 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface, appid, data, 1016 size ); 1017 } 1018 1019 static HRESULT WINAPI IDirectPlayLobby3AImpl_GetConnectionSettings( IDirectPlayLobby3A *iface, 1020 DWORD dwAppID, void *lpData, DWORD *lpdwDataSize ) 1021 { 1022 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 1023 HRESULT hr; 1024 1025 TRACE("(%p)->(0x%08x,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize ); 1026 1027 EnterCriticalSection( &This->lock ); 1028 1029 hr = DPLAYX_GetConnectionSettingsA( dwAppID, 1030 lpData, 1031 lpdwDataSize 1032 ); 1033 1034 LeaveCriticalSection( &This->lock ); 1035 1036 return hr; 1037 } 1038 1039 static HRESULT WINAPI IDirectPlayLobby3Impl_GetConnectionSettings( IDirectPlayLobby3 *iface, 1040 DWORD dwAppID, void *lpData, DWORD *lpdwDataSize ) 1041 { 1042 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 1043 HRESULT hr; 1044 1045 TRACE("(%p)->(0x%08x,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize ); 1046 1047 EnterCriticalSection( &This->lock ); 1048 1049 hr = DPLAYX_GetConnectionSettingsW( dwAppID, 1050 lpData, 1051 lpdwDataSize 1052 ); 1053 1054 LeaveCriticalSection( &This->lock ); 1055 1056 return hr; 1057 } 1058 1059 /******************************************************************** 1060 * 1061 * Retrieves the message sent between a lobby client and a DirectPlay 1062 * application. All messages are queued until received. 1063 * 1064 */ 1065 static HRESULT WINAPI IDirectPlayLobbyAImpl_ReceiveLobbyMessage( IDirectPlayLobbyA *iface, 1066 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size ) 1067 { 1068 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 1069 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid, 1070 msgflags, data, size ); 1071 } 1072 1073 static HRESULT WINAPI IDirectPlayLobbyImpl_ReceiveLobbyMessage( IDirectPlayLobby *iface, 1074 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size ) 1075 { 1076 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 1077 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid, 1078 msgflags, data, size ); 1079 } 1080 1081 static HRESULT WINAPI IDirectPlayLobby2AImpl_ReceiveLobbyMessage( IDirectPlayLobby2A *iface, 1082 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size ) 1083 { 1084 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 1085 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid, 1086 msgflags, data, size ); 1087 } 1088 1089 static HRESULT WINAPI IDirectPlayLobby2Impl_ReceiveLobbyMessage( IDirectPlayLobby2 *iface, 1090 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size ) 1091 { 1092 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 1093 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid, 1094 msgflags, data, size ); 1095 } 1096 1097 static HRESULT WINAPI IDirectPlayLobby3AImpl_ReceiveLobbyMessage( IDirectPlayLobby3A *iface, 1098 DWORD dwFlags, DWORD dwAppID, DWORD *lpdwMessageFlags, void *lpData, 1099 DWORD *lpdwDataSize ) 1100 { 1101 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 1102 FIXME(":stub %p %08x %08x %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData, 1103 lpdwDataSize ); 1104 return DPERR_OUTOFMEMORY; 1105 } 1106 1107 static HRESULT WINAPI IDirectPlayLobby3Impl_ReceiveLobbyMessage( IDirectPlayLobby3 *iface, 1108 DWORD dwFlags, DWORD dwAppID, DWORD *lpdwMessageFlags, void *lpData, 1109 DWORD *lpdwDataSize ) 1110 { 1111 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 1112 FIXME(":stub %p %08x %08x %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData, 1113 lpdwDataSize ); 1114 return DPERR_OUTOFMEMORY; 1115 } 1116 1117 typedef struct tagRunApplicationEnumStruct 1118 { 1119 IDirectPlayLobbyImpl *This; 1120 1121 GUID appGUID; 1122 LPSTR lpszPath; 1123 LPSTR lpszFileName; 1124 LPSTR lpszCommandLine; 1125 LPSTR lpszCurrentDirectory; 1126 } RunApplicationEnumStruct, *lpRunApplicationEnumStruct; 1127 1128 /* To be called by RunApplication to find how to invoke the function */ 1129 static BOOL CALLBACK RunApplicationA_EnumLocalApplications 1130 ( LPCDPLAPPINFO lpAppInfo, 1131 LPVOID lpContext, 1132 DWORD dwFlags ) 1133 { 1134 lpRunApplicationEnumStruct lpData = (lpRunApplicationEnumStruct)lpContext; 1135 1136 if( IsEqualGUID( &lpAppInfo->guidApplication, &lpData->appGUID ) ) 1137 { 1138 char returnBuffer[200]; 1139 DWORD returnType, sizeOfReturnBuffer; 1140 LPCSTR clSubKey = "CommandLine"; 1141 LPCSTR cdSubKey = "CurrentDirectory"; 1142 LPCSTR fileSubKey = "File"; 1143 LPCSTR pathSubKey = "Path"; 1144 1145 /* FIXME: Lazy man hack - dplay struct has the present reg key saved */ 1146 1147 sizeOfReturnBuffer = 200; 1148 1149 /* Get all the appropriate data from the registry */ 1150 if( RegQueryValueExA( lpData->This->cbkeyhack, clSubKey, 1151 NULL, &returnType, (LPBYTE)returnBuffer, 1152 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 1153 { 1154 ERR( ": missing CommandLine registry data member\n" ); 1155 } 1156 else 1157 { 1158 if ((lpData->lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 ))) 1159 strcpy( lpData->lpszCommandLine, returnBuffer ); 1160 } 1161 1162 sizeOfReturnBuffer = 200; 1163 1164 if( RegQueryValueExA( lpData->This->cbkeyhack, cdSubKey, 1165 NULL, &returnType, (LPBYTE)returnBuffer, 1166 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 1167 { 1168 ERR( ": missing CurrentDirectory registry data member\n" ); 1169 } 1170 else 1171 { 1172 if ((lpData->lpszCurrentDirectory = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 ))) 1173 strcpy( lpData->lpszCurrentDirectory, returnBuffer ); 1174 } 1175 1176 sizeOfReturnBuffer = 200; 1177 1178 if( RegQueryValueExA( lpData->This->cbkeyhack, fileSubKey, 1179 NULL, &returnType, (LPBYTE)returnBuffer, 1180 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 1181 { 1182 ERR( ": missing File registry data member\n" ); 1183 } 1184 else 1185 { 1186 if ((lpData->lpszFileName = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 ))) 1187 strcpy( lpData->lpszFileName, returnBuffer ); 1188 } 1189 1190 sizeOfReturnBuffer = 200; 1191 1192 if( RegQueryValueExA( lpData->This->cbkeyhack, pathSubKey, 1193 NULL, &returnType, (LPBYTE)returnBuffer, 1194 &sizeOfReturnBuffer ) != ERROR_SUCCESS ) 1195 { 1196 ERR( ": missing Path registry data member\n" ); 1197 } 1198 else 1199 { 1200 if ((lpData->lpszPath = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 ))) 1201 strcpy( lpData->lpszPath, returnBuffer ); 1202 } 1203 1204 return FALSE; /* No need to keep going as we found what we wanted */ 1205 } 1206 1207 return TRUE; /* Keep enumerating, haven't found the application yet */ 1208 } 1209 1210 static BOOL DPL_CreateAndSetLobbyHandles( DWORD dwDestProcessId, HANDLE hDestProcess, 1211 LPHANDLE lphStart, LPHANDLE lphDeath, 1212 LPHANDLE lphRead ) 1213 { 1214 /* These are the handles for the created process */ 1215 HANDLE hAppStart = 0, hAppDeath = 0, hAppRead = 0; 1216 SECURITY_ATTRIBUTES s_attrib; 1217 1218 s_attrib.nLength = sizeof( s_attrib ); 1219 s_attrib.lpSecurityDescriptor = NULL; 1220 s_attrib.bInheritHandle = TRUE; 1221 1222 *lphStart = CreateEventW( &s_attrib, TRUE, FALSE, NULL ); 1223 *lphDeath = CreateEventW( &s_attrib, TRUE, FALSE, NULL ); 1224 *lphRead = CreateEventW( &s_attrib, TRUE, FALSE, NULL ); 1225 1226 if( ( !DuplicateHandle( GetCurrentProcess(), *lphStart, 1227 hDestProcess, &hAppStart, 1228 0, FALSE, DUPLICATE_SAME_ACCESS ) ) || 1229 ( !DuplicateHandle( GetCurrentProcess(), *lphDeath, 1230 hDestProcess, &hAppDeath, 1231 0, FALSE, DUPLICATE_SAME_ACCESS ) ) || 1232 ( !DuplicateHandle( GetCurrentProcess(), *lphRead, 1233 hDestProcess, &hAppRead, 1234 0, FALSE, DUPLICATE_SAME_ACCESS ) ) 1235 ) 1236 { 1237 if (*lphStart) { CloseHandle(*lphStart); *lphStart = 0; } 1238 if (*lphDeath) { CloseHandle(*lphDeath); *lphDeath = 0; } 1239 if (*lphRead) { CloseHandle(*lphRead); *lphRead = 0; } 1240 /* FIXME: Handle leak... */ 1241 ERR( "Unable to dup handles\n" ); 1242 return FALSE; 1243 } 1244 1245 if( !DPLAYX_SetLobbyHandles( dwDestProcessId, 1246 hAppStart, hAppDeath, hAppRead ) ) 1247 { 1248 /* FIXME: Handle leak... */ 1249 return FALSE; 1250 } 1251 1252 return TRUE; 1253 } 1254 1255 1256 /******************************************************************** 1257 * 1258 * Starts an application and passes to it all the information to 1259 * connect to a session. 1260 * 1261 */ 1262 static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication( IDirectPlayLobbyA *iface, DWORD flags, 1263 DWORD *appid, DPLCONNECTION *conn, HANDLE event ) 1264 { 1265 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 1266 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3A_iface, flags, appid, conn, 1267 event ); 1268 } 1269 1270 static HRESULT WINAPI IDirectPlayLobbyImpl_RunApplication( IDirectPlayLobby *iface, DWORD flags, 1271 DWORD *appid, DPLCONNECTION *conn, HANDLE event ) 1272 { 1273 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 1274 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3_iface, flags, appid, conn, 1275 event ); 1276 } 1277 1278 static HRESULT WINAPI IDirectPlayLobby2AImpl_RunApplication( IDirectPlayLobby2A *iface, DWORD flags, 1279 DWORD *appid, DPLCONNECTION *conn, HANDLE event ) 1280 { 1281 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 1282 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3A_iface, flags, appid, conn, 1283 event ); 1284 } 1285 1286 static HRESULT WINAPI IDirectPlayLobby2Impl_RunApplication( IDirectPlayLobby2 *iface, DWORD flags, 1287 DWORD *appid, DPLCONNECTION *conn, HANDLE event ) 1288 { 1289 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 1290 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3_iface, flags, appid, conn, 1291 event ); 1292 } 1293 1294 static HRESULT WINAPI IDirectPlayLobby3AImpl_RunApplication( IDirectPlayLobby3A *iface, 1295 DWORD dwFlags, DWORD *lpdwAppID, DPLCONNECTION *lpConn, HANDLE hReceiveEvent ) 1296 { 1297 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 1298 HRESULT hr; 1299 RunApplicationEnumStruct enumData; 1300 char temp[200]; 1301 STARTUPINFOA startupInfo; 1302 PROCESS_INFORMATION newProcessInfo; 1303 LPSTR appName; 1304 DWORD dwSuspendCount; 1305 HANDLE hStart, hDeath, hSettingRead; 1306 1307 TRACE( "(%p)->(0x%08x,%p,%p,%p)\n", 1308 This, dwFlags, lpdwAppID, lpConn, hReceiveEvent ); 1309 1310 if( dwFlags != 0 ) 1311 { 1312 return DPERR_INVALIDPARAMS; 1313 } 1314 1315 if( DPLAYX_AnyLobbiesWaitingForConnSettings() ) 1316 { 1317 FIXME( "Waiting lobby not being handled correctly\n" ); 1318 } 1319 1320 EnterCriticalSection( &This->lock ); 1321 1322 ZeroMemory( &enumData, sizeof( enumData ) ); 1323 enumData.This = This; 1324 enumData.appGUID = lpConn->lpSessionDesc->guidApplication; 1325 1326 /* Our callback function will fill up the enumData structure with all the information 1327 required to start a new process */ 1328 IDirectPlayLobby_EnumLocalApplications( iface, RunApplicationA_EnumLocalApplications, 1329 (&enumData), 0 ); 1330 1331 /* First the application name */ 1332 strcpy( temp, enumData.lpszPath ); 1333 strcat( temp, "\\" ); 1334 strcat( temp, enumData.lpszFileName ); 1335 HeapFree( GetProcessHeap(), 0, enumData.lpszPath ); 1336 HeapFree( GetProcessHeap(), 0, enumData.lpszFileName ); 1337 if ((appName = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 ))) strcpy( appName, temp ); 1338 1339 /* Now the command line */ 1340 strcat( temp, " " ); 1341 strcat( temp, enumData.lpszCommandLine ); 1342 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine ); 1343 if ((enumData.lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 ))) 1344 strcpy( enumData.lpszCommandLine, temp ); 1345 1346 ZeroMemory( &startupInfo, sizeof( startupInfo ) ); 1347 startupInfo.cb = sizeof( startupInfo ); 1348 /* FIXME: Should any fields be filled in? */ 1349 1350 ZeroMemory( &newProcessInfo, sizeof( newProcessInfo ) ); 1351 1352 if( !CreateProcessA( appName, 1353 enumData.lpszCommandLine, 1354 NULL, 1355 NULL, 1356 FALSE, 1357 CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_SUSPENDED, /* Creation Flags */ 1358 NULL, 1359 enumData.lpszCurrentDirectory, 1360 &startupInfo, 1361 &newProcessInfo 1362 ) 1363 ) 1364 { 1365 ERR( "Failed to create process for app %s\n", appName ); 1366 1367 HeapFree( GetProcessHeap(), 0, appName ); 1368 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine ); 1369 HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory ); 1370 1371 LeaveCriticalSection( &This->lock ); 1372 return DPERR_CANTCREATEPROCESS; 1373 } 1374 1375 HeapFree( GetProcessHeap(), 0, appName ); 1376 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine ); 1377 HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory ); 1378 1379 /* Reserve this global application id! */ 1380 if( !DPLAYX_CreateLobbyApplication( newProcessInfo.dwProcessId ) ) 1381 { 1382 ERR( "Unable to create global application data for 0x%08x\n", 1383 newProcessInfo.dwProcessId ); 1384 } 1385 1386 hr = IDirectPlayLobby_SetConnectionSettings( iface, 0, newProcessInfo.dwProcessId, lpConn ); 1387 1388 if( hr != DP_OK ) 1389 { 1390 ERR( "SetConnectionSettings failure %s\n", DPLAYX_HresultToString( hr ) ); 1391 LeaveCriticalSection( &This->lock ); 1392 return hr; 1393 } 1394 1395 /* Setup the handles for application notification */ 1396 DPL_CreateAndSetLobbyHandles( newProcessInfo.dwProcessId, 1397 newProcessInfo.hProcess, 1398 &hStart, &hDeath, &hSettingRead ); 1399 1400 /* Setup the message thread ID */ 1401 This->msgtid = CreateLobbyMessageReceptionThread( hReceiveEvent, hStart, hDeath, hSettingRead ); 1402 1403 DPLAYX_SetLobbyMsgThreadId( newProcessInfo.dwProcessId, This->msgtid ); 1404 1405 LeaveCriticalSection( &This->lock ); 1406 1407 /* Everything seems to have been set correctly, update the dwAppID */ 1408 *lpdwAppID = newProcessInfo.dwProcessId; 1409 1410 /* Unsuspend the process - should return the prev suspension count */ 1411 if( ( dwSuspendCount = ResumeThread( newProcessInfo.hThread ) ) != 1 ) 1412 { 1413 ERR( "ResumeThread failed with 0x%08x\n", dwSuspendCount ); 1414 } 1415 1416 return DP_OK; 1417 } 1418 1419 static HRESULT WINAPI IDirectPlayLobby3Impl_RunApplication( IDirectPlayLobby3 *iface, DWORD dwFlags, 1420 DWORD *lpdwAppID, DPLCONNECTION *lpConn, HANDLE hReceiveEvent ) 1421 { 1422 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 1423 FIXME( "(%p)->(0x%08x,%p,%p,%p):stub\n", This, dwFlags, lpdwAppID, lpConn, hReceiveEvent ); 1424 return DPERR_OUTOFMEMORY; 1425 } 1426 1427 /******************************************************************** 1428 * 1429 * Sends a message between the application and the lobby client. 1430 * All messages are queued until received. 1431 * 1432 */ 1433 static HRESULT WINAPI IDirectPlayLobbyAImpl_SendLobbyMessage( IDirectPlayLobbyA *iface, DWORD flags, 1434 DWORD appid, void *data, DWORD size ) 1435 { 1436 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 1437 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid, data, 1438 size ); 1439 } 1440 1441 static HRESULT WINAPI IDirectPlayLobbyImpl_SendLobbyMessage( IDirectPlayLobby *iface, DWORD flags, 1442 DWORD appid, void *data, DWORD size ) 1443 { 1444 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 1445 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid, data, 1446 size ); 1447 } 1448 1449 static HRESULT WINAPI IDirectPlayLobby2AImpl_SendLobbyMessage( IDirectPlayLobby2A *iface, 1450 DWORD flags, DWORD appid, void *data, DWORD size ) 1451 { 1452 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 1453 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid, data, 1454 size ); 1455 } 1456 1457 static HRESULT WINAPI IDirectPlayLobby2Impl_SendLobbyMessage( IDirectPlayLobby2 *iface, DWORD flags, 1458 DWORD appid, void *data, DWORD size ) 1459 { 1460 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 1461 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid, data, 1462 size ); 1463 } 1464 1465 static HRESULT WINAPI IDirectPlayLobby3AImpl_SendLobbyMessage( IDirectPlayLobby3A *iface, 1466 DWORD flags, DWORD appid, void *data, DWORD size ) 1467 { 1468 FIXME(":stub\n"); 1469 return DPERR_OUTOFMEMORY; 1470 } 1471 1472 static HRESULT WINAPI IDirectPlayLobby3Impl_SendLobbyMessage( IDirectPlayLobby3 *iface, 1473 DWORD flags, DWORD appid, void *data, DWORD size ) 1474 { 1475 FIXME(":stub\n"); 1476 return DPERR_OUTOFMEMORY; 1477 } 1478 1479 /******************************************************************** 1480 * 1481 * Modifies the DPLCONNECTION structure to contain all information 1482 * needed to start and connect an application. 1483 * 1484 */ 1485 static HRESULT WINAPI IDirectPlayLobby3Impl_SetConnectionSettings( IDirectPlayLobby3 *iface, 1486 DWORD dwFlags, DWORD dwAppID, DPLCONNECTION *lpConn ) 1487 { 1488 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 1489 HRESULT hr; 1490 1491 TRACE("(%p)->(0x%08x,0x%08x,%p)\n", This, dwFlags, dwAppID, lpConn ); 1492 1493 EnterCriticalSection( &This->lock ); 1494 1495 hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn ); 1496 1497 /* FIXME: Don't think that this is supposed to fail, but the documentation 1498 is somewhat sketchy. I'll try creating a lobby application 1499 for this... */ 1500 if( hr == DPERR_NOTLOBBIED ) 1501 { 1502 FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" ); 1503 if( dwAppID == 0 ) 1504 { 1505 dwAppID = GetCurrentProcessId(); 1506 } 1507 DPLAYX_CreateLobbyApplication( dwAppID ); 1508 hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn ); 1509 } 1510 1511 LeaveCriticalSection( &This->lock ); 1512 1513 return hr; 1514 } 1515 1516 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetConnectionSettings( IDirectPlayLobbyA *iface, 1517 DWORD flags, DWORD appid, DPLCONNECTION *conn ) 1518 { 1519 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 1520 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3A_iface, flags, 1521 appid, conn ); 1522 } 1523 1524 static HRESULT WINAPI IDirectPlayLobbyImpl_SetConnectionSettings( IDirectPlayLobby *iface, 1525 DWORD flags, DWORD appid, DPLCONNECTION *conn ) 1526 { 1527 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 1528 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3_iface, flags, 1529 appid, conn ); 1530 } 1531 1532 static HRESULT WINAPI IDirectPlayLobby2AImpl_SetConnectionSettings( IDirectPlayLobby2A *iface, 1533 DWORD flags, DWORD appid, DPLCONNECTION *conn ) 1534 { 1535 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 1536 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3A_iface, flags, 1537 appid, conn ); 1538 } 1539 1540 static HRESULT WINAPI IDirectPlayLobby2Impl_SetConnectionSettings( IDirectPlayLobby2 *iface, 1541 DWORD flags, DWORD appid, DPLCONNECTION *conn ) 1542 { 1543 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 1544 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3_iface, flags, 1545 appid, conn ); 1546 } 1547 1548 static HRESULT WINAPI IDirectPlayLobby3AImpl_SetConnectionSettings( IDirectPlayLobby3A *iface, 1549 DWORD dwFlags, DWORD dwAppID, DPLCONNECTION *lpConn ) 1550 { 1551 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 1552 HRESULT hr; 1553 1554 TRACE("(%p)->(0x%08x,0x%08x,%p)\n", This, dwFlags, dwAppID, lpConn ); 1555 1556 EnterCriticalSection( &This->lock ); 1557 1558 hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn ); 1559 1560 /* FIXME: Don't think that this is supposed to fail, but the documentation 1561 is somewhat sketchy. I'll try creating a lobby application 1562 for this... */ 1563 if( hr == DPERR_NOTLOBBIED ) 1564 { 1565 FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" ); 1566 dwAppID = GetCurrentProcessId(); 1567 DPLAYX_CreateLobbyApplication( dwAppID ); 1568 hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn ); 1569 } 1570 1571 LeaveCriticalSection( &This->lock ); 1572 1573 return hr; 1574 } 1575 1576 /******************************************************************** 1577 * 1578 * Registers an event that will be set when a lobby message is received. 1579 * 1580 */ 1581 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetLobbyMessageEvent( IDirectPlayLobbyA *iface, 1582 DWORD flags, DWORD appid, HANDLE event ) 1583 { 1584 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface ); 1585 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3A_iface, flags, appid, 1586 event ); 1587 } 1588 1589 static HRESULT WINAPI IDirectPlayLobbyImpl_SetLobbyMessageEvent( IDirectPlayLobby *iface, 1590 DWORD flags, DWORD appid, HANDLE event ) 1591 { 1592 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface ); 1593 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3_iface, flags, appid, 1594 event ); 1595 } 1596 1597 static HRESULT WINAPI IDirectPlayLobby2AImpl_SetLobbyMessageEvent( IDirectPlayLobby2A *iface, 1598 DWORD flags, DWORD appid, HANDLE event ) 1599 { 1600 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 1601 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3A_iface, flags, appid, 1602 event ); 1603 } 1604 1605 static HRESULT WINAPI IDirectPlayLobby2Impl_SetLobbyMessageEvent( IDirectPlayLobby2 *iface, 1606 DWORD flags, DWORD appid, HANDLE event ) 1607 { 1608 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 1609 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3_iface, flags, appid, 1610 event ); 1611 } 1612 1613 static HRESULT WINAPI IDirectPlayLobby3AImpl_SetLobbyMessageEvent( IDirectPlayLobby3A *iface, 1614 DWORD flags, DWORD appid, HANDLE event ) 1615 { 1616 FIXME(":stub\n"); 1617 return DPERR_OUTOFMEMORY; 1618 } 1619 1620 static HRESULT WINAPI IDirectPlayLobby3Impl_SetLobbyMessageEvent( IDirectPlayLobby3 *iface, 1621 DWORD flags, DWORD appid, HANDLE event ) 1622 { 1623 FIXME(":stub\n"); 1624 return DPERR_OUTOFMEMORY; 1625 } 1626 1627 1628 /* DPL 2 methods */ 1629 static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateCompoundAddress( IDirectPlayLobby2A *iface, 1630 const DPCOMPOUNDADDRESSELEMENT *elements, DWORD count, void *address, DWORD *size ) 1631 { 1632 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface ); 1633 return IDirectPlayLobby_CreateCompoundAddress( &This->IDirectPlayLobby3A_iface, elements, 1634 count, address, size ); 1635 } 1636 1637 static HRESULT WINAPI IDirectPlayLobby2Impl_CreateCompoundAddress( IDirectPlayLobby2 *iface, 1638 const DPCOMPOUNDADDRESSELEMENT *elements, DWORD count, void *address, DWORD *size ) 1639 { 1640 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface ); 1641 return IDirectPlayLobby_CreateCompoundAddress( &This->IDirectPlayLobby3_iface, elements, 1642 count, address, size ); 1643 } 1644 1645 static HRESULT WINAPI IDirectPlayLobby3Impl_CreateCompoundAddress( IDirectPlayLobby3 *iface, 1646 const DPCOMPOUNDADDRESSELEMENT *lpElements, DWORD dwElementCount, void *lpAddress, 1647 DWORD *lpdwAddressSize ) 1648 { 1649 return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, FALSE ); 1650 } 1651 1652 static HRESULT WINAPI IDirectPlayLobby3AImpl_CreateCompoundAddress( IDirectPlayLobby3A *iface, 1653 const DPCOMPOUNDADDRESSELEMENT *lpElements, DWORD dwElementCount, void *lpAddress, 1654 DWORD *lpdwAddressSize ) 1655 { 1656 return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, TRUE ); 1657 } 1658 1659 HRESULT DPL_CreateCompoundAddress 1660 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, 1661 DWORD dwElementCount, 1662 LPVOID lpAddress, 1663 LPDWORD lpdwAddressSize, 1664 BOOL bAnsiInterface ) 1665 { 1666 DWORD dwSizeRequired = 0; 1667 DWORD dwElements; 1668 LPCDPCOMPOUNDADDRESSELEMENT lpOrigElements = lpElements; 1669 1670 TRACE("(%p,0x%08x,%p,%p)\n", lpElements, dwElementCount, lpAddress, lpdwAddressSize ); 1671 1672 /* Parameter check */ 1673 if( ( lpElements == NULL ) || 1674 ( dwElementCount == 0 ) /* FIXME: Not sure if this is a failure case */ 1675 ) 1676 { 1677 return DPERR_INVALIDPARAMS; 1678 } 1679 1680 /* Add the total size chunk */ 1681 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DWORD ); 1682 1683 /* Calculate the size of the buffer required */ 1684 for ( dwElements = dwElementCount; dwElements > 0; --dwElements, ++lpElements ) 1685 { 1686 if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) || 1687 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) ) 1688 ) 1689 { 1690 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( GUID ); 1691 } 1692 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) || 1693 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) || 1694 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) ) 1695 ) 1696 { 1697 if( !bAnsiInterface ) 1698 { 1699 ERR( "Ansi GUIDs used for unicode interface\n" ); 1700 return DPERR_INVALIDFLAGS; 1701 } 1702 1703 dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize; 1704 } 1705 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) || 1706 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) || 1707 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) ) 1708 ) 1709 { 1710 if( bAnsiInterface ) 1711 { 1712 ERR( "Unicode GUIDs used for ansi interface\n" ); 1713 return DPERR_INVALIDFLAGS; 1714 } 1715 1716 FIXME( "Right size for unicode interface?\n" ); 1717 dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize * sizeof( WCHAR ); 1718 } 1719 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) ) 1720 { 1721 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( WORD ); 1722 } 1723 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) ) 1724 { 1725 FIXME( "Right size for unicode interface?\n" ); 1726 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DPCOMPORTADDRESS ); /* FIXME: Right size? */ 1727 } 1728 else 1729 { 1730 WARN( "Skipping Unknown GUID %s\n", debugstr_guid(&lpElements->guidDataType) ); 1731 } 1732 } 1733 1734 /* The user wants to know how big a buffer to allocate for us */ 1735 if( ( lpAddress == NULL ) || 1736 ( *lpdwAddressSize < dwSizeRequired ) 1737 ) 1738 { 1739 *lpdwAddressSize = dwSizeRequired; 1740 return DPERR_BUFFERTOOSMALL; 1741 } 1742 1743 /* Add the total size chunk */ 1744 { 1745 LPDPADDRESS lpdpAddress = lpAddress; 1746 1747 lpdpAddress->guidDataType = DPAID_TotalSize; 1748 lpdpAddress->dwDataSize = sizeof( DWORD ); 1749 lpAddress = (char *) lpAddress + sizeof( DPADDRESS ); 1750 1751 *(LPDWORD)lpAddress = dwSizeRequired; 1752 lpAddress = (char *) lpAddress + sizeof( DWORD ); 1753 } 1754 1755 /* Calculate the size of the buffer required */ 1756 for( dwElements = dwElementCount, lpElements = lpOrigElements; 1757 dwElements > 0; 1758 --dwElements, ++lpElements ) 1759 { 1760 if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) || 1761 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) ) 1762 ) 1763 { 1764 LPDPADDRESS lpdpAddress = lpAddress; 1765 1766 lpdpAddress->guidDataType = lpElements->guidDataType; 1767 lpdpAddress->dwDataSize = sizeof( GUID ); 1768 lpAddress = (char *) lpAddress + sizeof( DPADDRESS ); 1769 1770 CopyMemory( lpAddress, lpElements->lpData, sizeof( GUID ) ); 1771 lpAddress = (char *) lpAddress + sizeof( GUID ); 1772 } 1773 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) || 1774 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) || 1775 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) ) 1776 ) 1777 { 1778 LPDPADDRESS lpdpAddress = lpAddress; 1779 1780 lpdpAddress->guidDataType = lpElements->guidDataType; 1781 lpdpAddress->dwDataSize = lpElements->dwDataSize; 1782 lpAddress = (char *) lpAddress + sizeof( DPADDRESS ); 1783 1784 lstrcpynA( lpAddress, lpElements->lpData, lpElements->dwDataSize ); 1785 lpAddress = (char *) lpAddress + lpElements->dwDataSize; 1786 } 1787 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) || 1788 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) || 1789 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) ) 1790 ) 1791 { 1792 LPDPADDRESS lpdpAddress = lpAddress; 1793 1794 lpdpAddress->guidDataType = lpElements->guidDataType; 1795 lpdpAddress->dwDataSize = lpElements->dwDataSize; 1796 lpAddress = (char *) lpAddress + sizeof( DPADDRESS ); 1797 1798 lstrcpynW( lpAddress, lpElements->lpData, lpElements->dwDataSize ); 1799 lpAddress = (char *) lpAddress + lpElements->dwDataSize * sizeof( WCHAR ); 1800 } 1801 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) ) 1802 { 1803 LPDPADDRESS lpdpAddress = lpAddress; 1804 1805 lpdpAddress->guidDataType = lpElements->guidDataType; 1806 lpdpAddress->dwDataSize = lpElements->dwDataSize; 1807 lpAddress = (char *) lpAddress + sizeof( DPADDRESS ); 1808 1809 *((LPWORD)lpAddress) = *((LPWORD)lpElements->lpData); 1810 lpAddress = (char *) lpAddress + sizeof( WORD ); 1811 } 1812 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) ) 1813 { 1814 LPDPADDRESS lpdpAddress = lpAddress; 1815 1816 lpdpAddress->guidDataType = lpElements->guidDataType; 1817 lpdpAddress->dwDataSize = lpElements->dwDataSize; 1818 lpAddress = (char *) lpAddress + sizeof( DPADDRESS ); 1819 1820 CopyMemory( lpAddress, lpElements->lpData, sizeof( DPADDRESS ) ); 1821 lpAddress = (char *) lpAddress + sizeof( DPADDRESS ); 1822 } 1823 } 1824 1825 return DP_OK; 1826 } 1827 1828 /* DPL 3 methods */ 1829 1830 static HRESULT WINAPI IDirectPlayLobby3Impl_ConnectEx( IDirectPlayLobby3 *iface, DWORD dwFlags, 1831 REFIID riid, LPVOID* lplpDP, IUnknown* pUnk ) 1832 { 1833 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface ); 1834 return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk ); 1835 } 1836 1837 static HRESULT WINAPI IDirectPlayLobby3AImpl_ConnectEx( IDirectPlayLobby3A *iface, DWORD dwFlags, 1838 REFIID riid, void **lplpDP, IUnknown *pUnk ) 1839 { 1840 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface ); 1841 return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk ); 1842 } 1843 1844 static HRESULT WINAPI IDirectPlayLobby3Impl_RegisterApplication( IDirectPlayLobby3 *iface, 1845 DWORD flags, DPAPPLICATIONDESC *appdesc ) 1846 { 1847 FIXME(":stub\n"); 1848 return DP_OK; 1849 } 1850 1851 static HRESULT WINAPI IDirectPlayLobby3AImpl_RegisterApplication( IDirectPlayLobby3A *iface, 1852 DWORD flags, DPAPPLICATIONDESC *appdesc ) 1853 { 1854 FIXME(":stub\n"); 1855 return DP_OK; 1856 } 1857 1858 static HRESULT WINAPI IDirectPlayLobby3Impl_UnregisterApplication( IDirectPlayLobby3 *iface, 1859 DWORD flags, REFGUID appdesc ) 1860 { 1861 FIXME(":stub\n"); 1862 return DP_OK; 1863 } 1864 1865 static HRESULT WINAPI IDirectPlayLobby3AImpl_UnregisterApplication( IDirectPlayLobby3A *iface, 1866 DWORD flags, REFGUID appdesc ) 1867 { 1868 FIXME(":stub\n"); 1869 return DP_OK; 1870 } 1871 1872 static HRESULT WINAPI IDirectPlayLobby3Impl_WaitForConnectionSettings( IDirectPlayLobby3 *iface, 1873 DWORD dwFlags ) 1874 { 1875 HRESULT hr = DP_OK; 1876 BOOL bStartWait = !(dwFlags & DPLWAIT_CANCEL); 1877 1878 TRACE( "(%p)->(0x%08x)\n", iface, dwFlags ); 1879 1880 if( DPLAYX_WaitForConnectionSettings( bStartWait ) ) 1881 { 1882 /* FIXME: What is the correct error return code? */ 1883 hr = DPERR_NOTLOBBIED; 1884 } 1885 1886 return hr; 1887 } 1888 1889 static HRESULT WINAPI IDirectPlayLobby3AImpl_WaitForConnectionSettings( IDirectPlayLobby3A *iface, 1890 DWORD dwFlags ) 1891 { 1892 HRESULT hr = DP_OK; 1893 BOOL bStartWait = !(dwFlags & DPLWAIT_CANCEL); 1894 1895 TRACE( "(%p)->(0x%08x)\n", iface, dwFlags ); 1896 1897 if( DPLAYX_WaitForConnectionSettings( bStartWait ) ) 1898 { 1899 /* FIXME: What is the correct error return code? */ 1900 hr = DPERR_NOTLOBBIED; 1901 } 1902 1903 return hr; 1904 } 1905 1906 static const IDirectPlayLobbyVtbl dplA_vt = 1907 { 1908 IDirectPlayLobbyAImpl_QueryInterface, 1909 IDirectPlayLobbyAImpl_AddRef, 1910 IDirectPlayLobbyAImpl_Release, 1911 IDirectPlayLobbyAImpl_Connect, 1912 IDirectPlayLobbyAImpl_CreateAddress, 1913 IDirectPlayLobbyAImpl_EnumAddress, 1914 IDirectPlayLobbyAImpl_EnumAddressTypes, 1915 IDirectPlayLobbyAImpl_EnumLocalApplications, 1916 IDirectPlayLobbyAImpl_GetConnectionSettings, 1917 IDirectPlayLobbyAImpl_ReceiveLobbyMessage, 1918 IDirectPlayLobbyAImpl_RunApplication, 1919 IDirectPlayLobbyAImpl_SendLobbyMessage, 1920 IDirectPlayLobbyAImpl_SetConnectionSettings, 1921 IDirectPlayLobbyAImpl_SetLobbyMessageEvent 1922 }; 1923 1924 static const IDirectPlayLobbyVtbl dpl_vt = 1925 { 1926 IDirectPlayLobbyImpl_QueryInterface, 1927 IDirectPlayLobbyImpl_AddRef, 1928 IDirectPlayLobbyImpl_Release, 1929 IDirectPlayLobbyImpl_Connect, 1930 IDirectPlayLobbyImpl_CreateAddress, 1931 IDirectPlayLobbyImpl_EnumAddress, 1932 IDirectPlayLobbyImpl_EnumAddressTypes, 1933 IDirectPlayLobbyImpl_EnumLocalApplications, 1934 IDirectPlayLobbyImpl_GetConnectionSettings, 1935 IDirectPlayLobbyImpl_ReceiveLobbyMessage, 1936 IDirectPlayLobbyImpl_RunApplication, 1937 IDirectPlayLobbyImpl_SendLobbyMessage, 1938 IDirectPlayLobbyImpl_SetConnectionSettings, 1939 IDirectPlayLobbyImpl_SetLobbyMessageEvent 1940 }; 1941 1942 static const IDirectPlayLobby2Vtbl dpl2A_vt = 1943 { 1944 IDirectPlayLobby2AImpl_QueryInterface, 1945 IDirectPlayLobby2AImpl_AddRef, 1946 IDirectPlayLobby2AImpl_Release, 1947 IDirectPlayLobby2AImpl_Connect, 1948 IDirectPlayLobby2AImpl_CreateAddress, 1949 IDirectPlayLobby2AImpl_EnumAddress, 1950 IDirectPlayLobby2AImpl_EnumAddressTypes, 1951 IDirectPlayLobby2AImpl_EnumLocalApplications, 1952 IDirectPlayLobby2AImpl_GetConnectionSettings, 1953 IDirectPlayLobby2AImpl_ReceiveLobbyMessage, 1954 IDirectPlayLobby2AImpl_RunApplication, 1955 IDirectPlayLobby2AImpl_SendLobbyMessage, 1956 IDirectPlayLobby2AImpl_SetConnectionSettings, 1957 IDirectPlayLobby2AImpl_SetLobbyMessageEvent, 1958 IDirectPlayLobby2AImpl_CreateCompoundAddress 1959 }; 1960 1961 static const IDirectPlayLobby2Vtbl dpl2_vt = 1962 { 1963 IDirectPlayLobby2Impl_QueryInterface, 1964 IDirectPlayLobby2Impl_AddRef, 1965 IDirectPlayLobby2Impl_Release, 1966 IDirectPlayLobby2Impl_Connect, 1967 IDirectPlayLobby2Impl_CreateAddress, 1968 IDirectPlayLobby2Impl_EnumAddress, 1969 IDirectPlayLobby2Impl_EnumAddressTypes, 1970 IDirectPlayLobby2Impl_EnumLocalApplications, 1971 IDirectPlayLobby2Impl_GetConnectionSettings, 1972 IDirectPlayLobby2Impl_ReceiveLobbyMessage, 1973 IDirectPlayLobby2Impl_RunApplication, 1974 IDirectPlayLobby2Impl_SendLobbyMessage, 1975 IDirectPlayLobby2Impl_SetConnectionSettings, 1976 IDirectPlayLobby2Impl_SetLobbyMessageEvent, 1977 IDirectPlayLobby2Impl_CreateCompoundAddress 1978 }; 1979 1980 static const IDirectPlayLobby3Vtbl dpl3A_vt = 1981 { 1982 IDirectPlayLobby3AImpl_QueryInterface, 1983 IDirectPlayLobby3AImpl_AddRef, 1984 IDirectPlayLobby3AImpl_Release, 1985 IDirectPlayLobby3AImpl_Connect, 1986 IDirectPlayLobby3AImpl_CreateAddress, 1987 IDirectPlayLobby3AImpl_EnumAddress, 1988 IDirectPlayLobby3AImpl_EnumAddressTypes, 1989 IDirectPlayLobby3AImpl_EnumLocalApplications, 1990 IDirectPlayLobby3AImpl_GetConnectionSettings, 1991 IDirectPlayLobby3AImpl_ReceiveLobbyMessage, 1992 IDirectPlayLobby3AImpl_RunApplication, 1993 IDirectPlayLobby3AImpl_SendLobbyMessage, 1994 IDirectPlayLobby3AImpl_SetConnectionSettings, 1995 IDirectPlayLobby3AImpl_SetLobbyMessageEvent, 1996 IDirectPlayLobby3AImpl_CreateCompoundAddress, 1997 IDirectPlayLobby3AImpl_ConnectEx, 1998 IDirectPlayLobby3AImpl_RegisterApplication, 1999 IDirectPlayLobby3AImpl_UnregisterApplication, 2000 IDirectPlayLobby3AImpl_WaitForConnectionSettings 2001 }; 2002 2003 static const IDirectPlayLobby3Vtbl dpl3_vt = 2004 { 2005 IDirectPlayLobby3Impl_QueryInterface, 2006 IDirectPlayLobby3Impl_AddRef, 2007 IDirectPlayLobby3Impl_Release, 2008 IDirectPlayLobby3Impl_Connect, 2009 IDirectPlayLobby3Impl_CreateAddress, 2010 IDirectPlayLobby3Impl_EnumAddress, 2011 IDirectPlayLobby3Impl_EnumAddressTypes, 2012 IDirectPlayLobby3Impl_EnumLocalApplications, 2013 IDirectPlayLobby3Impl_GetConnectionSettings, 2014 IDirectPlayLobby3Impl_ReceiveLobbyMessage, 2015 IDirectPlayLobby3Impl_RunApplication, 2016 IDirectPlayLobby3Impl_SendLobbyMessage, 2017 IDirectPlayLobby3Impl_SetConnectionSettings, 2018 IDirectPlayLobby3Impl_SetLobbyMessageEvent, 2019 IDirectPlayLobby3Impl_CreateCompoundAddress, 2020 IDirectPlayLobby3Impl_ConnectEx, 2021 IDirectPlayLobby3Impl_RegisterApplication, 2022 IDirectPlayLobby3Impl_UnregisterApplication, 2023 IDirectPlayLobby3Impl_WaitForConnectionSettings 2024 }; 2025 2026 HRESULT dplobby_create( REFIID riid, void **ppv ) 2027 { 2028 IDirectPlayLobbyImpl *obj; 2029 HRESULT hr; 2030 2031 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv ); 2032 2033 *ppv = NULL; 2034 obj = HeapAlloc( GetProcessHeap(), 0, sizeof( *obj ) ); 2035 if ( !obj ) 2036 return DPERR_OUTOFMEMORY; 2037 2038 obj->IDirectPlayLobby_iface.lpVtbl = &dpl_vt; 2039 obj->IDirectPlayLobbyA_iface.lpVtbl = &dplA_vt; 2040 obj->IDirectPlayLobby2_iface.lpVtbl = &dpl2_vt; 2041 obj->IDirectPlayLobby2A_iface.lpVtbl = &dpl2A_vt; 2042 obj->IDirectPlayLobby3_iface.lpVtbl = &dpl3_vt; 2043 obj->IDirectPlayLobby3A_iface.lpVtbl = &dpl3A_vt; 2044 obj->numIfaces = 1; 2045 obj->msgtid = 0; 2046 obj->ref = 0; 2047 obj->refA = 0; 2048 obj->ref2 = 0; 2049 obj->ref2A = 0; 2050 obj->ref3 = 1; 2051 obj->ref3A = 0; 2052 2053 InitializeCriticalSection( &obj->lock ); 2054 obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayLobbyImpl.lock"); 2055 DPQ_INIT( obj->msgs ); 2056 2057 hr = IDirectPlayLobby_QueryInterface( &obj->IDirectPlayLobby3_iface, riid, ppv ); 2058 IDirectPlayLobby_Release( &obj->IDirectPlayLobby3_iface ); 2059 2060 return hr; 2061 } 2062 2063 2064 2065 /*************************************************************************** 2066 * DirectPlayLobbyCreateA (DPLAYX.4) 2067 * 2068 */ 2069 HRESULT WINAPI DirectPlayLobbyCreateA( GUID *lpGUIDDSP, IDirectPlayLobbyA **lplpDPL, 2070 IUnknown *lpUnk, void *lpData, DWORD dwDataSize ) 2071 { 2072 TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08x\n", 2073 lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize); 2074 2075 /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must 2076 * equal 0. These fields are mostly for future expansion. 2077 */ 2078 if ( lpGUIDDSP || lpData || dwDataSize ) 2079 { 2080 *lplpDPL = NULL; 2081 return DPERR_INVALIDPARAMS; 2082 } 2083 2084 if( lpUnk ) 2085 { 2086 *lplpDPL = NULL; 2087 ERR("Bad parameters!\n" ); 2088 return CLASS_E_NOAGGREGATION; 2089 } 2090 2091 return dplobby_create( &IID_IDirectPlayLobbyA, (void**)lplpDPL ); 2092 } 2093 2094 /*************************************************************************** 2095 * DirectPlayLobbyCreateW (DPLAYX.5) 2096 * 2097 */ 2098 HRESULT WINAPI DirectPlayLobbyCreateW( GUID *lpGUIDDSP, IDirectPlayLobby **lplpDPL, 2099 IUnknown *lpUnk, void *lpData, DWORD dwDataSize ) 2100 { 2101 TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08x\n", 2102 lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize); 2103 2104 /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must 2105 * equal 0. These fields are mostly for future expansion. 2106 */ 2107 if ( lpGUIDDSP || lpData || dwDataSize ) 2108 { 2109 *lplpDPL = NULL; 2110 ERR("Bad parameters!\n" ); 2111 return DPERR_INVALIDPARAMS; 2112 } 2113 2114 if( lpUnk ) 2115 { 2116 *lplpDPL = NULL; 2117 ERR("Bad parameters!\n" ); 2118 return CLASS_E_NOAGGREGATION; 2119 } 2120 2121 return dplobby_create( &IID_IDirectPlayLobby, (void**)lplpDPL ); 2122 } 2123