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