Sync with trunk for console graphics palettes.
[reactos.git] / dll / directx / wine / dplayx / dplobby.c
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 #define NONAMELESSSTRUCT
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 FILETIME filetime;
766
767
768 TRACE(" this time through: %s\n", subKeyName );
769
770 /* Get a handle for this particular service provider */
771 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
772 &hkServiceProvider ) != ERROR_SUCCESS )
773 {
774 ERR(": what the heck is going on?\n" );
775 continue;
776 }
777
778 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
779 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
780 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
781 {
782 ERR(": missing GUID registry data members\n" );
783 continue;
784 }
785
786 /* FIXME: Check return types to ensure we're interpreting data right */
787 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
788 CLSIDFromString( buff, &serviceProviderGUID );
789 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
790
791 /* Determine if this is the Service Provider that the user asked for */
792 if( !IsEqualGUID( &serviceProviderGUID, guidSP ) )
793 {
794 continue;
795 }
796
797 /* Get a handle for this particular service provider */
798 if( RegOpenKeyExA( hkServiceProvider, atKey, 0, KEY_READ,
799 &hkServiceProviderAt ) != ERROR_SUCCESS )
800 {
801 TRACE(": No Address Types registry data sub key/members\n" );
802 break;
803 }
804
805 /* Traverse all the address type we have available */
806 for( dwAtIndex=0;
807 RegEnumKeyExA( hkServiceProviderAt, dwAtIndex, atSubKey, &sizeOfSubKeyName,
808 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
809 ++dwAtIndex, sizeOfSubKeyName=50 )
810 {
811 TRACE( "Found Address Type GUID %s\n", atSubKey );
812
813 /* FIXME: Check return types to ensure we're interpreting data right */
814 MultiByteToWideChar( CP_ACP, 0, atSubKey, -1, buff, sizeof(buff)/sizeof(WCHAR) );
815 CLSIDFromString( buff, &serviceProviderGUID );
816 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
817
818 /* The enumeration will return FALSE if we are not to continue */
819 if( !lpEnumAddressTypeCallback( &serviceProviderGUID, lpContext, 0 ) )
820 {
821 WARN("lpEnumCallback returning FALSE\n" );
822 break; /* FIXME: This most likely has to break from the procedure...*/
823 }
824
825 }
826
827 /* We only enumerate address types for 1 GUID. We've found it, so quit looking */
828 break;
829 }
830
831 return DP_OK;
832 }
833
834 static HRESULT WINAPI IDirectPlayLobby3Impl_EnumAddressTypes( IDirectPlayLobby3 *iface,
835 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
836 {
837 FIXME(":stub\n");
838 return DPERR_OUTOFMEMORY;
839 }
840
841 /********************************************************************
842 *
843 * Enumerates what applications are registered with DirectPlay by
844 * invoking the callback function with lpContext.
845 *
846 */
847 static HRESULT WINAPI IDirectPlayLobby3Impl_EnumLocalApplications( IDirectPlayLobby3 *iface,
848 LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback, void *lpContext, DWORD dwFlags )
849 {
850 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
851
852 FIXME("(%p)->(%p,%p,0x%08x):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
853
854 return DPERR_OUTOFMEMORY;
855 }
856
857 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumLocalApplications( IDirectPlayLobbyA *iface,
858 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
859 {
860 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
861 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3A_iface, enumlocalappcb,
862 context, flags );
863 }
864
865 static HRESULT WINAPI IDirectPlayLobbyImpl_EnumLocalApplications( IDirectPlayLobby *iface,
866 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
867 {
868 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
869 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3_iface, enumlocalappcb,
870 context, flags );
871 }
872
873 static HRESULT WINAPI IDirectPlayLobby2AImpl_EnumLocalApplications( IDirectPlayLobby2A *iface,
874 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
875 {
876 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
877 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3A_iface, enumlocalappcb,
878 context, flags );
879 }
880
881 static HRESULT WINAPI IDirectPlayLobby2Impl_EnumLocalApplications( IDirectPlayLobby2 *iface,
882 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
883 {
884 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
885 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3_iface, enumlocalappcb,
886 context, flags );
887 }
888
889 static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumLocalApplications( IDirectPlayLobby3A *iface,
890 LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback, void *lpContext, DWORD dwFlags )
891 {
892 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
893
894 HKEY hkResult;
895 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Applications";
896 LPCSTR guidDataSubKey = "Guid";
897 DWORD dwIndex, sizeOfSubKeyName=50;
898 char subKeyName[51];
899 FILETIME filetime;
900
901 TRACE("(%p)->(%p,%p,0x%08x)\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
902
903 if( dwFlags != 0 )
904 {
905 return DPERR_INVALIDPARAMS;
906 }
907
908 if( !lpEnumLocalAppCallback )
909 {
910 return DPERR_INVALIDPARAMS;
911 }
912
913 /* Need to loop over the service providers in the registry */
914 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
915 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
916 {
917 /* Hmmm. Does this mean that there are no service providers? */
918 ERR(": no service providers?\n");
919 return DP_OK;
920 }
921
922 /* Traverse all registered applications */
923 for( dwIndex=0;
924 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
925 ++dwIndex, sizeOfSubKeyName=50 )
926 {
927
928 HKEY hkServiceProvider;
929 GUID serviceProviderGUID;
930 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
931 char returnBuffer[51];
932 WCHAR buff[51];
933 DPLAPPINFO dplAppInfo;
934
935 TRACE(" this time through: %s\n", subKeyName );
936
937 /* Get a handle for this particular service provider */
938 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
939 &hkServiceProvider ) != ERROR_SUCCESS )
940 {
941 ERR(": what the heck is going on?\n" );
942 continue;
943 }
944
945 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
946 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
947 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
948 {
949 ERR(": missing GUID registry data members\n" );
950 continue;
951 }
952
953 /* FIXME: Check return types to ensure we're interpreting data right */
954 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
955 CLSIDFromString( buff, &serviceProviderGUID );
956 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
957
958 dplAppInfo.dwSize = sizeof( dplAppInfo );
959 dplAppInfo.guidApplication = serviceProviderGUID;
960 dplAppInfo.u.lpszAppNameA = subKeyName;
961
962 EnterCriticalSection( &This->lock );
963
964 memcpy( &This->cbkeyhack, &hkServiceProvider, sizeof( hkServiceProvider ) );
965
966 if( !lpEnumLocalAppCallback( &dplAppInfo, lpContext, dwFlags ) )
967 {
968 LeaveCriticalSection( &This->lock );
969 break;
970 }
971
972 LeaveCriticalSection( &This->lock );
973 }
974
975 return DP_OK;
976 }
977
978 /********************************************************************
979 *
980 * Retrieves the DPLCONNECTION structure that contains all the information
981 * needed to start and connect an application. This was generated using
982 * either the RunApplication or SetConnectionSettings methods.
983 *
984 * NOTES: If lpData is NULL then just return lpdwDataSize. This allows
985 * the data structure to be allocated by our caller which can then
986 * call this procedure/method again with a valid data pointer.
987 */
988 static HRESULT WINAPI IDirectPlayLobbyAImpl_GetConnectionSettings( IDirectPlayLobbyA *iface,
989 DWORD appid, void *data, DWORD *size )
990 {
991 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
992 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3A_iface, appid, data,
993 size );
994 }
995
996 static HRESULT WINAPI IDirectPlayLobbyImpl_GetConnectionSettings( IDirectPlayLobby *iface,
997 DWORD appid, void *data, DWORD *size )
998 {
999 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1000 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface, appid, data,
1001 size );
1002 }
1003
1004 static HRESULT WINAPI IDirectPlayLobby2AImpl_GetConnectionSettings( IDirectPlayLobby2A *iface,
1005 DWORD appid, void *data, DWORD *size )
1006 {
1007 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1008 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3A_iface, appid, data,
1009 size );
1010 }
1011
1012 static HRESULT WINAPI IDirectPlayLobby2Impl_GetConnectionSettings( IDirectPlayLobby2 *iface,
1013 DWORD appid, void *data, DWORD *size )
1014 {
1015 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1016 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface, appid, data,
1017 size );
1018 }
1019
1020 static HRESULT WINAPI IDirectPlayLobby3AImpl_GetConnectionSettings( IDirectPlayLobby3A *iface,
1021 DWORD dwAppID, void *lpData, DWORD *lpdwDataSize )
1022 {
1023 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
1024 HRESULT hr;
1025
1026 TRACE("(%p)->(0x%08x,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
1027
1028 EnterCriticalSection( &This->lock );
1029
1030 hr = DPLAYX_GetConnectionSettingsA( dwAppID,
1031 lpData,
1032 lpdwDataSize
1033 );
1034
1035 LeaveCriticalSection( &This->lock );
1036
1037 return hr;
1038 }
1039
1040 static HRESULT WINAPI IDirectPlayLobby3Impl_GetConnectionSettings( IDirectPlayLobby3 *iface,
1041 DWORD dwAppID, void *lpData, DWORD *lpdwDataSize )
1042 {
1043 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
1044 HRESULT hr;
1045
1046 TRACE("(%p)->(0x%08x,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
1047
1048 EnterCriticalSection( &This->lock );
1049
1050 hr = DPLAYX_GetConnectionSettingsW( dwAppID,
1051 lpData,
1052 lpdwDataSize
1053 );
1054
1055 LeaveCriticalSection( &This->lock );
1056
1057 return hr;
1058 }
1059
1060 /********************************************************************
1061 *
1062 * Retrieves the message sent between a lobby client and a DirectPlay
1063 * application. All messages are queued until received.
1064 *
1065 */
1066 static HRESULT WINAPI IDirectPlayLobbyAImpl_ReceiveLobbyMessage( IDirectPlayLobbyA *iface,
1067 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
1068 {
1069 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
1070 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid,
1071 msgflags, data, size );
1072 }
1073
1074 static HRESULT WINAPI IDirectPlayLobbyImpl_ReceiveLobbyMessage( IDirectPlayLobby *iface,
1075 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
1076 {
1077 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1078 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid,
1079 msgflags, data, size );
1080 }
1081
1082 static HRESULT WINAPI IDirectPlayLobby2AImpl_ReceiveLobbyMessage( IDirectPlayLobby2A *iface,
1083 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
1084 {
1085 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1086 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid,
1087 msgflags, data, size );
1088 }
1089
1090 static HRESULT WINAPI IDirectPlayLobby2Impl_ReceiveLobbyMessage( IDirectPlayLobby2 *iface,
1091 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
1092 {
1093 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1094 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid,
1095 msgflags, data, size );
1096 }
1097
1098 static HRESULT WINAPI IDirectPlayLobby3AImpl_ReceiveLobbyMessage( IDirectPlayLobby3A *iface,
1099 DWORD dwFlags, DWORD dwAppID, DWORD *lpdwMessageFlags, void *lpData,
1100 DWORD *lpdwDataSize )
1101 {
1102 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
1103 FIXME(":stub %p %08x %08x %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
1104 lpdwDataSize );
1105 return DPERR_OUTOFMEMORY;
1106 }
1107
1108 static HRESULT WINAPI IDirectPlayLobby3Impl_ReceiveLobbyMessage( IDirectPlayLobby3 *iface,
1109 DWORD dwFlags, DWORD dwAppID, DWORD *lpdwMessageFlags, void *lpData,
1110 DWORD *lpdwDataSize )
1111 {
1112 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
1113 FIXME(":stub %p %08x %08x %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
1114 lpdwDataSize );
1115 return DPERR_OUTOFMEMORY;
1116 }
1117
1118 typedef struct tagRunApplicationEnumStruct
1119 {
1120 IDirectPlayLobbyImpl *This;
1121
1122 GUID appGUID;
1123 LPSTR lpszPath;
1124 LPSTR lpszFileName;
1125 LPSTR lpszCommandLine;
1126 LPSTR lpszCurrentDirectory;
1127 } RunApplicationEnumStruct, *lpRunApplicationEnumStruct;
1128
1129 /* To be called by RunApplication to find how to invoke the function */
1130 static BOOL CALLBACK RunApplicationA_EnumLocalApplications
1131 ( LPCDPLAPPINFO lpAppInfo,
1132 LPVOID lpContext,
1133 DWORD dwFlags )
1134 {
1135 lpRunApplicationEnumStruct lpData = (lpRunApplicationEnumStruct)lpContext;
1136
1137 if( IsEqualGUID( &lpAppInfo->guidApplication, &lpData->appGUID ) )
1138 {
1139 char returnBuffer[200];
1140 DWORD returnType, sizeOfReturnBuffer;
1141 LPCSTR clSubKey = "CommandLine";
1142 LPCSTR cdSubKey = "CurrentDirectory";
1143 LPCSTR fileSubKey = "File";
1144 LPCSTR pathSubKey = "Path";
1145
1146 /* FIXME: Lazy man hack - dplay struct has the present reg key saved */
1147
1148 sizeOfReturnBuffer = 200;
1149
1150 /* Get all the appropriate data from the registry */
1151 if( RegQueryValueExA( lpData->This->cbkeyhack, clSubKey,
1152 NULL, &returnType, (LPBYTE)returnBuffer,
1153 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1154 {
1155 ERR( ": missing CommandLine registry data member\n" );
1156 }
1157 else
1158 {
1159 if ((lpData->lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
1160 strcpy( lpData->lpszCommandLine, returnBuffer );
1161 }
1162
1163 sizeOfReturnBuffer = 200;
1164
1165 if( RegQueryValueExA( lpData->This->cbkeyhack, cdSubKey,
1166 NULL, &returnType, (LPBYTE)returnBuffer,
1167 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1168 {
1169 ERR( ": missing CurrentDirectory registry data member\n" );
1170 }
1171 else
1172 {
1173 if ((lpData->lpszCurrentDirectory = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
1174 strcpy( lpData->lpszCurrentDirectory, returnBuffer );
1175 }
1176
1177 sizeOfReturnBuffer = 200;
1178
1179 if( RegQueryValueExA( lpData->This->cbkeyhack, fileSubKey,
1180 NULL, &returnType, (LPBYTE)returnBuffer,
1181 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1182 {
1183 ERR( ": missing File registry data member\n" );
1184 }
1185 else
1186 {
1187 if ((lpData->lpszFileName = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
1188 strcpy( lpData->lpszFileName, returnBuffer );
1189 }
1190
1191 sizeOfReturnBuffer = 200;
1192
1193 if( RegQueryValueExA( lpData->This->cbkeyhack, pathSubKey,
1194 NULL, &returnType, (LPBYTE)returnBuffer,
1195 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1196 {
1197 ERR( ": missing Path registry data member\n" );
1198 }
1199 else
1200 {
1201 if ((lpData->lpszPath = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
1202 strcpy( lpData->lpszPath, returnBuffer );
1203 }
1204
1205 return FALSE; /* No need to keep going as we found what we wanted */
1206 }
1207
1208 return TRUE; /* Keep enumerating, haven't found the application yet */
1209 }
1210
1211 static BOOL DPL_CreateAndSetLobbyHandles( DWORD dwDestProcessId, HANDLE hDestProcess,
1212 LPHANDLE lphStart, LPHANDLE lphDeath,
1213 LPHANDLE lphRead )
1214 {
1215 /* These are the handles for the created process */
1216 HANDLE hAppStart = 0, hAppDeath = 0, hAppRead = 0;
1217 SECURITY_ATTRIBUTES s_attrib;
1218
1219 s_attrib.nLength = sizeof( s_attrib );
1220 s_attrib.lpSecurityDescriptor = NULL;
1221 s_attrib.bInheritHandle = TRUE;
1222
1223 *lphStart = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
1224 *lphDeath = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
1225 *lphRead = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
1226
1227 if( ( !DuplicateHandle( GetCurrentProcess(), *lphStart,
1228 hDestProcess, &hAppStart,
1229 0, FALSE, DUPLICATE_SAME_ACCESS ) ) ||
1230 ( !DuplicateHandle( GetCurrentProcess(), *lphDeath,
1231 hDestProcess, &hAppDeath,
1232 0, FALSE, DUPLICATE_SAME_ACCESS ) ) ||
1233 ( !DuplicateHandle( GetCurrentProcess(), *lphRead,
1234 hDestProcess, &hAppRead,
1235 0, FALSE, DUPLICATE_SAME_ACCESS ) )
1236 )
1237 {
1238 if (*lphStart) { CloseHandle(*lphStart); *lphStart = 0; }
1239 if (*lphDeath) { CloseHandle(*lphDeath); *lphDeath = 0; }
1240 if (*lphRead) { CloseHandle(*lphRead); *lphRead = 0; }
1241 /* FIXME: Handle leak... */
1242 ERR( "Unable to dup handles\n" );
1243 return FALSE;
1244 }
1245
1246 if( !DPLAYX_SetLobbyHandles( dwDestProcessId,
1247 hAppStart, hAppDeath, hAppRead ) )
1248 {
1249 /* FIXME: Handle leak... */
1250 return FALSE;
1251 }
1252
1253 return TRUE;
1254 }
1255
1256
1257 /********************************************************************
1258 *
1259 * Starts an application and passes to it all the information to
1260 * connect to a session.
1261 *
1262 */
1263 static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication( IDirectPlayLobbyA *iface, DWORD flags,
1264 DWORD *appid, DPLCONNECTION *conn, HANDLE event )
1265 {
1266 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
1267 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3A_iface, flags, appid, conn,
1268 event );
1269 }
1270
1271 static HRESULT WINAPI IDirectPlayLobbyImpl_RunApplication( IDirectPlayLobby *iface, DWORD flags,
1272 DWORD *appid, DPLCONNECTION *conn, HANDLE event )
1273 {
1274 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1275 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3_iface, flags, appid, conn,
1276 event );
1277 }
1278
1279 static HRESULT WINAPI IDirectPlayLobby2AImpl_RunApplication( IDirectPlayLobby2A *iface, DWORD flags,
1280 DWORD *appid, DPLCONNECTION *conn, HANDLE event )
1281 {
1282 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1283 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3A_iface, flags, appid, conn,
1284 event );
1285 }
1286
1287 static HRESULT WINAPI IDirectPlayLobby2Impl_RunApplication( IDirectPlayLobby2 *iface, DWORD flags,
1288 DWORD *appid, DPLCONNECTION *conn, HANDLE event )
1289 {
1290 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1291 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3_iface, flags, appid, conn,
1292 event );
1293 }
1294
1295 static HRESULT WINAPI IDirectPlayLobby3AImpl_RunApplication( IDirectPlayLobby3A *iface,
1296 DWORD dwFlags, DWORD *lpdwAppID, DPLCONNECTION *lpConn, HANDLE hReceiveEvent )
1297 {
1298 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
1299 HRESULT hr;
1300 RunApplicationEnumStruct enumData;
1301 char temp[200];
1302 STARTUPINFOA startupInfo;
1303 PROCESS_INFORMATION newProcessInfo;
1304 LPSTR appName;
1305 DWORD dwSuspendCount;
1306 HANDLE hStart, hDeath, hSettingRead;
1307
1308 TRACE( "(%p)->(0x%08x,%p,%p,%p)\n",
1309 This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
1310
1311 if( dwFlags != 0 )
1312 {
1313 return DPERR_INVALIDPARAMS;
1314 }
1315
1316 if( DPLAYX_AnyLobbiesWaitingForConnSettings() )
1317 {
1318 FIXME( "Waiting lobby not being handled correctly\n" );
1319 }
1320
1321 EnterCriticalSection( &This->lock );
1322
1323 ZeroMemory( &enumData, sizeof( enumData ) );
1324 enumData.This = This;
1325 enumData.appGUID = lpConn->lpSessionDesc->guidApplication;
1326
1327 /* Our callback function will fill up the enumData structure with all the information
1328 required to start a new process */
1329 IDirectPlayLobby_EnumLocalApplications( iface, RunApplicationA_EnumLocalApplications,
1330 (&enumData), 0 );
1331
1332 /* First the application name */
1333 strcpy( temp, enumData.lpszPath );
1334 strcat( temp, "\\" );
1335 strcat( temp, enumData.lpszFileName );
1336 HeapFree( GetProcessHeap(), 0, enumData.lpszPath );
1337 HeapFree( GetProcessHeap(), 0, enumData.lpszFileName );
1338 if ((appName = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 ))) strcpy( appName, temp );
1339
1340 /* Now the command line */
1341 strcat( temp, " " );
1342 strcat( temp, enumData.lpszCommandLine );
1343 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
1344 if ((enumData.lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 )))
1345 strcpy( enumData.lpszCommandLine, temp );
1346
1347 ZeroMemory( &startupInfo, sizeof( startupInfo ) );
1348 startupInfo.cb = sizeof( startupInfo );
1349 /* FIXME: Should any fields be filled in? */
1350
1351 ZeroMemory( &newProcessInfo, sizeof( newProcessInfo ) );
1352
1353 if( !CreateProcessA( appName,
1354 enumData.lpszCommandLine,
1355 NULL,
1356 NULL,
1357 FALSE,
1358 CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_SUSPENDED, /* Creation Flags */
1359 NULL,
1360 enumData.lpszCurrentDirectory,
1361 &startupInfo,
1362 &newProcessInfo
1363 )
1364 )
1365 {
1366 ERR( "Failed to create process for app %s\n", appName );
1367
1368 HeapFree( GetProcessHeap(), 0, appName );
1369 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
1370 HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
1371
1372 LeaveCriticalSection( &This->lock );
1373 return DPERR_CANTCREATEPROCESS;
1374 }
1375
1376 HeapFree( GetProcessHeap(), 0, appName );
1377 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
1378 HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
1379
1380 /* Reserve this global application id! */
1381 if( !DPLAYX_CreateLobbyApplication( newProcessInfo.dwProcessId ) )
1382 {
1383 ERR( "Unable to create global application data for 0x%08x\n",
1384 newProcessInfo.dwProcessId );
1385 }
1386
1387 hr = IDirectPlayLobby_SetConnectionSettings( iface, 0, newProcessInfo.dwProcessId, lpConn );
1388
1389 if( hr != DP_OK )
1390 {
1391 ERR( "SetConnectionSettings failure %s\n", DPLAYX_HresultToString( hr ) );
1392 LeaveCriticalSection( &This->lock );
1393 return hr;
1394 }
1395
1396 /* Setup the handles for application notification */
1397 DPL_CreateAndSetLobbyHandles( newProcessInfo.dwProcessId,
1398 newProcessInfo.hProcess,
1399 &hStart, &hDeath, &hSettingRead );
1400
1401 /* Setup the message thread ID */
1402 This->msgtid = CreateLobbyMessageReceptionThread( hReceiveEvent, hStart, hDeath, hSettingRead );
1403
1404 DPLAYX_SetLobbyMsgThreadId( newProcessInfo.dwProcessId, This->msgtid );
1405
1406 LeaveCriticalSection( &This->lock );
1407
1408 /* Everything seems to have been set correctly, update the dwAppID */
1409 *lpdwAppID = newProcessInfo.dwProcessId;
1410
1411 /* Unsuspend the process - should return the prev suspension count */
1412 if( ( dwSuspendCount = ResumeThread( newProcessInfo.hThread ) ) != 1 )
1413 {
1414 ERR( "ResumeThread failed with 0x%08x\n", dwSuspendCount );
1415 }
1416
1417 return DP_OK;
1418 }
1419
1420 static HRESULT WINAPI IDirectPlayLobby3Impl_RunApplication( IDirectPlayLobby3 *iface, DWORD dwFlags,
1421 DWORD *lpdwAppID, DPLCONNECTION *lpConn, HANDLE hReceiveEvent )
1422 {
1423 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
1424 FIXME( "(%p)->(0x%08x,%p,%p,%p):stub\n", This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
1425 return DPERR_OUTOFMEMORY;
1426 }
1427
1428 /********************************************************************
1429 *
1430 * Sends a message between the application and the lobby client.
1431 * All messages are queued until received.
1432 *
1433 */
1434 static HRESULT WINAPI IDirectPlayLobbyAImpl_SendLobbyMessage( IDirectPlayLobbyA *iface, DWORD flags,
1435 DWORD appid, void *data, DWORD size )
1436 {
1437 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
1438 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid, data,
1439 size );
1440 }
1441
1442 static HRESULT WINAPI IDirectPlayLobbyImpl_SendLobbyMessage( IDirectPlayLobby *iface, DWORD flags,
1443 DWORD appid, void *data, DWORD size )
1444 {
1445 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1446 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid, data,
1447 size );
1448 }
1449
1450 static HRESULT WINAPI IDirectPlayLobby2AImpl_SendLobbyMessage( IDirectPlayLobby2A *iface,
1451 DWORD flags, DWORD appid, void *data, DWORD size )
1452 {
1453 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1454 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid, data,
1455 size );
1456 }
1457
1458 static HRESULT WINAPI IDirectPlayLobby2Impl_SendLobbyMessage( IDirectPlayLobby2 *iface, DWORD flags,
1459 DWORD appid, void *data, DWORD size )
1460 {
1461 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1462 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid, data,
1463 size );
1464 }
1465
1466 static HRESULT WINAPI IDirectPlayLobby3AImpl_SendLobbyMessage( IDirectPlayLobby3A *iface,
1467 DWORD flags, DWORD appid, void *data, DWORD size )
1468 {
1469 FIXME(":stub\n");
1470 return DPERR_OUTOFMEMORY;
1471 }
1472
1473 static HRESULT WINAPI IDirectPlayLobby3Impl_SendLobbyMessage( IDirectPlayLobby3 *iface,
1474 DWORD flags, DWORD appid, void *data, DWORD size )
1475 {
1476 FIXME(":stub\n");
1477 return DPERR_OUTOFMEMORY;
1478 }
1479
1480 /********************************************************************
1481 *
1482 * Modifies the DPLCONNECTION structure to contain all information
1483 * needed to start and connect an application.
1484 *
1485 */
1486 static HRESULT WINAPI IDirectPlayLobby3Impl_SetConnectionSettings( IDirectPlayLobby3 *iface,
1487 DWORD dwFlags, DWORD dwAppID, DPLCONNECTION *lpConn )
1488 {
1489 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
1490 HRESULT hr;
1491
1492 TRACE("(%p)->(0x%08x,0x%08x,%p)\n", This, dwFlags, dwAppID, lpConn );
1493
1494 EnterCriticalSection( &This->lock );
1495
1496 hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
1497
1498 /* FIXME: Don't think that this is supposed to fail, but the documentation
1499 is somewhat sketchy. I'll try creating a lobby application
1500 for this... */
1501 if( hr == DPERR_NOTLOBBIED )
1502 {
1503 FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
1504 if( dwAppID == 0 )
1505 {
1506 dwAppID = GetCurrentProcessId();
1507 }
1508 DPLAYX_CreateLobbyApplication( dwAppID );
1509 hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
1510 }
1511
1512 LeaveCriticalSection( &This->lock );
1513
1514 return hr;
1515 }
1516
1517 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetConnectionSettings( IDirectPlayLobbyA *iface,
1518 DWORD flags, DWORD appid, DPLCONNECTION *conn )
1519 {
1520 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
1521 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3A_iface, flags,
1522 appid, conn );
1523 }
1524
1525 static HRESULT WINAPI IDirectPlayLobbyImpl_SetConnectionSettings( IDirectPlayLobby *iface,
1526 DWORD flags, DWORD appid, DPLCONNECTION *conn )
1527 {
1528 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1529 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3_iface, flags,
1530 appid, conn );
1531 }
1532
1533 static HRESULT WINAPI IDirectPlayLobby2AImpl_SetConnectionSettings( IDirectPlayLobby2A *iface,
1534 DWORD flags, DWORD appid, DPLCONNECTION *conn )
1535 {
1536 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1537 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3A_iface, flags,
1538 appid, conn );
1539 }
1540
1541 static HRESULT WINAPI IDirectPlayLobby2Impl_SetConnectionSettings( IDirectPlayLobby2 *iface,
1542 DWORD flags, DWORD appid, DPLCONNECTION *conn )
1543 {
1544 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1545 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3_iface, flags,
1546 appid, conn );
1547 }
1548
1549 static HRESULT WINAPI IDirectPlayLobby3AImpl_SetConnectionSettings( IDirectPlayLobby3A *iface,
1550 DWORD dwFlags, DWORD dwAppID, DPLCONNECTION *lpConn )
1551 {
1552 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
1553 HRESULT hr;
1554
1555 TRACE("(%p)->(0x%08x,0x%08x,%p)\n", This, dwFlags, dwAppID, lpConn );
1556
1557 EnterCriticalSection( &This->lock );
1558
1559 hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
1560
1561 /* FIXME: Don't think that this is supposed to fail, but the documentation
1562 is somewhat sketchy. I'll try creating a lobby application
1563 for this... */
1564 if( hr == DPERR_NOTLOBBIED )
1565 {
1566 FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
1567 dwAppID = GetCurrentProcessId();
1568 DPLAYX_CreateLobbyApplication( dwAppID );
1569 hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
1570 }
1571
1572 LeaveCriticalSection( &This->lock );
1573
1574 return hr;
1575 }
1576
1577 /********************************************************************
1578 *
1579 * Registers an event that will be set when a lobby message is received.
1580 *
1581 */
1582 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetLobbyMessageEvent( IDirectPlayLobbyA *iface,
1583 DWORD flags, DWORD appid, HANDLE event )
1584 {
1585 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
1586 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3A_iface, flags, appid,
1587 event );
1588 }
1589
1590 static HRESULT WINAPI IDirectPlayLobbyImpl_SetLobbyMessageEvent( IDirectPlayLobby *iface,
1591 DWORD flags, DWORD appid, HANDLE event )
1592 {
1593 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1594 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3_iface, flags, appid,
1595 event );
1596 }
1597
1598 static HRESULT WINAPI IDirectPlayLobby2AImpl_SetLobbyMessageEvent( IDirectPlayLobby2A *iface,
1599 DWORD flags, DWORD appid, HANDLE event )
1600 {
1601 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1602 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3A_iface, flags, appid,
1603 event );
1604 }
1605
1606 static HRESULT WINAPI IDirectPlayLobby2Impl_SetLobbyMessageEvent( IDirectPlayLobby2 *iface,
1607 DWORD flags, DWORD appid, HANDLE event )
1608 {
1609 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1610 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3_iface, flags, appid,
1611 event );
1612 }
1613
1614 static HRESULT WINAPI IDirectPlayLobby3AImpl_SetLobbyMessageEvent( IDirectPlayLobby3A *iface,
1615 DWORD flags, DWORD appid, HANDLE event )
1616 {
1617 FIXME(":stub\n");
1618 return DPERR_OUTOFMEMORY;
1619 }
1620
1621 static HRESULT WINAPI IDirectPlayLobby3Impl_SetLobbyMessageEvent( IDirectPlayLobby3 *iface,
1622 DWORD flags, DWORD appid, HANDLE event )
1623 {
1624 FIXME(":stub\n");
1625 return DPERR_OUTOFMEMORY;
1626 }
1627
1628
1629 /* DPL 2 methods */
1630 static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateCompoundAddress( IDirectPlayLobby2A *iface,
1631 const DPCOMPOUNDADDRESSELEMENT *elements, DWORD count, void *address, DWORD *size )
1632 {
1633 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1634 return IDirectPlayLobby_CreateCompoundAddress( &This->IDirectPlayLobby3A_iface, elements,
1635 count, address, size );
1636 }
1637
1638 static HRESULT WINAPI IDirectPlayLobby2Impl_CreateCompoundAddress( IDirectPlayLobby2 *iface,
1639 const DPCOMPOUNDADDRESSELEMENT *elements, DWORD count, void *address, DWORD *size )
1640 {
1641 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1642 return IDirectPlayLobby_CreateCompoundAddress( &This->IDirectPlayLobby3_iface, elements,
1643 count, address, size );
1644 }
1645
1646 static HRESULT WINAPI IDirectPlayLobby3Impl_CreateCompoundAddress( IDirectPlayLobby3 *iface,
1647 const DPCOMPOUNDADDRESSELEMENT *lpElements, DWORD dwElementCount, void *lpAddress,
1648 DWORD *lpdwAddressSize )
1649 {
1650 return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, FALSE );
1651 }
1652
1653 static HRESULT WINAPI IDirectPlayLobby3AImpl_CreateCompoundAddress( IDirectPlayLobby3A *iface,
1654 const DPCOMPOUNDADDRESSELEMENT *lpElements, DWORD dwElementCount, void *lpAddress,
1655 DWORD *lpdwAddressSize )
1656 {
1657 return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, TRUE );
1658 }
1659
1660 HRESULT DPL_CreateCompoundAddress
1661 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1662 DWORD dwElementCount,
1663 LPVOID lpAddress,
1664 LPDWORD lpdwAddressSize,
1665 BOOL bAnsiInterface )
1666 {
1667 DWORD dwSizeRequired = 0;
1668 DWORD dwElements;
1669 LPCDPCOMPOUNDADDRESSELEMENT lpOrigElements = lpElements;
1670
1671 TRACE("(%p,0x%08x,%p,%p)\n", lpElements, dwElementCount, lpAddress, lpdwAddressSize );
1672
1673 /* Parameter check */
1674 if( ( lpElements == NULL ) ||
1675 ( dwElementCount == 0 ) /* FIXME: Not sure if this is a failure case */
1676 )
1677 {
1678 return DPERR_INVALIDPARAMS;
1679 }
1680
1681 /* Add the total size chunk */
1682 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DWORD );
1683
1684 /* Calculate the size of the buffer required */
1685 for ( dwElements = dwElementCount; dwElements > 0; --dwElements, ++lpElements )
1686 {
1687 if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
1688 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
1689 )
1690 {
1691 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( GUID );
1692 }
1693 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
1694 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
1695 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
1696 )
1697 {
1698 if( !bAnsiInterface )
1699 {
1700 ERR( "Ansi GUIDs used for unicode interface\n" );
1701 return DPERR_INVALIDFLAGS;
1702 }
1703
1704 dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize;
1705 }
1706 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
1707 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
1708 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
1709 )
1710 {
1711 if( bAnsiInterface )
1712 {
1713 ERR( "Unicode GUIDs used for ansi interface\n" );
1714 return DPERR_INVALIDFLAGS;
1715 }
1716
1717 FIXME( "Right size for unicode interface?\n" );
1718 dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize * sizeof( WCHAR );
1719 }
1720 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
1721 {
1722 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( WORD );
1723 }
1724 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
1725 {
1726 FIXME( "Right size for unicode interface?\n" );
1727 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DPCOMPORTADDRESS ); /* FIXME: Right size? */
1728 }
1729 else
1730 {
1731 ERR( "Unknown GUID %s\n", debugstr_guid(&lpElements->guidDataType) );
1732 return DPERR_INVALIDFLAGS;
1733 }
1734 }
1735
1736 /* The user wants to know how big a buffer to allocate for us */
1737 if( ( lpAddress == NULL ) ||
1738 ( *lpdwAddressSize < dwSizeRequired )
1739 )
1740 {
1741 *lpdwAddressSize = dwSizeRequired;
1742 return DPERR_BUFFERTOOSMALL;
1743 }
1744
1745 /* Add the total size chunk */
1746 {
1747 LPDPADDRESS lpdpAddress = lpAddress;
1748
1749 lpdpAddress->guidDataType = DPAID_TotalSize;
1750 lpdpAddress->dwDataSize = sizeof( DWORD );
1751 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1752
1753 *(LPDWORD)lpAddress = dwSizeRequired;
1754 lpAddress = (char *) lpAddress + sizeof( DWORD );
1755 }
1756
1757 /* Calculate the size of the buffer required */
1758 for( dwElements = dwElementCount, lpElements = lpOrigElements;
1759 dwElements > 0;
1760 --dwElements, ++lpElements )
1761 {
1762 if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
1763 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
1764 )
1765 {
1766 LPDPADDRESS lpdpAddress = lpAddress;
1767
1768 lpdpAddress->guidDataType = lpElements->guidDataType;
1769 lpdpAddress->dwDataSize = sizeof( GUID );
1770 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1771
1772 CopyMemory( lpAddress, lpElements->lpData, sizeof( GUID ) );
1773 lpAddress = (char *) lpAddress + sizeof( GUID );
1774 }
1775 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
1776 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
1777 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
1778 )
1779 {
1780 LPDPADDRESS lpdpAddress = lpAddress;
1781
1782 lpdpAddress->guidDataType = lpElements->guidDataType;
1783 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1784 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1785
1786 lstrcpynA( lpAddress, lpElements->lpData, lpElements->dwDataSize );
1787 lpAddress = (char *) lpAddress + lpElements->dwDataSize;
1788 }
1789 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
1790 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
1791 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
1792 )
1793 {
1794 LPDPADDRESS lpdpAddress = lpAddress;
1795
1796 lpdpAddress->guidDataType = lpElements->guidDataType;
1797 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1798 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1799
1800 lstrcpynW( lpAddress, lpElements->lpData, lpElements->dwDataSize );
1801 lpAddress = (char *) lpAddress + lpElements->dwDataSize * sizeof( WCHAR );
1802 }
1803 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
1804 {
1805 LPDPADDRESS lpdpAddress = lpAddress;
1806
1807 lpdpAddress->guidDataType = lpElements->guidDataType;
1808 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1809 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1810
1811 *((LPWORD)lpAddress) = *((LPWORD)lpElements->lpData);
1812 lpAddress = (char *) lpAddress + sizeof( WORD );
1813 }
1814 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
1815 {
1816 LPDPADDRESS lpdpAddress = lpAddress;
1817
1818 lpdpAddress->guidDataType = lpElements->guidDataType;
1819 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1820 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1821
1822 CopyMemory( lpAddress, lpElements->lpData, sizeof( DPADDRESS ) );
1823 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1824 }
1825 }
1826
1827 return DP_OK;
1828 }
1829
1830 /* DPL 3 methods */
1831
1832 static HRESULT WINAPI IDirectPlayLobby3Impl_ConnectEx( IDirectPlayLobby3 *iface, DWORD dwFlags,
1833 REFIID riid, LPVOID* lplpDP, IUnknown* pUnk )
1834 {
1835 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
1836 return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk );
1837 }
1838
1839 static HRESULT WINAPI IDirectPlayLobby3AImpl_ConnectEx( IDirectPlayLobby3A *iface, DWORD dwFlags,
1840 REFIID riid, void **lplpDP, IUnknown *pUnk )
1841 {
1842 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
1843 return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk );
1844 }
1845
1846 static HRESULT WINAPI IDirectPlayLobby3Impl_RegisterApplication( IDirectPlayLobby3 *iface,
1847 DWORD flags, DPAPPLICATIONDESC *appdesc )
1848 {
1849 FIXME(":stub\n");
1850 return DP_OK;
1851 }
1852
1853 static HRESULT WINAPI IDirectPlayLobby3AImpl_RegisterApplication( IDirectPlayLobby3A *iface,
1854 DWORD flags, DPAPPLICATIONDESC *appdesc )
1855 {
1856 FIXME(":stub\n");
1857 return DP_OK;
1858 }
1859
1860 static HRESULT WINAPI IDirectPlayLobby3Impl_UnregisterApplication( IDirectPlayLobby3 *iface,
1861 DWORD flags, REFGUID appdesc )
1862 {
1863 FIXME(":stub\n");
1864 return DP_OK;
1865 }
1866
1867 static HRESULT WINAPI IDirectPlayLobby3AImpl_UnregisterApplication( IDirectPlayLobby3A *iface,
1868 DWORD flags, REFGUID appdesc )
1869 {
1870 FIXME(":stub\n");
1871 return DP_OK;
1872 }
1873
1874 static HRESULT WINAPI IDirectPlayLobby3Impl_WaitForConnectionSettings( IDirectPlayLobby3 *iface,
1875 DWORD dwFlags )
1876 {
1877 HRESULT hr = DP_OK;
1878 BOOL bStartWait = !(dwFlags & DPLWAIT_CANCEL);
1879
1880 TRACE( "(%p)->(0x%08x)\n", iface, dwFlags );
1881
1882 if( DPLAYX_WaitForConnectionSettings( bStartWait ) )
1883 {
1884 /* FIXME: What is the correct error return code? */
1885 hr = DPERR_NOTLOBBIED;
1886 }
1887
1888 return hr;
1889 }
1890
1891 static HRESULT WINAPI IDirectPlayLobby3AImpl_WaitForConnectionSettings( IDirectPlayLobby3A *iface,
1892 DWORD dwFlags )
1893 {
1894 HRESULT hr = DP_OK;
1895 BOOL bStartWait = !(dwFlags & DPLWAIT_CANCEL);
1896
1897 TRACE( "(%p)->(0x%08x)\n", iface, dwFlags );
1898
1899 if( DPLAYX_WaitForConnectionSettings( bStartWait ) )
1900 {
1901 /* FIXME: What is the correct error return code? */
1902 hr = DPERR_NOTLOBBIED;
1903 }
1904
1905 return hr;
1906 }
1907
1908 static const IDirectPlayLobbyVtbl dplA_vt =
1909 {
1910 IDirectPlayLobbyAImpl_QueryInterface,
1911 IDirectPlayLobbyAImpl_AddRef,
1912 IDirectPlayLobbyAImpl_Release,
1913 IDirectPlayLobbyAImpl_Connect,
1914 IDirectPlayLobbyAImpl_CreateAddress,
1915 IDirectPlayLobbyAImpl_EnumAddress,
1916 IDirectPlayLobbyAImpl_EnumAddressTypes,
1917 IDirectPlayLobbyAImpl_EnumLocalApplications,
1918 IDirectPlayLobbyAImpl_GetConnectionSettings,
1919 IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
1920 IDirectPlayLobbyAImpl_RunApplication,
1921 IDirectPlayLobbyAImpl_SendLobbyMessage,
1922 IDirectPlayLobbyAImpl_SetConnectionSettings,
1923 IDirectPlayLobbyAImpl_SetLobbyMessageEvent
1924 };
1925
1926 static const IDirectPlayLobbyVtbl dpl_vt =
1927 {
1928 IDirectPlayLobbyImpl_QueryInterface,
1929 IDirectPlayLobbyImpl_AddRef,
1930 IDirectPlayLobbyImpl_Release,
1931 IDirectPlayLobbyImpl_Connect,
1932 IDirectPlayLobbyImpl_CreateAddress,
1933 IDirectPlayLobbyImpl_EnumAddress,
1934 IDirectPlayLobbyImpl_EnumAddressTypes,
1935 IDirectPlayLobbyImpl_EnumLocalApplications,
1936 IDirectPlayLobbyImpl_GetConnectionSettings,
1937 IDirectPlayLobbyImpl_ReceiveLobbyMessage,
1938 IDirectPlayLobbyImpl_RunApplication,
1939 IDirectPlayLobbyImpl_SendLobbyMessage,
1940 IDirectPlayLobbyImpl_SetConnectionSettings,
1941 IDirectPlayLobbyImpl_SetLobbyMessageEvent
1942 };
1943
1944 static const IDirectPlayLobby2Vtbl dpl2A_vt =
1945 {
1946 IDirectPlayLobby2AImpl_QueryInterface,
1947 IDirectPlayLobby2AImpl_AddRef,
1948 IDirectPlayLobby2AImpl_Release,
1949 IDirectPlayLobby2AImpl_Connect,
1950 IDirectPlayLobby2AImpl_CreateAddress,
1951 IDirectPlayLobby2AImpl_EnumAddress,
1952 IDirectPlayLobby2AImpl_EnumAddressTypes,
1953 IDirectPlayLobby2AImpl_EnumLocalApplications,
1954 IDirectPlayLobby2AImpl_GetConnectionSettings,
1955 IDirectPlayLobby2AImpl_ReceiveLobbyMessage,
1956 IDirectPlayLobby2AImpl_RunApplication,
1957 IDirectPlayLobby2AImpl_SendLobbyMessage,
1958 IDirectPlayLobby2AImpl_SetConnectionSettings,
1959 IDirectPlayLobby2AImpl_SetLobbyMessageEvent,
1960 IDirectPlayLobby2AImpl_CreateCompoundAddress
1961 };
1962
1963 static const IDirectPlayLobby2Vtbl dpl2_vt =
1964 {
1965 IDirectPlayLobby2Impl_QueryInterface,
1966 IDirectPlayLobby2Impl_AddRef,
1967 IDirectPlayLobby2Impl_Release,
1968 IDirectPlayLobby2Impl_Connect,
1969 IDirectPlayLobby2Impl_CreateAddress,
1970 IDirectPlayLobby2Impl_EnumAddress,
1971 IDirectPlayLobby2Impl_EnumAddressTypes,
1972 IDirectPlayLobby2Impl_EnumLocalApplications,
1973 IDirectPlayLobby2Impl_GetConnectionSettings,
1974 IDirectPlayLobby2Impl_ReceiveLobbyMessage,
1975 IDirectPlayLobby2Impl_RunApplication,
1976 IDirectPlayLobby2Impl_SendLobbyMessage,
1977 IDirectPlayLobby2Impl_SetConnectionSettings,
1978 IDirectPlayLobby2Impl_SetLobbyMessageEvent,
1979 IDirectPlayLobby2Impl_CreateCompoundAddress
1980 };
1981
1982 static const IDirectPlayLobby3Vtbl dpl3A_vt =
1983 {
1984 IDirectPlayLobby3AImpl_QueryInterface,
1985 IDirectPlayLobby3AImpl_AddRef,
1986 IDirectPlayLobby3AImpl_Release,
1987 IDirectPlayLobby3AImpl_Connect,
1988 IDirectPlayLobby3AImpl_CreateAddress,
1989 IDirectPlayLobby3AImpl_EnumAddress,
1990 IDirectPlayLobby3AImpl_EnumAddressTypes,
1991 IDirectPlayLobby3AImpl_EnumLocalApplications,
1992 IDirectPlayLobby3AImpl_GetConnectionSettings,
1993 IDirectPlayLobby3AImpl_ReceiveLobbyMessage,
1994 IDirectPlayLobby3AImpl_RunApplication,
1995 IDirectPlayLobby3AImpl_SendLobbyMessage,
1996 IDirectPlayLobby3AImpl_SetConnectionSettings,
1997 IDirectPlayLobby3AImpl_SetLobbyMessageEvent,
1998 IDirectPlayLobby3AImpl_CreateCompoundAddress,
1999 IDirectPlayLobby3AImpl_ConnectEx,
2000 IDirectPlayLobby3AImpl_RegisterApplication,
2001 IDirectPlayLobby3AImpl_UnregisterApplication,
2002 IDirectPlayLobby3AImpl_WaitForConnectionSettings
2003 };
2004
2005 static const IDirectPlayLobby3Vtbl dpl3_vt =
2006 {
2007 IDirectPlayLobby3Impl_QueryInterface,
2008 IDirectPlayLobby3Impl_AddRef,
2009 IDirectPlayLobby3Impl_Release,
2010 IDirectPlayLobby3Impl_Connect,
2011 IDirectPlayLobby3Impl_CreateAddress,
2012 IDirectPlayLobby3Impl_EnumAddress,
2013 IDirectPlayLobby3Impl_EnumAddressTypes,
2014 IDirectPlayLobby3Impl_EnumLocalApplications,
2015 IDirectPlayLobby3Impl_GetConnectionSettings,
2016 IDirectPlayLobby3Impl_ReceiveLobbyMessage,
2017 IDirectPlayLobby3Impl_RunApplication,
2018 IDirectPlayLobby3Impl_SendLobbyMessage,
2019 IDirectPlayLobby3Impl_SetConnectionSettings,
2020 IDirectPlayLobby3Impl_SetLobbyMessageEvent,
2021 IDirectPlayLobby3Impl_CreateCompoundAddress,
2022 IDirectPlayLobby3Impl_ConnectEx,
2023 IDirectPlayLobby3Impl_RegisterApplication,
2024 IDirectPlayLobby3Impl_UnregisterApplication,
2025 IDirectPlayLobby3Impl_WaitForConnectionSettings
2026 };
2027
2028 HRESULT dplobby_create( REFIID riid, void **ppv )
2029 {
2030 IDirectPlayLobbyImpl *obj;
2031 HRESULT hr;
2032
2033 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv );
2034
2035 *ppv = NULL;
2036 obj = HeapAlloc( GetProcessHeap(), 0, sizeof( *obj ) );
2037 if ( !obj )
2038 return DPERR_OUTOFMEMORY;
2039
2040 obj->IDirectPlayLobby_iface.lpVtbl = &dpl_vt;
2041 obj->IDirectPlayLobbyA_iface.lpVtbl = &dplA_vt;
2042 obj->IDirectPlayLobby2_iface.lpVtbl = &dpl2_vt;
2043 obj->IDirectPlayLobby2A_iface.lpVtbl = &dpl2A_vt;
2044 obj->IDirectPlayLobby3_iface.lpVtbl = &dpl3_vt;
2045 obj->IDirectPlayLobby3A_iface.lpVtbl = &dpl3A_vt;
2046 obj->numIfaces = 1;
2047 obj->ref = 0;
2048 obj->refA = 0;
2049 obj->ref2 = 0;
2050 obj->ref2A = 0;
2051 obj->ref3 = 1;
2052 obj->ref3A = 0;
2053
2054 InitializeCriticalSection( &obj->lock );
2055 obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayLobbyImpl.lock");
2056 DPQ_INIT( obj->msgs );
2057
2058 hr = IDirectPlayLobby_QueryInterface( &obj->IDirectPlayLobby3_iface, riid, ppv );
2059 IDirectPlayLobby_Release( &obj->IDirectPlayLobby3_iface );
2060
2061 return hr;
2062 }
2063
2064
2065
2066 /***************************************************************************
2067 * DirectPlayLobbyCreateA (DPLAYX.4)
2068 *
2069 */
2070 HRESULT WINAPI DirectPlayLobbyCreateA( GUID *lpGUIDDSP, IDirectPlayLobbyA **lplpDPL,
2071 IUnknown *lpUnk, void *lpData, DWORD dwDataSize )
2072 {
2073 TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08x\n",
2074 lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
2075
2076 /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
2077 * equal 0. These fields are mostly for future expansion.
2078 */
2079 if ( lpGUIDDSP || lpData || dwDataSize )
2080 {
2081 *lplpDPL = NULL;
2082 return DPERR_INVALIDPARAMS;
2083 }
2084
2085 if( lpUnk )
2086 {
2087 *lplpDPL = NULL;
2088 ERR("Bad parameters!\n" );
2089 return CLASS_E_NOAGGREGATION;
2090 }
2091
2092 return dplobby_create( &IID_IDirectPlayLobbyA, (void**)lplpDPL );
2093 }
2094
2095 /***************************************************************************
2096 * DirectPlayLobbyCreateW (DPLAYX.5)
2097 *
2098 */
2099 HRESULT WINAPI DirectPlayLobbyCreateW( GUID *lpGUIDDSP, IDirectPlayLobby **lplpDPL,
2100 IUnknown *lpUnk, void *lpData, DWORD dwDataSize )
2101 {
2102 TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08x\n",
2103 lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
2104
2105 /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
2106 * equal 0. These fields are mostly for future expansion.
2107 */
2108 if ( lpGUIDDSP || lpData || dwDataSize )
2109 {
2110 *lplpDPL = NULL;
2111 ERR("Bad parameters!\n" );
2112 return DPERR_INVALIDPARAMS;
2113 }
2114
2115 if( lpUnk )
2116 {
2117 *lplpDPL = NULL;
2118 ERR("Bad parameters!\n" );
2119 return CLASS_E_NOAGGREGATION;
2120 }
2121
2122 return dplobby_create( &IID_IDirectPlayLobby, (void**)lplpDPL );
2123 }