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