Added missing prototypes for StrRetToBuf(A|W).
[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 #include "winerror.h"
10 #include "winnt.h"
11 #include "winreg.h"
12 #include "dplobby.h"
13 #include "heap.h"
14 #include "debugtools.h"
15
16 DEFAULT_DEBUG_CHANNEL(dplay)
17
18 /*****************************************************************************
19  * Predeclare the interface implementation structures
20  */
21 typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyImpl;
22 typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyAImpl;
23 typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyWImpl;
24 typedef struct IDirectPlayLobbyImpl IDirectPlayLobby2Impl;
25 typedef struct IDirectPlayLobbyImpl IDirectPlayLobby2AImpl;
26 typedef struct IDirectPlayLobbyImpl IDirectPlayLobby3Impl;
27 typedef struct IDirectPlayLobbyImpl IDirectPlayLobby3AImpl;
28
29 /*****************************************************************************
30  * IDirectPlayLobby {1,2,3} implementation structure
31  * 
32  * The philosophy behind this extra pointer derefernce is that I wanted to 
33  * have the same structure for all types of objects without having to do
34  * alot of casting. I also only wanted to implement an interface in the 
35  * object it was "released" with IUnknown interface being implemented in the 1 version.
36  * Of course, with these new interfaces comes the data required to keep the state required
37  * by these interfaces. So, basically, the pointers contain the data associated with
38  * a release. If you use the data associated with release 3 in a release 2 object, you'll
39  * get a run time trap, as that won't have any data.
40  *
41  */
42
43 typedef struct tagDirectPlayLobbyIUnknownData
44 {
45   DWORD             ref;
46   CRITICAL_SECTION  DPL_lock;
47 } DirectPlayLobbyIUnknownData;
48
49 /* FIXME: I don't think that everything belongs here...*/
50 typedef struct tagDirectPlayLobbyData
51 {
52   DWORD                     dwConnFlags;
53   DPSESSIONDESC2            sessionDesc;
54   DPNAME                    playerName;
55   GUID                      guidSP;
56   LPVOID                    lpAddress;
57   DWORD                     dwAddressSize;
58 } DirectPlayLobbyData;
59
60 typedef struct tagDirectPlayLobby2Data
61 {
62   BOOL dummy;
63 } DirectPlayLobby2Data;
64
65 typedef struct tagDirectPlayLobby3Data
66 {
67   BOOL dummy;
68 } DirectPlayLobby3Data;
69
70 struct IDirectPlayLobbyImpl
71 {
72     ICOM_VTABLE(IDirectPlayLobby)* lpvtbl;
73  
74     /* IUnknown fields */
75     DirectPlayLobbyIUnknownData*  unk;
76
77     /* IDirectPlayLobby 1 fields */
78     DirectPlayLobbyData*          dpl;
79
80     /* IDirectPlayLobby 2 fields */
81     DirectPlayLobby2Data*         dpl2;
82
83     /* IDirectPlayLobby 3 fields */
84     DirectPlayLobby3Data*         dpl3;
85 };
86
87 /* Forward declarations of virtual tables */
88 static ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyAVT;
89 static ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyWVT;
90 static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2AVT;
91 static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2WVT;
92 static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3AVT;
93 static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3WVT;
94
95
96
97
98 /* The COM interface for upversioning an interface
99  * We've been given a GUID (riid) and we need to replace the present
100  * interface with that of the requested interface.
101  *
102  * Snip from some Microsoft document:
103  * There are four requirements for implementations of QueryInterface (In these
104  * cases, "must succeed" means "must succeed barring catastrophic failure."):
105  *
106  *  * The set of interfaces accessible on an object through
107  *    IUnknown::QueryInterface must be static, not dynamic. This means that
108  *    if a call to QueryInterface for a pointer to a specified interface
109  *    succeeds the first time, it must succeed again, and if it fails the
110  *    first time, it must fail on all subsequent queries.
111  *  * It must be symmetric ~W if a client holds a pointer to an interface on
112  *    an object, and queries for that interface, the call must succeed.
113  *  * It must be reflexive ~W if a client holding a pointer to one interface
114  *    queries successfully for another, a query through the obtained pointer
115  *    for the first interface must succeed.
116  *  * It must be transitive ~W if a client holding a pointer to one interface
117  *    queries successfully for a second, and through that pointer queries
118  *    successfully for a third interface, a query for the first interface
119  *    through the pointer for the third interface must succeed.
120  *
121  *  As you can see, this interface doesn't qualify but will most likely
122  *  be good enough for the time being.
123  */
124
125
126 BOOL DPL_CreateIUnknown( IDirectPlayLobbyImpl* lpDPL ) 
127 {
128   lpDPL->unk = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 
129                                                         sizeof( *(lpDPL->unk) ) ); 
130   if ( lpDPL->unk != NULL )
131   {
132     InitializeCriticalSection( &lpDPL->unk->DPL_lock );
133
134     IDirectPlayLobby_AddRef( (IDirectPlayLobby*)lpDPL );
135
136     return TRUE; 
137   }
138
139   return FALSE;
140 }
141
142 BOOL DPL_DestroyIUnknown( IDirectPlayLobbyImpl* lpDPL )
143 {
144   DeleteCriticalSection( &lpDPL->unk->DPL_lock );
145   HeapFree( GetProcessHeap(), 0, lpDPL->unk );
146
147   return TRUE;
148 }
149
150 BOOL DPL_CreateLobby1( IDirectPlayLobbyImpl* lpDPL )
151 {
152   lpDPL->dpl = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
153                                                         sizeof( *(lpDPL->dpl) ) );
154   if ( lpDPL->dpl == NULL )
155   {
156     return FALSE;
157   }
158
159   /* Initialize the dwSize fields for internal structures */
160
161   lpDPL->dpl->sessionDesc.dwSize = sizeof( lpDPL->dpl->sessionDesc ); 
162   lpDPL->dpl->playerName.dwSize = sizeof( lpDPL->dpl->playerName );
163   /* lpDPL->dpl->dwAddressSize = 0; Done in HeapAlloc */
164   
165   return TRUE;  
166 }
167
168 BOOL DPL_DestroyLobby1( IDirectPlayLobbyImpl* lpDPL )
169 {
170   /* Delete the contents */
171   HeapFree( GetProcessHeap(), 0, lpDPL->dpl->sessionDesc.sess.lpszSessionNameA );
172   HeapFree( GetProcessHeap(), 0, lpDPL->dpl->sessionDesc.pass.lpszPasswordA );
173
174   HeapFree( GetProcessHeap(), 0, lpDPL->dpl->playerName.psn.lpszShortNameA );
175   HeapFree( GetProcessHeap(), 0, lpDPL->dpl->playerName.pln.lpszLongNameA );
176
177   HeapFree( GetProcessHeap(), 0, lpDPL->dpl->lpAddress );
178
179   HeapFree( GetProcessHeap(), 0, lpDPL->dpl );
180
181   return TRUE;
182 }
183
184 BOOL DPL_CreateLobby2( IDirectPlayLobbyImpl* lpDPL )
185 {
186   lpDPL->dpl2 = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
187                                                          sizeof( *(lpDPL->dpl2) ) );
188   if ( lpDPL->dpl2 == NULL )
189   {
190     return FALSE;
191   }
192
193   return TRUE;
194 }
195
196 BOOL DPL_DestroyLobby2( IDirectPlayLobbyImpl* lpDPL )
197 {
198   HeapFree( GetProcessHeap(), 0, lpDPL->dpl2 );
199
200   return TRUE;
201 }
202
203 BOOL DPL_CreateLobby3( IDirectPlayLobbyImpl* lpDPL )
204 {
205   lpDPL->dpl3 = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
206                                                          sizeof( *(lpDPL->dpl3) ) );
207   if ( lpDPL->dpl3 == NULL )
208   {
209     return FALSE;
210   }
211
212   return TRUE;
213 }
214
215 BOOL DPL_DestroyLobby3( IDirectPlayLobbyImpl* lpDPL )
216 {
217   HeapFree( GetProcessHeap(), 0, lpDPL->dpl3 );
218
219   return TRUE;
220 }
221
222
223 /* Helper function for DirectPlayLobby  QueryInterface */ 
224 extern 
225 HRESULT directPlayLobby_QueryInterface
226          ( REFIID riid, LPVOID* ppvObj )
227 {
228   IDirectPlayLobby3AImpl* lpDPL = NULL;
229
230   if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
231   {
232     lpDPL = (IDirectPlayLobbyImpl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
233                                               sizeof( *lpDPL ) );
234
235     if( !lpDPL )
236     {
237       return E_OUTOFMEMORY;
238     }
239
240     lpDPL->lpvtbl = &directPlayLobbyWVT;
241
242     if ( DPL_CreateIUnknown( lpDPL ) &&
243          DPL_CreateLobby1( lpDPL ) 
244        )
245     { 
246       *ppvObj = lpDPL;
247       return S_OK;
248     }
249   }
250   else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
251   {
252     lpDPL = (IDirectPlayLobbyAImpl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
253                                                sizeof( *lpDPL ) );
254
255     if( !lpDPL )
256     {
257       return E_OUTOFMEMORY;
258     }
259
260     lpDPL->lpvtbl = &directPlayLobbyAVT;
261
262     if ( DPL_CreateIUnknown( lpDPL ) &&
263          DPL_CreateLobby1( lpDPL ) 
264        )
265     { 
266       *ppvObj = lpDPL;
267       return S_OK;
268     }
269   }
270   else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
271   {
272     lpDPL = (IDirectPlayLobby2Impl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
273                                                sizeof( *lpDPL ) );
274
275     if( !lpDPL )
276     {
277       return E_OUTOFMEMORY;
278     }
279
280     lpDPL->lpvtbl = &directPlayLobby2WVT;
281
282     if ( DPL_CreateIUnknown( lpDPL ) &&
283          DPL_CreateLobby1( lpDPL ) &&
284          DPL_CreateLobby2( lpDPL )
285        )
286     {
287       *ppvObj = lpDPL;
288       return S_OK;
289     }
290   }
291   else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
292   {
293     lpDPL = (IDirectPlayLobby2AImpl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
294                                                 sizeof( *lpDPL ) );
295
296     if( !lpDPL )
297     {
298       return E_OUTOFMEMORY;
299     }
300
301     lpDPL->lpvtbl = &directPlayLobby2AVT;
302
303     if ( DPL_CreateIUnknown( lpDPL ) &&
304          DPL_CreateLobby1( lpDPL )  &&
305          DPL_CreateLobby2( lpDPL )
306        )
307     {
308       *ppvObj = lpDPL;
309       return S_OK;
310     }
311   }
312   else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
313   {
314     lpDPL = (IDirectPlayLobby3Impl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
315                                                sizeof( *lpDPL ) );
316
317     if( !lpDPL )
318     {
319       return E_OUTOFMEMORY;
320     }
321
322     lpDPL->lpvtbl = &directPlayLobby3WVT;
323
324     if ( DPL_CreateIUnknown( lpDPL ) &&
325          DPL_CreateLobby1( lpDPL ) &&
326          DPL_CreateLobby2( lpDPL ) &&
327          DPL_CreateLobby3( lpDPL )
328        )
329     {
330       *ppvObj = lpDPL;
331       return S_OK;
332     }
333   }
334   else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
335   {
336      lpDPL = (IDirectPlayLobby3AImpl*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
337                                              sizeof( *lpDPL ) );
338
339     if( !lpDPL )
340     {
341       return E_OUTOFMEMORY;
342     }
343
344     lpDPL->lpvtbl = &directPlayLobby3AVT;
345
346     if ( DPL_CreateIUnknown( lpDPL ) &&
347          DPL_CreateLobby1( lpDPL ) &&
348          DPL_CreateLobby2( lpDPL ) &&
349          DPL_CreateLobby3( lpDPL )
350        )
351     {
352       *ppvObj = lpDPL;
353       return S_OK;
354     }
355   }
356
357   /* Check if we had problems creating an interface */
358   if ( lpDPL != NULL )
359   {
360     DPL_DestroyLobby3( lpDPL );
361     DPL_DestroyLobby2( lpDPL );
362     DPL_DestroyLobby1( lpDPL );
363     DPL_DestroyIUnknown( lpDPL );
364     HeapFree( GetProcessHeap(), 0, lpDPL );
365
366     *ppvObj = NULL;
367
368     return DPERR_NOMEMORY;
369   }
370   else /* Unsupported interface */
371   {
372     *ppvObj = NULL;
373     return E_NOINTERFACE;
374   }
375 }
376
377 static HRESULT WINAPI IDirectPlayLobbyAImpl_QueryInterface
378 ( LPDIRECTPLAYLOBBYA iface,
379   REFIID riid,
380   LPVOID* ppvObj )
381 {
382   ICOM_THIS(IDirectPlayLobby2Impl,iface);
383   TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
384
385   if( IsEqualGUID( &IID_IUnknown, riid )  ||
386       IsEqualGUID( &IID_IDirectPlayLobbyA, riid )
387     )
388   {
389     IDirectPlayLobby_AddRef( iface );
390     *ppvObj = This;
391     return S_OK;
392   }
393
394   return directPlayLobby_QueryInterface( riid, ppvObj );
395
396 }
397
398 static HRESULT WINAPI IDirectPlayLobbyW_QueryInterface
399 ( LPDIRECTPLAYLOBBY iface,
400   REFIID riid,
401   LPVOID* ppvObj )
402 {
403   ICOM_THIS(IDirectPlayLobbyImpl,iface);
404   TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
405
406   if( IsEqualGUID( &IID_IUnknown, riid )  ||
407       IsEqualGUID( &IID_IDirectPlayLobby, riid )
408     )
409   {
410     IDirectPlayLobby_AddRef( iface );
411     *ppvObj = This;
412     return S_OK;
413   }
414
415   return directPlayLobby_QueryInterface( riid, ppvObj );
416 }
417
418
419 static HRESULT WINAPI IDirectPlayLobby2AImpl_QueryInterface
420 ( LPDIRECTPLAYLOBBY2A iface,
421   REFIID riid,
422   LPVOID* ppvObj )
423 {
424   ICOM_THIS(IDirectPlayLobby2Impl,iface);
425   TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
426
427   /* Compare riids. We know this object is a direct play lobby 2A object.
428      If we are asking about the same type of interface we're fine.
429    */
430   if( IsEqualGUID( &IID_IUnknown, riid )  ||
431       IsEqualGUID( &IID_IDirectPlayLobby2A, riid )
432     )
433   {
434     IDirectPlayLobby_AddRef( iface );
435     *ppvObj = This;
436     return S_OK;
437   }
438   return directPlayLobby_QueryInterface( riid, ppvObj ); 
439 }
440
441 static HRESULT WINAPI IDirectPlayLobby2WImpl_QueryInterface
442 ( LPDIRECTPLAYLOBBY2 iface,
443   REFIID riid,
444   LPVOID* ppvObj )
445 {
446   ICOM_THIS(IDirectPlayLobby2Impl,iface);
447
448   /* Compare riids. We know this object is a direct play lobby 2 object.
449      If we are asking about the same type of interface we're fine.
450    */
451   if( IsEqualGUID( &IID_IUnknown, riid ) ||
452       IsEqualGUID( &IID_IDirectPlayLobby2, 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 IDirectPlayLobby3AImpl_QueryInterface
465 ( LPDIRECTPLAYLOBBY3A iface,
466   REFIID riid,
467   LPVOID* ppvObj )
468 {
469   ICOM_THIS(IDirectPlayLobby3Impl,iface);
470
471   /* Compare riids. We know this object is a direct play lobby 3 object.
472      If we are asking about the same type of interface we're fine.
473    */
474   if( IsEqualGUID( &IID_IUnknown, riid ) ||
475       IsEqualGUID( &IID_IDirectPlayLobby3A, riid )
476     )
477   {
478     IDirectPlayLobby_AddRef( (IDirectPlayLobby*)This );
479     *ppvObj = This;
480     return S_OK;
481   }
482
483   return directPlayLobby_QueryInterface( riid, ppvObj );
484
485 }
486
487 static HRESULT WINAPI IDirectPlayLobby3WImpl_QueryInterface
488 ( LPDIRECTPLAYLOBBY3 iface,
489   REFIID riid,
490   LPVOID* ppvObj )
491 {
492   ICOM_THIS(IDirectPlayLobby3Impl,iface);
493
494   /* Compare riids. We know this object is a direct play lobby 3 object.
495      If we are asking about the same type of interface we're fine.
496    */
497   if( IsEqualGUID( &IID_IUnknown, riid ) ||
498       IsEqualGUID( &IID_IDirectPlayLobby3, riid )
499     )
500   {
501     IDirectPlayLobby_AddRef( (IDirectPlayLobby*)This );
502     *ppvObj = This;
503     return S_OK;
504   }
505
506   return directPlayLobby_QueryInterface( riid, ppvObj );
507
508 }
509
510 /* 
511  * Simple procedure. Just increment the reference count to this
512  * structure and return the new reference count.
513  */
514 static ULONG WINAPI IDirectPlayLobbyAImpl_AddRef
515 ( LPDIRECTPLAYLOBBYA iface )
516 {
517   ULONG refCount;
518   ICOM_THIS(IDirectPlayLobby2Impl,iface);
519
520   EnterCriticalSection( &This->unk->DPL_lock );
521   {
522     refCount = ++(This->unk->ref);
523   }
524   LeaveCriticalSection( &This->unk->DPL_lock );
525
526   TRACE("ref count incremented to %lu for %p\n", refCount, This );
527
528   return refCount;
529 }
530
531 /*
532  * Simple COM procedure. Decrease the reference count to this object.
533  * If the object no longer has any reference counts, free up the associated
534  * memory.
535  */
536 static ULONG WINAPI IDirectPlayLobbyAImpl_Release
537 ( LPDIRECTPLAYLOBBYA iface )
538 {
539   ULONG refCount;
540
541   ICOM_THIS(IDirectPlayLobby2Impl,iface);
542
543   EnterCriticalSection( &This->unk->DPL_lock );
544   {
545     refCount = --(This->unk->ref);
546   }
547   LeaveCriticalSection( &This->unk->DPL_lock );
548
549   TRACE("ref count decremeneted to %lu for %p\n", refCount, This );
550
551   /* Deallocate if this is the last reference to the object */
552   if( refCount )
553   {
554      DPL_DestroyLobby3( This );
555      DPL_DestroyLobby2( This );
556      DPL_DestroyLobby1( This );
557      DPL_DestroyIUnknown( This );
558      HeapFree( GetProcessHeap(), 0, This );
559   }
560
561   return refCount;
562 }
563
564
565 /********************************************************************
566  * 
567  * Connects an application to the session specified by the DPLCONNECTION
568  * structure currently stored with the DirectPlayLobby object.
569  *
570  * Returns a IDirectPlay interface.
571  *
572  */
573 static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect
574 ( LPDIRECTPLAYLOBBYA iface,
575   DWORD dwFlags,
576   LPDIRECTPLAY2A* lplpDP,
577   IUnknown* pUnk)
578 {
579   ICOM_THIS(IDirectPlayLobbyImpl,iface);
580
581   LPDIRECTPLAY2A      lpDirectPlay2A;
582   LPDIRECTPLAY3A      lpDirectPlay3A;
583   LPDIRECTPLAYLOBBY2A lpDirectPlayLobby2A;
584   HRESULT             rc;
585
586   FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, dwFlags, lplpDP, pUnk );
587
588   if( dwFlags || pUnk )
589   {
590      return DPERR_INVALIDPARAMS;
591   }
592
593   if( ( rc = DirectPlayCreate( (LPGUID)&IID_IDirectPlay2A, lplpDP, pUnk ) ) != DP_OK )
594   {
595      ERR("error creating Direct Play 2W interface. Return Code = 0x%lx.\n", rc );
596      return rc;
597   }
598
599   lpDirectPlay2A = *lplpDP;
600
601   /* This should invoke IDirectPlay3::InitializeConnection IDirectPlay3::Open */
602   /* - Use This object to get a DPL2 object using QueryInterface
603    * - Need to call CreateCompoundAddress to create the lpConnection param for IDirectPlay::InitializeConnection
604    * - Call IDirectPlay::InitializeConnection
605    * - Call IDirectPlay::Open 
606    */
607 #if 0
608   create_address:
609   {
610     DPCOMPOUNDADDRESSELEMENT compoundAddress;
611
612     /* Get lobby version capable of supporting CreateCompoundAddress */ 
613     if( ( rc = IDirectPlayLobby_QueryInterface( This, &IID_IDirectPlayLobby2A, &lpDirectPlayLobby2A ) ) != DP_OK )
614     {
615       return rc;
616     }
617
618     EnterCriticalSection( &This->unk->DPL_lock );
619
620     /* Actually create the compound address */
621     memcpy( compoundAddress.guidDataType, This->dpl->guidSP, sizeof( compoundAddress.guidDataType ) );
622
623     LeaveCriticalSection( &This->unk->DPL_lock );
624
625     rc = IDirectPlayLobby_CreateCompoundAddress( lpDirectPlayLobby2A, lpElements, dwElementCount, lpAddress, lpdwAddressSize ) 
626
627     /* Free the lobby object since we're done with it */
628     IDirectPlayLobby_Release( lpDirectPlayLobby2A );
629
630     if( rc != DP_OK )
631     {
632       return rc; 
633     }
634   }
635
636   if( ( rc = IDirectPlayX_QueryInterface( directPlay2A, &IID_IDirectPlay3A, &lpDirectPlay3A ) ) != DP_OK )
637   {
638     return rc;
639   }
640 #endif
641
642   return DP_OK;
643
644 }
645
646 static HRESULT WINAPI IDirectPlayLobbyWImpl_Connect
647 ( LPDIRECTPLAYLOBBY iface,
648   DWORD dwFlags,
649   LPDIRECTPLAY2* lplpDP,
650   IUnknown* pUnk)
651 {
652   ICOM_THIS(IDirectPlayLobbyImpl,iface);
653   LPDIRECTPLAY2* directPlay2W;
654   HRESULT        createRC;
655
656   FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, dwFlags, lplpDP, pUnk );
657
658   if( dwFlags || pUnk )
659   {
660      return DPERR_INVALIDPARAMS;
661   }
662
663   if( ( createRC = DirectPlayCreate( (LPGUID)&IID_IDirectPlay2, lplpDP, pUnk ) ) != DP_OK )
664   {
665      ERR("error creating Direct Play 2W interface. Return Code = 0x%lx.\n", createRC );
666      return createRC;
667   } 
668
669   /* This should invoke IDirectPlay3::InitializeConnection IDirectPlay3::Open */  
670   directPlay2W = lplpDP; 
671  
672   return DP_OK;
673
674 }
675
676 /********************************************************************
677  *
678  * Creates a DirectPlay Address, given a service provider-specific network
679  * address. 
680  * Returns an address contains the globally unique identifier
681  * (GUID) of the service provider and data that the service provider can
682  * interpret as a network address.
683  *
684  */
685 static HRESULT WINAPI IDirectPlayLobbyAImpl_CreateAddress
686 ( LPDIRECTPLAYLOBBYA iface,
687   REFGUID guidSP,
688   REFGUID guidDataType,
689   LPCVOID lpData, 
690   DWORD dwDataSize,
691   LPVOID lpAddress, 
692   LPDWORD lpdwAddressSize )
693 {
694   FIXME(":stub\n");
695   return DPERR_OUTOFMEMORY;
696 }
697
698 static HRESULT WINAPI IDirectPlayLobbyWImpl_CreateAddress
699 ( LPDIRECTPLAYLOBBY iface,
700   REFGUID guidSP,
701   REFGUID guidDataType,
702   LPCVOID lpData,
703   DWORD dwDataSize,
704   LPVOID lpAddress,
705   LPDWORD lpdwAddressSize )
706 {
707   FIXME(":stub\n");
708   return DPERR_OUTOFMEMORY;
709 }
710
711
712 /********************************************************************
713  *
714  * Parses out chunks from the DirectPlay Address buffer by calling the
715  * given callback function, with lpContext, for each of the chunks.
716  *
717  */
718 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddress
719 ( LPDIRECTPLAYLOBBYA iface,
720   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
721   LPCVOID lpAddress,
722   DWORD dwAddressSize,
723   LPVOID lpContext )
724 {
725   FIXME(":stub\n");
726   return DPERR_OUTOFMEMORY;
727 }
728
729 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumAddress
730 ( LPDIRECTPLAYLOBBY iface,
731   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
732   LPCVOID lpAddress,
733   DWORD dwAddressSize,
734   LPVOID lpContext )
735 {
736   FIXME(":stub\n");
737   return DPERR_OUTOFMEMORY;
738 }
739
740 /********************************************************************
741  *
742  * Enumerates all the address types that a given service provider needs to
743  * build the DirectPlay Address.
744  *
745  */
746 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddressTypes
747 ( LPDIRECTPLAYLOBBYA iface,
748   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
749   REFGUID guidSP,
750   LPVOID lpContext,
751   DWORD dwFlags )
752 {
753   FIXME(":stub\n");
754   return DPERR_OUTOFMEMORY;
755 }
756
757 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumAddressTypes
758 ( LPDIRECTPLAYLOBBY iface,
759   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
760   REFGUID guidSP,
761   LPVOID lpContext,
762   DWORD dwFlags )
763 {
764   FIXME(":stub\n");
765   return DPERR_OUTOFMEMORY;
766 }
767
768 /********************************************************************
769  *
770  * Enumerates what applications are registered with DirectPlay by
771  * invoking the callback function with lpContext.
772  *
773  */
774 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumLocalApplications
775 ( LPDIRECTPLAYLOBBY iface,
776   LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback,
777   LPVOID lpContext,
778   DWORD dwFlags )
779 {
780   ICOM_THIS(IDirectPlayLobbyImpl,iface);
781
782   FIXME("(%p)->(%p,%p,0x%08lx):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
783
784   return DPERR_OUTOFMEMORY;
785 }
786
787 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumLocalApplications
788 ( LPDIRECTPLAYLOBBYA iface,
789   LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback,
790   LPVOID lpContext,
791   DWORD dwFlags )
792 {
793   ICOM_THIS(IDirectPlayLobbyImpl,iface);
794
795   FIXME("(%p)->(%p,%p,0x%08lx):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
796
797   return DPERR_OUTOFMEMORY;
798 }
799
800 /********************************************************************
801  *
802  * Retrieves the DPLCONNECTION structure that contains all the information
803  * needed to start and connect an application. This was generated using
804  * either the RunApplication or SetConnectionSettings methods.
805  *
806  * NOTES: If lpData is NULL then just return lpdwDataSize. This allows
807  *        the data structure to be allocated by our caller which can then
808  *        call this procedure/method again with a valid data pointer.
809  */
810 static HRESULT WINAPI IDirectPlayLobbyAImpl_GetConnectionSettings
811 ( LPDIRECTPLAYLOBBYA iface,
812   DWORD dwAppID,
813   LPVOID lpData,
814   LPDWORD lpdwDataSize )
815 {
816   ICOM_THIS(IDirectPlayLobbyImpl,iface);
817   LPDPLCONNECTION lpDplConnection;
818
819   FIXME(": semi stub (%p)->(0x%08lx,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
820  
821   /* Application is requesting us to give the required size */
822   if ( lpData == NULL )
823   {
824     *lpdwDataSize = sizeof( DPLCONNECTION );
825     return DPERR_BUFFERTOOSMALL;
826   }
827
828   /* Let's check the size of the buffer that the application has allocated */
829   if ( *lpdwDataSize < sizeof( DPLCONNECTION ) )
830   {
831     *lpdwDataSize = sizeof( DPLCONNECTION );
832     return DPERR_BUFFERTOOSMALL;
833   }
834
835   /* FIXME: Who's supposed to own the data */
836
837   /* Fill in the fields - let them just use the ptrs */
838   lpDplConnection = (LPDPLCONNECTION)lpData;
839
840   /* Copy everything we've got into here */
841   /* Need to actually store the stuff here. Check if we've already allocated each field first. */
842   lpDplConnection->dwFlags = This->dpl->dwConnFlags;
843
844   /* Copy LPDPSESSIONDESC2 struct */
845   lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( This->dpl->sessionDesc ) );
846   memcpy( lpDplConnection->lpSessionDesc, &This->dpl->sessionDesc, sizeof( This->dpl->sessionDesc ) );
847
848   if( This->dpl->sessionDesc.sess.lpszSessionName )
849   {
850     lpDplConnection->lpSessionDesc->sess.lpszSessionName = 
851       HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, This->dpl->sessionDesc.sess.lpszSessionNameA );
852   }
853
854   if( This->dpl->sessionDesc.pass.lpszPassword )
855   {
856     lpDplConnection->lpSessionDesc->pass.lpszPassword = 
857       HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, This->dpl->sessionDesc.pass.lpszPasswordA );
858   }
859      
860   lpDplConnection->lpSessionDesc->dwReserved1 = This->dpl->sessionDesc.dwReserved1;
861   lpDplConnection->lpSessionDesc->dwReserved2 = This->dpl->sessionDesc.dwReserved2;
862
863   /* Copy DPNAME struct - seems to be optional - check for existance first */
864   lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( This->dpl->playerName ) );
865   memcpy( lpDplConnection->lpPlayerName, &(This->dpl->playerName), sizeof( This->dpl->playerName ) );
866
867   if( This->dpl->playerName.psn.lpszShortName )
868   {
869     lpDplConnection->lpPlayerName->psn.lpszShortName =
870       HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, This->dpl->playerName.psn.lpszShortNameA );  
871   }
872
873   if( This->dpl->playerName.pln.lpszLongName )
874   {
875     lpDplConnection->lpPlayerName->pln.lpszLongName =
876       HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, This->dpl->playerName.pln.lpszLongNameA );
877   }
878
879   memcpy( &lpDplConnection->guidSP, &This->dpl->guidSP, sizeof( This->dpl->guidSP ) );
880
881   lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, This->dpl->dwAddressSize );
882   memcpy( lpDplConnection->lpAddress, This->dpl->lpAddress, This->dpl->dwAddressSize );
883
884   lpDplConnection->dwAddressSize = This->dpl->dwAddressSize;
885
886   return DP_OK;
887 }
888
889 static HRESULT WINAPI IDirectPlayLobbyWImpl_GetConnectionSettings
890 ( LPDIRECTPLAYLOBBY iface,
891   DWORD dwAppID,
892   LPVOID lpData,
893   LPDWORD lpdwDataSize )
894 {
895   ICOM_THIS(IDirectPlayLobbyImpl,iface);
896   FIXME(":semi stub %p %08lx %p %p \n", This, dwAppID, lpData, lpdwDataSize );
897
898   /* Application is requesting us to give the required size */ 
899   if ( !lpData )
900   {
901     /* Let's check the size of the buffer that the application has allocated */
902     if( *lpdwDataSize >= sizeof( DPLCONNECTION ) )
903     {
904       return DP_OK;  
905     }
906     else
907     {
908       *lpdwDataSize = sizeof( DPLCONNECTION );
909       return DPERR_BUFFERTOOSMALL;
910     }
911   }
912
913   /* Fill in the fields - see above */
914   FIXME("stub\n" );
915
916   return DP_OK;
917 }
918
919 /********************************************************************
920  *
921  * Retrieves the message sent between a lobby client and a DirectPlay 
922  * application. All messages are queued until received.
923  *
924  */
925 static HRESULT WINAPI IDirectPlayLobbyAImpl_ReceiveLobbyMessage
926 ( LPDIRECTPLAYLOBBYA iface,
927   DWORD dwFlags,
928   DWORD dwAppID,
929   LPDWORD lpdwMessageFlags,
930   LPVOID lpData,
931   LPDWORD lpdwDataSize )
932 {
933   ICOM_THIS(IDirectPlayLobbyImpl,iface);
934   FIXME(":stub %p %08lx %08lx %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
935          lpdwDataSize );
936   return DPERR_OUTOFMEMORY;
937 }
938
939 static HRESULT WINAPI IDirectPlayLobbyWImpl_ReceiveLobbyMessage
940 ( LPDIRECTPLAYLOBBY iface,
941   DWORD dwFlags,
942   DWORD dwAppID,
943   LPDWORD lpdwMessageFlags,
944   LPVOID lpData,
945   LPDWORD lpdwDataSize )
946 {
947   ICOM_THIS(IDirectPlayLobbyImpl,iface);
948   FIXME(":stub %p %08lx %08lx %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
949          lpdwDataSize );
950   return DPERR_OUTOFMEMORY;
951 }
952
953 /********************************************************************
954  *
955  * Starts an application and passes to it all the information to
956  * connect to a session.
957  *
958  */
959 static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication
960 ( LPDIRECTPLAYLOBBYA iface,
961   DWORD dwFlags,
962   LPDWORD lpdwAppID,
963   LPDPLCONNECTION lpConn,
964   HANDLE hReceiveEvent )
965 {
966   FIXME(":stub\n");
967   return DPERR_OUTOFMEMORY;
968 }
969
970 static HRESULT WINAPI IDirectPlayLobbyWImpl_RunApplication
971 ( LPDIRECTPLAYLOBBY iface,
972   DWORD dwFlags,
973   LPDWORD lpdwAppID,
974   LPDPLCONNECTION lpConn,
975   HANDLE hReceiveEvent )
976 {
977   FIXME(":stub\n");
978   return DPERR_OUTOFMEMORY;
979 }
980
981 /********************************************************************
982  *
983  * Sends a message between the application and the lobby client.
984  * All messages are queued until received.
985  *
986  */
987 static HRESULT WINAPI IDirectPlayLobbyAImpl_SendLobbyMessage
988 ( LPDIRECTPLAYLOBBYA iface,
989   DWORD dwFlags,
990   DWORD dwAppID,
991   LPVOID lpData,
992   DWORD dwDataSize )
993 {
994   FIXME(":stub\n");
995   return DPERR_OUTOFMEMORY;
996 }
997
998 static HRESULT WINAPI IDirectPlayLobbyWImpl_SendLobbyMessage
999 ( LPDIRECTPLAYLOBBY iface,
1000   DWORD dwFlags,
1001   DWORD dwAppID,
1002   LPVOID lpData,
1003   DWORD dwDataSize )
1004 {
1005   FIXME(":stub\n");
1006   return DPERR_OUTOFMEMORY;
1007 }
1008
1009 /********************************************************************
1010  *
1011  * Modifies the DPLCONNECTION structure to contain all information
1012  * needed to start and connect an application.
1013  *
1014  */
1015 static HRESULT WINAPI IDirectPlayLobbyWImpl_SetConnectionSettings
1016 ( LPDIRECTPLAYLOBBY iface,
1017   DWORD dwFlags,
1018   DWORD dwAppID,
1019   LPDPLCONNECTION lpConn )
1020 {
1021   ICOM_THIS(IDirectPlayLobbyImpl,iface);
1022   TRACE(": This=%p, dwFlags=%08lx, dwAppId=%08lx, lpConn=%p\n",
1023          This, dwFlags, dwAppID, lpConn );
1024
1025   /* Paramater check */
1026   if( dwFlags || !This || !lpConn )
1027   {
1028     ERR("invalid parameters.\n");
1029     return DPERR_INVALIDPARAMS;
1030   }
1031
1032   /* See if there is a connection associated with this request.
1033    * dwAppID == 0 indicates that this request isn't associated with a connection.
1034    */
1035   if( dwAppID )
1036   {
1037      FIXME(": Connection dwAppID=%08lx given. Not implemented yet.\n",
1038             dwAppID );
1039
1040      /* Need to add a check for this application Id...*/
1041      return DPERR_NOTLOBBIED;
1042   }
1043
1044   if(  lpConn->dwSize != sizeof(DPLCONNECTION) )
1045   {
1046     ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n", 
1047          lpConn->dwSize, sizeof( DPLCONNECTION ) );
1048     return DPERR_INVALIDPARAMS;
1049   }
1050
1051   /* Need to investigate the lpConn->lpSessionDesc to figure out
1052    * what type of session we need to join/create.
1053    */
1054   if(  (!lpConn->lpSessionDesc ) || 
1055        ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
1056     )
1057   {
1058     ERR("DPSESSIONDESC passed in? Size=%08lx vs. expected=%ul bytes\n",
1059          lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
1060     return DPERR_INVALIDPARAMS;
1061   }
1062
1063   EnterCriticalSection( &This->unk->DPL_lock );
1064
1065   /* Need to actually store the stuff here. Check if we've already allocated each field first. */
1066   This->dpl->dwConnFlags = lpConn->dwFlags;
1067
1068   /* Copy LPDPSESSIONDESC2 struct - this is required */
1069   memcpy( &This->dpl->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
1070
1071   /* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */
1072   if( lpConn->lpSessionDesc->sess.lpszSessionName )
1073     This->dpl->sessionDesc.sess.lpszSessionName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionName );
1074   else
1075     This->dpl->sessionDesc.sess.lpszSessionName = NULL;
1076  
1077   if( lpConn->lpSessionDesc->pass.lpszPassword )
1078     This->dpl->sessionDesc.pass.lpszPassword = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPassword );
1079   else
1080     This->dpl->sessionDesc.pass.lpszPassword = NULL;
1081
1082   This->dpl->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1;
1083   This->dpl->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2;
1084
1085   /* Copy DPNAME struct - seems to be optional - check for existance first */
1086   if( lpConn->lpPlayerName )
1087   {
1088      memcpy( &This->dpl->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) ); 
1089
1090      if( lpConn->lpPlayerName->psn.lpszShortName )
1091        This->dpl->playerName.psn.lpszShortName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortName );
1092
1093      if( lpConn->lpPlayerName->pln.lpszLongName )
1094        This->dpl->playerName.pln.lpszLongName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongName );
1095
1096   }
1097
1098   memcpy( &This->dpl->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) );  
1099   
1100   This->dpl->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize ); 
1101   memcpy( This->dpl->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
1102
1103   This->dpl->dwAddressSize = lpConn->dwAddressSize;
1104
1105   LeaveCriticalSection( &This->unk->DPL_lock );
1106
1107   return DP_OK;
1108 }
1109
1110 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetConnectionSettings
1111 ( LPDIRECTPLAYLOBBYA iface,
1112   DWORD dwFlags,
1113   DWORD dwAppID,
1114   LPDPLCONNECTION lpConn )
1115 {
1116   ICOM_THIS(IDirectPlayLobbyImpl,iface);
1117   TRACE(": This=%p, dwFlags=%08lx, dwAppId=%08lx, lpConn=%p\n",
1118          This, dwFlags, dwAppID, lpConn );
1119
1120   /* Paramater check */
1121   if( dwFlags || !This || !lpConn )
1122   {
1123     ERR("invalid parameters.\n");
1124     return DPERR_INVALIDPARAMS;
1125   }
1126
1127   /* See if there is a connection associated with this request.
1128    * dwAppID == 0 indicates that this request isn't associated with a connection.
1129    */
1130   if( dwAppID )
1131   {
1132      FIXME(": Connection dwAppID=%08lx given. Not implemented yet.\n",
1133             dwAppID );
1134
1135      /* Need to add a check for this application Id...*/
1136      return DPERR_NOTLOBBIED;
1137   }
1138
1139   if(  lpConn->dwSize != sizeof(DPLCONNECTION) )
1140   {
1141     ERR(": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n",
1142          lpConn->dwSize, sizeof( DPLCONNECTION ) );
1143     return DPERR_INVALIDPARAMS;
1144   }
1145
1146   /* Need to investigate the lpConn->lpSessionDesc to figure out
1147    * what type of session we need to join/create.
1148    */
1149   if(  (!lpConn->lpSessionDesc ) ||
1150        ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
1151     )
1152   {
1153     ERR("DPSESSIONDESC passed in? Size=%08lx vs. expected=%ul bytes\n",
1154          lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
1155     return DPERR_INVALIDPARAMS;
1156   }
1157
1158   EnterCriticalSection( &This->unk->DPL_lock );
1159
1160   /* Need to actually store the stuff here. Check if we've already allocated each field first. */
1161   This->dpl->dwConnFlags = lpConn->dwFlags;
1162
1163   /* Copy LPDPSESSIONDESC2 struct - this is required */
1164   memcpy( &This->dpl->sessionDesc, lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
1165
1166   /* FIXME: Can this just be shorted? Does it handle the NULL case correctly? */
1167   if( lpConn->lpSessionDesc->sess.lpszSessionNameA )
1168     This->dpl->sessionDesc.sess.lpszSessionNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionNameA );
1169   else
1170     This->dpl->sessionDesc.sess.lpszSessionNameA = NULL;
1171
1172   if( lpConn->lpSessionDesc->pass.lpszPasswordA )
1173     This->dpl->sessionDesc.pass.lpszPasswordA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPasswordA );
1174   else
1175     This->dpl->sessionDesc.pass.lpszPasswordA = NULL;
1176
1177   This->dpl->sessionDesc.dwReserved1 = lpConn->lpSessionDesc->dwReserved1;
1178   This->dpl->sessionDesc.dwReserved2 = lpConn->lpSessionDesc->dwReserved2;
1179
1180   /* Copy DPNAME struct - seems to be optional - check for existance first */
1181   if( lpConn->lpPlayerName )
1182   {
1183      memcpy( &This->dpl->playerName, lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) );
1184
1185      if( lpConn->lpPlayerName->psn.lpszShortNameA )
1186        This->dpl->playerName.psn.lpszShortNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortNameA );
1187
1188      if( lpConn->lpPlayerName->pln.lpszLongNameA )
1189        This->dpl->playerName.pln.lpszLongNameA = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongNameA );
1190
1191   }
1192
1193   memcpy( &This->dpl->guidSP, &lpConn->guidSP, sizeof( lpConn->guidSP ) );
1194
1195   This->dpl->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize );
1196   memcpy( This->dpl->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
1197
1198   This->dpl->dwAddressSize = lpConn->dwAddressSize;
1199
1200   LeaveCriticalSection( &This->unk->DPL_lock );
1201
1202   return DP_OK;
1203 }
1204
1205 /********************************************************************
1206  *
1207  * Registers an event that will be set when a lobby message is received.
1208  *
1209  */
1210 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetLobbyMessageEvent
1211 ( LPDIRECTPLAYLOBBYA iface,
1212   DWORD dwFlags,
1213   DWORD dwAppID,
1214   HANDLE hReceiveEvent )
1215 {
1216   FIXME(":stub\n");
1217   return DPERR_OUTOFMEMORY;
1218 }
1219
1220 static HRESULT WINAPI IDirectPlayLobbyWImpl_SetLobbyMessageEvent
1221 ( LPDIRECTPLAYLOBBY iface,
1222   DWORD dwFlags,
1223   DWORD dwAppID,
1224   HANDLE hReceiveEvent )
1225 {
1226   FIXME(":stub\n");
1227   return DPERR_OUTOFMEMORY;
1228 }
1229
1230
1231 /* DPL 2 methods - well actuall only one */
1232
1233 /********************************************************************
1234  *
1235  * Registers an event that will be set when a lobby message is received.
1236  *
1237  */
1238 static HRESULT WINAPI IDirectPlayLobby2WImpl_CreateCompoundAddress
1239 ( LPDIRECTPLAYLOBBY2 iface,
1240   LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1241   DWORD dwElementCount,
1242   LPVOID lpAddress,
1243   LPDWORD lpdwAddressSize )
1244 {
1245   FIXME(":stub\n");
1246   return DPERR_OUTOFMEMORY;
1247 }
1248
1249 static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateCompoundAddress
1250 ( LPDIRECTPLAYLOBBY2A iface,
1251   LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1252   DWORD dwElementCount,
1253   LPVOID lpAddress,
1254   LPDWORD lpdwAddressSize )
1255 {
1256   FIXME(":stub\n");
1257   return DPERR_OUTOFMEMORY;
1258 }
1259
1260 /* DPL 3 methods */
1261
1262 static HRESULT WINAPI IDirectPlayLobby3WImpl_ConnectEx
1263 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, REFIID riid, LPVOID* lplpDP, IUnknown* pUnk )
1264 {
1265   FIXME(":stub\n");
1266   return DP_OK;
1267 }
1268
1269 static HRESULT WINAPI IDirectPlayLobby3AImpl_ConnectEx
1270 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, REFIID riid, LPVOID* lplpDP, IUnknown* pUnk )
1271 {
1272   FIXME(":stub\n");
1273   return DP_OK;
1274 }
1275
1276 static HRESULT WINAPI IDirectPlayLobby3WImpl_RegisterApplication
1277 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, LPDPAPPLICATIONDESC lpAppDesc )
1278 {
1279   FIXME(":stub\n");
1280   return DP_OK;
1281 }
1282
1283 static HRESULT WINAPI IDirectPlayLobby3AImpl_RegisterApplication
1284 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, LPDPAPPLICATIONDESC lpAppDesc )
1285 {
1286   FIXME(":stub\n");
1287   return DP_OK;
1288 }
1289
1290 static HRESULT WINAPI IDirectPlayLobby3WImpl_UnregisterApplication
1291 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, REFGUID lpAppDesc )
1292 {
1293   FIXME(":stub\n");
1294   return DP_OK;
1295 }
1296
1297 static HRESULT WINAPI IDirectPlayLobby3AImpl_UnregisterApplication
1298 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, REFGUID lpAppDesc )
1299 {
1300   FIXME(":stub\n");
1301   return DP_OK;
1302 }
1303
1304 static HRESULT WINAPI IDirectPlayLobby3WImpl_WaitForConnectionSettings
1305 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags )
1306 {
1307   FIXME(":stub\n");
1308   return DP_OK;
1309 }
1310
1311 static HRESULT WINAPI IDirectPlayLobby3AImpl_WaitForConnectionSettings
1312 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags )
1313 {
1314   FIXME(":stub\n");
1315   return DP_OK;
1316 }
1317
1318
1319 /* Virtual Table definitions for DPL{1,2,3}{A,W} */
1320
1321 /* Note: Hack so we can reuse the old functions without compiler warnings */
1322 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1323 # define XCAST(fun)     (typeof(directPlayLobbyAVT.fn##fun))
1324 #else
1325 # define XCAST(fun)     (void*)
1326 #endif
1327
1328 /* Direct Play Lobby 1 (ascii) Virtual Table for methods */
1329 /* All lobby 1 methods are exactly the same except QueryInterface */
1330 static struct ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyAVT = 
1331 {
1332   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1333
1334   IDirectPlayLobbyAImpl_QueryInterface,
1335   XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef,
1336   XCAST(Release)IDirectPlayLobbyAImpl_Release,
1337
1338   IDirectPlayLobbyAImpl_Connect,
1339   IDirectPlayLobbyAImpl_CreateAddress,
1340   IDirectPlayLobbyAImpl_EnumAddress,
1341   IDirectPlayLobbyAImpl_EnumAddressTypes,
1342   IDirectPlayLobbyAImpl_EnumLocalApplications,
1343   IDirectPlayLobbyAImpl_GetConnectionSettings,
1344   IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
1345   IDirectPlayLobbyAImpl_RunApplication,
1346   IDirectPlayLobbyAImpl_SendLobbyMessage,
1347   IDirectPlayLobbyAImpl_SetConnectionSettings,
1348   IDirectPlayLobbyAImpl_SetLobbyMessageEvent
1349 };
1350 #undef XCAST
1351
1352
1353 /* Note: Hack so we can reuse the old functions without compiler warnings */
1354 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1355 # define XCAST(fun)     (typeof(directPlayLobbyWVT.fn##fun))
1356 #else
1357 # define XCAST(fun)     (void*)
1358 #endif
1359
1360 /* Direct Play Lobby 1 (unicode) Virtual Table for methods */
1361 static ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyWVT = 
1362 {
1363   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1364
1365   IDirectPlayLobbyW_QueryInterface,
1366   XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef,
1367   XCAST(Release)IDirectPlayLobbyAImpl_Release,
1368
1369   IDirectPlayLobbyWImpl_Connect,
1370   IDirectPlayLobbyWImpl_CreateAddress, 
1371   IDirectPlayLobbyWImpl_EnumAddress,
1372   IDirectPlayLobbyWImpl_EnumAddressTypes,
1373   IDirectPlayLobbyWImpl_EnumLocalApplications,
1374   IDirectPlayLobbyWImpl_GetConnectionSettings,
1375   IDirectPlayLobbyWImpl_ReceiveLobbyMessage,
1376   IDirectPlayLobbyWImpl_RunApplication,
1377   IDirectPlayLobbyWImpl_SendLobbyMessage,
1378   IDirectPlayLobbyWImpl_SetConnectionSettings,
1379   IDirectPlayLobbyWImpl_SetLobbyMessageEvent
1380 };
1381 #undef XCAST
1382
1383 /* Note: Hack so we can reuse the old functions without compiler warnings */
1384 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1385 # define XCAST(fun)     (typeof(directPlayLobby2AVT.fn##fun))
1386 #else
1387 # define XCAST(fun)     (void*)
1388 #endif
1389
1390 /* Direct Play Lobby 2 (ascii) Virtual Table for methods */
1391 static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2AVT = 
1392 {
1393   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1394
1395   IDirectPlayLobby2AImpl_QueryInterface,
1396   XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef,
1397   XCAST(Release)IDirectPlayLobbyAImpl_Release,
1398
1399   XCAST(Connect)IDirectPlayLobbyAImpl_Connect,
1400   XCAST(CreateAddress)IDirectPlayLobbyAImpl_CreateAddress,
1401   XCAST(EnumAddress)IDirectPlayLobbyAImpl_EnumAddress,
1402   XCAST(EnumAddressTypes)IDirectPlayLobbyAImpl_EnumAddressTypes,
1403   XCAST(EnumLocalApplications)IDirectPlayLobbyAImpl_EnumLocalApplications,
1404   XCAST(GetConnectionSettings)IDirectPlayLobbyAImpl_GetConnectionSettings,
1405   XCAST(ReceiveLobbyMessage)IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
1406   XCAST(RunApplication)IDirectPlayLobbyAImpl_RunApplication,
1407   XCAST(SendLobbyMessage)IDirectPlayLobbyAImpl_SendLobbyMessage,
1408   XCAST(SetConnectionSettings)IDirectPlayLobbyAImpl_SetConnectionSettings,
1409   XCAST(SetLobbyMessageEvent)IDirectPlayLobbyAImpl_SetLobbyMessageEvent,
1410
1411   IDirectPlayLobby2AImpl_CreateCompoundAddress 
1412 };
1413 #undef XCAST
1414
1415 /* Note: Hack so we can reuse the old functions without compiler warnings */
1416 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1417 # define XCAST(fun)     (typeof(directPlayLobby2AVT.fn##fun))
1418 #else
1419 # define XCAST(fun)     (void*)
1420 #endif
1421
1422 /* Direct Play Lobby 2 (unicode) Virtual Table for methods */
1423 static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2WVT = 
1424 {
1425   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1426
1427   IDirectPlayLobby2WImpl_QueryInterface,
1428   XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef, 
1429   XCAST(Release)IDirectPlayLobbyAImpl_Release,
1430
1431   XCAST(Connect)IDirectPlayLobbyWImpl_Connect,
1432   XCAST(CreateAddress)IDirectPlayLobbyWImpl_CreateAddress,
1433   XCAST(EnumAddress)IDirectPlayLobbyWImpl_EnumAddress,
1434   XCAST(EnumAddressTypes)IDirectPlayLobbyWImpl_EnumAddressTypes,
1435   XCAST(EnumLocalApplications)IDirectPlayLobbyWImpl_EnumLocalApplications,
1436   XCAST(GetConnectionSettings)IDirectPlayLobbyWImpl_GetConnectionSettings,
1437   XCAST(ReceiveLobbyMessage)IDirectPlayLobbyWImpl_ReceiveLobbyMessage,
1438   XCAST(RunApplication)IDirectPlayLobbyWImpl_RunApplication,
1439   XCAST(SendLobbyMessage)IDirectPlayLobbyWImpl_SendLobbyMessage,
1440   XCAST(SetConnectionSettings)IDirectPlayLobbyWImpl_SetConnectionSettings,
1441   XCAST(SetLobbyMessageEvent)IDirectPlayLobbyWImpl_SetLobbyMessageEvent,
1442
1443   IDirectPlayLobby2WImpl_CreateCompoundAddress
1444 };
1445 #undef XCAST
1446
1447 /* Direct Play Lobby 3 (ascii) Virtual Table for methods */
1448
1449 /* Note: Hack so we can reuse the old functions without compiler warnings */
1450 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1451 # define XCAST(fun)     (typeof(directPlayLobby3AVT.fn##fun))
1452 #else
1453 # define XCAST(fun)     (void*)
1454 #endif
1455
1456 static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3AVT =
1457 {
1458   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1459   IDirectPlayLobby3AImpl_QueryInterface,
1460   XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef,
1461   XCAST(Release)IDirectPlayLobbyAImpl_Release,
1462
1463   XCAST(Connect)IDirectPlayLobbyAImpl_Connect,
1464   XCAST(CreateAddress)IDirectPlayLobbyAImpl_CreateAddress,
1465   XCAST(EnumAddress)IDirectPlayLobbyAImpl_EnumAddress,
1466   XCAST(EnumAddressTypes)IDirectPlayLobbyAImpl_EnumAddressTypes,
1467   XCAST(EnumLocalApplications)IDirectPlayLobbyAImpl_EnumLocalApplications,
1468   XCAST(GetConnectionSettings)IDirectPlayLobbyAImpl_GetConnectionSettings,
1469   XCAST(ReceiveLobbyMessage)IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
1470   XCAST(RunApplication)IDirectPlayLobbyAImpl_RunApplication,
1471   XCAST(SendLobbyMessage)IDirectPlayLobbyAImpl_SendLobbyMessage,
1472   XCAST(SetConnectionSettings)IDirectPlayLobbyAImpl_SetConnectionSettings,
1473   XCAST(SetLobbyMessageEvent)IDirectPlayLobbyAImpl_SetLobbyMessageEvent,
1474
1475   XCAST(CreateCompoundAddress)IDirectPlayLobby2AImpl_CreateCompoundAddress,
1476
1477   IDirectPlayLobby3AImpl_ConnectEx,
1478   IDirectPlayLobby3AImpl_RegisterApplication,
1479   IDirectPlayLobby3AImpl_UnregisterApplication,
1480   IDirectPlayLobby3AImpl_WaitForConnectionSettings
1481 };
1482 #undef XCAST
1483
1484 /* Direct Play Lobby 3 (unicode) Virtual Table for methods */
1485
1486 /* Note: Hack so we can reuse the old functions without compiler warnings */
1487 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1488 # define XCAST(fun)     (typeof(directPlayLobby3WVT.fn##fun))
1489 #else
1490 # define XCAST(fun)     (void*)
1491 #endif
1492
1493 static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3WVT =
1494 {
1495   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1496   IDirectPlayLobby3WImpl_QueryInterface,
1497   XCAST(AddRef)IDirectPlayLobbyAImpl_AddRef,
1498   XCAST(Release)IDirectPlayLobbyAImpl_Release,
1499
1500   XCAST(Connect)IDirectPlayLobbyWImpl_Connect,
1501   XCAST(CreateAddress)IDirectPlayLobbyWImpl_CreateAddress,
1502   XCAST(EnumAddress)IDirectPlayLobbyWImpl_EnumAddress,
1503   XCAST(EnumAddressTypes)IDirectPlayLobbyWImpl_EnumAddressTypes,
1504   XCAST(EnumLocalApplications)IDirectPlayLobbyWImpl_EnumLocalApplications,
1505   XCAST(GetConnectionSettings)IDirectPlayLobbyWImpl_GetConnectionSettings,
1506   XCAST(ReceiveLobbyMessage)IDirectPlayLobbyWImpl_ReceiveLobbyMessage,
1507   XCAST(RunApplication)IDirectPlayLobbyWImpl_RunApplication,
1508   XCAST(SendLobbyMessage)IDirectPlayLobbyWImpl_SendLobbyMessage,
1509   XCAST(SetConnectionSettings)IDirectPlayLobbyWImpl_SetConnectionSettings,
1510   XCAST(SetLobbyMessageEvent)IDirectPlayLobbyWImpl_SetLobbyMessageEvent,
1511
1512   XCAST(CreateCompoundAddress)IDirectPlayLobby2WImpl_CreateCompoundAddress,
1513
1514   IDirectPlayLobby3WImpl_ConnectEx,
1515   IDirectPlayLobby3WImpl_RegisterApplication,
1516   IDirectPlayLobby3WImpl_UnregisterApplication,
1517   IDirectPlayLobby3WImpl_WaitForConnectionSettings
1518 };
1519 #undef XCAST
1520
1521
1522 /*********************************************************
1523  *
1524  * Direct Play and Direct Play Lobby Interface Implementation 
1525  * 
1526  *********************************************************/ 
1527
1528 /***************************************************************************
1529  *  DirectPlayLobbyCreateA   (DPLAYX.4)
1530  *
1531  */
1532 HRESULT WINAPI DirectPlayLobbyCreateA( LPGUID lpGUIDDSP,
1533                                        LPDIRECTPLAYLOBBYA *lplpDPL,
1534                                        IUnknown *lpUnk, 
1535                                        LPVOID lpData,
1536                                        DWORD dwDataSize )
1537 {
1538   TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\n",
1539         lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
1540
1541   /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
1542    * equal 0. These fields are mostly for future expansion.
1543    */
1544   if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
1545   {
1546      *lplpDPL = NULL;
1547      return DPERR_INVALIDPARAMS;
1548   }
1549
1550   return directPlayLobby_QueryInterface( &IID_IDirectPlayLobbyA, (void**)lplpDPL ); 
1551 }
1552
1553 /***************************************************************************
1554  *  DirectPlayLobbyCreateW   (DPLAYX.5)
1555  *
1556  */
1557 HRESULT WINAPI DirectPlayLobbyCreateW( LPGUID lpGUIDDSP, 
1558                                        LPDIRECTPLAYLOBBY *lplpDPL,
1559                                        IUnknown *lpUnk,
1560                                        LPVOID lpData, 
1561                                        DWORD dwDataSize )
1562 {
1563   TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\n",
1564         lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
1565
1566   /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must 
1567    * equal 0. These fields are mostly for future expansion.
1568    */
1569   if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
1570   {
1571      *lplpDPL = NULL;
1572      ERR("Bad parameters!\n" );
1573      return DPERR_INVALIDPARAMS;
1574   }
1575
1576   return directPlayLobby_QueryInterface( &IID_IDirectPlayLobby, (void**)lplpDPL );  
1577
1578 }