Re-implemented using a real semaphore.
[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@nortelnetworks.com>
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     DWORD                    dwConnFlags;
27     DPSESSIONDESC2           sessionDesc;
28     DPNAME                   playerName;
29     GUID                     guidSP;
30     LPVOID                   lpAddress;
31     DWORD                    dwAddressSize;
32 };
33
34 struct IDirectPlayLobby2 {
35     LPDIRECTPLAYLOBBY2_VTABLE lpVtbl;
36     ULONG                     ref;
37     DWORD                     dwConnFlags;
38     DPSESSIONDESC2            lpSessionDesc;
39     DPNAME                    lpPlayerName;
40     GUID                      guidSP;
41     LPVOID                    lpAddress;
42     DWORD                     dwAddressSize;
43 };
44
45
46 /* Forward declarations of virtual tables */
47 static DIRECTPLAYLOBBY_VTABLE  directPlayLobbyAVT;
48 static DIRECTPLAYLOBBY_VTABLE  directPlayLobbyWVT;
49 static DIRECTPLAYLOBBY2_VTABLE directPlayLobby2AVT;
50 static DIRECTPLAYLOBBY2_VTABLE directPlayLobby2WVT;
51
52
53 static DIRECTPLAY2_VTABLE directPlay2AVT;
54 static DIRECTPLAY3_VTABLE directPlay3VT;
55
56
57
58
59 struct IDirectPlay2 {
60   LPDIRECTPLAY2_VTABLE lpVtbl;
61   ULONG                ref;
62 };
63
64 struct IDirectPlay3 {
65   LPDIRECTPLAY3_VTABLE lpVtbl;
66   ULONG                ref;
67 };
68
69 /* Routine called when starting up the server thread */
70 DWORD DPLobby_Spawn_Server( LPVOID startData )
71 {
72   DPSESSIONDESC2* lpSession = (DPSESSIONDESC2*) startData;
73   DWORD sessionDwFlags = lpSession->dwFlags;
74  
75   TRACE( dplay, "spawing thread for lpConn=%p dwFlags=%08lx\n", lpSession, sessionDwFlags );
76   FIXME( dplay, "thread needs something to do\n" ); 
77
78 /*for(;;)*/
79   {
80      
81     /* Check out the connection flags to determine what to do. Ensure we have 
82        no leftover bits in this structure */
83     if( sessionDwFlags & DPSESSION_CLIENTSERVER )
84     {
85        /* This indicates that the application which is requesting the creation
86         * of this session is going to be the server (application/player)
87         */ 
88        if( sessionDwFlags & DPSESSION_SECURESERVER )
89        {
90          sessionDwFlags &= ~DPSESSION_SECURESERVER; 
91        }
92        sessionDwFlags &= ~DPSESSION_CLIENTSERVER;  
93     }
94
95     if( sessionDwFlags & DPSESSION_JOINDISABLED )
96     {
97        sessionDwFlags &= ~DPSESSION_JOINDISABLED; 
98     } 
99
100     if( sessionDwFlags & DPSESSION_KEEPALIVE )
101     {
102        sessionDwFlags &= ~DPSESSION_KEEPALIVE;
103     }
104
105     if( sessionDwFlags & DPSESSION_MIGRATEHOST )
106     {
107        sessionDwFlags &= ~DPSESSION_MIGRATEHOST;
108     }
109
110     if( sessionDwFlags & DPSESSION_MULTICASTSERVER )
111     {
112        sessionDwFlags &= ~DPSESSION_MULTICASTSERVER;
113     }
114
115     if( sessionDwFlags & DPSESSION_NEWPLAYERSDISABLED )
116     {
117        sessionDwFlags &= ~DPSESSION_NEWPLAYERSDISABLED; 
118     }
119
120     if( sessionDwFlags & DPSESSION_NODATAMESSAGES )
121     {
122        sessionDwFlags &= ~DPSESSION_NODATAMESSAGES; 
123     } 
124
125     if( sessionDwFlags & DPSESSION_NOMESSAGEID )
126     {
127        sessionDwFlags &= ~DPSESSION_NOMESSAGEID;
128     }
129
130     if( sessionDwFlags & DPSESSION_PASSWORDREQUIRED )
131     {
132        sessionDwFlags &= ~DPSESSION_PASSWORDREQUIRED;
133     }
134
135   }
136
137   ExitThread(0);
138   return 0; 
139 }
140
141
142 /*********************************************************
143  *
144  * Direct Play and Direct Play Lobby Interface Implementation 
145  * 
146  *********************************************************/ 
147
148 /* The COM interface for upversioning an interface
149  * We've been given a GUID (riid) and we need to replace the present
150  * interface with that of the requested interface.
151  *
152  * Snip from some Microsoft document:
153  * There are four requirements for implementations of QueryInterface (In these
154  * cases, "must succeed" means "must succeed barring catastrophic failure."):
155  *
156  *  * The set of interfaces accessible on an object through
157  *    IUnknown::QueryInterface must be static, not dynamic. This means that
158  *    if a call to QueryInterface for a pointer to a specified interface
159  *    succeeds the first time, it must succeed again, and if it fails the
160  *    first time, it must fail on all subsequent queries.
161  *  * It must be symmetric ~W if a client holds a pointer to an interface on
162  *    an object, and queries for that interface, the call must succeed.
163  *  * It must be reflexive ~W if a client holding a pointer to one interface
164  *    queries successfully for another, a query through the obtained pointer
165  *    for the first interface must succeed.
166  *  * It must be transitive ~W if a client holding a pointer to one interface
167  *    queries successfully for a second, and through that pointer queries
168  *    successfully for a third interface, a query for the first interface
169  *    through the pointer for the third interface must succeed.
170  *
171  *  As you can see, this interface doesn't qualify but will most likely
172  *  be good enough for the time being.
173  */
174 static HRESULT WINAPI IDirectPlayLobbyA_QueryInterface
175 ( LPDIRECTPLAYLOBBYA this,
176   REFIID riid,
177   LPVOID* ppvObj )
178 {
179   FIXME( dplay, "(%p)->(%p,%p): stub\n", this, riid, ppvObj );
180   return E_NOINTERFACE;
181 }
182
183 static HRESULT WINAPI IDirectPlayLobbyW_QueryInterface
184 ( LPDIRECTPLAYLOBBY this,
185   REFIID riid,
186   LPVOID* ppvObj )
187 {
188   FIXME( dplay, "(%p)->(%p,%p): stub\n", this, riid, ppvObj );
189   return E_NOINTERFACE;
190 }
191
192
193 static HRESULT WINAPI IDirectPlayLobby2A_QueryInterface
194 ( LPDIRECTPLAYLOBBY2A this,
195   REFIID riid,
196   LPVOID* ppvObj )
197 {
198   TRACE( dplay, "(%p)->(%p,%p)\n", this, riid, ppvObj );
199
200   /* Compare riids. We know this object is a direct play lobby 2A object.
201      If we are asking about the same type of interface we're fine.
202    */
203   if( IsEqualGUID( &IID_IUnknown, riid )  ||
204       IsEqualGUID( &IID_IDirectPlayLobby2A, riid )
205     )
206   {
207     this->lpVtbl->fnAddRef( this );
208     *ppvObj = this;
209     return S_OK;
210   }
211   /* They're requesting a unicode version of the interface */
212   else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
213   {
214      LPDIRECTPLAYLOBBY2 lpDpL = (LPDIRECTPLAYLOBBY2)(*ppvObj);
215
216      lpDpL = (LPDIRECTPLAYLOBBY2)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
217                                              sizeof( IDirectPlayLobby2 ) );
218
219     if( !lpDpL )
220     {
221       return E_NOINTERFACE;
222     }
223
224     lpDpL->lpVtbl = &directPlayLobby2WVT;
225     lpDpL->ref    = 1;
226
227     return S_OK;
228   }
229
230   /* Unexpected interface request! */ 
231   *ppvObj = NULL;
232   return E_NOINTERFACE; 
233 };
234
235 static HRESULT WINAPI IDirectPlayLobby2W_QueryInterface
236 ( LPDIRECTPLAYLOBBY2 this,
237   REFIID riid,
238   LPVOID* ppvObj )
239 {
240
241   /* Compare riids. We know this object is a direct play lobby 2 object.
242      If we are asking about the same type of interface we're fine.
243    */
244   if( IsEqualGUID( &IID_IUnknown, riid ) ||
245       IsEqualGUID( &IID_IDirectPlayLobby2, riid ) 
246     )
247   {
248     this->lpVtbl->fnAddRef( this );
249     *ppvObj = this;
250     return S_OK;
251   }
252   else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
253   {
254      LPDIRECTPLAYLOBBY2A lpDpL = (LPDIRECTPLAYLOBBY2A)(*ppvObj);
255
256      lpDpL = (LPDIRECTPLAYLOBBY2A)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
257                                              sizeof( IDirectPlayLobby2A ) );
258
259     if( !lpDpL )
260     {
261       return E_NOINTERFACE;
262     }
263
264     lpDpL->lpVtbl = &directPlayLobby2AVT;
265     lpDpL->ref    = 1;
266
267     return S_OK;
268   }
269
270   /* Unexpected interface request! */
271   *ppvObj = NULL;
272   return E_NOINTERFACE;
273
274 };
275
276 /* 
277  * Simple procedure. Just increment the reference count to this
278  * structure and return the new reference count.
279  */
280 static ULONG WINAPI IDirectPlayLobby2A_AddRef
281 ( LPDIRECTPLAYLOBBY2A this )
282 {
283   ++(this->ref);
284   TRACE( dplay,"ref count now %lu\n", this->ref );
285   return (this->ref);
286 };
287
288 static ULONG WINAPI IDirectPlayLobby2W_AddRef
289 ( LPDIRECTPLAYLOBBY2 this )
290 {
291   return IDirectPlayLobby2A_AddRef( (LPDIRECTPLAYLOBBY2) this );
292 };
293
294
295 /*
296  * Simple COM procedure. Decrease the reference count to this object.
297  * If the object no longer has any reference counts, free up the associated
298  * memory.
299  */
300 static ULONG WINAPI IDirectPlayLobby2A_Release
301 ( LPDIRECTPLAYLOBBY2A this )
302 {
303   TRACE( dplay, "ref count decremeneted from %lu\n", this->ref );
304
305   this->ref--;
306
307   /* Deallocate if this is the last reference to the object */
308   if( !(this->ref) )
309   {
310     FIXME( dplay, "memory leak\n" );
311     /* Implement memory deallocation */
312
313     HeapFree( GetProcessHeap(), 0, this );
314
315     return 0;
316   }
317
318   return this->ref;
319 };
320
321 static ULONG WINAPI IDirectPlayLobby2W_Release
322 ( LPDIRECTPLAYLOBBY2 this )
323 {
324   return IDirectPlayLobby2A_Release( (LPDIRECTPLAYLOBBY2A) this );
325 };
326
327
328 /********************************************************************
329  * 
330  * Connects an application to the session specified by the DPLCONNECTION
331  * structure currently stored with the DirectPlayLobby object.
332  *
333  * Returns a IDirectPlay interface.
334  *
335  */
336 static HRESULT WINAPI IDirectPlayLobby2A_Connect
337 ( LPDIRECTPLAYLOBBY2A this,
338   DWORD dwFlags,
339   LPDIRECTPLAY2* lplpDP,
340   IUnknown* pUnk)
341 {
342   FIXME( dplay, ": dwFlags=%08lx %p %p stub\n", dwFlags, lplpDP, pUnk );
343   return DPERR_OUTOFMEMORY;
344 };
345
346 static HRESULT WINAPI IDirectPlayLobby2W_Connect
347 ( LPDIRECTPLAYLOBBY2 this,
348   DWORD dwFlags,
349   LPDIRECTPLAY2* lplpDP,
350   IUnknown* pUnk)
351 {
352   LPDIRECTPLAY2* directPlay2W;
353   HRESULT        createRC;
354
355   FIXME( dplay, ": dwFlags=%08lx %p %p stub\n", dwFlags, lplpDP, pUnk );
356
357   if( dwFlags )
358   {
359      return DPERR_INVALIDPARAMS;
360   }
361
362   if( ( createRC = DirectPlayCreate( &IID_IDirectPlayLobby2, lplpDP, pUnk ) ) != DP_OK )
363   {
364      ERR( dplay, "error creating Direct Play 2 (W) interface. Return Code = %ld.\n", createRC );
365      return createRC;
366   } 
367
368   /* This should invoke IDirectPlay3::InitializeConnection IDirectPlay3::Open */  
369   directPlay2W = lplpDP; 
370   
371
372
373 #if 0
374   /* All the stuff below this is WRONG! */
375   if( this->lpSession->dwFlags == DPLCONNECTION_CREATESESSION )
376   {
377     DWORD threadIdSink;
378
379     /* Spawn a thread to deal with all of this and to handle the incomming requests */
380     threadIdSink = CreateThread( NULL, 0, &DPLobby_Spawn_Server,
381                                 (LPVOID)this->lpSession->lpConn->lpSessionDesc, 0, &threadIdSink );  
382
383   }
384   else if ( this->lpSession->dwFlags == DPLCONNECTION_JOINSESSION ) 
385   {
386     /* Let's search for a matching session */
387     FIXME( dplay, "joining session not yet supported.\n");
388     return DPERR_OUTOFMEMORY;
389   }
390   else /* Unknown type of connection request */
391   {
392      ERR( dplay, ": Unknown connection request lpConn->dwFlags=%08lx\n",
393           lpConn->dwFlags ); 
394
395      return DPERR_OUTOFMEMORY;
396   }
397
398   /* This does the work of the following methods...
399      IDirectPlay3::InitializeConnection,
400      IDirectPlay3::EnumSessions,
401      IDirectPlay3::Open
402    */
403   
404
405 #endif
406
407   return DP_OK;
408
409 };
410
411 /********************************************************************
412  *
413  * Creates a DirectPlay Address, given a service provider-specific network
414  * address. 
415  * Returns an address contains the globally unique identifier
416  * (GUID) of the service provider and data that the service provider can
417  * interpret as a network address.
418  *
419  */
420 static HRESULT WINAPI IDirectPlayLobby2A_CreateAddress
421 ( LPDIRECTPLAYLOBBY2A this,
422   REFGUID guidSP,
423   REFGUID guidDataType,
424   LPCVOID lpData, 
425   DWORD dwDataSize,
426   LPVOID lpAddress, 
427   LPDWORD lpdwAddressSize )
428 {
429   FIXME( dplay, ":stub\n");
430   return DPERR_OUTOFMEMORY;
431 };
432
433 static HRESULT WINAPI IDirectPlayLobby2W_CreateAddress
434 ( LPDIRECTPLAYLOBBY2 this,
435   REFGUID guidSP,
436   REFGUID guidDataType,
437   LPCVOID lpData,
438   DWORD dwDataSize,
439   LPVOID lpAddress,
440   LPDWORD lpdwAddressSize )
441 {
442   FIXME( dplay, ":stub\n");
443   return DPERR_OUTOFMEMORY;
444 };
445
446
447 /********************************************************************
448  *
449  * Parses out chunks from the DirectPlay Address buffer by calling the
450  * given callback function, with lpContext, for each of the chunks.
451  *
452  */
453 static HRESULT WINAPI IDirectPlayLobby2A_EnumAddress
454 ( LPDIRECTPLAYLOBBY2A this,
455   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
456   LPCVOID lpAddress,
457   DWORD dwAddressSize,
458   LPVOID lpContext )
459 {
460   FIXME( dplay, ":stub\n");
461   return DPERR_OUTOFMEMORY;
462 };
463
464 static HRESULT WINAPI IDirectPlayLobby2W_EnumAddress
465 ( LPDIRECTPLAYLOBBY2 this,
466   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
467   LPCVOID lpAddress,
468   DWORD dwAddressSize,
469   LPVOID lpContext )
470 {
471   FIXME( dplay, ":stub\n");
472   return DPERR_OUTOFMEMORY;
473 };
474
475 /********************************************************************
476  *
477  * Enumerates all the address types that a given service provider needs to
478  * build the DirectPlay Address.
479  *
480  */
481 static HRESULT WINAPI IDirectPlayLobbyA_EnumAddressTypes
482 ( LPDIRECTPLAYLOBBYA this,
483   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
484   REFGUID guidSP,
485   LPVOID lpContext,
486   DWORD dwFlags )
487 {
488   FIXME( dplay, ":stub\n");
489   return DPERR_OUTOFMEMORY;
490 };
491
492 static HRESULT WINAPI IDirectPlayLobby2A_EnumAddressTypes
493 ( LPDIRECTPLAYLOBBY2A this,
494   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
495   REFGUID guidSP, 
496   LPVOID lpContext,
497   DWORD dwFlags )
498 {
499   return IDirectPlayLobbyA_EnumAddressTypes( (LPDIRECTPLAYLOBBYA)this, lpEnumAddressTypeCallback,
500                                              guidSP, lpContext, dwFlags );
501 };
502
503 static HRESULT WINAPI IDirectPlayLobby2W_EnumAddressTypes
504 ( LPDIRECTPLAYLOBBY2 this,
505   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
506   REFGUID guidSP,
507   LPVOID lpContext,
508   DWORD dwFlags )
509 {
510   FIXME( dplay, ":stub\n");
511   return DPERR_OUTOFMEMORY;
512 };
513
514 /********************************************************************
515  *
516  * Enumerates what applications are registered with DirectPlay by
517  * invoking the callback function with lpContext.
518  *
519  */
520 static HRESULT WINAPI IDirectPlayLobbyW_EnumLocalApplications
521 ( LPDIRECTPLAYLOBBY this,
522   LPDPLENUMLOCALAPPLICATIONSCALLBACK a,
523   LPVOID lpContext,
524   DWORD dwFlags )
525 {
526   FIXME( dplay, ":stub\n");
527   return DPERR_OUTOFMEMORY;
528 };
529
530 static HRESULT WINAPI IDirectPlayLobby2W_EnumLocalApplications
531 ( LPDIRECTPLAYLOBBY2 this,
532   LPDPLENUMLOCALAPPLICATIONSCALLBACK a,
533   LPVOID lpContext,
534   DWORD dwFlags )
535 {
536   return IDirectPlayLobbyW_EnumLocalApplications( (LPDIRECTPLAYLOBBY)this, a,
537                                                   lpContext, dwFlags ); 
538 };
539
540 static HRESULT WINAPI IDirectPlayLobbyA_EnumLocalApplications
541 ( LPDIRECTPLAYLOBBYA this,
542   LPDPLENUMLOCALAPPLICATIONSCALLBACK a,
543   LPVOID lpContext,
544   DWORD dwFlags )
545 {
546   FIXME( dplay, ":stub\n");
547   return DPERR_OUTOFMEMORY;
548 };
549
550 static HRESULT WINAPI IDirectPlayLobby2A_EnumLocalApplications
551 ( LPDIRECTPLAYLOBBY2A this,
552   LPDPLENUMLOCALAPPLICATIONSCALLBACK a,
553   LPVOID lpContext,
554   DWORD dwFlags )
555 {
556   return IDirectPlayLobbyA_EnumLocalApplications( (LPDIRECTPLAYLOBBYA)this, a,
557                                                   lpContext, dwFlags ); 
558 };
559
560
561 /********************************************************************
562  *
563  * Retrieves the DPLCONNECTION structure that contains all the information
564  * needed to start and connect an application. This was generated using
565  * either the RunApplication or SetConnectionSettings methods.
566  *
567  * NOTES: If lpData is NULL then just return lpdwDataSize. This allows
568  *        the data structure to be allocated by our caller which can then
569  *        call this procedure/method again with a valid data pointer.
570  */
571 static HRESULT WINAPI IDirectPlayLobbyA_GetConnectionSettings
572 ( LPDIRECTPLAYLOBBYA this,
573   DWORD dwAppID,
574   LPVOID lpData,
575   LPDWORD lpdwDataSize )
576 {
577   LPDPLCONNECTION lpDplConnection;
578
579   FIXME( dplay, ": semi stub (%p)->(0x%08lx,%p,%p)\n", this, dwAppID, lpData, lpdwDataSize );
580  
581   /* Application is requesting us to give the required size */
582   if ( !lpData )
583   {
584     /* Let's check the size of the buffer that the application has allocated */
585     if( *lpdwDataSize >= sizeof( DPLCONNECTION ) )
586     {
587       return DP_OK;
588     }
589     else
590     {
591       *lpdwDataSize = sizeof( DPLCONNECTION );
592       return DPERR_BUFFERTOOSMALL;
593     }
594   }
595
596   /* Fill in the fields - let them just use the ptrs */
597   lpDplConnection = (LPDPLCONNECTION)lpData;
598
599   /* Make sure we were given the right size */
600   if( lpDplConnection->dwSize < sizeof( DPLCONNECTION ) )
601   {
602      ERR( dplay, "bad passed size 0x%08lx.\n", lpDplConnection->dwSize );
603      return DPERR_INVALIDPARAMS;
604   }
605
606   /* Copy everything we've got into here */
607   /* Need to actually store the stuff here. Check if we've already allocated each field first. */
608   lpDplConnection->dwFlags = this->dwConnFlags;
609
610   /* Copy LPDPSESSIONDESC2 struct */
611   lpDplConnection->lpSessionDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( this->sessionDesc ) );
612   memcpy( lpDplConnection, &(this->sessionDesc), sizeof( this->sessionDesc ) );
613
614   if( this->sessionDesc.sess.lpszSessionName )
615   {
616     lpDplConnection->lpSessionDesc->sess.lpszSessionName = 
617       HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, this->sessionDesc.sess.lpszSessionName );
618   }
619
620   if( this->sessionDesc.pass.lpszPassword )
621   {
622     lpDplConnection->lpSessionDesc->pass.lpszPassword = 
623       HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, this->sessionDesc.pass.lpszPassword );
624   }
625      
626   /* I don't know what to use the reserved for. We'll set it to 0 just for fun */
627   this->sessionDesc.dwReserved1 = this->sessionDesc.dwReserved2 = 0;
628
629   /* Copy DPNAME struct - seems to be optional - check for existance first */
630   lpDplConnection->lpPlayerName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( this->playerName ) );
631   memcpy( lpDplConnection->lpPlayerName, &(this->playerName), sizeof( this->playerName ) );
632
633   if( this->playerName.psn.lpszShortName )
634   {
635     lpDplConnection->lpPlayerName->psn.lpszShortName =
636       HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, this->playerName.psn.lpszShortName );  
637   }
638
639   if( this->playerName.pln.lpszLongName )
640   {
641     lpDplConnection->lpPlayerName->pln.lpszLongName =
642       HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, this->playerName.pln.lpszLongName );
643   }
644
645
646
647   memcpy( &(lpDplConnection->guidSP), &(this->guidSP), sizeof( this->guidSP ) );
648
649   lpDplConnection->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, this->dwAddressSize );
650   memcpy( lpDplConnection->lpAddress, this->lpAddress, this->dwAddressSize );
651
652   lpDplConnection->dwAddressSize = this->dwAddressSize;
653
654   return DP_OK;
655 }
656
657 static HRESULT WINAPI IDirectPlayLobby2A_GetConnectionSettings
658 ( LPDIRECTPLAYLOBBY2A this,
659   DWORD dwAppID,
660   LPVOID lpData,
661   LPDWORD lpdwDataSize )
662 {
663   return IDirectPlayLobbyA_GetConnectionSettings( (LPDIRECTPLAYLOBBYA)this,
664                                                   dwAppID, lpData, lpdwDataSize ); 
665 }
666
667 static HRESULT WINAPI IDirectPlayLobbyW_GetConnectionSettings
668 ( LPDIRECTPLAYLOBBY this,
669   DWORD dwAppID,
670   LPVOID lpData,
671   LPDWORD lpdwDataSize )
672 {
673   FIXME( dplay, ":semi stub %p %08lx %p %p \n", this, dwAppID, lpData, lpdwDataSize );
674
675   /* Application is requesting us to give the required size */ 
676   if ( !lpData )
677   {
678     /* Let's check the size of the buffer that the application has allocated */
679     if( *lpdwDataSize >= sizeof( DPLCONNECTION ) )
680     {
681       return DP_OK;  
682     }
683     else
684     {
685       *lpdwDataSize = sizeof( DPLCONNECTION );
686       return DPERR_BUFFERTOOSMALL;
687     }
688   }
689
690   /* Fill in the fields - let them just use the ptrs */
691   FIXME( dplay, "stub\n" );
692
693   return DP_OK;
694 };
695
696 static HRESULT WINAPI IDirectPlayLobby2W_GetConnectionSettings
697 ( LPDIRECTPLAYLOBBY2 this,
698   DWORD dwAppID,
699   LPVOID lpData,
700   LPDWORD lpdwDataSize )
701 {
702   return IDirectPlayLobbyW_GetConnectionSettings( (LPDIRECTPLAYLOBBY)this,
703                                                   dwAppID, lpData, lpdwDataSize );
704 }
705
706 /********************************************************************
707  *
708  * Retrieves the message sent between a lobby client and a DirectPlay 
709  * application. All messages are queued until received.
710  *
711  */
712 static HRESULT WINAPI IDirectPlayLobbyA_ReceiveLobbyMessage
713 ( LPDIRECTPLAYLOBBYA this,
714   DWORD dwFlags,
715   DWORD dwAppID,
716   LPDWORD lpdwMessageFlags,
717   LPVOID lpData,
718   LPDWORD lpdwDataSize )
719 {
720   FIXME( dplay, ":stub %p %08lx %08lx %p %p %p\n", this, dwFlags, dwAppID, lpdwMessageFlags, lpData,
721          lpdwDataSize );
722   return DPERR_OUTOFMEMORY;
723 };
724
725 static HRESULT WINAPI IDirectPlayLobby2A_ReceiveLobbyMessage
726 ( LPDIRECTPLAYLOBBY2A this,
727   DWORD dwFlags,
728   DWORD dwAppID,
729   LPDWORD lpdwMessageFlags,
730   LPVOID lpData,
731   LPDWORD lpdwDataSize )
732 {
733   return IDirectPlayLobbyA_ReceiveLobbyMessage( (LPDIRECTPLAYLOBBYA)this, dwFlags, dwAppID,
734                                                  lpdwMessageFlags, lpData, lpdwDataSize );
735 };
736
737
738 static HRESULT WINAPI IDirectPlayLobbyW_ReceiveLobbyMessage
739 ( LPDIRECTPLAYLOBBY this,
740   DWORD dwFlags,
741   DWORD dwAppID,
742   LPDWORD lpdwMessageFlags,
743   LPVOID lpData,
744   LPDWORD lpdwDataSize )
745 {
746   FIXME( dplay, ":stub %p %08lx %08lx %p %p %p\n", this, dwFlags, dwAppID, lpdwMessageFlags, lpData,
747          lpdwDataSize );
748   return DPERR_OUTOFMEMORY;
749 };
750
751 static HRESULT WINAPI IDirectPlayLobby2W_ReceiveLobbyMessage
752 ( LPDIRECTPLAYLOBBY2 this,
753   DWORD dwFlags,
754   DWORD dwAppID,
755   LPDWORD lpdwMessageFlags,
756   LPVOID lpData,
757   LPDWORD lpdwDataSize )
758 {
759   return IDirectPlayLobbyW_ReceiveLobbyMessage( (LPDIRECTPLAYLOBBY)this, dwFlags, dwAppID,
760                                                  lpdwMessageFlags, lpData, lpdwDataSize );
761 };
762
763 /********************************************************************
764  *
765  * Starts an application and passes to it all the information to
766  * connect to a session.
767  *
768  */
769 static HRESULT WINAPI IDirectPlayLobbyA_RunApplication
770 ( LPDIRECTPLAYLOBBYA this,
771   DWORD dwFlags,
772   LPDWORD lpdwAppID,
773   LPDPLCONNECTION lpConn,
774   HANDLE32 hReceiveEvent )
775 {
776   FIXME( dplay, ":stub\n");
777   return DPERR_OUTOFMEMORY;
778 };
779
780 static HRESULT WINAPI IDirectPlayLobby2A_RunApplication
781 ( LPDIRECTPLAYLOBBY2A this,
782   DWORD dwFlags,
783   LPDWORD lpdwAppID,
784   LPDPLCONNECTION lpConn,
785   HANDLE32 hReceiveEvent )
786 {
787   return IDirectPlayLobbyA_RunApplication( (LPDIRECTPLAYLOBBYA)this, dwFlags,
788                                            lpdwAppID, lpConn, hReceiveEvent );
789 };
790
791 static HRESULT WINAPI IDirectPlayLobbyW_RunApplication
792 ( LPDIRECTPLAYLOBBY this,
793   DWORD dwFlags,
794   LPDWORD lpdwAppID,
795   LPDPLCONNECTION lpConn,
796   HANDLE32 hReceiveEvent )
797 {
798   FIXME( dplay, ":stub\n");
799   return DPERR_OUTOFMEMORY;
800 };
801
802 static HRESULT WINAPI IDirectPlayLobby2W_RunApplication
803 ( LPDIRECTPLAYLOBBY2 this,
804   DWORD dwFlags,
805   LPDWORD lpdwAppID,
806   LPDPLCONNECTION lpConn,
807   HANDLE32 hReceiveEvent )
808 {
809   return IDirectPlayLobbyW_RunApplication( (LPDIRECTPLAYLOBBY)this, dwFlags,
810                                            lpdwAppID, lpConn, hReceiveEvent );
811 };
812
813
814 /********************************************************************
815  *
816  * Sends a message between the application and the lobby client.
817  * All messages are queued until received.
818  *
819  */
820 static HRESULT WINAPI IDirectPlayLobbyA_SendLobbyMessage
821 ( LPDIRECTPLAYLOBBYA this,
822   DWORD dwFlags,
823   DWORD dwAppID,
824   LPVOID lpData,
825   DWORD dwDataSize )
826 {
827   FIXME( dplay, ":stub\n");
828   return DPERR_OUTOFMEMORY;
829 };
830
831 static HRESULT WINAPI IDirectPlayLobby2A_SendLobbyMessage
832 ( LPDIRECTPLAYLOBBY2A this,
833   DWORD dwFlags,
834   DWORD dwAppID,
835   LPVOID lpData,
836   DWORD dwDataSize )
837 {
838   return IDirectPlayLobbyA_SendLobbyMessage( (LPDIRECTPLAYLOBBYA)this, dwFlags, 
839                                              dwAppID, lpData, dwDataSize ); 
840 };
841
842
843 static HRESULT WINAPI IDirectPlayLobbyW_SendLobbyMessage
844 ( LPDIRECTPLAYLOBBY this,
845   DWORD dwFlags,
846   DWORD dwAppID,
847   LPVOID lpData,
848   DWORD dwDataSize )
849 {
850   FIXME( dplay, ":stub\n");
851   return DPERR_OUTOFMEMORY;
852 };
853
854 static HRESULT WINAPI IDirectPlayLobby2W_SendLobbyMessage
855 ( LPDIRECTPLAYLOBBY2 this,
856   DWORD dwFlags,
857   DWORD dwAppID,
858   LPVOID lpData,
859   DWORD dwDataSize )
860 {
861   return IDirectPlayLobbyW_SendLobbyMessage( (LPDIRECTPLAYLOBBY)this, dwFlags,
862                                               dwAppID, lpData, dwDataSize );
863 };
864
865 /********************************************************************
866  *
867  * Modifies the DPLCONNECTION structure to contain all information
868  * needed to start and connect an application.
869  *
870  */
871 static HRESULT WINAPI IDirectPlayLobbyW_SetConnectionSettings
872 ( LPDIRECTPLAYLOBBY this,
873   DWORD dwFlags,
874   DWORD dwAppID,
875   LPDPLCONNECTION lpConn )
876 {
877   TRACE( dplay, ": this=%p, dwFlags=%08lx, dwAppId=%08lx, lpConn=%p\n",
878          this, dwFlags, dwAppID, lpConn );
879
880   /* Paramater check */
881   if( dwFlags || !this || !lpConn )
882   {
883     ERR( dplay, "invalid parameters.\n");
884     return DPERR_INVALIDPARAMS;
885   }
886
887   /* See if there is a connection associated with this request.
888    * dwAppID == 0 indicates that this request isn't associated with a connection.
889    */
890   if( dwAppID )
891   {
892      FIXME( dplay, ": Connection dwAppID=%08lx given. Not implemented yet.\n",
893             dwAppID );
894
895      /* Need to add a check for this application Id...*/
896      return DPERR_NOTLOBBIED;
897   }
898
899   if(  lpConn->dwSize != sizeof(DPLCONNECTION) )
900   {
901     ERR( dplay, ": old/new DPLCONNECTION type? Size=%08lx vs. expected=%ul bytes\n", 
902          lpConn->dwSize, sizeof( DPLCONNECTION ) );
903     return DPERR_INVALIDPARAMS;
904   }
905
906   /* Need to investigate the lpConn->lpSessionDesc to figure out
907    * what type of session we need to join/create.
908    */
909   if(  (!lpConn->lpSessionDesc ) || 
910        ( lpConn->lpSessionDesc->dwSize != sizeof( DPSESSIONDESC2 ) )
911     )
912   {
913     ERR( dplay, "DPSESSIONDESC passed in? Size=%08lx vs. expected=%ul bytes\n",
914          lpConn->lpSessionDesc->dwSize, sizeof( DPSESSIONDESC2 ) );
915     return DPERR_INVALIDPARAMS;
916   }
917
918   /* Need to actually store the stuff here. Check if we've already allocated each field first. */
919   this->dwConnFlags = lpConn->dwFlags;
920
921   /* Copy LPDPSESSIONDESC2 struct - this is required */
922   memcpy( &(this->sessionDesc), lpConn->lpSessionDesc, sizeof( *(lpConn->lpSessionDesc) ) );
923
924   if( lpConn->lpSessionDesc->sess.lpszSessionName )
925     this->sessionDesc.sess.lpszSessionName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->sess.lpszSessionName );
926   else
927     this->sessionDesc.sess.lpszSessionName = NULL;
928  
929   if( lpConn->lpSessionDesc->pass.lpszPassword )
930     this->sessionDesc.pass.lpszPassword = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpSessionDesc->pass.lpszPassword );
931   else
932     this->sessionDesc.pass.lpszPassword = NULL;
933
934   /* I don't know what to use the reserved for ... */
935   this->sessionDesc.dwReserved1 = this->sessionDesc.dwReserved2 = 0;
936
937   /* Copy DPNAME struct - seems to be optional - check for existance first */
938   if( lpConn->lpPlayerName )
939   {
940      memcpy( &(this->playerName), lpConn->lpPlayerName, sizeof( *lpConn->lpPlayerName ) ); 
941
942      if( lpConn->lpPlayerName->psn.lpszShortName )
943        this->playerName.psn.lpszShortName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->psn.lpszShortName ); 
944
945      if( lpConn->lpPlayerName->pln.lpszLongName )
946        this->playerName.pln.lpszLongName = HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->lpPlayerName->pln.lpszLongName );
947
948   }
949
950   memcpy( &(this->guidSP), &(lpConn->guidSP), sizeof( lpConn->guidSP ) );  
951   
952   this->lpAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, lpConn->dwAddressSize ); 
953   memcpy( this->lpAddress, lpConn->lpAddress, lpConn->dwAddressSize );
954
955   this->dwAddressSize = lpConn->dwAddressSize;
956
957   return DP_OK;
958 };
959
960 static HRESULT WINAPI IDirectPlayLobby2W_SetConnectionSettings
961 ( LPDIRECTPLAYLOBBY2 this,
962   DWORD dwFlags,
963   DWORD dwAppID,
964   LPDPLCONNECTION lpConn )
965 {
966   return IDirectPlayLobbyW_SetConnectionSettings( (LPDIRECTPLAYLOBBY)this, 
967                                                   dwFlags, dwAppID, lpConn );
968 }
969
970 static HRESULT WINAPI IDirectPlayLobbyA_SetConnectionSettings
971 ( LPDIRECTPLAYLOBBYA this,
972   DWORD dwFlags,
973   DWORD dwAppID,
974   LPDPLCONNECTION lpConn )
975 {
976   FIXME( dplay, ": this=%p, dwFlags=%08lx, dwAppId=%08lx, lpConn=%p: stub\n",
977          this, dwFlags, dwAppID, lpConn );
978   return DPERR_OUTOFMEMORY;
979 }
980
981 static HRESULT WINAPI IDirectPlayLobby2A_SetConnectionSettings
982 ( LPDIRECTPLAYLOBBY2A this,
983   DWORD dwFlags,
984   DWORD dwAppID,
985   LPDPLCONNECTION lpConn )
986 {
987   return IDirectPlayLobbyA_SetConnectionSettings( (LPDIRECTPLAYLOBBYA)this,
988                                                   dwFlags, dwAppID, lpConn );
989 };
990
991 /********************************************************************
992  *
993  * Registers an event that will be set when a lobby message is received.
994  *
995  */
996 static HRESULT WINAPI IDirectPlayLobbyA_SetLobbyMessageEvent
997 ( LPDIRECTPLAYLOBBYA this,
998   DWORD dwFlags,
999   DWORD dwAppID,
1000   HANDLE32 hReceiveEvent )
1001 {
1002   FIXME( dplay, ":stub\n");
1003   return DPERR_OUTOFMEMORY;
1004 };
1005
1006 static HRESULT WINAPI IDirectPlayLobby2A_SetLobbyMessageEvent
1007 ( LPDIRECTPLAYLOBBY2A this,
1008   DWORD dwFlags,
1009   DWORD dwAppID,
1010   HANDLE32 hReceiveEvent )
1011 {
1012   return IDirectPlayLobbyA_SetLobbyMessageEvent( (LPDIRECTPLAYLOBBYA)this, dwFlags,
1013                                                  dwAppID, hReceiveEvent ); 
1014 };
1015
1016 static HRESULT WINAPI IDirectPlayLobbyW_SetLobbyMessageEvent
1017 ( LPDIRECTPLAYLOBBY this,
1018   DWORD dwFlags,
1019   DWORD dwAppID,
1020   HANDLE32 hReceiveEvent )
1021 {
1022   FIXME( dplay, ":stub\n");
1023   return DPERR_OUTOFMEMORY;
1024 };
1025
1026 static HRESULT WINAPI IDirectPlayLobby2W_SetLobbyMessageEvent
1027 ( LPDIRECTPLAYLOBBY2 this,
1028   DWORD dwFlags,
1029   DWORD dwAppID,
1030   HANDLE32 hReceiveEvent )
1031 {
1032   return IDirectPlayLobbyW_SetLobbyMessageEvent( (LPDIRECTPLAYLOBBY)this, dwFlags,
1033                                                  dwAppID, hReceiveEvent ); 
1034 };
1035
1036
1037 /********************************************************************
1038  *
1039  * Registers an event that will be set when a lobby message is received.
1040  *
1041  */
1042 static HRESULT WINAPI IDirectPlayLobby2W_CreateCompoundAddress
1043 ( LPDIRECTPLAYLOBBY2 this,
1044   LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1045   DWORD dwElementCount,
1046   LPVOID lpAddress,
1047   LPDWORD lpdwAddressSize )
1048 {
1049   FIXME( dplay, ":stub\n");
1050   return DPERR_OUTOFMEMORY;
1051 };
1052
1053 static HRESULT WINAPI IDirectPlayLobby2A_CreateCompoundAddress
1054 ( LPDIRECTPLAYLOBBY2A this,
1055   LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1056   DWORD dwElementCount,
1057   LPVOID lpAddress,
1058   LPDWORD lpdwAddressSize )
1059 {
1060   FIXME( dplay, ":stub\n");
1061   return DPERR_OUTOFMEMORY;
1062 };
1063
1064
1065 /* Direct Play Lobby 1 (ascii) Virtual Table for methods */
1066 /* All lobby 1 methods are exactly the same except QueryInterface */
1067 static struct tagLPDIRECTPLAYLOBBY_VTABLE directPlayLobbyAVT = {
1068   IDirectPlayLobbyA_QueryInterface,
1069   (void*)IDirectPlayLobby2A_AddRef,
1070   (void*)IDirectPlayLobby2A_Release,
1071   (void*)IDirectPlayLobby2A_Connect,
1072   (void*)IDirectPlayLobby2A_CreateAddress,
1073   (void*)IDirectPlayLobby2A_EnumAddress,
1074   (void*)IDirectPlayLobby2A_EnumAddressTypes,
1075   (void*)IDirectPlayLobby2A_EnumLocalApplications,
1076   (void*)IDirectPlayLobby2A_GetConnectionSettings,
1077   (void*)IDirectPlayLobby2A_ReceiveLobbyMessage,
1078   (void*)IDirectPlayLobby2A_RunApplication,
1079   (void*)IDirectPlayLobby2A_SendLobbyMessage,
1080   (void*)IDirectPlayLobby2A_SetConnectionSettings,
1081   (void*)IDirectPlayLobby2A_SetLobbyMessageEvent
1082 };
1083
1084 /* Direct Play Lobby 1 (unicode) Virtual Table for methods */
1085 static struct tagLPDIRECTPLAYLOBBY_VTABLE directPlayLobbyWVT = {
1086   IDirectPlayLobbyW_QueryInterface,
1087   (void*)IDirectPlayLobby2W_AddRef,
1088   (void*)IDirectPlayLobby2W_Release,
1089   (void*)IDirectPlayLobby2W_Connect,
1090   (void*)IDirectPlayLobby2W_CreateAddress, 
1091   (void*)IDirectPlayLobby2W_EnumAddress,
1092   (void*)IDirectPlayLobby2W_EnumAddressTypes,
1093   (void*)IDirectPlayLobby2W_EnumLocalApplications,
1094   (void*)IDirectPlayLobby2W_GetConnectionSettings,
1095   (void*)IDirectPlayLobby2W_ReceiveLobbyMessage,
1096   (void*)IDirectPlayLobby2W_RunApplication,
1097   (void*)IDirectPlayLobby2W_SendLobbyMessage,
1098   (void*)IDirectPlayLobby2W_SetConnectionSettings,
1099   (void*)IDirectPlayLobby2W_SetLobbyMessageEvent
1100 };
1101
1102
1103 /* Direct Play Lobby 2 (ascii) Virtual Table for methods */
1104 static struct tagLPDIRECTPLAYLOBBY2_VTABLE directPlayLobby2AVT = {
1105   IDirectPlayLobby2A_QueryInterface,
1106   IDirectPlayLobby2A_AddRef,
1107   IDirectPlayLobby2A_Release,
1108   IDirectPlayLobby2A_Connect,
1109   IDirectPlayLobby2A_CreateAddress,
1110   IDirectPlayLobby2A_EnumAddress,
1111   IDirectPlayLobby2A_EnumAddressTypes,
1112   IDirectPlayLobby2A_EnumLocalApplications,
1113   IDirectPlayLobby2A_GetConnectionSettings,
1114   IDirectPlayLobby2A_ReceiveLobbyMessage,
1115   IDirectPlayLobby2A_RunApplication,
1116   IDirectPlayLobby2A_SendLobbyMessage,
1117   IDirectPlayLobby2A_SetConnectionSettings,
1118   IDirectPlayLobby2A_SetLobbyMessageEvent,
1119   IDirectPlayLobby2A_CreateCompoundAddress 
1120 };
1121
1122 /* Direct Play Lobby 2 (unicode) Virtual Table for methods */
1123 static struct tagLPDIRECTPLAYLOBBY2_VTABLE directPlayLobby2WVT = {
1124   IDirectPlayLobby2W_QueryInterface,
1125   IDirectPlayLobby2W_AddRef, 
1126   IDirectPlayLobby2W_Release,
1127   IDirectPlayLobby2W_Connect,
1128   IDirectPlayLobby2W_CreateAddress,
1129   IDirectPlayLobby2W_EnumAddress,
1130   IDirectPlayLobby2W_EnumAddressTypes,
1131   IDirectPlayLobby2W_EnumLocalApplications,
1132   IDirectPlayLobby2W_GetConnectionSettings,
1133   IDirectPlayLobby2W_ReceiveLobbyMessage,
1134   IDirectPlayLobby2W_RunApplication,
1135   IDirectPlayLobby2W_SendLobbyMessage,
1136   IDirectPlayLobby2W_SetConnectionSettings,
1137   IDirectPlayLobby2W_SetLobbyMessageEvent,
1138   IDirectPlayLobby2W_CreateCompoundAddress
1139 };
1140
1141 /***************************************************************************
1142  *  DirectPlayLobbyCreateA   (DPLAYX.4)
1143  *
1144  */
1145 HRESULT WINAPI DirectPlayLobbyCreateA( LPGUID lpGUIDDSP,
1146                                        LPDIRECTPLAYLOBBYA *lplpDPL,
1147                                        IUnknown *lpUnk, 
1148                                        LPVOID lpData,
1149                                        DWORD dwDataSize )
1150 {
1151   TRACE(dplay,"lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\n",
1152         lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
1153
1154   /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
1155    * equal 0. These fields are mostly for future expansion.
1156    */
1157   if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
1158   {
1159      *lplpDPL = NULL;
1160      return DPERR_INVALIDPARAMS;
1161   }
1162
1163   /* Yes...really we should be returning a lobby 1 object */
1164   *lplpDPL = (LPDIRECTPLAYLOBBYA)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1165                                             sizeof( IDirectPlayLobbyA ) );
1166
1167   if( ! (*lplpDPL) )
1168   {
1169      return DPERR_OUTOFMEMORY;
1170   }
1171
1172   (*lplpDPL)->lpVtbl = &directPlayLobbyAVT;
1173   (*lplpDPL)->ref    = 1;
1174
1175   /* All fields were nulled out by the allocation */
1176
1177   return DP_OK;
1178 }
1179
1180 /***************************************************************************
1181  *  DirectPlayLobbyCreateW   (DPLAYX.5)
1182  *
1183  */
1184 HRESULT WINAPI DirectPlayLobbyCreateW( LPGUID lpGUIDDSP, 
1185                                        LPDIRECTPLAYLOBBY *lplpDPL,
1186                                        IUnknown *lpUnk,
1187                                        LPVOID lpData, 
1188                                        DWORD dwDataSize )
1189 {
1190   TRACE(dplay,"lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\n",
1191         lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
1192
1193   /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must 
1194    * equal 0. These fields are mostly for future expansion.
1195    */
1196   if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
1197   {
1198      *lplpDPL = NULL;
1199      ERR( dplay, "Bad parameters!\n" );
1200      return DPERR_INVALIDPARAMS;
1201   }
1202
1203   /* Yes...really we should bre returning a lobby 1 object */
1204   *lplpDPL = (LPDIRECTPLAYLOBBY)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1205                                            sizeof( IDirectPlayLobby ) );
1206
1207   if( !*lplpDPL)
1208   {
1209      return DPERR_OUTOFMEMORY;
1210   }
1211
1212   (*lplpDPL)->lpVtbl = &directPlayLobbyWVT;
1213   (*lplpDPL)->ref    = 1;
1214
1215   /* All fields were nulled out by the allocation */
1216
1217   return DP_OK;
1218
1219 }
1220
1221 /***************************************************************************
1222  *  DirectPlayEnumerateA (DPLAYX.2) 
1223  *
1224  *  The pointer to the structure lpContext will be filled with the 
1225  *  appropriate data for each service offered by the OS. These services are
1226  *  not necessarily available on this particular machine but are defined
1227  *  as simple service providers under the "Service Providers" registry key.
1228  *  This structure is then passed to lpEnumCallback for each of the different 
1229  *  services. 
1230  *
1231  *  This API is useful only for applications written using DirectX3 or
1232  *  worse. It is superceeded by IDirectPlay3::EnumConnections which also
1233  *  gives information on the actual connections.
1234  *
1235  * defn of a service provider:
1236  * A dynamic-link library used by DirectPlay to communicate over a network. 
1237  * The service provider contains all the network-specific code required
1238  * to send and receive messages. Online services and network operators can
1239  * supply service providers to use specialized hardware, protocols, communications
1240  * media, and network resources. 
1241  *
1242  * TODO: Allocate string buffer space from the heap (length from reg)
1243  *       Pass real device driver numbers...
1244  *       Get the GUID properly...
1245  */
1246 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
1247                                      LPVOID lpContext )
1248 {
1249
1250   HKEY hkResult; 
1251   LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
1252   LPSTR guidDataSubKey   = "Guid";
1253   LPSTR majVerDataSubKey = "dwReserved1";
1254   DWORD dwIndex, sizeOfSubKeyName=50;
1255   char subKeyName[51]; 
1256
1257   TRACE( dplay, ": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
1258
1259   if( !lpEnumCallback || !*lpEnumCallback )
1260   {
1261      return DPERR_INVALIDPARAMS;
1262   }
1263
1264   /* Need to loop over the service providers in the registry */
1265   if( RegOpenKeyEx32A( HKEY_LOCAL_MACHINE, searchSubKey,
1266                        0, KEY_ENUMERATE_SUB_KEYS, &hkResult ) != ERROR_SUCCESS )
1267   {
1268     /* Hmmm. Does this mean that there are no service providers? */ 
1269     ERR(dplay, ": no service providers?\n");
1270     return DP_OK; 
1271   }
1272
1273   /* Traverse all the service providers we have available */
1274   for( dwIndex=0;
1275        RegEnumKey32A( hkResult, dwIndex, subKeyName, sizeOfSubKeyName ) !=
1276          ERROR_NO_MORE_ITEMS;
1277        ++dwIndex )
1278   {
1279     HKEY     hkServiceProvider;
1280     GUID     serviceProviderGUID;
1281     DWORD    returnTypeGUID, returnTypeReserved1, sizeOfReturnBuffer=50;
1282     char     returnBuffer[51];
1283     DWORD    majVersionNum, minVersionNum;
1284     LPWSTR   lpWGUIDString; 
1285
1286     TRACE( dplay, " this time through: %s\n", subKeyName );
1287
1288     /* Get a handle for this particular service provider */
1289     if( RegOpenKeyEx32A( hkResult, subKeyName, 0, KEY_QUERY_VALUE,
1290                          &hkServiceProvider ) != ERROR_SUCCESS )
1291     {
1292       ERR( dplay, ": what the heck is going on?\n" );
1293       continue;
1294     }
1295
1296     /* Get the GUID, Device major number and device minor number 
1297      * from the registry. 
1298      */
1299     if( RegQueryValueEx32A( hkServiceProvider, guidDataSubKey,
1300                             NULL, &returnTypeGUID, returnBuffer,
1301                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1302     {
1303       ERR( dplay, ": missing GUID registry data members\n" );
1304       continue; 
1305     }
1306
1307     /* FIXME: Check return types to ensure we're interpreting data right */
1308     lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
1309     CLSIDFromString32( (LPCOLESTR32)lpWGUIDString, &serviceProviderGUID ); 
1310     HeapFree( GetProcessHeap(), 0, lpWGUIDString );
1311
1312     sizeOfReturnBuffer = 50;
1313  
1314     if( RegQueryValueEx32A( hkServiceProvider, majVerDataSubKey,
1315                             NULL, &returnTypeReserved1, returnBuffer,
1316                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1317     {
1318       ERR( dplay, ": missing dwReserved1 registry data members\n") ;
1319       continue; 
1320     }
1321     /* FIXME: This couldn't possibly be right...*/
1322     majVersionNum = GET_DWORD( returnBuffer );
1323
1324     /* The enumeration will return FALSE if we are not to continue */
1325     if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
1326                          majVersionNum, (DWORD)0, lpContext ) )
1327     {
1328       WARN( dplay, "lpEnumCallback returning FALSE\n" );
1329       break;
1330     }
1331   }
1332
1333   return DP_OK;
1334
1335 };
1336
1337 /***************************************************************************
1338  *  DirectPlayEnumerateW (DPLAYX.3)
1339  *
1340  */
1341 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
1342 {
1343
1344   FIXME( dplay, ":stub\n");
1345
1346   return DPERR_OUTOFMEMORY; 
1347
1348 };
1349
1350 /***************************************************************************
1351  *  DirectPlayCreate (DPLAYX.1) (DPLAY.1)
1352  *
1353  */
1354 HRESULT WINAPI DirectPlayCreate
1355 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
1356 {
1357
1358   TRACE(dplay,"\n" );
1359
1360   if( pUnk != NULL )
1361   {
1362     /* Hmmm...wonder what this means! */
1363     ERR(dplay, "What does a NULL here mean?\n" ); 
1364     return DPERR_OUTOFMEMORY;
1365   }
1366
1367   *lplpDP = (LPDIRECTPLAY2)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
1368                                       sizeof( **lplpDP ) );
1369
1370   if( !*lplpDP )
1371   {
1372      return DPERR_OUTOFMEMORY;
1373   }
1374
1375   (*lplpDP)->lpVtbl = &directPlay2AVT;
1376   (*lplpDP)->ref    = 1;
1377
1378   return DP_OK;
1379
1380 };
1381
1382
1383 /* Direct Play methods */
1384 static HRESULT WINAPI DirectPlay2W_QueryInterface
1385          ( LPDIRECTPLAY2 this, REFIID riid, LPVOID* ppvObj )
1386 {
1387   FIXME( dplay, "(%p)->(%p,%p): stub\n", this, riid, ppvObj );
1388   return E_NOINTERFACE;
1389 }
1390
1391 static HRESULT WINAPI DirectPlay2A_QueryInterface
1392          ( LPDIRECTPLAY2A this, REFIID riid, LPVOID* ppvObj )
1393 {
1394   FIXME( dplay, "(%p)->(%p,%p): stub\n", this, riid, ppvObj );
1395   return E_NOINTERFACE;
1396 }
1397
1398 static HRESULT WINAPI DirectPlay3W_QueryInterface
1399          ( LPDIRECTPLAY3 this, REFIID riid, LPVOID* ppvObj )
1400 {
1401   FIXME( dplay, "(%p)->(%p,%p): stub\n", this, riid, ppvObj );
1402   return E_NOINTERFACE;
1403 }
1404
1405 static HRESULT WINAPI DirectPlay3A_QueryInterface
1406          ( LPDIRECTPLAY3A this, REFIID riid, LPVOID* ppvObj )
1407 {
1408   FIXME( dplay, "(%p)->(%p,%p): stub\n", this, riid, ppvObj );
1409   return E_NOINTERFACE;
1410 }
1411
1412
1413 static ULONG WINAPI DirectPlay3W_AddRef
1414          ( LPDIRECTPLAY3 this )
1415 {
1416   ++(this->ref);
1417   TRACE( dplay,"ref count now %lu\n", this->ref );
1418   return (this->ref);
1419 }
1420
1421 static ULONG WINAPI DirectPlay3W_Release
1422 ( LPDIRECTPLAY3 this )
1423 {
1424   TRACE( dplay, "ref count decremeneted from %lu\n", this->ref );
1425
1426   this->ref--;
1427
1428   /* Deallocate if this is the last reference to the object */
1429   if( !(this->ref) )
1430   {
1431     FIXME( dplay, "memory leak\n" );
1432     /* Implement memory deallocation */
1433
1434     HeapFree( GetProcessHeap(), 0, this );
1435
1436     return 0;
1437   }
1438
1439   return this->ref;
1440 };
1441
1442         
1443
1444
1445 HRESULT WINAPI DirectPlay3W_AddPlayerToGroup
1446           ( LPDIRECTPLAY3 this, DPID a, DPID b )
1447 {
1448   FIXME( dplay,"(%p)->(0x%08lx,0x%08lx): stub", this, a, b );
1449   return DP_OK;
1450 }
1451
1452 HRESULT WINAPI DirectPlay3W_Close
1453           ( LPDIRECTPLAY3 this )
1454 {
1455   FIXME( dplay,"(%p)->(): stub", this );
1456   return DP_OK;
1457 }
1458
1459 HRESULT WINAPI DirectPlay3W_CreateGroup
1460           ( LPDIRECTPLAY3 this, LPDPID a, LPDPNAME b, LPVOID c, DWORD d, DWORD e )
1461 {
1462   FIXME( dplay,"(%p)->(%p,%p,%p,0x%08lx,0x%08lx): stub", this, a, b, c, d, e );
1463   return DP_OK;
1464 }
1465
1466 HRESULT WINAPI DirectPlay3W_CreatePlayer
1467           ( LPDIRECTPLAY3 this, LPDPID a, LPDPNAME b, HANDLE32 c, LPVOID d, DWORD e, DWORD f )
1468 {
1469   FIXME( dplay,"(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx): stub", this, a, b, c, d, e, f );
1470   return DP_OK;
1471 }
1472
1473 HRESULT WINAPI DirectPlay3W_DeletePlayerFromGroup
1474           ( LPDIRECTPLAY3 this, DPID a, DPID b )
1475 {
1476   FIXME( dplay,"(%p)->(0x%08lx,0x%08lx): stub", this, a, b );
1477   return DP_OK;
1478 }
1479
1480 HRESULT WINAPI DirectPlay3W_DestroyGroup
1481           ( LPDIRECTPLAY3 this, DPID a )
1482 {
1483   FIXME( dplay,"(%p)->(0x%08lx): stub", this, a );
1484   return DP_OK;
1485 }
1486
1487 HRESULT WINAPI DirectPlay3W_DestroyPlayer
1488           ( LPDIRECTPLAY3 this, DPID a )
1489 {
1490   FIXME( dplay,"(%p)->(0x%08lx): stub", this, a );
1491   return DP_OK;
1492 }
1493
1494 HRESULT WINAPI DirectPlay3W_EnumGroupPlayers
1495           ( LPDIRECTPLAY3 this, DPID a, LPGUID b, LPDPENUMPLAYERSCALLBACK2 c,
1496             LPVOID d, DWORD e )
1497 {
1498   FIXME( dplay,"(%p)->(0x%08lx,%p,%p,%p,0x%08lx): stub", this, a, b, c, d, e );
1499   return DP_OK;
1500 }
1501
1502 HRESULT WINAPI DirectPlay3W_EnumGroups
1503           ( LPDIRECTPLAY3 this, LPGUID a, LPDPENUMPLAYERSCALLBACK2 b, LPVOID c, DWORD d )
1504 {
1505   FIXME( dplay,"(%p)->(%p,%p,%p,0x%08lx): stub", this, a, b, c, d );
1506   return DP_OK;
1507 }
1508
1509 HRESULT WINAPI DirectPlay3W_EnumPlayers
1510           ( LPDIRECTPLAY3 this, LPGUID a, LPDPENUMPLAYERSCALLBACK2 b, LPVOID c, DWORD d )
1511 {
1512   FIXME( dplay,"(%p)->(%p,%p,%p,0x%08lx): stub", this, a, b, c, d );
1513   return DP_OK;
1514 }
1515
1516 HRESULT WINAPI DirectPlay3W_EnumSessions
1517           ( LPDIRECTPLAY3 this, LPDPSESSIONDESC2 a, DWORD b, LPDPENUMSESSIONSCALLBACK2 c,
1518             LPVOID d, DWORD e )
1519 {
1520   FIXME( dplay,"(%p)->(%p,0x%08lx,%p,%p,0x%08lx): stub", this, a, b, c, d, e );
1521   return DP_OK;
1522 }
1523
1524 HRESULT WINAPI DirectPlay3W_GetCaps
1525           ( LPDIRECTPLAY3 this, LPDPCAPS a, DWORD b )
1526 {
1527   FIXME( dplay,"(%p)->(%p,0x%08lx): stub", this, a, b );
1528   return DP_OK;
1529 }
1530
1531 HRESULT WINAPI DirectPlay3W_GetGroupData
1532           ( LPDIRECTPLAY3 this, DPID a, LPVOID b, LPDWORD c, DWORD d )
1533 {
1534   FIXME( dplay,"(%p)->(0x%08lx,%p,%p,0x%08lx): stub", this, a, b, c, d );
1535   return DP_OK;
1536 }
1537
1538 HRESULT WINAPI DirectPlay3W_GetGroupName
1539           ( LPDIRECTPLAY3 this, DPID a, LPVOID b, LPDWORD c )
1540 {
1541   FIXME( dplay,"(%p)->(0x%08lx,%p,%p): stub", this, a, b, c );
1542   return DP_OK;
1543 }
1544
1545 HRESULT WINAPI DirectPlay3W_GetMessageCount
1546           ( LPDIRECTPLAY3 this, DPID a, LPDWORD b )
1547 {
1548   FIXME( dplay,"(%p)->(0x%08lx,%p): stub", this, a, b );
1549   return DP_OK;
1550 }
1551
1552 HRESULT WINAPI DirectPlay3W_GetPlayerAddress
1553           ( LPDIRECTPLAY3 this, DPID a, LPVOID b, LPDWORD c )
1554 {
1555   FIXME( dplay,"(%p)->(0x%08lx,%p,%p): stub", this, a, b, c );
1556   return DP_OK;
1557 }
1558
1559 HRESULT WINAPI DirectPlay3W_GetPlayerCaps
1560           ( LPDIRECTPLAY3 this, DPID a, LPDPCAPS b, DWORD c )
1561 {
1562   FIXME( dplay,"(%p)->(0x%08lx,%p,0x%08lx): stub", this, a, b, c );
1563   return DP_OK;
1564 }
1565
1566 HRESULT WINAPI DirectPlay3W_GetPlayerData
1567           ( LPDIRECTPLAY3 this, DPID a, LPVOID b, LPDWORD c, DWORD d )
1568 {
1569   FIXME( dplay,"(%p)->(0x%08lx,%p,%p,0x%08lx): stub", this, a, b, c, d );
1570   return DP_OK;
1571 }
1572
1573 HRESULT WINAPI DirectPlay3W_GetPlayerName
1574           ( LPDIRECTPLAY3 this, DPID a, LPVOID b, LPDWORD c )
1575 {
1576   FIXME( dplay,"(%p)->(0x%08lx,%p,%p): stub", this, a, b, c );
1577   return DP_OK;
1578 }
1579
1580 HRESULT WINAPI DirectPlay3W_GetSessionDesc
1581           ( LPDIRECTPLAY3 this, LPVOID a, LPDWORD b )
1582 {
1583   FIXME( dplay,"(%p)->(%p,%p): stub", this, a, b );
1584   return DP_OK;
1585 }
1586
1587 HRESULT WINAPI DirectPlay3W_Initialize
1588           ( LPDIRECTPLAY3 this, LPGUID a )
1589 {
1590   FIXME( dplay,"(%p)->(%p): stub", this, a );
1591   return DP_OK;
1592 }
1593
1594 HRESULT WINAPI DirectPlay3W_Open
1595           ( LPDIRECTPLAY3 this, LPDPSESSIONDESC2 a, DWORD b )
1596 {
1597   FIXME( dplay,"(%p)->(%p,0x%08lx): stub", this, a, b );
1598   return DP_OK;
1599 }
1600
1601 HRESULT WINAPI DirectPlay3W_Receive
1602           ( LPDIRECTPLAY3 this, LPDPID a, LPDPID b, DWORD c, LPVOID d, LPDWORD e )
1603 {
1604   FIXME( dplay,"(%p)->(%p,%p,0x%08lx,%p,%p): stub", this, a, b, c, d, e );
1605   return DP_OK;
1606 }
1607
1608 HRESULT WINAPI DirectPlay3W_Send
1609           ( LPDIRECTPLAY3 this, DPID a, DPID b, DWORD c, LPVOID d, DWORD e )
1610 {
1611   FIXME( dplay,"(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx): stub", this, a, b, c, d, e );
1612   return DP_OK;
1613 }
1614
1615 HRESULT WINAPI DirectPlay3W_SetGroupData
1616           ( LPDIRECTPLAY3 this, DPID a, LPVOID b, DWORD c, DWORD d )
1617 {   
1618   FIXME( dplay,"(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub", this, a, b, c, d );
1619   return DP_OK;
1620 }
1621
1622 HRESULT WINAPI DirectPlay3W_SetGroupName
1623           ( LPDIRECTPLAY3 this, DPID a, LPDPNAME b, DWORD c )
1624 {
1625   FIXME( dplay,"(%p)->(0x%08lx,%p,0x%08lx): stub", this, a, b, c );
1626   return DP_OK;
1627 }
1628
1629 HRESULT WINAPI DirectPlay3W_SetPlayerData
1630           ( LPDIRECTPLAY3 this, DPID a, LPVOID b, DWORD c, DWORD d )
1631 {
1632   FIXME( dplay,"(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub", this, a, b, c, d );
1633   return DP_OK;
1634 }
1635
1636 HRESULT WINAPI DirectPlay3W_SetPlayerName
1637           ( LPDIRECTPLAY3 this, DPID a, LPDPNAME b, DWORD c )
1638 {
1639   FIXME( dplay,"(%p)->(0x%08lx,%p,0x%08lx): stub", this, a, b, c );
1640   return DP_OK;
1641 }
1642
1643 HRESULT WINAPI DirectPlay3W_SetSessionDesc
1644           ( LPDIRECTPLAY3 this, LPDPSESSIONDESC2 a, DWORD b )
1645 {
1646   FIXME( dplay,"(%p)->(%p,0x%08lx): stub", this, a, b );
1647   return DP_OK;
1648 }
1649
1650 HRESULT WINAPI DirectPlay3W_AddGroupToGroup
1651           ( LPDIRECTPLAY3 this, DPID a, DPID b )
1652 {
1653   FIXME( dplay,"(%p)->(0x%08lx,0x%08lx): stub", this, a, b );
1654   return DP_OK;
1655 }
1656
1657 HRESULT WINAPI DirectPlay3W_CreateGroupInGroup
1658           ( LPDIRECTPLAY3 this, DPID a, LPDPID b, LPDPNAME c, LPVOID d, DWORD e, DWORD f )
1659 {
1660   FIXME( dplay,"(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx): stub", this, a, b, c, d, e, f );
1661   return DP_OK;
1662 }
1663
1664 HRESULT WINAPI DirectPlay3W_DeleteGroupFromGroup
1665           ( LPDIRECTPLAY3 this, DPID a, DPID b )
1666 {
1667   FIXME( dplay,"(%p)->(0x%08lx,0x%08lx): stub", this, a, b );
1668   return DP_OK;
1669 }
1670
1671 HRESULT WINAPI DirectPlay3W_EnumConnections
1672           ( LPDIRECTPLAY3 this, LPCGUID a, LPDPENUMCONNECTIONSCALLBACK b, LPVOID c, DWORD d )
1673
1674   FIXME( dplay,"(%p)->(%p,%p,%p,0x%08lx): stub", this, a, b, c, d );
1675   return DP_OK;
1676 }
1677
1678 HRESULT WINAPI DirectPlay3W_EnumGroupsInGroup
1679           ( LPDIRECTPLAY3 this, DPID a, LPGUID b, LPDPENUMPLAYERSCALLBACK2 c, LPVOID d, DWORD e )
1680 {
1681   FIXME( dplay,"(%p)->(0x%08lx,%p,%p,%p,0x%08lx): stub", this, a, b, c, d, e );
1682   return DP_OK;
1683 }
1684
1685 HRESULT WINAPI DirectPlay3W_GetGroupConnectionSettings
1686           ( LPDIRECTPLAY3 this, DWORD a, DPID b, LPVOID c, LPDWORD d )
1687 {
1688   FIXME( dplay,"(%p)->(0x%08lx,0x%08lx,%p,%p): stub", this, a, b, c, d );
1689   return DP_OK;
1690 }
1691
1692 HRESULT WINAPI DirectPlay3W_InitializeConnection
1693           ( LPDIRECTPLAY3 this, LPVOID a, DWORD b )
1694 {
1695   FIXME( dplay,"(%p)->(%p,0x%08lx): stub", this, a, b );
1696   return DP_OK;
1697 }
1698
1699 HRESULT WINAPI DirectPlay3W_SecureOpen
1700           ( LPDIRECTPLAY3 this, LPCDPSESSIONDESC2 a, DWORD b, LPCDPSECURITYDESC c, LPCDPCREDENTIALS d )
1701 {   
1702   FIXME( dplay,"(%p)->(%p,0x%08lx,%p,%p): stub", this, a, b, c, d );
1703   return DP_OK;
1704 }
1705
1706 HRESULT WINAPI DirectPlay3W_SendChatMessage
1707           ( LPDIRECTPLAY3 this, DPID a, DPID b, DWORD c, LPDPCHAT d )
1708 {
1709   FIXME( dplay,"(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub", this, a, b, c, d );
1710   return DP_OK;
1711 }
1712
1713 HRESULT WINAPI DirectPlay3W_SetGroupConnectionSettings
1714           ( LPDIRECTPLAY3 this, DWORD a, DPID b, LPDPLCONNECTION c )
1715 {
1716   FIXME( dplay,"(%p)->(0x%08lx,0x%08lx,%p): stub", this, a, b, c );
1717   return DP_OK;
1718 }
1719
1720 HRESULT WINAPI DirectPlay3W_StartSession
1721           ( LPDIRECTPLAY3 this, DWORD a, DPID b )
1722 {
1723   FIXME( dplay,"(%p)->(0x%08lx,0x%08lx): stub", this, a, b );
1724   return DP_OK;
1725 }
1726  
1727 HRESULT WINAPI DirectPlay3W_GetGroupFlags
1728           ( LPDIRECTPLAY3 this, DPID a, LPDWORD b )
1729 {
1730   FIXME( dplay,"(%p)->(0x%08lx,%p): stub", this, a, b );
1731   return DP_OK;
1732 }
1733
1734 HRESULT WINAPI DirectPlay3W_GetGroupParent
1735           ( LPDIRECTPLAY3 this, DPID a, LPDPID b )
1736 {
1737   FIXME( dplay,"(%p)->(0x%08lx,%p): stub", this, a, b );
1738   return DP_OK;
1739 }
1740
1741 HRESULT WINAPI DirectPlay3W_GetPlayerAccount
1742           ( LPDIRECTPLAY3 this, DPID a, DWORD b, LPVOID c, LPDWORD d )
1743 {
1744   FIXME( dplay,"(%p)->(0x%08lx,0x%08lx,%p,%p): stub", this, a, b, c, d );
1745   return DP_OK;
1746 }
1747
1748 HRESULT WINAPI DirectPlay3W_GetPlayerFlags
1749           ( LPDIRECTPLAY3 this, DPID a, LPDWORD b )
1750 {
1751   FIXME( dplay,"(%p)->(0x%08lx,%p): stub", this, a, b );
1752   return DP_OK;
1753 }
1754
1755 static struct tagLPDIRECTPLAY2_VTABLE directPlay2WVT = {
1756   DirectPlay2W_QueryInterface,
1757   (void*)DirectPlay3W_AddRef,
1758   (void*)DirectPlay3W_Release,
1759   (void*)DirectPlay3W_AddPlayerToGroup,
1760   (void*)DirectPlay3W_Close,
1761   (void*)DirectPlay3W_CreateGroup,
1762   (void*)DirectPlay3W_CreatePlayer,
1763   (void*)DirectPlay3W_DeletePlayerFromGroup,
1764   (void*)DirectPlay3W_DestroyGroup,
1765   (void*)DirectPlay3W_DestroyPlayer,
1766   (void*)DirectPlay3W_EnumGroupPlayers,
1767   (void*)DirectPlay3W_EnumGroups,
1768   (void*)DirectPlay3W_EnumPlayers,
1769   (void*)DirectPlay3W_EnumSessions,
1770   (void*)DirectPlay3W_GetCaps,
1771   (void*)DirectPlay3W_GetGroupData,
1772   (void*)DirectPlay3W_GetGroupName,
1773   (void*)DirectPlay3W_GetMessageCount,
1774   (void*)DirectPlay3W_GetPlayerAddress,
1775   (void*)DirectPlay3W_GetPlayerCaps,
1776   (void*)DirectPlay3W_GetPlayerData,
1777   (void*)DirectPlay3W_GetPlayerName,
1778   (void*)DirectPlay3W_GetSessionDesc,
1779   (void*)DirectPlay3W_Initialize,
1780   (void*)DirectPlay3W_Open,
1781   (void*)DirectPlay3W_Receive,
1782   (void*)DirectPlay3W_Send,
1783   (void*)DirectPlay3W_SetGroupData,
1784   (void*)DirectPlay3W_SetGroupName,
1785   (void*)DirectPlay3W_SetPlayerData,
1786   (void*)DirectPlay3W_SetPlayerName,
1787   (void*)DirectPlay3W_SetSessionDesc
1788 };
1789
1790 static struct tagLPDIRECTPLAY2_VTABLE directPlay2AVT = {
1791   DirectPlay2A_QueryInterface,
1792   (void*)DirectPlay3W_AddRef,
1793   (void*)DirectPlay3W_Release,
1794   (void*)DirectPlay3W_AddPlayerToGroup,
1795   (void*)DirectPlay3W_Close,
1796   (void*)DirectPlay3W_CreateGroup,
1797   (void*)DirectPlay3W_CreatePlayer,
1798   (void*)DirectPlay3W_DeletePlayerFromGroup,
1799   (void*)DirectPlay3W_DestroyGroup,
1800   (void*)DirectPlay3W_DestroyPlayer,
1801   (void*)DirectPlay3W_EnumGroupPlayers,
1802   (void*)DirectPlay3W_EnumGroups,
1803   (void*)DirectPlay3W_EnumPlayers,
1804   (void*)DirectPlay3W_EnumSessions,
1805   (void*)DirectPlay3W_GetCaps,
1806   (void*)DirectPlay3W_GetGroupData,
1807   (void*)DirectPlay3W_GetGroupName,
1808   (void*)DirectPlay3W_GetMessageCount,
1809   (void*)DirectPlay3W_GetPlayerAddress,
1810   (void*)DirectPlay3W_GetPlayerCaps,
1811   (void*)DirectPlay3W_GetPlayerData,
1812   (void*)DirectPlay3W_GetPlayerName,
1813   (void*)DirectPlay3W_GetSessionDesc,
1814   (void*)DirectPlay3W_Initialize,
1815   (void*)DirectPlay3W_Open,
1816   (void*)DirectPlay3W_Receive,
1817   (void*)DirectPlay3W_Send,
1818   (void*)DirectPlay3W_SetGroupData,
1819   (void*)DirectPlay3W_SetGroupName,
1820   (void*)DirectPlay3W_SetPlayerData,
1821   (void*)DirectPlay3W_SetPlayerName,
1822   (void*)DirectPlay3W_SetSessionDesc
1823 };
1824
1825 static struct tagLPDIRECTPLAY3_VTABLE directPlay3AVT = {
1826   DirectPlay3A_QueryInterface,
1827   (void*)DirectPlay3W_AddRef,
1828   (void*)DirectPlay3W_Release,
1829   (void*)DirectPlay3W_AddPlayerToGroup,
1830   (void*)DirectPlay3W_Close,
1831   (void*)DirectPlay3W_CreateGroup,
1832   (void*)DirectPlay3W_CreatePlayer,
1833   (void*)DirectPlay3W_DeletePlayerFromGroup,
1834   (void*)DirectPlay3W_DestroyGroup,
1835   (void*)DirectPlay3W_DestroyPlayer,
1836   (void*)DirectPlay3W_EnumGroupPlayers,
1837   (void*)DirectPlay3W_EnumGroups,
1838   (void*)DirectPlay3W_EnumPlayers,
1839   (void*)DirectPlay3W_EnumSessions,
1840   (void*)DirectPlay3W_GetCaps,
1841   (void*)DirectPlay3W_GetGroupData,
1842   (void*)DirectPlay3W_GetGroupName,
1843   (void*)DirectPlay3W_GetMessageCount,
1844   (void*)DirectPlay3W_GetPlayerAddress,
1845   (void*)DirectPlay3W_GetPlayerCaps,
1846   (void*)DirectPlay3W_GetPlayerData,
1847   (void*)DirectPlay3W_GetPlayerName,
1848   (void*)DirectPlay3W_GetSessionDesc,
1849   (void*)DirectPlay3W_Initialize,
1850   (void*)DirectPlay3W_Open,
1851   (void*)DirectPlay3W_Receive,
1852   (void*)DirectPlay3W_Send,
1853   (void*)DirectPlay3W_SetGroupData,
1854   (void*)DirectPlay3W_SetGroupName,
1855   (void*)DirectPlay3W_SetPlayerData,
1856   (void*)DirectPlay3W_SetPlayerName,
1857   (void*)DirectPlay3W_SetSessionDesc,
1858
1859   (void*)DirectPlay3W_AddGroupToGroup,
1860   (void*)DirectPlay3W_CreateGroupInGroup,
1861   (void*)DirectPlay3W_DeleteGroupFromGroup,
1862   (void*)DirectPlay3W_EnumConnections,
1863   (void*)DirectPlay3W_EnumGroupsInGroup,
1864   (void*)DirectPlay3W_GetGroupConnectionSettings,
1865   (void*)DirectPlay3W_InitializeConnection,
1866   (void*)DirectPlay3W_SecureOpen,
1867   (void*)DirectPlay3W_SendChatMessage,
1868   (void*)DirectPlay3W_SetGroupConnectionSettings,
1869   (void*)DirectPlay3W_StartSession,
1870   (void*)DirectPlay3W_GetGroupFlags,
1871   (void*)DirectPlay3W_GetGroupParent,
1872   (void*)DirectPlay3W_GetPlayerAccount,
1873   (void*)DirectPlay3W_GetPlayerFlags
1874 };
1875
1876 static struct tagLPDIRECTPLAY3_VTABLE directPlay3WVT = {
1877   DirectPlay3W_QueryInterface,
1878   DirectPlay3W_AddRef,
1879   DirectPlay3W_Release,
1880   DirectPlay3W_AddPlayerToGroup,
1881   DirectPlay3W_Close,
1882   DirectPlay3W_CreateGroup,
1883   DirectPlay3W_CreatePlayer,
1884   DirectPlay3W_DeletePlayerFromGroup,
1885   DirectPlay3W_DestroyGroup,
1886   DirectPlay3W_DestroyPlayer,
1887   DirectPlay3W_EnumGroupPlayers,
1888   DirectPlay3W_EnumGroups,
1889   DirectPlay3W_EnumPlayers,
1890   DirectPlay3W_EnumSessions,
1891   DirectPlay3W_GetCaps,
1892   DirectPlay3W_GetGroupData,
1893   DirectPlay3W_GetGroupName,
1894   DirectPlay3W_GetMessageCount,
1895   DirectPlay3W_GetPlayerAddress,
1896   DirectPlay3W_GetPlayerCaps,
1897   DirectPlay3W_GetPlayerData,
1898   DirectPlay3W_GetPlayerName,
1899   DirectPlay3W_GetSessionDesc,
1900   DirectPlay3W_Initialize,
1901   DirectPlay3W_Open,
1902   DirectPlay3W_Receive,
1903   DirectPlay3W_Send,
1904   DirectPlay3W_SetGroupData,
1905   DirectPlay3W_SetGroupName,
1906   DirectPlay3W_SetPlayerData,
1907   DirectPlay3W_SetPlayerName,
1908   DirectPlay3W_SetSessionDesc,
1909
1910   DirectPlay3W_AddGroupToGroup,
1911   DirectPlay3W_CreateGroupInGroup,
1912   DirectPlay3W_DeleteGroupFromGroup,
1913   DirectPlay3W_EnumConnections,
1914   DirectPlay3W_EnumGroupsInGroup,
1915   DirectPlay3W_GetGroupConnectionSettings,
1916   DirectPlay3W_InitializeConnection,
1917   DirectPlay3W_SecureOpen,
1918   DirectPlay3W_SendChatMessage,
1919   DirectPlay3W_SetGroupConnectionSettings,
1920   DirectPlay3W_StartSession,
1921   DirectPlay3W_GetGroupFlags,
1922   DirectPlay3W_GetGroupParent,
1923   DirectPlay3W_GetPlayerAccount,
1924   DirectPlay3W_GetPlayerFlags
1925 };
1926