Another missing WINAPI.
[wine] / multimedia / dplay.c
1 /* Direct Play 3 and Direct Play Lobby 2 Implementation
2  *
3  * Copyright 1998 - Peter Hunnisett
4  *
5  * <presently under construction - contact hunnise@nortel.ca>
6  *
7  */
8 #include "interfaces.h"
9 #include "heap.h"
10 #include "winerror.h"
11 #include "debug.h"
12 #include "winnt.h"
13 #include "winreg.h"
14 #include "compobj.h"
15 #include "dplay.h"
16
17 #include "thread.h"
18
19 #define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
20 #define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
21 #define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)
22
23 struct IDirectPlayLobby {
24     LPDIRECTPLAYLOBBY_VTABLE lpVtbl;
25     ULONG                    ref;
26     LPDPLCONNECTION          lpSession;
27 };
28
29 struct IDirectPlayLobby2 {
30     LPDIRECTPLAYLOBBY2_VTABLE lpVtbl;
31     ULONG                     ref;
32     LPDPLCONNECTION           lpSession;
33 };
34
35
36 /* Forward declarations of virtual tables */
37 static DIRECTPLAYLOBBY_VTABLE  directPlayLobbyAVT;
38 static DIRECTPLAYLOBBY_VTABLE  directPlayLobbyWVT;
39 static DIRECTPLAYLOBBY2_VTABLE directPlayLobby2AVT;
40 static DIRECTPLAYLOBBY2_VTABLE directPlayLobby2WVT;
41
42 struct IDirectPlay2 {
43   LPDIRECTPLAY2_VTABLE lpVtbl;
44   ULONG                ref;
45 };
46
47 struct IDirectPlay3 {
48   LPDIRECTPLAY3_VTABLE lpVtbl;
49   ULONG                ref;
50 };
51
52
53 static DIRECTPLAY2_VTABLE directPlay2AVT;
54 static DIRECTPLAY2_VTABLE directPlay2WVT;
55 static DIRECTPLAY3_VTABLE directPlay3AVT;
56 static DIRECTPLAY3_VTABLE directPlay3WVT;
57
58 /* Routine to delete the entire DPLCONNECTION tree. Works for both unicode and ascii. */
59 void deleteDPConnection( LPDPLCONNECTION* ptrToDelete )
60 {
61  
62   /* This is most definitely wrong. We're not even keeping dwCurrentPlayers over this */
63    LPDPLCONNECTION toDelete = *ptrToDelete;
64
65    FIXME( dplay, "incomplete.\n" );
66
67    if( !toDelete )
68      return;
69     
70    /* Clear out DPSESSIONDESC2 */
71    if( toDelete->lpSessionDesc )
72    {
73      if( toDelete->lpSessionDesc->sess.lpszSessionName )
74        HeapFree( GetProcessHeap(), 0, toDelete->lpSessionDesc->sess.lpszSessionName );
75
76      if( toDelete->lpSessionDesc->pass.lpszPassword ) 
77        HeapFree( GetProcessHeap(), 0, toDelete->lpSessionDesc->pass.lpszPassword ); 
78
79      if( toDelete->lpSessionDesc );  
80        HeapFree( GetProcessHeap(), 0, toDelete->lpSessionDesc ); 
81    }
82
83    /* Clear out LPDPNAME */
84    if( toDelete->lpPlayerName )
85    { 
86      if( toDelete->lpPlayerName->psn.lpszShortName )
87        HeapFree( GetProcessHeap(), 0, toDelete->lpPlayerName->psn.lpszShortName );
88
89      if( toDelete->lpPlayerName->pln.lpszLongName ) 
90        HeapFree( GetProcessHeap(), 0, toDelete->lpPlayerName->pln.lpszLongName );
91
92      if( toDelete->lpPlayerName ) 
93        HeapFree( GetProcessHeap(), 0, toDelete->lpPlayerName );
94    }
95
96    /* Clear out lpAddress. TO DO...Once we actually copy it. */
97
98    /* Clear out DPLCONNECTION */
99    HeapFree( GetProcessHeap(), 0, toDelete );
100
101    toDelete = NULL;
102 }
103
104
105 #if 0
106 /* Routine which copies and allocates all the store required for the DPLCONNECTION struct. */
107 void rebuildDPConnectionW( LPDPLCONNECTION dest, LPDPLCONNECTION src )
108 {
109  
110   /* Need to delete everything that already exists first */
111   FIXME( dplay, "function is incomplete.\n" ); 
112
113   if( !src )
114   {
115     /* Nothing to copy...hmmm...*/
116     ERR( dplay, "nothing to copy\n" );
117     return;
118   }
119
120   /* Copy DPLCONNECTION struct. If dest isn't NULL then we have a DPLCONNECTION
121      struct but that's it
122    */
123   if( dest == NULL )
124   {
125     dest = HeapAlloc( GetProcessHeap(), 0, sizeof( *src ) );
126   }
127   memcpy( dest, src, sizeof( *src ) );
128
129   /* Copy LPDPSESSIONDESC2 struct */
130   if( src->lpSessionDesc )
131   {
132     dest->lpSessionDesc = HeapAlloc( GetProcessHeap(), 0,
133                                      sizeof( *(src->lpSessionDesc) ) );
134
135     memcpy( dest->lpSessionDesc, src->lpSessionDesc,
136             sizeof( *(src->lpSessionDesc) ) ); 
137
138     if( src->lpSessionDesc )
139     { 
140       /* Hmmm...do we have to assume the system heap? */ 
141       dest->lpSessionDesc->sess.lpszSessionName = HEAP_strdupW( GetProcessHeap(), 0,
142                                                                 src->lpSessionDesc->sess.lpszSessionName );
143     }
144
145     if( src->lpSessionDesc->pass.lpszPassword )
146     {
147       dest->lpSessionDesc->pass.lpszPassword = HEAP_strdupW( GetProcessHeap(), 0,
148                                                              src->lpSessionDesc->pass.lpszPassword );
149     }
150     dest->lpSessionDesc->dwReserved1 = src->lpSessionDesc->dwReserved2 = 0;
151   }
152
153   /* Copy DPNAME struct */      
154   if( src->lpPlayerName )
155   {
156     dest->lpPlayerName = HeapAlloc( GetProcessHeap(), 0, sizeof( *(src->lpPlayerName) ) ); 
157     memcpy( dest->lpPlayerName, src->lpPlayerName, sizeof( *(src->lpPlayerName) ) ); 
158
159     if( src->lpPlayerName->psn.lpszShortName )
160     { 
161       dest->lpPlayerName->psn.lpszShortName = HEAP_strdupW( GetProcessHeap(), 0,
162                                                             src->lpPlayerName->psn.lpszShortName );
163     }
164  
165     if( src->lpPlayerName->pln.lpszLongName )
166     {
167       dest->lpPlayerName->pln.lpszLongName = HEAP_strdupW( GetProcessHeap(), 0,
168                                                            src->lpPlayerName->pln.lpszLongName );
169     }
170   }
171
172   /* Copy Address of Service Provider -TBD */
173   if( src->lpAddress ) 
174   {
175     /* What do we do here? */ 
176   } 
177
178 }
179
180 #endif
181
182 /* Routine called when starting up the server thread */
183 DWORD DPLobby_Spawn_Server( LPVOID startData )
184 {
185   DPSESSIONDESC2* lpSession = (DPSESSIONDESC2*) startData;
186   DWORD sessionDwFlags = lpSession->dwFlags;
187  
188   TRACE( dplay, "spawing thread for lpConn=%p dwFlags=%08lx\n", lpSession, sessionDwFlags );
189   FIXME( dplay, "thread needs something to do\n" ); 
190
191 /*for(;;)*/
192   {
193      
194     /* Check out the connection flags to determine what to do. Ensure we have 
195        no leftover bits in this structure */
196     if( sessionDwFlags & DPSESSION_CLIENTSERVER )
197     {
198        /* This indicates that the application which is requesting the creation
199         * of this session is going to be the server (application/player)
200         */ 
201        if( sessionDwFlags & DPSESSION_SECURESERVER )
202        {
203          sessionDwFlags &= ~DPSESSION_SECURESERVER; 
204        }
205        sessionDwFlags &= ~DPSESSION_CLIENTSERVER;  
206     }
207
208     if( sessionDwFlags & DPSESSION_JOINDISABLED )
209     {
210        sessionDwFlags &= ~DPSESSION_JOINDISABLED; 
211     } 
212
213     if( sessionDwFlags & DPSESSION_KEEPALIVE )
214     {
215        sessionDwFlags &= ~DPSESSION_KEEPALIVE;
216     }
217
218     if( sessionDwFlags & DPSESSION_MIGRATEHOST )
219     {
220        sessionDwFlags &= ~DPSESSION_MIGRATEHOST;
221     }
222
223     if( sessionDwFlags & DPSESSION_MULTICASTSERVER )
224     {
225        sessionDwFlags &= ~DPSESSION_MULTICASTSERVER;
226     }
227
228     if( sessionDwFlags & DPSESSION_NEWPLAYERSDISABLED )
229     {
230        sessionDwFlags &= ~DPSESSION_NEWPLAYERSDISABLED; 
231     }
232
233     if( sessionDwFlags & DPSESSION_NODATAMESSAGES )
234     {
235        sessionDwFlags &= ~DPSESSION_NODATAMESSAGES; 
236     } 
237
238     if( sessionDwFlags & DPSESSION_NOMESSAGEID )
239     {
240        sessionDwFlags &= ~DPSESSION_NOMESSAGEID;
241     }
242
243     if( sessionDwFlags & DPSESSION_PASSWORDREQUIRED )
244     {
245        sessionDwFlags &= ~DPSESSION_PASSWORDREQUIRED;
246     }
247
248   }
249
250   ExitThread(0);
251   return 0; 
252 }
253
254
255 /*********************************************************
256  *
257  * Direct Play and Direct Play Lobby Interface Implementation 
258  * 
259  *********************************************************/ 
260
261 /* The COM interface for upversioning an interface
262  * We've been given a GUID (riid) and we need to replace the present
263  * interface with that of the requested interface.
264  *
265  * Snip from some Microsoft document:
266  * There are four requirements for implementations of QueryInterface (In these
267  * cases, "must succeed" means "must succeed barring catastrophic failure."):
268  *
269  *  * The set of interfaces accessible on an object through
270  *    IUnknown::QueryInterface must be static, not dynamic. This means that
271  *    if a call to QueryInterface for a pointer to a specified interface
272  *    succeeds the first time, it must succeed again, and if it fails the
273  *    first time, it must fail on all subsequent queries.
274  *  * It must be symmetric ~W if a client holds a pointer to an interface on
275  *    an object, and queries for that interface, the call must succeed.
276  *  * It must be reflexive ~W if a client holding a pointer to one interface
277  *    queries successfully for another, a query through the obtained pointer
278  *    for the first interface must succeed.
279  *  * It must be transitive ~W if a client holding a pointer to one interface
280  *    queries successfully for a second, and through that pointer queries
281  *    successfully for a third interface, a query for the first interface
282  *    through the pointer for the third interface must succeed.
283  *
284  *  As you can see, this interface doesn't qualify but will most likely
285  *  be good enough for the time being.
286  */
287 static HRESULT WINAPI IDirectPlayLobbyA_QueryInterface
288 ( LPDIRECTPLAYLOBBYA this,
289   REFIID riid,
290   LPVOID* ppvObj )
291 {
292   return DPERR_OUTOFMEMORY; 
293 }
294
295 static HRESULT WINAPI IDirectPlayLobbyW_QueryInterface
296 ( LPDIRECTPLAYLOBBY this,
297   REFIID riid,
298   LPVOID* ppvObj )
299 {
300   return DPERR_OUTOFMEMORY;
301 }
302
303 static HRESULT WINAPI IDirectPlayLobby2A_QueryInterface
304 ( LPDIRECTPLAYLOBBY2A this,
305   REFIID riid,
306   LPVOID* ppvObj )
307 {
308   /* Compare riids. We know this object is a direct play lobby 2A object.
309      If we are asking about the same type of interface we're fine.
310    */
311   if( IsEqualGUID( &IID_IUnknown, riid )  ||
312       IsEqualGUID( &IID_IDirectPlayLobby2A, riid )
313     )
314   {
315     this->lpVtbl->fnAddRef( this );
316     *ppvObj = this;
317     return S_OK;
318   }
319   /* They're requesting a unicode version of the interface */
320   else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
321   {
322      LPDIRECTPLAYLOBBY2 lpDpL = (LPDIRECTPLAYLOBBY2)(*ppvObj);
323
324      lpDpL = (LPDIRECTPLAYLOBBY2)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
325                                              sizeof( IDirectPlayLobby2 ) );
326
327     if( !lpDpL )
328     {
329       return E_NOINTERFACE;
330     }
331
332     lpDpL->lpVtbl = &directPlayLobby2WVT;
333     lpDpL->ref    = 1;
334
335     return S_OK;
336   }
337
338   /* Unexpected interface request! */ 
339   *ppvObj = NULL;
340   return E_NOINTERFACE; 
341 };
342
343 static HRESULT WINAPI IDirectPlayLobby2W_QueryInterface
344 ( LPDIRECTPLAYLOBBY2 this,
345   REFIID riid,
346   LPVOID* ppvObj )
347 {
348
349   /* Compare riids. We know this object is a direct play lobby 2 object.
350      If we are asking about the same type of interface we're fine.
351    */
352   if( IsEqualGUID( &IID_IUnknown, riid ) ||
353       IsEqualGUID( &IID_IDirectPlayLobby2, riid ) 
354     )
355   {
356     this->lpVtbl->fnAddRef( this );
357     *ppvObj = this;
358     return S_OK;
359   }
360   else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
361   {
362      LPDIRECTPLAYLOBBY2A lpDpL = (LPDIRECTPLAYLOBBY2A)(*ppvObj);
363
364      lpDpL = (LPDIRECTPLAYLOBBY2A)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
365                                              sizeof( IDirectPlayLobby2A ) );
366
367     if( !lpDpL )
368     {
369       return E_NOINTERFACE;
370     }
371
372     lpDpL->lpVtbl = &directPlayLobby2AVT;
373     lpDpL->ref    = 1;
374
375     return S_OK;
376   }
377
378   /* Unexpected interface request! */
379   *ppvObj = NULL;
380   return E_NOINTERFACE;
381
382 };
383
384 /* 
385  * Simple procedure. Just increment the reference count to this
386  * structure and return the new reference count.
387  */
388 static ULONG WINAPI IDirectPlayLobbyA_AddRef
389 ( LPDIRECTPLAYLOBBYA this )
390 {
391   ++(this->ref);
392   TRACE( dplay,"ref count now %lu\n", this->ref );
393   return (this->ref);
394 }
395 static ULONG WINAPI IDirectPlayLobbyW_AddRef
396 ( LPDIRECTPLAYLOBBY this )
397 {
398   return IDirectPlayLobbyA_AddRef( (LPDIRECTPLAYLOBBY) this );
399 }
400
401 static ULONG WINAPI IDirectPlayLobby2A_AddRef
402 ( LPDIRECTPLAYLOBBY2A this )
403 {
404   return IDirectPlayLobbyA_AddRef( (LPDIRECTPLAYLOBBY) this );
405 };
406
407 static ULONG WINAPI IDirectPlayLobby2W_AddRef
408 ( LPDIRECTPLAYLOBBY2 this )
409 {
410   return IDirectPlayLobbyA_AddRef( (LPDIRECTPLAYLOBBY) this );
411 };
412
413
414 /*
415  * Simple COM procedure. Decrease the reference count to this object.
416  * If the object no longer has any reference counts, free up the associated
417  * memory.
418  */
419 static ULONG WINAPI IDirectPlayLobbyA_Release
420 ( LPDIRECTPLAYLOBBYA this )
421 {
422   TRACE( dplay, "ref count decremeneted from %lu\n", this->ref );
423
424   this->ref--;
425
426   /* Deallocate if this is the last reference to the object */
427   if( !(this->ref) )
428   {
429     deleteDPConnection( &(this->lpSession) );
430     HeapFree( GetProcessHeap(), 0, this );
431     return S_OK;
432   }
433
434   return this->ref;
435
436 }
437 static ULONG WINAPI IDirectPlayLobbyW_Release
438 ( LPDIRECTPLAYLOBBY this )
439 {
440   return IDirectPlayLobbyA_Release( (LPDIRECTPLAYLOBBYA) this );
441 }
442 static ULONG WINAPI IDirectPlayLobby2A_Release
443 ( LPDIRECTPLAYLOBBY2A this )
444 {
445   return IDirectPlayLobbyA_Release( (LPDIRECTPLAYLOBBYA) this );
446 };
447
448 static ULONG WINAPI IDirectPlayLobby2W_Release
449 ( LPDIRECTPLAYLOBBY2 this )
450 {
451   return IDirectPlayLobbyA_Release( (LPDIRECTPLAYLOBBYA) this );
452 };
453
454
455 /********************************************************************
456  * 
457  * Connects an application to the session specified by the DPLCONNECTION
458  * structure currently stored with the DirectPlayLobby object.
459  *
460  * Returns a IDirectPlay interface.
461  *
462  */
463 static HRESULT WINAPI IDirectPlayLobbyA_Connect
464 ( LPDIRECTPLAYLOBBYA this,
465   DWORD dwFlags,
466   LPDIRECTPLAY* lplpDP,
467   IUnknown* pUnk)
468 {
469   FIXME( dplay, ": dwFlags=%08lx %p %p stub\n", dwFlags, lplpDP, pUnk );
470   return DPERR_OUTOFMEMORY;
471 };
472
473 static HRESULT WINAPI IDirectPlayLobby2A_Connect
474 ( LPDIRECTPLAYLOBBY2A this,
475   DWORD dwFlags,
476   LPDIRECTPLAY* lplpDP,
477   IUnknown* pUnk)
478 {
479   return IDirectPlayLobbyA_Connect( (LPDIRECTPLAYLOBBYA)this, dwFlags, lplpDP, pUnk );
480 };
481
482 static HRESULT WINAPI IDirectPlayLobbyW_Connect
483 ( LPDIRECTPLAYLOBBY this,
484   DWORD dwFlags,
485   LPDIRECTPLAY* lplpDP,
486   IUnknown* pUnk)
487 {
488   LPDIRECTPLAY2A directPlay2A;
489   LPDIRECTPLAY2  directPlay2W;
490   HRESULT        createRC;
491
492   FIXME( dplay, ": dwFlags=%08lx %p %p stub\n", dwFlags, lplpDP, pUnk );
493
494 #if 0
495
496   /* See dpbuild_4301.txt */
497   /* Create the direct play 2 W interface */
498   if( ( ( createRC = DirectPlayCreate( NULL, &directPlay2A, pUnk ) ) != DP_OK ) ||
499       ( ( createRC = directPlay2A->lpVtbl->fnQueryInterface
500            ( directPlay2A, IID_IDirectPlay2, &directPlay2W ) ) != DP_OK )
501     )
502   {
503      ERR( dplay, "error creating Direct Play 2 (W) interface. Return Code = %d.\n", createRC );
504      return createRC;
505   }
506
507   /* All the stuff below this is WRONG! */
508   if( this->lpSession->dwFlags == DPLCONNECTION_CREATESESSION )
509   {
510     DWORD threadIdSink;
511
512     /* Spawn a thread to deal with all of this and to handle the incomming requests */
513     threadIdSink = CreateThread( NULL, 0, &DPLobby_Spawn_Server,
514                                 (LPVOID)this->lpSession->lpConn->lpSessionDesc, 0, &threadIdSink );  
515
516   }
517   else if ( this->lpSession->dwFlags == DPLCONNECTION_JOINSESSION ) 
518   {
519     /* Let's search for a matching session */
520     FIXME( dplay, "joining session not yet supported.\n");
521     return DPERR_OUTOFMEMORY;
522   }
523   else /* Unknown type of connection request */
524   {
525      ERR( dplay, ": Unknown connection request lpConn->dwFlags=%08lx\n",
526           lpConn->dwFlags ); 
527
528      return DPERR_OUTOFMEMORY;
529   }
530
531   /* This does the work of the following methods...
532      IDirectPlay3::InitializeConnection,
533      IDirectPlay3::EnumSessions,
534      IDirectPlay3::Open
535    */
536   
537
538 #endif
539
540   return DP_OK;
541
542 };
543
544 static HRESULT WINAPI IDirectPlayLobby2W_Connect
545 ( LPDIRECTPLAYLOBBY2 this,
546   DWORD dwFlags,
547   LPDIRECTPLAY* lplpDP,
548   IUnknown* pUnk)
549 {
550   return IDirectPlayLobbyW_Connect( (LPDIRECTPLAYLOBBY)this, dwFlags, lplpDP, pUnk ); 
551 };
552
553 /********************************************************************
554  *
555  * Creates a DirectPlay Address, given a service provider-specific network
556  * address. 
557  * Returns an address contains the globally unique identifier
558  * (GUID) of the service provider and data that the service provider can
559  * interpret as a network address.
560  *
561  */
562 static HRESULT WINAPI IDirectPlayLobbyA_CreateAddress
563 ( LPDIRECTPLAYLOBBY this,
564   REFGUID guidSP,
565   REFGUID guidDataType,
566   LPCVOID lpData,
567   DWORD dwDataSize,
568   LPVOID lpAddress,
569   LPDWORD lpdwAddressSize )
570 {
571   FIXME( dplay, ":stub\n");
572   return DPERR_OUTOFMEMORY;
573 };
574
575 static HRESULT WINAPI IDirectPlayLobby2A_CreateAddress
576 ( LPDIRECTPLAYLOBBY2A this,
577   REFGUID guidSP,
578   REFGUID guidDataType,
579   LPCVOID lpData, 
580   DWORD dwDataSize,
581   LPVOID lpAddress, 
582   LPDWORD lpdwAddressSize )
583 {
584   return IDirectPlayLobbyA_CreateAddress( (LPDIRECTPLAYLOBBY)this, guidSP, guidDataType,
585                                            lpData, dwDataSize, lpAddress, lpdwAddressSize ); 
586 };
587
588 static HRESULT WINAPI IDirectPlayLobbyW_CreateAddress
589 ( LPDIRECTPLAYLOBBY this,
590   REFGUID guidSP,
591   REFGUID guidDataType,
592   LPCVOID lpData,
593   DWORD dwDataSize,
594   LPVOID lpAddress,
595   LPDWORD lpdwAddressSize )
596 {
597   FIXME( dplay, ":stub\n");
598   return DPERR_OUTOFMEMORY;
599 };
600
601
602 static HRESULT WINAPI IDirectPlayLobby2W_CreateAddress
603 ( LPDIRECTPLAYLOBBY2 this,
604   REFGUID guidSP,
605   REFGUID guidDataType,
606   LPCVOID lpData,
607   DWORD dwDataSize,
608   LPVOID lpAddress,
609   LPDWORD lpdwAddressSize )
610 {
611   return IDirectPlayLobbyW_CreateAddress( (LPDIRECTPLAYLOBBY)this, guidSP, guidDataType, 
612                                           lpData, dwDataSize, lpAddress, lpdwAddressSize );
613 };
614
615
616 /********************************************************************
617  *
618  * Parses out chunks from the DirectPlay Address buffer by calling the
619  * given callback function, with lpContext, for each of the chunks.
620  *
621  */
622 static HRESULT WINAPI IDirectPlayLobbyA_EnumAddress
623 ( LPDIRECTPLAYLOBBYA this,
624   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
625   LPCVOID lpAddress,
626   DWORD dwAddressSize,
627   LPVOID lpContext )
628 {
629   FIXME( dplay, ":stub\n");
630   return DPERR_OUTOFMEMORY;
631 };
632
633 static HRESULT WINAPI IDirectPlayLobby2A_EnumAddress
634 ( LPDIRECTPLAYLOBBY2A this,
635   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, 
636   LPCVOID lpAddress,
637   DWORD dwAddressSize, 
638   LPVOID lpContext )
639 {
640   return IDirectPlayLobbyA_EnumAddress( (LPDIRECTPLAYLOBBYA)this, lpEnumAddressCallback,
641                                         lpAddress, dwAddressSize, lpContext );
642 };
643
644 static HRESULT WINAPI IDirectPlayLobbyW_EnumAddress
645 ( LPDIRECTPLAYLOBBY this,
646   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
647   LPCVOID lpAddress,
648   DWORD dwAddressSize,
649   LPVOID lpContext )
650 {
651   FIXME( dplay, ":stub\n");
652   return DPERR_OUTOFMEMORY;
653 };
654
655 static HRESULT WINAPI IDirectPlayLobby2W_EnumAddress
656 ( LPDIRECTPLAYLOBBY2 this,
657   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
658   LPCVOID lpAddress,
659   DWORD dwAddressSize,
660   LPVOID lpContext )
661 {
662   return IDirectPlayLobbyW_EnumAddress( (LPDIRECTPLAYLOBBY)this, lpEnumAddressCallback,
663                                         lpAddress, dwAddressSize, lpContext );
664 };
665
666
667 /********************************************************************
668  *
669  * Enumerates all the address types that a given service provider needs to
670  * build the DirectPlay Address.
671  *
672  */
673 static HRESULT WINAPI IDirectPlayLobbyA_EnumAddressTypes
674 ( LPDIRECTPLAYLOBBYA this,
675   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
676   REFGUID guidSP,
677   LPVOID lpContext,
678   DWORD dwFlags )
679 {
680   FIXME( dplay, ":stub\n");
681   return DPERR_OUTOFMEMORY;
682 };
683
684 static HRESULT WINAPI IDirectPlayLobby2A_EnumAddressTypes
685 ( LPDIRECTPLAYLOBBY2A this,
686   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
687   REFGUID guidSP, 
688   LPVOID lpContext,
689   DWORD dwFlags )
690 {
691   return IDirectPlayLobbyA_EnumAddressTypes( (LPDIRECTPLAYLOBBYA)this, lpEnumAddressTypeCallback,
692                                              guidSP, lpContext, dwFlags );
693 };
694
695 static HRESULT WINAPI IDirectPlayLobbyW_EnumAddressTypes
696 ( LPDIRECTPLAYLOBBY this,
697   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
698   REFGUID guidSP,
699   LPVOID lpContext,
700   DWORD dwFlags )
701 {
702   FIXME( dplay, ":stub\n");
703   return DPERR_OUTOFMEMORY;
704 };
705
706 static HRESULT WINAPI IDirectPlayLobby2W_EnumAddressTypes
707 ( LPDIRECTPLAYLOBBY2 this,
708   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
709   REFGUID guidSP,
710   LPVOID lpContext,
711   DWORD dwFlags )
712 {
713   return IDirectPlayLobbyW_EnumAddressTypes( (LPDIRECTPLAYLOBBY)this, lpEnumAddressTypeCallback,
714                                              guidSP, lpContext, dwFlags );
715 };
716
717
718 /********************************************************************
719  *
720  * Enumerates what applications are registered with DirectPlay by
721  * invoking the callback function with lpContext.
722  *
723  */
724 static HRESULT WINAPI IDirectPlayLobbyW_EnumLocalApplications
725 ( LPDIRECTPLAYLOBBY this,
726   LPDPLENUMLOCALAPPLICATIONSCALLBACK a,
727   LPVOID lpContext,
728   DWORD dwFlags )
729 {
730   FIXME( dplay, ":stub\n");
731   return DPERR_OUTOFMEMORY;
732 };
733
734 static HRESULT WINAPI IDirectPlayLobby2W_EnumLocalApplications
735 ( LPDIRECTPLAYLOBBY2 this,
736   LPDPLENUMLOCALAPPLICATIONSCALLBACK a,
737   LPVOID lpContext,
738   DWORD dwFlags )
739 {
740   return IDirectPlayLobbyW_EnumLocalApplications( (LPDIRECTPLAYLOBBY)this, a,
741                                                   lpContext, dwFlags ); 
742 };
743
744 static HRESULT WINAPI IDirectPlayLobbyA_EnumLocalApplications
745 ( LPDIRECTPLAYLOBBYA this,
746   LPDPLENUMLOCALAPPLICATIONSCALLBACK a,
747   LPVOID lpContext,
748   DWORD dwFlags )
749 {
750   FIXME( dplay, ":stub\n");
751   return DPERR_OUTOFMEMORY;
752 };
753
754 static HRESULT WINAPI IDirectPlayLobby2A_EnumLocalApplications
755 ( LPDIRECTPLAYLOBBY2A this,
756   LPDPLENUMLOCALAPPLICATIONSCALLBACK a,
757   LPVOID lpContext,
758   DWORD dwFlags )
759 {
760   return IDirectPlayLobbyA_EnumLocalApplications( (LPDIRECTPLAYLOBBYA)this, a,
761                                                   lpContext, dwFlags ); 
762 };
763
764
765 /********************************************************************
766  *
767  * Retrieves the DPLCONNECTION structure that contains all the information
768  * needed to start and connect an application. This was generated using
769  * either the RunApplication or SetConnectionSettings methods.
770  *
771  * NOTES: If lpData is NULL then just return lpdwDataSize. This allows
772  *        the data structure to be allocated by our caller which can then
773  *        call this procedure/method again with a valid data pointer.
774  */
775 static HRESULT WINAPI IDirectPlayLobbyA_GetConnectionSettings
776 ( LPDIRECTPLAYLOBBYA this,
777   DWORD dwAppID,
778   LPVOID lpData,
779   LPDWORD lpdwDataSize )
780 {
781   FIXME( dplay, ": semi stub %p %08lx %p %p \n", this, dwAppID, lpData, lpdwDataSize );
782  
783   /* Application is requesting us to give the required size */
784   if ( !lpData )
785   {
786     /* Let's check the size of the buffer that the application has allocated */
787     if( *lpdwDataSize >= sizeof( DPLCONNECTION ) )
788     {
789       return DP_OK;
790     }
791     else
792     {
793       *lpdwDataSize = sizeof( DPLCONNECTION );
794       return DPERR_BUFFERTOOSMALL;
795     }
796   }
797
798   /* Fill in the fields - let them just use the ptrs */
799   if( ((LPDPLCONNECTION)lpData)->lpSessionDesc )
800   {
801     
802   }
803   memcpy( lpData, this->lpSession, sizeof( *(this->lpSession) ) );
804
805   return DP_OK;
806 }
807
808 static HRESULT WINAPI IDirectPlayLobby2A_GetConnectionSettings
809 ( LPDIRECTPLAYLOBBY2A this,
810   DWORD dwAppID,
811   LPVOID lpData,
812   LPDWORD lpdwDataSize )
813 {
814   return IDirectPlayLobbyA_GetConnectionSettings( (LPDIRECTPLAYLOBBYA)this,
815                                                   dwAppID, lpData, lpdwDataSize ); 
816 }
817
818 static HRESULT WINAPI IDirectPlayLobbyW_GetConnectionSettings
819 ( LPDIRECTPLAYLOBBY this,
820   DWORD dwAppID,
821   LPVOID lpData,
822   LPDWORD lpdwDataSize )
823 {
824   FIXME( dplay, ":semi stub %p %08lx %p %p \n", this, dwAppID, lpData, lpdwDataSize );
825
826   /* Application is requesting us to give the required size */ 
827   if ( !lpData )
828   {
829     /* Let's check the size of the buffer that the application has allocated */
830     if( *lpdwDataSize >= sizeof( DPLCONNECTION ) )
831     {
832       return DP_OK;  
833     }
834     else
835     {
836       *lpdwDataSize = sizeof( DPLCONNECTION );
837       return DPERR_BUFFERTOOSMALL;
838     }
839   }
840
841   /* Fill in the fields - let them just use the ptrs */
842   memcpy( lpData, this->lpSession, sizeof( *(this->lpSession) ) );
843
844   return DP_OK;
845 };
846
847 static HRESULT WINAPI IDirectPlayLobby2W_GetConnectionSettings
848 ( LPDIRECTPLAYLOBBY2 this,
849   DWORD dwAppID,
850   LPVOID lpData,
851   LPDWORD lpdwDataSize )
852 {
853   return IDirectPlayLobbyW_GetConnectionSettings( (LPDIRECTPLAYLOBBY)this,
854                                                   dwAppID, lpData, lpdwDataSize );
855 }
856
857 /********************************************************************
858  *
859  * Retrieves the message sent between a lobby client and a DirectPlay 
860  * application. All messages are queued until received.
861  *
862  */
863 static HRESULT WINAPI IDirectPlayLobbyA_ReceiveLobbyMessage
864 ( LPDIRECTPLAYLOBBYA this,
865   DWORD dwFlags,
866   DWORD dwAppID,
867   LPDWORD lpdwMessageFlags,
868   LPVOID lpData,
869   LPDWORD lpdwDataSize )
870 {
871   FIXME( dplay, ":stub %p %08lx %08lx %p %p %p\n", this, dwFlags, dwAppID, lpdwMessageFlags, lpData,
872          lpdwDataSize );
873   return DPERR_OUTOFMEMORY;
874 };
875
876 static HRESULT WINAPI IDirectPlayLobby2A_ReceiveLobbyMessage
877 ( LPDIRECTPLAYLOBBY2A this,
878   DWORD dwFlags,
879   DWORD dwAppID,
880   LPDWORD lpdwMessageFlags,
881   LPVOID lpData,
882   LPDWORD lpdwDataSize )
883 {
884   return IDirectPlayLobbyA_ReceiveLobbyMessage( (LPDIRECTPLAYLOBBYA)this, dwFlags, dwAppID,
885                                                  lpdwMessageFlags, lpData, lpdwDataSize );
886 };
887
888
889 static HRESULT WINAPI IDirectPlayLobbyW_ReceiveLobbyMessage
890 ( LPDIRECTPLAYLOBBY this,
891   DWORD dwFlags,
892   DWORD dwAppID,
893   LPDWORD lpdwMessageFlags,
894   LPVOID lpData,
895   LPDWORD lpdwDataSize )
896 {
897   FIXME( dplay, ":stub %p %08lx %08lx %p %p %p\n", this, dwFlags, dwAppID, lpdwMessageFlags, lpData,
898          lpdwDataSize );
899   return DPERR_OUTOFMEMORY;
900 };
901
902 static HRESULT WINAPI IDirectPlayLobby2W_ReceiveLobbyMessage
903 ( LPDIRECTPLAYLOBBY2 this,
904   DWORD dwFlags,
905   DWORD dwAppID,
906   LPDWORD lpdwMessageFlags,
907   LPVOID lpData,
908   LPDWORD lpdwDataSize )
909 {
910   return IDirectPlayLobbyW_ReceiveLobbyMessage( (LPDIRECTPLAYLOBBY)this, dwFlags, dwAppID,
911                                                  lpdwMessageFlags, lpData, lpdwDataSize );
912 };
913
914 /********************************************************************
915  *
916  * Starts an application and passes to it all the information to
917  * connect to a session.
918  *
919  */
920 static HRESULT WINAPI IDirectPlayLobbyA_RunApplication
921 ( LPDIRECTPLAYLOBBYA this,
922   DWORD dwFlags,
923   LPDWORD lpdwAppID,
924   LPDPLCONNECTION lpConn,
925   HANDLE32 hReceiveEvent )
926 {
927   FIXME( dplay, ":stub\n");
928   return DPERR_OUTOFMEMORY;
929 };
930
931 static HRESULT WINAPI IDirectPlayLobby2A_RunApplication
932 ( LPDIRECTPLAYLOBBY2A this,
933   DWORD dwFlags,
934   LPDWORD lpdwAppID,
935   LPDPLCONNECTION lpConn,
936   HANDLE32 hReceiveEvent )
937 {
938   return IDirectPlayLobbyA_RunApplication( (LPDIRECTPLAYLOBBYA)this, dwFlags,
939                                            lpdwAppID, lpConn, hReceiveEvent );
940 };
941
942 static HRESULT WINAPI IDirectPlayLobbyW_RunApplication
943 ( LPDIRECTPLAYLOBBY this,
944   DWORD dwFlags,
945   LPDWORD lpdwAppID,
946   LPDPLCONNECTION lpConn,
947   HANDLE32 hReceiveEvent )
948 {
949   FIXME( dplay, ":stub\n");
950   return DPERR_OUTOFMEMORY;
951 };
952
953 static HRESULT WINAPI IDirectPlayLobby2W_RunApplication
954 ( LPDIRECTPLAYLOBBY2 this,
955   DWORD dwFlags,
956   LPDWORD lpdwAppID,
957   LPDPLCONNECTION lpConn,
958   HANDLE32 hReceiveEvent )
959 {
960   return IDirectPlayLobbyW_RunApplication( (LPDIRECTPLAYLOBBY)this, dwFlags,
961                                            lpdwAppID, lpConn, hReceiveEvent );
962 };
963
964
965 /********************************************************************
966  *
967  * Sends a message between the application and the lobby client.
968  * All messages are queued until received.
969  *
970  */
971 static HRESULT WINAPI IDirectPlayLobbyA_SendLobbyMessage
972 ( LPDIRECTPLAYLOBBYA this,
973   DWORD dwFlags,
974   DWORD dwAppID,
975   LPVOID lpData,
976   DWORD dwDataSize )
977 {
978   FIXME( dplay, ":stub\n");
979   return DPERR_OUTOFMEMORY;
980 };
981
982 static HRESULT WINAPI IDirectPlayLobby2A_SendLobbyMessage
983 ( LPDIRECTPLAYLOBBY2A this,
984   DWORD dwFlags,
985   DWORD dwAppID,
986   LPVOID lpData,
987   DWORD dwDataSize )
988 {
989   return IDirectPlayLobbyA_SendLobbyMessage( (LPDIRECTPLAYLOBBYA)this, dwFlags, 
990                                              dwAppID, lpData, dwDataSize ); 
991 };
992
993
994 static HRESULT WINAPI IDirectPlayLobbyW_SendLobbyMessage
995 ( LPDIRECTPLAYLOBBY this,
996   DWORD dwFlags,
997   DWORD dwAppID,
998   LPVOID lpData,
999   DWORD dwDataSize )
1000 {
1001   FIXME( dplay, ":stub\n");
1002   return DPERR_OUTOFMEMORY;
1003 };
1004
1005 static HRESULT WINAPI IDirectPlayLobby2W_SendLobbyMessage
1006 ( LPDIRECTPLAYLOBBY2 this,
1007   DWORD dwFlags,
1008   DWORD dwAppID,
1009   LPVOID lpData,
1010   DWORD dwDataSize )
1011 {
1012   return IDirectPlayLobbyW_SendLobbyMessage( (LPDIRECTPLAYLOBBY)this, dwFlags,
1013                                               dwAppID, lpData, dwDataSize );
1014 };
1015
1016 /********************************************************************
1017  *
1018  * Modifies the DPLCONNECTION structure to contain all information
1019  * needed to start and connect an application.
1020  *
1021  */
1022 static HRESULT WINAPI IDirectPlayLobbyW_SetConnectionSettings
1023 ( LPDIRECTPLAYLOBBY this,
1024   DWORD dwFlags,
1025   DWORD dwAppID,
1026   LPDPLCONNECTION lpConn )
1027 {
1028   FIXME( dplay, ": this=%p, dwFlags=%08lx, dwAppId=%08lx, lpConn=%p: semi stub\n",
1029          this, dwFlags, dwAppID, lpConn );
1030
1031   /* Paramater check */
1032   if( dwFlags || !this || !lpConn )
1033   {
1034     ERR( dplay, "invalid parameters.\n");
1035     return DPERR_INVALIDPARAMS;
1036   }
1037
1038   /* See if there is a connection associated with this request.
1039    * dwAppID == 0 indicates that this request isn't associated with a connection.
1040    */
1041   if( dwAppID )
1042   {
1043      FIXME( dplay, ": Connection dwAppID=%08lx given. Not implemented yet.\n",
1044             dwAppID );
1045
1046      /* Need to add a check for this application Id...*/
1047      return DPERR_NOTLOBBIED;
1048   }
1049
1050   if(  lpConn->dwSize != sizeof(DPLCONNECTION) )
1051   {
1052     ERR( dplay, ": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n", 
1053          lpConn->dwSize, sizeof( DPLCONNECTION ) );
1054     return DPERR_INVALIDPARAMS;
1055   }
1056
1057   /* Need to investigate the lpConn->lpSessionDesc to figure out
1058    * what type of session we need to join/create.
1059    */
1060   if(  (!lpConn->lpSessionDesc ) || 
1061        ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
1062     )
1063   {
1064     ERR( dplay, "DPSESSIONDESC passed in? Size=%08lx vs. expected=%ul bytes\n",
1065          lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
1066     return DPERR_INVALIDPARAMS;
1067   }
1068
1069   /* Need to actually store the stuff here */
1070
1071   return DPERR_OUTOFMEMORY;
1072 };
1073
1074 static HRESULT WINAPI IDirectPlayLobby2W_SetConnectionSettings
1075 ( LPDIRECTPLAYLOBBY2 this,
1076   DWORD dwFlags,
1077   DWORD dwAppID,
1078   LPDPLCONNECTION lpConn )
1079 {
1080   return IDirectPlayLobbyW_SetConnectionSettings( (LPDIRECTPLAYLOBBY)this, 
1081                                                   dwFlags, dwAppID, lpConn );
1082 }
1083
1084 static HRESULT WINAPI IDirectPlayLobbyA_SetConnectionSettings
1085 ( LPDIRECTPLAYLOBBYA this,
1086   DWORD dwFlags,
1087   DWORD dwAppID,
1088   LPDPLCONNECTION lpConn )
1089 {
1090   FIXME( dplay, ": this=%p, dwFlags=%08lx, dwAppId=%08lx, lpConn=%p: stub\n",
1091          this, dwFlags, dwAppID, lpConn );
1092   return DPERR_OUTOFMEMORY;
1093 }
1094
1095 static HRESULT WINAPI IDirectPlayLobby2A_SetConnectionSettings
1096 ( LPDIRECTPLAYLOBBY2A this,
1097   DWORD dwFlags,
1098   DWORD dwAppID,
1099   LPDPLCONNECTION lpConn )
1100 {
1101   return IDirectPlayLobbyA_SetConnectionSettings( (LPDIRECTPLAYLOBBYA)this,
1102                                                   dwFlags, dwAppID, lpConn );
1103 };
1104
1105 /********************************************************************
1106  *
1107  * Registers an event that will be set when a lobby message is received.
1108  *
1109  */
1110 static HRESULT WINAPI IDirectPlayLobbyA_SetLobbyMessageEvent
1111 ( LPDIRECTPLAYLOBBYA this,
1112   DWORD dwFlags,
1113   DWORD dwAppID,
1114   HANDLE32 hReceiveEvent )
1115 {
1116   FIXME( dplay, ":stub\n");
1117   return DPERR_OUTOFMEMORY;
1118 };
1119
1120 static HRESULT WINAPI IDirectPlayLobby2A_SetLobbyMessageEvent
1121 ( LPDIRECTPLAYLOBBY2A this,
1122   DWORD dwFlags,
1123   DWORD dwAppID,
1124   HANDLE32 hReceiveEvent )
1125 {
1126   return IDirectPlayLobbyA_SetLobbyMessageEvent( (LPDIRECTPLAYLOBBYA)this, dwFlags,
1127                                                  dwAppID, hReceiveEvent ); 
1128 };
1129
1130 static HRESULT WINAPI IDirectPlayLobbyW_SetLobbyMessageEvent
1131 ( LPDIRECTPLAYLOBBY this,
1132   DWORD dwFlags,
1133   DWORD dwAppID,
1134   HANDLE32 hReceiveEvent )
1135 {
1136   FIXME( dplay, ":stub\n");
1137   return DPERR_OUTOFMEMORY;
1138 };
1139
1140 static HRESULT WINAPI IDirectPlayLobby2W_SetLobbyMessageEvent
1141 ( LPDIRECTPLAYLOBBY2 this,
1142   DWORD dwFlags,
1143   DWORD dwAppID,
1144   HANDLE32 hReceiveEvent )
1145 {
1146   return IDirectPlayLobbyW_SetLobbyMessageEvent( (LPDIRECTPLAYLOBBY)this, dwFlags,
1147                                                  dwAppID, hReceiveEvent ); 
1148 };
1149
1150
1151 /********************************************************************
1152  *
1153  * Registers an event that will be set when a lobby message is received.
1154  *
1155  */
1156 static HRESULT WINAPI IDirectPlayLobby2W_CreateCompoundAddress
1157 ( LPDIRECTPLAYLOBBY2 this,
1158   LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1159   DWORD dwElementCount,
1160   LPVOID lpAddress,
1161   LPDWORD lpdwAddressSize )
1162 {
1163   FIXME( dplay, ":stub\n");
1164   return DPERR_OUTOFMEMORY;
1165 };
1166
1167 static HRESULT WINAPI IDirectPlayLobby2A_CreateCompoundAddress
1168 ( LPDIRECTPLAYLOBBY2A this,
1169   LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1170   DWORD dwElementCount,
1171   LPVOID lpAddress,
1172   LPDWORD lpdwAddressSize )
1173 {
1174   FIXME( dplay, ":stub\n");
1175   return DPERR_OUTOFMEMORY;
1176 };
1177
1178
1179 /* Direct Play Lobby 1 (ascii) Virtual Table for methods */
1180 static struct tagLPDIRECTPLAYLOBBY_VTABLE directPlayLobbyAVT = {
1181   IDirectPlayLobbyA_QueryInterface,
1182   IDirectPlayLobbyA_AddRef,
1183   IDirectPlayLobbyA_Release,
1184   IDirectPlayLobbyA_Connect,
1185   IDirectPlayLobbyA_CreateAddress,
1186   IDirectPlayLobbyA_EnumAddress,
1187   IDirectPlayLobbyA_EnumAddressTypes,
1188   IDirectPlayLobbyA_EnumLocalApplications,
1189   IDirectPlayLobbyA_GetConnectionSettings,
1190   IDirectPlayLobbyA_ReceiveLobbyMessage,
1191   IDirectPlayLobbyA_RunApplication,
1192   IDirectPlayLobbyA_SendLobbyMessage,
1193   IDirectPlayLobbyA_SetConnectionSettings,
1194   IDirectPlayLobbyA_SetLobbyMessageEvent
1195 };
1196
1197 /* Direct Play Lobby 1 (unicode) Virtual Table for methods */
1198 static struct tagLPDIRECTPLAYLOBBY_VTABLE directPlayLobbyWVT = {
1199   IDirectPlayLobbyW_QueryInterface,
1200   IDirectPlayLobbyW_AddRef,
1201   IDirectPlayLobbyW_Release,
1202   IDirectPlayLobbyW_Connect,
1203   IDirectPlayLobbyW_CreateAddress, 
1204   IDirectPlayLobbyW_EnumAddress,
1205   IDirectPlayLobbyW_EnumAddressTypes,
1206   IDirectPlayLobbyW_EnumLocalApplications,
1207   IDirectPlayLobbyW_GetConnectionSettings,
1208   IDirectPlayLobbyW_ReceiveLobbyMessage,
1209   IDirectPlayLobbyW_RunApplication,
1210   IDirectPlayLobbyW_SendLobbyMessage,
1211   IDirectPlayLobbyW_SetConnectionSettings,
1212   IDirectPlayLobbyW_SetLobbyMessageEvent
1213 };
1214
1215
1216 /* Direct Play Lobby 2 (ascii) Virtual Table for methods */
1217 static struct tagLPDIRECTPLAYLOBBY2_VTABLE directPlayLobby2AVT = {
1218   IDirectPlayLobby2A_QueryInterface,
1219   IDirectPlayLobby2A_AddRef,
1220   IDirectPlayLobby2A_Release,
1221   IDirectPlayLobby2A_Connect,
1222   IDirectPlayLobby2A_CreateAddress,
1223   IDirectPlayLobby2A_EnumAddress,
1224   IDirectPlayLobby2A_EnumAddressTypes,
1225   IDirectPlayLobby2A_EnumLocalApplications,
1226   IDirectPlayLobby2A_GetConnectionSettings,
1227   IDirectPlayLobby2A_ReceiveLobbyMessage,
1228   IDirectPlayLobby2A_RunApplication,
1229   IDirectPlayLobby2A_SendLobbyMessage,
1230   IDirectPlayLobby2A_SetConnectionSettings,
1231   IDirectPlayLobby2A_SetLobbyMessageEvent,
1232   IDirectPlayLobby2A_CreateCompoundAddress 
1233 };
1234
1235 /* Direct Play Lobby 2 (unicode) Virtual Table for methods */
1236 static struct tagLPDIRECTPLAYLOBBY2_VTABLE directPlayLobby2WVT = {
1237   IDirectPlayLobby2W_QueryInterface,
1238   IDirectPlayLobby2W_AddRef, 
1239   IDirectPlayLobby2W_Release,
1240   IDirectPlayLobby2W_Connect,
1241   IDirectPlayLobby2W_CreateAddress,
1242   IDirectPlayLobby2W_EnumAddress,
1243   IDirectPlayLobby2W_EnumAddressTypes,
1244   IDirectPlayLobby2W_EnumLocalApplications,
1245   IDirectPlayLobby2W_GetConnectionSettings,
1246   IDirectPlayLobby2W_ReceiveLobbyMessage,
1247   IDirectPlayLobby2W_RunApplication,
1248   IDirectPlayLobby2W_SendLobbyMessage,
1249   IDirectPlayLobby2W_SetConnectionSettings,
1250   IDirectPlayLobby2W_SetLobbyMessageEvent,
1251   IDirectPlayLobby2W_CreateCompoundAddress
1252 };
1253
1254 /***************************************************************************
1255  *  DirectPlayLobbyCreateA   (DPLAYX.4)
1256  *
1257  */
1258 HRESULT WINAPI DirectPlayLobbyCreateA( LPGUID lpGUIDDSP,
1259                                        LPDIRECTPLAYLOBBYA *lplpDPL,
1260                                        IUnknown *lpUnk, 
1261                                        LPVOID lpData,
1262                                        DWORD dwDataSize )
1263 {
1264   TRACE(dplay,"lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\n",
1265         lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
1266
1267   /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
1268    * equal 0. These fields are mostly for future expansion.
1269    */
1270   if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
1271   {
1272      *lplpDPL = NULL;
1273      return DPERR_INVALIDPARAMS;
1274   }
1275
1276   /* Yes...really we should bre returning a lobby 1 object */
1277   *lplpDPL = (LPDIRECTPLAYLOBBYA)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1278                                             sizeof( IDirectPlayLobbyA ) );
1279
1280   if( ! (*lplpDPL) )
1281   {
1282      return DPERR_OUTOFMEMORY;
1283   }
1284
1285   (*lplpDPL)->lpVtbl = &directPlayLobbyAVT;
1286   (*lplpDPL)->ref    = 1;
1287
1288   (*lplpDPL)->lpSession = (LPDPLCONNECTION)HeapAlloc( GetProcessHeap(),
1289                                                       HEAP_ZERO_MEMORY,
1290                                                       sizeof( DPLCONNECTION ) );
1291   (*lplpDPL)->lpSession->dwSize = sizeof( DPLCONNECTION );
1292
1293   (*lplpDPL)->lpSession->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc(
1294           GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( DPSESSIONDESC2 ) );
1295   (*lplpDPL)->lpSession->lpSessionDesc->dwSize = sizeof( DPSESSIONDESC2 ); 
1296
1297   return DP_OK;
1298 }
1299
1300 /***************************************************************************
1301  *  DirectPlayLobbyCreateW   (DPLAYX.5)
1302  *
1303  */
1304 HRESULT WINAPI DirectPlayLobbyCreateW( LPGUID lpGUIDDSP, 
1305                                        LPDIRECTPLAYLOBBY *lplpDPL,
1306                                        IUnknown *lpUnk,
1307                                        LPVOID lpData, 
1308                                        DWORD dwDataSize )
1309 {
1310   TRACE(dplay,"lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\n",
1311         lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
1312
1313   /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must 
1314    * equal 0. These fields are mostly for future expansion.
1315    */
1316   if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
1317   {
1318      *lplpDPL = NULL;
1319      ERR( dplay, "Bad parameters!\n" );
1320      return DPERR_INVALIDPARAMS;
1321   }
1322
1323   /* Yes...really we should bre returning a lobby 1 object */
1324   *lplpDPL = (LPDIRECTPLAYLOBBY)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1325                                            sizeof( IDirectPlayLobby ) );
1326
1327   if( !*lplpDPL)
1328   {
1329      return DPERR_OUTOFMEMORY;
1330   }
1331
1332   (*lplpDPL)->lpVtbl = &directPlayLobbyWVT;
1333   (*lplpDPL)->ref    = 1;
1334
1335
1336   (*lplpDPL)->lpSession = (LPDPLCONNECTION)HeapAlloc( GetProcessHeap(), 
1337                                                       HEAP_ZERO_MEMORY,
1338                                                       sizeof( DPLCONNECTION ) );
1339   (*lplpDPL)->lpSession->dwSize = sizeof( DPLCONNECTION );
1340   (*lplpDPL)->lpSession->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc(
1341           GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( DPSESSIONDESC2 ) );
1342   (*lplpDPL)->lpSession->lpSessionDesc->dwSize = sizeof( DPSESSIONDESC2 ); 
1343
1344   return DP_OK;
1345
1346 }
1347
1348 /***************************************************************************
1349  *  DirectPlayEnumerateA (DPLAYX.2) 
1350  *
1351  *  The pointer to the structure lpContext will be filled with the 
1352  *  appropriate data for each service offered by the OS. These services are
1353  *  not necessarily available on this particular machine but are defined
1354  *  as simple service providers under the "Service Providers" registry key.
1355  *  This structure is then passed to lpEnumCallback for each of the different 
1356  *  services. 
1357  *
1358  *  This API is useful only for applications written using DirectX3 or
1359  *  worse. It is superceeded by IDirectPlay3::EnumConnections which also
1360  *  gives information on the actual connections.
1361  *
1362  * defn of a service provider:
1363  * A dynamic-link library used by DirectPlay to communicate over a network. 
1364  * The service provider contains all the network-specific code required
1365  * to send and receive messages. Online services and network operators can
1366  * supply service providers to use specialized hardware, protocols, communications
1367  * media, and network resources. 
1368  *
1369  * TODO: Allocate string buffer space from the heap (length from reg)
1370  *       Pass real device driver numbers...
1371  *       Get the GUID properly...
1372  */
1373 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
1374                                      LPVOID lpContext )
1375 {
1376
1377   HKEY hkResult; 
1378   LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
1379   LPSTR guidDataSubKey   = "Guid";
1380   LPSTR majVerDataSubKey = "dwReserved1";
1381   DWORD dwIndex, sizeOfSubKeyName=50;
1382   char subKeyName[51]; 
1383
1384   TRACE( dplay, ": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
1385
1386   if( !lpEnumCallback || !*lpEnumCallback )
1387   {
1388      return DPERR_INVALIDPARAMS;
1389   }
1390
1391   /* Need to loop over the service providers in the registry */
1392   if( RegOpenKeyEx32A( HKEY_LOCAL_MACHINE, searchSubKey,
1393                        0, KEY_ENUMERATE_SUB_KEYS, &hkResult ) != ERROR_SUCCESS )
1394   {
1395     /* Hmmm. Does this mean that there are no service providers? */ 
1396     ERR(dplay, ": no service providers?\n");
1397     return DP_OK; 
1398   }
1399
1400   /* Traverse all the service providers we have available */
1401   for( dwIndex=0;
1402        RegEnumKey32A( hkResult, dwIndex, subKeyName, sizeOfSubKeyName ) !=
1403          ERROR_NO_MORE_ITEMS;
1404        ++dwIndex )
1405   {
1406     HKEY     hkServiceProvider;
1407     GUID     serviceProviderGUID;
1408     DWORD    returnTypeGUID, returnTypeReserved1, sizeOfReturnBuffer=50;
1409     char     returnBuffer[51];
1410     DWORD    majVersionNum, minVersionNum;
1411     LPWSTR   lpWGUIDString; 
1412
1413     TRACE( dplay, " this time through: %s\n", subKeyName );
1414
1415     /* Get a handle for this particular service provider */
1416     if( RegOpenKeyEx32A( hkResult, subKeyName, 0, KEY_QUERY_VALUE,
1417                          &hkServiceProvider ) != ERROR_SUCCESS )
1418     {
1419       ERR( dplay, ": what the heck is going on?\n" );
1420       continue;
1421     }
1422
1423     /* Get the GUID, Device major number and device minor number 
1424      * from the registry. 
1425      */
1426     if( RegQueryValueEx32A( hkServiceProvider, guidDataSubKey,
1427                             NULL, &returnTypeGUID, returnBuffer,
1428                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1429     {
1430       ERR( dplay, ": missing GUID registry data members\n" );
1431       continue; 
1432     }
1433
1434     /* FIXME: Check return types to ensure we're interpreting data right */
1435     lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
1436     CLSIDFromString32( (LPCOLESTR32)lpWGUIDString, &serviceProviderGUID ); 
1437     HeapFree( GetProcessHeap(), 0, lpWGUIDString );
1438
1439     sizeOfReturnBuffer = 50;
1440  
1441     if( RegQueryValueEx32A( hkServiceProvider, majVerDataSubKey,
1442                             NULL, &returnTypeReserved1, returnBuffer,
1443                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1444     {
1445       ERR( dplay, ": missing dwReserved1 registry data members\n") ;
1446       continue; 
1447     }
1448     /* FIXME: This couldn't possibly be right...*/
1449     majVersionNum = GET_DWORD( returnBuffer );
1450
1451     /* The enumeration will return FALSE if we are not to continue */
1452     if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
1453                          majVersionNum, (DWORD)0, lpContext ) )
1454     {
1455       WARN( dplay, "lpEnumCallback returning FALSE\n" );
1456       break;
1457     }
1458   }
1459
1460   return DP_OK;
1461
1462 };
1463
1464 /***************************************************************************
1465  *  DirectPlayEnumerateW (DPLAYX.3)
1466  *
1467  */
1468 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
1469 {
1470
1471   FIXME( dplay, ":stub\n");
1472
1473   return DPERR_OUTOFMEMORY; 
1474
1475 };
1476
1477 /***************************************************************************
1478  *  DirectPlayCreate (DPLAYX.1) (DPLAY.1)
1479  *
1480  */
1481 HRESULT WINAPI DirectPlayCreate
1482 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
1483 {
1484
1485   FIXME( dplay, ":stub\n");
1486   return DPERR_OUTOFMEMORY;
1487
1488   TRACE(dplay,"\n" );
1489
1490   if( pUnk != NULL )
1491   {
1492     /* Hmmm...wonder what this means! */
1493     ERR(dplay, "What does a NULL here mean?\n" ); 
1494     return DPERR_OUTOFMEMORY;
1495   }
1496
1497   *lplpDP = (LPDIRECTPLAY)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1498                                      sizeof( **lplpDP ) );
1499
1500   if( !*lplpDP )
1501   {
1502      return DPERR_OUTOFMEMORY;
1503   }
1504
1505   (*lplpDP)->lpVtbl = &directPlay2AVT;
1506   (*lplpDP)->ref    = 1;
1507
1508   return DP_OK;
1509
1510 };
1511