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