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