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