Release 1.5.29.
[wine] / dlls / 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 }