POSIX threads emulation, tricks glibc into being threadsafe.
[wine] / dlls / dplayx / dplay.c
1 /* Direct Play 2,3,4 Implementation
2  *
3  * Copyright 1998,1999,2000 - Peter Hunnisett
4  *
5  * <presently under construction - contact hunnise@nortelnetworks.com>
6  *
7  */
8 #include <string.h>
9
10 #include "winerror.h"
11 #include "winbase.h"
12 #include "winnt.h"
13 #include "winreg.h"
14 #include "dplay.h"
15 #include "heap.h"
16 #include "debugtools.h"
17
18 #include "dpinit.h"
19 #include "dplayx_global.h"
20 #include "name_server.h"
21
22 /* FIXME: This stuff shouldn't really be here. It indicates a poor architectural coupling */
23 #include "dplobby.h"
24 extern HRESULT DPL_CreateCompoundAddress ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
25                                            LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
26
27 DEFAULT_DEBUG_CHANNEL(dplay)
28
29
30 /*****************************************************************************
31  * Predeclare the interface implementation structures
32  */
33 typedef struct IDirectPlay2Impl IDirectPlay2AImpl;
34 typedef struct IDirectPlay2Impl IDirectPlay2Impl;
35 typedef struct IDirectPlay3Impl IDirectPlay3AImpl;
36 typedef struct IDirectPlay3Impl IDirectPlay3Impl;
37 typedef struct IDirectPlay4Impl IDirectPlay4AImpl;
38 typedef struct IDirectPlay4Impl IDirectPlay4Impl;
39
40 /*****************************************************************************
41  * IDirectPlay implementation structure
42  *
43  * The philosophy behind this extra pointer derefernce is that I wanted to
44  * have the same structure for all types of objects without having to do
45  * alot of casting. I also only wanted to implement an interface in the
46  * object it was "released" with IUnknown interface being implemented in the 1 version.
47  * Of course, with these new interfaces comes the data required to keep the state required
48  * by these interfaces. So, basically, the pointers contain the data associated with
49  * a release. If you use the data associated with release 3 in a release 2 object, you'll
50  * get a run time trap, as that won't have any data.
51  * 
52  */
53 typedef struct tagDirectPlayIUnknownData
54 {
55   DWORD             ref;
56   CRITICAL_SECTION  DP_lock;
57 } DirectPlayIUnknownData;
58
59 typedef struct _enumSessionAsyncCallbackData
60 {
61   LPDPENUMSESSIONSCALLBACK2 cb;
62   LPVOID lpContext;
63   DWORD dwTimeout;
64 } EnumSessionAsyncCallbackData;
65
66 /* Contains all dp1 and dp2 data members */
67 typedef struct tagDirectPlay2Data
68 {
69   BOOL   bConnectionOpen;
70
71   HANDLE hEnumSessionThread;
72
73   EnumSessionAsyncCallbackData enumSessionAsyncCallbackData;
74 } DirectPlay2Data;
75
76 typedef struct tagDirectPlay3Data
77 {
78   BOOL bConnectionInitialized;
79 } DirectPlay3Data;
80
81 typedef struct tagDirectPlay4Data
82 {
83   BOOL dummy;
84 } DirectPlay4Data;
85
86 #define DP_IMPL_FIELDS \
87   DirectPlayIUnknownData*  unk; \
88   DirectPlay2Data*         dp2; \
89   DirectPlay3Data*         dp3; \
90   DirectPlay4Data*         dp4;
91
92 struct IDirectPlay2Impl
93 {
94   ICOM_VFIELD(IDirectPlay2); 
95   DP_IMPL_FIELDS
96 };
97
98 struct IDirectPlay3Impl
99 {
100   ICOM_VFIELD(IDirectPlay3);
101   DP_IMPL_FIELDS
102 };
103
104 struct IDirectPlay4Impl
105 {
106   ICOM_VFIELD(IDirectPlay4);
107   DP_IMPL_FIELDS
108 };
109
110 /* Forward declarations of virtual tables */
111 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT;
112 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT;
113 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT;
114
115 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT;
116 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT;
117 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT;
118
119 BOOL DP_CreateIUnknown( LPVOID lpDP )
120 {
121   ICOM_THIS(IDirectPlay2AImpl,lpDP);
122
123   This->unk = (DirectPlayIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
124                                                   sizeof( *(This->unk) ) );
125   if ( This->unk == NULL )
126   {
127     return FALSE;
128   }
129
130   InitializeCriticalSection( &This->unk->DP_lock );
131
132   IDirectPlay_AddRef( (LPDIRECTPLAY2A)lpDP );
133
134   return TRUE;
135 }
136
137 BOOL DP_DestroyIUnknown( LPVOID lpDP )
138 {
139   ICOM_THIS(IDirectPlay2AImpl,lpDP);
140
141   DeleteCriticalSection( &This->unk->DP_lock );
142   HeapFree( GetProcessHeap(), 0, This->unk );
143
144   return TRUE;
145 }
146
147 BOOL DP_CreateDirectPlay2( LPVOID lpDP )
148 {
149   ICOM_THIS(IDirectPlay2AImpl,lpDP);
150
151   This->dp2 = (DirectPlay2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
152                                            sizeof( *(This->dp2) ) );
153   if ( This->dp2 == NULL )
154   {
155     return FALSE;
156   }
157
158   This->dp2->bConnectionOpen = FALSE;
159
160   This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
161
162   This->dp2->enumSessionAsyncCallbackData.cb        = NULL; 
163   This->dp2->enumSessionAsyncCallbackData.lpContext = NULL;
164   This->dp2->enumSessionAsyncCallbackData.dwTimeout = INFINITE;
165
166   return TRUE;
167 }
168
169 BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
170 {
171   ICOM_THIS(IDirectPlay2AImpl,lpDP);
172
173   if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
174   {
175     TerminateThread( This->dp2->hEnumSessionThread, 0 );
176     CloseHandle( This->dp2->hEnumSessionThread );
177   }
178   
179   /* Delete the contents */
180   HeapFree( GetProcessHeap(), 0, This->dp2 );
181
182   return TRUE;
183 }
184
185 BOOL DP_CreateDirectPlay3( LPVOID lpDP )
186 {
187   ICOM_THIS(IDirectPlay3AImpl,lpDP);
188
189   This->dp3 = (DirectPlay3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
190                                            sizeof( *(This->dp3) ) );
191   if ( This->dp3 == NULL )
192   {
193     return FALSE;
194   }
195
196   This->dp3->bConnectionInitialized = FALSE;
197
198   return TRUE;
199 }
200
201 BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
202 {
203   ICOM_THIS(IDirectPlay3AImpl,lpDP);
204
205   /* Delete the contents */
206   HeapFree( GetProcessHeap(), 0, This->dp3 );
207
208   return TRUE;
209 }
210
211 BOOL DP_CreateDirectPlay4( LPVOID lpDP )
212 {
213   ICOM_THIS(IDirectPlay4AImpl,lpDP);
214
215   This->dp4 = (DirectPlay4Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
216                                            sizeof( *(This->dp4) ) );
217   if ( This->dp4 == NULL )
218   {
219     return FALSE;
220   }
221
222   return TRUE;
223 }
224
225 BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
226 {
227   ICOM_THIS(IDirectPlay3AImpl,lpDP);
228
229   /* Delete the contents */
230   HeapFree( GetProcessHeap(), 0, This->dp4 );
231
232   return TRUE;
233 }
234
235
236 /* Get a new interface. To be used by QueryInterface. */ 
237 extern 
238 HRESULT directPlay_QueryInterface 
239          ( REFIID riid, LPVOID* ppvObj )
240 {
241
242   if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
243   {
244     *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
245                          sizeof( IDirectPlay2Impl ) );
246
247     if( *ppvObj == NULL )
248     {
249        return DPERR_OUTOFMEMORY;
250     }
251
252     /* new scope for variable declaration */
253     {
254       ICOM_THIS(IDirectPlay2Impl,*ppvObj);
255
256       ICOM_VTBL(This) = &directPlay2WVT;
257
258       if ( DP_CreateIUnknown( (LPVOID)This ) &&
259            DP_CreateDirectPlay2( (LPVOID)This )
260          )
261       {
262         return S_OK;
263       }
264
265     }
266
267     goto error; 
268   } 
269   else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
270   {
271     *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
272                          sizeof( IDirectPlay2AImpl ) );
273
274     if( *ppvObj == NULL )
275     {
276        return DPERR_OUTOFMEMORY;
277     }
278
279     /* new scope for variable declaration */
280     {
281       ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
282
283       ICOM_VTBL(This) = &directPlay2AVT;
284
285       if ( DP_CreateIUnknown( (LPVOID)This ) &&
286            DP_CreateDirectPlay2( (LPVOID)This )
287          )
288       {
289         return S_OK;
290       }
291
292     }
293
294     goto error;
295   }
296   else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
297   {
298     *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
299                          sizeof( IDirectPlay3Impl ) );
300
301     if( *ppvObj == NULL )
302     {
303        return DPERR_OUTOFMEMORY;
304     }
305
306     /* new scope for variable declaration */
307     {
308       ICOM_THIS(IDirectPlay3Impl,*ppvObj);
309
310       ICOM_VTBL(This) = &directPlay3WVT;
311
312       if ( DP_CreateIUnknown( (LPVOID)This ) &&
313            DP_CreateDirectPlay2( (LPVOID)This ) &&
314            DP_CreateDirectPlay3( (LPVOID)This )
315          )
316       {
317         return S_OK;
318       }
319
320     }
321
322     goto error;
323   }
324   else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
325   {
326     *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
327                          sizeof( IDirectPlay3AImpl ) );
328
329     if( *ppvObj == NULL )
330     {
331        return DPERR_OUTOFMEMORY;
332     }
333
334     /* new scope for variable declaration */
335     {
336       ICOM_THIS(IDirectPlay3AImpl,*ppvObj);
337
338       ICOM_VTBL(This) = &directPlay3AVT;
339
340       if ( DP_CreateIUnknown( (LPVOID)This ) &&
341            DP_CreateDirectPlay2( (LPVOID)This ) &&
342            DP_CreateDirectPlay3( (LPVOID)This )
343          )
344       {
345         return S_OK;
346       }
347
348     }
349
350     goto error;
351   }
352   else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
353   {
354     *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
355                          sizeof( IDirectPlay4Impl ) );
356
357     if( *ppvObj == NULL )
358     {
359        return DPERR_OUTOFMEMORY;
360     }
361
362     /* new scope for variable declaration */
363     {
364       ICOM_THIS(IDirectPlay4Impl,*ppvObj);
365
366       ICOM_VTBL(This) = &directPlay4WVT;
367
368       if ( DP_CreateIUnknown( (LPVOID)This ) &&
369            DP_CreateDirectPlay2( (LPVOID)This ) &&
370            DP_CreateDirectPlay3( (LPVOID)This ) &&
371            DP_CreateDirectPlay4( (LPVOID)This )
372          )
373       {
374         return S_OK;
375       }
376
377     }
378
379     goto error;
380   }
381   else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
382   {
383     *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
384                          sizeof( IDirectPlay4AImpl ) );
385
386     if( *ppvObj == NULL )
387     {
388        return DPERR_OUTOFMEMORY;
389     }
390
391     /* new scope for variable declaration */
392     {
393       ICOM_THIS(IDirectPlay4AImpl,*ppvObj);
394
395       ICOM_VTBL(This) = &directPlay4AVT;
396
397       if ( DP_CreateIUnknown( (LPVOID)This ) &&
398            DP_CreateDirectPlay2( (LPVOID)This ) &&
399            DP_CreateDirectPlay3( (LPVOID)This ) &&
400            DP_CreateDirectPlay4( (LPVOID)This )
401          )
402       {
403         return S_OK;
404       }
405
406     }
407
408     goto error;
409   }
410
411   /* Unsupported interface */
412   *ppvObj = NULL;
413   return E_NOINTERFACE;
414
415 error:
416
417     DP_DestroyDirectPlay4( *ppvObj );
418     DP_DestroyDirectPlay3( *ppvObj );
419     DP_DestroyDirectPlay2( *ppvObj );
420     DP_DestroyIUnknown( *ppvObj );
421     HeapFree( GetProcessHeap(), 0, *ppvObj );
422
423     *ppvObj = NULL;
424     return DPERR_NOMEMORY;
425
426 }
427
428
429 /* Direct Play methods */
430 static HRESULT WINAPI DirectPlay2W_QueryInterface
431          ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
432 {
433   ICOM_THIS(IDirectPlay2Impl,iface);
434   TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
435
436   if( IsEqualGUID( &IID_IUnknown, riid ) ||
437       IsEqualGUID( &IID_IDirectPlay2, riid )
438     )
439   {
440     IDirectPlayX_AddRef( iface );
441     *ppvObj = This;
442     return S_OK;
443   }
444   return directPlay_QueryInterface( riid, ppvObj );
445 }
446
447 static HRESULT WINAPI DirectPlay2A_QueryInterface
448          ( LPDIRECTPLAY2A iface, REFIID riid, LPVOID* ppvObj )
449 {
450   ICOM_THIS(IDirectPlay2Impl,iface);
451   TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
452
453   if( IsEqualGUID( &IID_IUnknown, riid ) ||
454       IsEqualGUID( &IID_IDirectPlay2A, riid )
455     )
456   {
457     IDirectPlayX_AddRef( iface );
458     *ppvObj = This;
459     return S_OK;
460   }
461
462   return directPlay_QueryInterface( riid, ppvObj );
463 }
464
465 static HRESULT WINAPI DirectPlay3WImpl_QueryInterface
466          ( LPDIRECTPLAY3 iface, REFIID riid, LPVOID* ppvObj )
467 {
468   ICOM_THIS(IDirectPlay3Impl,iface);
469   TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
470
471   if( IsEqualGUID( &IID_IUnknown, riid ) ||
472       IsEqualGUID( &IID_IDirectPlay3, riid )
473     )
474   {
475     IDirectPlayX_AddRef( iface );
476     *ppvObj = This;
477     return S_OK;
478   }
479
480   return directPlay_QueryInterface( riid, ppvObj );
481 }
482
483 static HRESULT WINAPI DirectPlay3AImpl_QueryInterface
484          ( LPDIRECTPLAY3A iface, REFIID riid, LPVOID* ppvObj )
485 {
486   ICOM_THIS(IDirectPlay3Impl,iface);
487   TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
488
489   if( IsEqualGUID( &IID_IUnknown, riid ) ||
490       IsEqualGUID( &IID_IDirectPlay3A, riid )
491     )
492   {
493     IDirectPlayX_AddRef( iface );
494     *ppvObj = This;
495     return S_OK;
496   }
497
498   return directPlay_QueryInterface( riid, ppvObj );
499 }
500
501 static HRESULT WINAPI DirectPlay4WImpl_QueryInterface
502          ( LPDIRECTPLAY4 iface, REFIID riid, LPVOID* ppvObj )
503 {
504   ICOM_THIS(IDirectPlay4Impl,iface);
505   TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
506
507   if( IsEqualGUID( &IID_IUnknown, riid ) ||
508       IsEqualGUID( &IID_IDirectPlay4, riid )
509     )
510   {
511     IDirectPlayX_AddRef( iface );
512     *ppvObj = This;
513     return S_OK;
514   }
515
516   return directPlay_QueryInterface( riid, ppvObj );
517 }
518
519
520 static HRESULT WINAPI DirectPlay4AImpl_QueryInterface
521          ( LPDIRECTPLAY4A iface, REFIID riid, LPVOID* ppvObj )
522 {
523   ICOM_THIS(IDirectPlay4Impl,iface);
524   TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
525
526   if( IsEqualGUID( &IID_IUnknown, riid ) ||
527       IsEqualGUID( &IID_IDirectPlay4A, riid )
528     )
529   {
530     IDirectPlayX_AddRef( iface );
531     *ppvObj = This;
532     return S_OK;
533   }
534
535   return directPlay_QueryInterface( riid, ppvObj );
536 }
537
538
539 /* Shared between all dplay types */
540 static ULONG WINAPI DirectPlay2AImpl_AddRef
541          ( LPDIRECTPLAY3 iface )
542 {
543   ULONG refCount;
544   ICOM_THIS(IDirectPlay3Impl,iface);
545
546   EnterCriticalSection( &This->unk->DP_lock ); 
547   {
548     refCount = ++(This->unk->ref);
549   }  
550   LeaveCriticalSection( &This->unk->DP_lock );
551
552   TRACE("ref count incremented to %lu for %p\n", refCount, This );
553
554   return refCount;
555 }
556
557 static ULONG WINAPI DirectPlay2AImpl_Release
558 ( LPDIRECTPLAY3 iface )
559 {
560   ULONG refCount;
561
562   ICOM_THIS(IDirectPlay3Impl,iface);
563
564   EnterCriticalSection( &This->unk->DP_lock );
565   {
566     refCount = --(This->unk->ref);
567   }
568   LeaveCriticalSection( &This->unk->DP_lock );
569
570   TRACE("ref count decremented to %lu for %p\n", refCount, This );
571
572   /* Deallocate if this is the last reference to the object */
573   if( refCount == 0 )
574   {
575      DP_DestroyDirectPlay4( This );
576      DP_DestroyDirectPlay3( This );
577      DP_DestroyDirectPlay2( This );
578      DP_DestroyIUnknown( This );
579      HeapFree( GetProcessHeap(), 0, This );
580   }
581
582   return refCount;
583 }
584
585 static HRESULT WINAPI DirectPlay2AImpl_AddPlayerToGroup
586           ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
587 {
588   ICOM_THIS(IDirectPlay2Impl,iface);
589   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idPlayer );
590   return DP_OK;
591 }
592
593 static HRESULT WINAPI DirectPlay2WImpl_AddPlayerToGroup
594           ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
595 {
596   ICOM_THIS(IDirectPlay2Impl,iface);
597   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idPlayer );
598   return DP_OK;
599 }
600
601
602 static HRESULT WINAPI DirectPlay2AImpl_Close
603           ( LPDIRECTPLAY2A iface )
604 {
605   ICOM_THIS(IDirectPlay2Impl,iface);
606   FIXME("(%p)->(): stub\n", This );
607   return DP_OK;
608 }
609
610 static HRESULT WINAPI DirectPlay2WImpl_Close
611           ( LPDIRECTPLAY2 iface )
612 {
613   ICOM_THIS(IDirectPlay2Impl,iface);
614   FIXME("(%p)->(): stub\n", This );
615   return DP_OK;
616 }
617
618 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
619           ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
620 {
621   ICOM_THIS(IDirectPlay2Impl,iface);
622   FIXME("(%p)->(%p,%p,%p,0x%08lx,0x%08lx): stub\n", This, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags );
623   return DP_OK;
624 }
625
626 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
627           ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
628 {
629   ICOM_THIS(IDirectPlay2Impl,iface);
630   FIXME("(%p)->(%p,%p,%p,0x%08lx,0x%08lx): stub\n", This, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags );
631   return DP_OK;
632 }
633
634 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
635           ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
636 {
637   ICOM_THIS(IDirectPlay2Impl,iface);
638
639   FIXME("(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx): stub\n", This, lpidPlayer, lpPlayerName, hEvent, lpData, dwDataSize, dwFlags );
640
641   /* FIXME: Should send DPMSG_CREATEPLAYERORGROUP message to everyone, local and remote, that
642             belongs to this session */
643
644   return DP_OK;
645 }
646
647 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
648           ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
649 {
650   ICOM_THIS(IDirectPlay2Impl,iface);
651   FIXME("(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx): stub\n", This, lpidPlayer, lpPlayerName, hEvent, lpData, dwDataSize, dwFlags );
652   return DP_OK;
653 }
654
655 static HRESULT WINAPI DirectPlay2AImpl_DeletePlayerFromGroup
656           ( LPDIRECTPLAY2A iface, DPID idGroup, DPID idPlayer )
657 {
658   ICOM_THIS(IDirectPlay2Impl,iface);
659   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idPlayer );
660   return DP_OK;
661 }
662
663 static HRESULT WINAPI DirectPlay2WImpl_DeletePlayerFromGroup
664           ( LPDIRECTPLAY2 iface, DPID idGroup, DPID idPlayer )
665 {
666   ICOM_THIS(IDirectPlay2Impl,iface);
667   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idPlayer );
668   return DP_OK;
669 }
670
671 static HRESULT WINAPI DirectPlay2AImpl_DestroyGroup
672           ( LPDIRECTPLAY2A iface, DPID idGroup )
673 {
674   ICOM_THIS(IDirectPlay2Impl,iface);
675   FIXME("(%p)->(0x%08lx): stub\n", This, idGroup );
676   return DP_OK;
677 }
678
679 static HRESULT WINAPI DirectPlay2WImpl_DestroyGroup
680           ( LPDIRECTPLAY2 iface, DPID idGroup )
681 {
682   ICOM_THIS(IDirectPlay2Impl,iface);
683   FIXME("(%p)->(0x%08lx): stub\n", This, idGroup );
684   return DP_OK;
685 }
686
687 static HRESULT WINAPI DirectPlay2AImpl_DestroyPlayer
688           ( LPDIRECTPLAY2A iface, DPID idPlayer )
689 {
690   ICOM_THIS(IDirectPlay2Impl,iface);
691   FIXME("(%p)->(0x%08lx): stub\n", This, idPlayer );
692   return DP_OK;
693 }
694
695 static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
696           ( LPDIRECTPLAY2 iface, DPID idPlayer )
697 {
698   ICOM_THIS(IDirectPlay2Impl,iface);
699   FIXME("(%p)->(0x%08lx): stub\n", This, idPlayer );
700   return DP_OK;
701 }
702
703 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
704           ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
705             LPVOID lpContext, DWORD dwFlags )
706 {
707   ICOM_THIS(IDirectPlay2Impl,iface);
708   FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx): stub\n", This, idGroup, lpguidInstance, lpEnumPlayersCallback2, lpContext, dwFlags );
709   return DP_OK;
710 }
711
712 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
713           ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
714             LPVOID lpContext, DWORD dwFlags )
715 {
716   ICOM_THIS(IDirectPlay2Impl,iface);
717   FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx): stub\n", This, idGroup, lpguidInstance, lpEnumPlayersCallback2, lpContext, dwFlags );
718   return DP_OK;
719 }
720
721 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
722           ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, DWORD dwFlags )
723 {
724   ICOM_THIS(IDirectPlay2Impl,iface);
725   FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidInstance, lpEnumPlayersCallback2, lpContext, dwFlags );
726   return DP_OK;
727 }
728
729 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
730           ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, DWORD dwFlags )
731 {
732   ICOM_THIS(IDirectPlay2Impl,iface);
733   FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidInstance, lpEnumPlayersCallback2, lpContext, dwFlags );
734   return DP_OK;
735 }
736
737 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
738           ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, DWORD dwFlags )
739 {
740   ICOM_THIS(IDirectPlay2Impl,iface);
741   FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidInstance, lpEnumPlayersCallback2, lpContext, dwFlags );
742   return DP_OK;
743 }
744
745 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
746           ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, DWORD dwFlags )
747 {
748   ICOM_THIS(IDirectPlay2Impl,iface);
749   FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidInstance, lpEnumPlayersCallback2, lpContext, dwFlags );
750   return DP_OK;
751 }
752
753 void DP_SendSessionRequestBroadcast()
754 {
755   FIXME( ": stub\n" );
756
757
758 void DP_InvokeEnumSessionCallbacksA( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
759                                      LPVOID lpContext )
760 {
761   FIXME( ": stub\n" );
762 }
763
764 static DWORD CALLBACK DP_EnumSessionsSpwanThreadA( LPVOID lpContext )
765 {
766   ICOM_THIS(IDirectPlay2Impl,lpContext);
767   DWORD dwTimeout = This->dp2->enumSessionAsyncCallbackData.dwTimeout;
768
769   TRACE( "->(%p)->(0x%08lx)\n", This, dwTimeout );
770
771   /* FIXME: Don't think this is exactly right. It'll do for now */
772   for( ;; )
773   {
774     /* 2: Send the broadcast for session enumeration */
775     DP_SendSessionRequestBroadcast( NULL, 0 ); /* Should pass lpsd */
776
777     SleepEx( dwTimeout, FALSE ); 
778
779     DP_InvokeEnumSessionCallbacksA( This->dp2->enumSessionAsyncCallbackData.cb,
780                                     This->dp2->enumSessionAsyncCallbackData.lpContext );
781   }
782
783   return 0;
784 }
785
786 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
787           ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
788             LPVOID lpContext, DWORD dwFlags )
789 {
790   ICOM_THIS(IDirectPlay2Impl,iface);
791
792   TRACE("(%p)->(%p,0x%08lx,%p,%p,0x%08lx)\n", This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags );
793
794   if( dwTimeout == 0 )
795   {
796     FIXME( ": should provide a dependent dwTimeout\n" );
797     dwTimeout = 5 * 1000; /* 5 seconds */
798   }
799
800   if( dwFlags & DPENUMSESSIONS_STOPASYNC )
801   {
802     /* Does a thread exist? If so we were doing an async enum session */
803     if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
804     {
805       /* FIXME: This needs to be send an event to the thread to clean itself up */
806       TerminateThread( This->dp2->hEnumSessionThread, 0 );
807       CloseHandle( This->dp2->hEnumSessionThread );
808
809       This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
810
811       This->dp2->enumSessionAsyncCallbackData.cb        = NULL;
812       This->dp2->enumSessionAsyncCallbackData.lpContext = NULL;
813       This->dp2->enumSessionAsyncCallbackData.dwTimeout = INFINITE;
814
815       return DP_OK;
816     }
817   
818     /* Indicate some sort of error... */
819     WARN( "STOPASYNC attempted when no async running\n" );  
820     return DP_OK;
821   }
822
823   /* FIXME: Interface locking sucks in this method */
824
825   if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
826   {
827     DWORD dwThreadId;
828  
829     /* See if we've already created a thread to service this interface */
830     if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
831     {
832
833       This->dp2->enumSessionAsyncCallbackData.cb        = lpEnumSessionsCallback2;
834       This->dp2->enumSessionAsyncCallbackData.lpContext = lpContext;
835       This->dp2->enumSessionAsyncCallbackData.dwTimeout = dwTimeout;
836
837       TRACE( ": creating EnumSessions thread\n" );
838     
839       This->dp2->hEnumSessionThread = CreateThread( NULL,
840                                                     0,
841                                                     DP_EnumSessionsSpwanThreadA,
842                                                     This,
843                                                     0,
844                                                     &dwThreadId );
845     }
846
847     DP_InvokeEnumSessionCallbacksA( lpEnumSessionsCallback2, lpContext );
848   }
849   else
850   {
851     /* Send the broadcast for session enumeration */
852     /* FIXME: How to handle the replies? Queue? */
853     DP_SendSessionRequestBroadcast( lpsd, dwFlags );
854
855     SleepEx( dwTimeout, FALSE ); 
856  
857     DP_InvokeEnumSessionCallbacksA( lpEnumSessionsCallback2, lpContext );
858   }
859
860   return DP_OK;
861 }
862
863 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
864           ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
865             LPVOID lpContext, DWORD dwFlags )
866 {
867   ICOM_THIS(IDirectPlay2Impl,iface);
868   FIXME("(%p)->(%p,0x%08lx,%p,%p,0x%08lx): stub\n", This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags );
869   return DP_OK;
870 }
871
872 static HRESULT WINAPI DirectPlay2AImpl_GetCaps
873           ( LPDIRECTPLAY2A iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
874 {
875   ICOM_THIS(IDirectPlay2Impl,iface);
876   FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpDPCaps, dwFlags );
877   return DP_OK;
878 }
879
880 static HRESULT WINAPI DirectPlay2WImpl_GetCaps
881           ( LPDIRECTPLAY2 iface, LPDPCAPS lpDPCaps, DWORD dwFlags )
882 {
883   ICOM_THIS(IDirectPlay2Impl,iface);
884   FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpDPCaps, dwFlags );
885   return DP_OK;
886 }
887
888 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
889           ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize, DWORD dwFlags )
890 {
891   ICOM_THIS(IDirectPlay2Impl,iface);
892   FIXME("(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n", This, idGroup, lpData, lpdwDataSize, dwFlags );
893   return DP_OK;
894 }
895
896 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
897           ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize, DWORD dwFlags )
898 {
899   ICOM_THIS(IDirectPlay2Impl,iface);
900   FIXME("(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n", This, idGroup, lpData, lpdwDataSize, dwFlags );
901   return DP_OK;
902 }
903
904 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
905           ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
906 {
907   ICOM_THIS(IDirectPlay2Impl,iface);
908   FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idGroup, lpData, lpdwDataSize );
909   return DP_OK;
910 }
911
912 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
913           ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
914 {
915   ICOM_THIS(IDirectPlay2Impl,iface);
916   FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idGroup, lpData, lpdwDataSize );
917   return DP_OK;
918 }
919
920 static HRESULT WINAPI DirectPlay2AImpl_GetMessageCount
921           ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDWORD lpdwCount )
922 {
923   ICOM_THIS(IDirectPlay2Impl,iface);
924   FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwCount );
925   return DP_OK;
926 }
927
928 static HRESULT WINAPI DirectPlay2WImpl_GetMessageCount
929           ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDWORD lpdwCount )
930 {
931   ICOM_THIS(IDirectPlay2Impl,iface);
932   FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwCount );
933   return DP_OK;
934 }
935
936 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerAddress
937           ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
938 {
939   ICOM_THIS(IDirectPlay2Impl,iface);
940   FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
941   return DP_OK;
942 }
943
944 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
945           ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
946 {
947   ICOM_THIS(IDirectPlay2Impl,iface);
948   FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
949   return DP_OK;
950 }
951
952 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
953           ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps, DWORD dwFlags )
954 {
955   ICOM_THIS(IDirectPlay2Impl,iface);
956   FIXME("(%p)->(0x%08lx,%p,0x%08lx): stub\n", This, idPlayer, lpPlayerCaps, dwFlags );
957   return DP_OK;
958 }
959
960 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
961           ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps, DWORD dwFlags )
962 {
963   ICOM_THIS(IDirectPlay2Impl,iface);
964   FIXME("(%p)->(0x%08lx,%p,0x%08lx): stub\n", This, idPlayer, lpPlayerCaps, dwFlags );
965   return DP_OK;
966 }
967
968 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
969           ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize, DWORD dwFlags )
970 {
971   ICOM_THIS(IDirectPlay2Impl,iface);
972   FIXME("(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n", This, idPlayer, lpData, lpdwDataSize, dwFlags );
973   return DP_OK;
974 }
975
976 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
977           ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize, DWORD dwFlags )
978 {
979   ICOM_THIS(IDirectPlay2Impl,iface);
980   FIXME("(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n", This, idPlayer, lpData, lpdwDataSize, dwFlags );
981   return DP_OK;
982 }
983
984 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
985           ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
986 {
987   ICOM_THIS(IDirectPlay2Impl,iface);
988   FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
989   return DP_OK;
990 }
991
992 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
993           ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, LPDWORD lpdwDataSize )
994 {
995   ICOM_THIS(IDirectPlay2Impl,iface);
996   FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, idPlayer, lpData, lpdwDataSize );
997   return DP_OK;
998 }
999
1000 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
1001           ( LPDIRECTPLAY2A iface, LPVOID lpData, LPDWORD lpdwDataSize )
1002 {
1003   ICOM_THIS(IDirectPlay2Impl,iface);
1004   FIXME("(%p)->(%p,%p): stub\n", This, lpData, lpdwDataSize );
1005   return DP_OK;
1006 }
1007
1008 static HRESULT WINAPI DirectPlay2WImpl_GetSessionDesc
1009           ( LPDIRECTPLAY2 iface, LPVOID lpData, LPDWORD lpdwDataSize )
1010 {
1011   ICOM_THIS(IDirectPlay2Impl,iface);
1012   FIXME("(%p)->(%p,%p): stub\n", This, lpData, lpdwDataSize );
1013   return DP_OK;
1014 }
1015
1016 /* Intended only for COM compatibility. Always returns an error. */
1017 static HRESULT WINAPI DirectPlay2AImpl_Initialize
1018           ( LPDIRECTPLAY2A iface, LPGUID lpGUID )
1019 {
1020   ICOM_THIS(IDirectPlay2Impl,iface);
1021   TRACE("(%p)->(%p): stub\n", This, lpGUID );
1022   return DPERR_ALREADYINITIALIZED;
1023 }
1024
1025 /* Intended only for COM compatibility. Always returns an error. */
1026 static HRESULT WINAPI DirectPlay2WImpl_Initialize
1027           ( LPDIRECTPLAY2 iface, LPGUID lpGUID )
1028 {
1029   ICOM_THIS(IDirectPlay2Impl,iface);
1030   TRACE("(%p)->(%p): stub\n", This, lpGUID );
1031   return DPERR_ALREADYINITIALIZED;
1032 }
1033
1034
1035 static HRESULT WINAPI DirectPlay2AImpl_Open
1036           ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
1037 {
1038   ICOM_THIS(IDirectPlay2Impl,iface);
1039
1040   FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpsd, dwFlags );
1041
1042   if( This->dp2->bConnectionOpen )
1043   {
1044     TRACE( ": rejecting already open connection.\n" );
1045     return DPERR_ALREADYINITIALIZED;
1046   }
1047
1048   /* When we open we need to stop any EnumSession activity */
1049   IDirectPlayX_EnumSessions( iface, NULL, 0, NULL, NULL, DPENUMSESSIONS_STOPASYNC ); 
1050
1051   if( dwFlags & DPOPEN_CREATE )
1052   {
1053     dwFlags &= ~DPOPEN_CREATE;
1054
1055     /* Rightoo - this computer is the host and the local computer needs to be
1056        the name server so that others can join this session */
1057     DPLAYX_NS_SetLocalComputerAsNameServer( lpsd );
1058
1059   }
1060
1061   if( dwFlags )
1062   {
1063     ERR( ": ignored dwFlags 0x%08lx\n", dwFlags );
1064   }
1065
1066   return DP_OK;
1067 }
1068
1069 static HRESULT WINAPI DirectPlay2WImpl_Open
1070           ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwFlags )
1071 {
1072   ICOM_THIS(IDirectPlay2Impl,iface);
1073   FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpsd, dwFlags );
1074   return DP_OK;
1075 }
1076
1077 static HRESULT WINAPI DirectPlay2AImpl_Receive
1078           ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
1079 {
1080   ICOM_THIS(IDirectPlay2Impl,iface);
1081   FIXME("(%p)->(%p,%p,0x%08lx,%p,%p): stub\n", This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize );
1082   return DP_OK;
1083 }
1084
1085 static HRESULT WINAPI DirectPlay2WImpl_Receive
1086           ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
1087 {
1088   ICOM_THIS(IDirectPlay2Impl,iface);
1089   FIXME("(%p)->(%p,%p,0x%08lx,%p,%p): stub\n", This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize );
1090   return DP_OK;
1091 }
1092
1093 static HRESULT WINAPI DirectPlay2AImpl_Send
1094           ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
1095 {
1096   ICOM_THIS(IDirectPlay2Impl,iface);
1097   FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx): stub\n", This, idFrom, idTo, dwFlags, lpData, dwDataSize );
1098   return DP_OK;
1099 }
1100
1101 static HRESULT WINAPI DirectPlay2WImpl_Send
1102           ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
1103 {
1104   ICOM_THIS(IDirectPlay2Impl,iface);
1105   FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx): stub\n", This, idFrom, idTo, dwFlags, lpData, dwDataSize );
1106   return DP_OK;
1107 }
1108
1109 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
1110           ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1111 {
1112   ICOM_THIS(IDirectPlay2Impl,iface);
1113   FIXME("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n", This, idGroup, lpData, dwDataSize, dwFlags );
1114   return DP_OK;
1115 }
1116
1117 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
1118           ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1119 {   
1120   ICOM_THIS(IDirectPlay2Impl,iface);
1121   FIXME("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n", This, idGroup, lpData, dwDataSize, dwFlags );
1122   return DP_OK;
1123 }
1124
1125 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
1126           ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName, DWORD dwFlags )
1127 {
1128   ICOM_THIS(IDirectPlay2Impl,iface);
1129   FIXME("(%p)->(0x%08lx,%p,0x%08lx): stub\n", This, idGroup, lpGroupName, dwFlags );
1130   return DP_OK;
1131 }
1132
1133 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
1134           ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName, DWORD dwFlags )
1135 {
1136   ICOM_THIS(IDirectPlay2Impl,iface);
1137   FIXME("(%p)->(0x%08lx,%p,0x%08lx): stub\n", This, idGroup, lpGroupName, dwFlags );
1138   return DP_OK;
1139 }
1140
1141 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
1142           ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1143 {
1144   ICOM_THIS(IDirectPlay2Impl,iface);
1145   FIXME("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n", This, idPlayer, lpData, dwDataSize, dwFlags );
1146   return DP_OK;
1147 }
1148
1149 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
1150           ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1151 {
1152   ICOM_THIS(IDirectPlay2Impl,iface);
1153   FIXME("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n", This, idPlayer, lpData, dwDataSize, dwFlags );
1154   return DP_OK;
1155 }
1156
1157 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
1158           ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName, DWORD dwFlags )
1159 {
1160   ICOM_THIS(IDirectPlay2Impl,iface);
1161   FIXME("(%p)->(0x%08lx,%p,0x%08lx): stub\n", This, idPlayer, lpPlayerName, dwFlags );
1162   return DP_OK;
1163 }
1164
1165 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
1166           ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName, DWORD dwFlags )
1167 {
1168   ICOM_THIS(IDirectPlay2Impl,iface);
1169   FIXME("(%p)->(0x%08lx,%p,0x%08lx): stub\n", This, idPlayer, lpPlayerName, dwFlags );
1170   return DP_OK;
1171 }
1172
1173 static HRESULT WINAPI DirectPlay2AImpl_SetSessionDesc
1174           ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
1175 {
1176   ICOM_THIS(IDirectPlay2Impl,iface);
1177   FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpSessDesc, dwFlags );
1178   return DP_OK;
1179 }
1180
1181 static HRESULT WINAPI DirectPlay2WImpl_SetSessionDesc
1182           ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpSessDesc, DWORD dwFlags )
1183 {
1184   ICOM_THIS(IDirectPlay2Impl,iface);
1185   FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpSessDesc, dwFlags );
1186   return DP_OK;
1187 }
1188
1189 static HRESULT WINAPI DirectPlay3AImpl_AddGroupToGroup
1190           ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
1191 {
1192   ICOM_THIS(IDirectPlay3Impl,iface);
1193   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idParentGroup, idGroup );
1194   return DP_OK;
1195 }
1196
1197 static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
1198           ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
1199 {
1200   ICOM_THIS(IDirectPlay3Impl,iface);
1201   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idParentGroup, idGroup );
1202   return DP_OK;
1203 }
1204
1205 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
1206           ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1207 {
1208   ICOM_THIS(IDirectPlay3Impl,iface);
1209   FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx): stub\n", This, idParentGroup, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags );
1210   return DP_OK;
1211 }
1212
1213 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
1214           ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
1215 {
1216   ICOM_THIS(IDirectPlay3Impl,iface);
1217   FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx): stub\n", This, idParentGroup, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags );
1218   return DP_OK;
1219 }
1220
1221 static HRESULT WINAPI DirectPlay3AImpl_DeleteGroupFromGroup
1222           ( LPDIRECTPLAY3A iface, DPID idParentGroup, DPID idGroup )
1223 {
1224   ICOM_THIS(IDirectPlay3Impl,iface);
1225   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idParentGroup, idGroup );
1226   return DP_OK;
1227 }
1228
1229 static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
1230           ( LPDIRECTPLAY3 iface, DPID idParentGroup, DPID idGroup )
1231 {
1232   ICOM_THIS(IDirectPlay3Impl,iface);
1233   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idParentGroup, idGroup );
1234   return DP_OK;
1235 }
1236
1237 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
1238           ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
1239 {
1240   ICOM_THIS(IDirectPlay3Impl,iface);
1241   TRACE("(%p)->(%p,%p,%p,0x%08lx)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
1242
1243   /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
1244   if( dwFlags == 0 )
1245   {
1246     dwFlags = DPCONNECTION_DIRECTPLAY;
1247   }
1248
1249   if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
1250           ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
1251     ) 
1252   {
1253     return DPERR_INVALIDFLAGS;
1254   }
1255
1256   if( !lpEnumCallback || !*lpEnumCallback )
1257   {
1258      return DPERR_INVALIDPARAMS;
1259   }
1260
1261   /* Enumerate DirectPlay service providers */
1262   if( dwFlags & DPCONNECTION_DIRECTPLAY )
1263   {
1264     HKEY hkResult;
1265     LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
1266     LPSTR guidDataSubKey   = "Guid";
1267     char subKeyName[51]; 
1268     DWORD dwIndex, sizeOfSubKeyName=50;
1269     FILETIME filetime;
1270
1271     /* Need to loop over the service providers in the registry */
1272     if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
1273                          0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
1274     {
1275       /* Hmmm. Does this mean that there are no service providers? */
1276       ERR(": no service providers?\n");
1277       return DP_OK;
1278     }
1279
1280
1281     /* Traverse all the service providers we have available */
1282     for( dwIndex=0;
1283          RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 
1284                         NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
1285          ++dwIndex, sizeOfSubKeyName=51 )
1286     {
1287
1288       HKEY     hkServiceProvider;
1289       GUID     serviceProviderGUID;
1290       DWORD    returnTypeGUID, sizeOfReturnBuffer = 50;
1291       char     returnBuffer[51];
1292       LPWSTR   lpWGUIDString;
1293       DPNAME   dpName;
1294       HRESULT  hr;
1295
1296       DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
1297       LPVOID                   lpAddressBuffer = NULL;
1298       DWORD                    dwAddressBufferSize = 0;
1299
1300       TRACE(" this time through: %s\n", subKeyName );
1301
1302       /* Get a handle for this particular service provider */
1303       if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
1304                          &hkServiceProvider ) != ERROR_SUCCESS )
1305       {
1306          ERR(": what the heck is going on?\n" );
1307          continue;
1308       }
1309
1310       if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
1311                             NULL, &returnTypeGUID, returnBuffer,
1312                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1313       {
1314         ERR(": missing GUID registry data members\n" );
1315         continue;
1316       }
1317
1318       /* FIXME: Check return types to ensure we're interpreting data right */
1319       lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
1320       CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
1321       HeapFree( GetProcessHeap(), 0, lpWGUIDString );
1322       /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
1323
1324       /* Fill in the DPNAME struct for the service provider */
1325       dpName.dwSize             = sizeof( dpName );
1326       dpName.dwFlags            = 0;
1327       dpName.psn.lpszShortNameA = subKeyName;
1328       dpName.pln.lpszLongNameA  = NULL;
1329
1330       /* Create the compound address for the service provider. 
1331          NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
1332                nast stuff. This may be why the native dll just gets around this little bit by
1333                allocating an 80 byte buffer which isn't even a filled with a valid compound 
1334                address. Oh well. Creating a proper compound address is the way to go anyways 
1335                despite this method taking slightly more heap space and realtime :) */
1336       dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
1337       dpCompoundAddress.dwDataSize   = sizeof( GUID );
1338       dpCompoundAddress.lpData       = &serviceProviderGUID; 
1339
1340       if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer, 
1341                                      &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
1342       {
1343         ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
1344         return hr;
1345       }
1346
1347       /* Now allocate the buffer */
1348       lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
1349
1350       if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
1351                                      &dwAddressBufferSize, TRUE ) ) != DP_OK )
1352       {
1353         ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
1354         return hr;
1355       }
1356
1357       /* The enumeration will return FALSE if we are not to continue */
1358       if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize, 
1359                            &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
1360       {
1361          WARN("lpEnumCallback returning FALSE\n" );
1362
1363          return DP_OK;
1364       }
1365     }
1366   }
1367
1368   /* Enumerate DirectPlayLobby service providers */
1369   if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
1370   {
1371     FIXME( "DPCONNECTION_DIRECTPLAYLOBBY flag not handled\n" );
1372   }
1373
1374   return DP_OK;
1375 }
1376
1377 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
1378           ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
1379
1380   ICOM_THIS(IDirectPlay3Impl,iface);
1381   FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
1382   return DP_OK;
1383 }
1384
1385 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
1386           ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
1387 {
1388   ICOM_THIS(IDirectPlay3Impl,iface);
1389   FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx): stub\n", This, idGroup, lpguidInstance, lpEnumCallback, lpContext, dwFlags );
1390   return DP_OK;
1391 }
1392
1393 static HRESULT WINAPI DirectPlay3WImpl_EnumGroupsInGroup
1394           ( LPDIRECTPLAY3 iface, DPID idGroup, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
1395 {
1396   ICOM_THIS(IDirectPlay3Impl,iface);
1397   FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx): stub\n", This, idGroup, lpguidInstance, lpEnumCallback, lpContext, dwFlags );
1398   return DP_OK;
1399 }
1400
1401 static HRESULT WINAPI DirectPlay3AImpl_GetGroupConnectionSettings
1402           ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
1403 {
1404   ICOM_THIS(IDirectPlay3Impl,iface);
1405   FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
1406   return DP_OK;
1407 }
1408
1409 static HRESULT WINAPI DirectPlay3WImpl_GetGroupConnectionSettings
1410           ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPVOID lpData, LPDWORD lpdwDataSize )
1411 {
1412   ICOM_THIS(IDirectPlay3Impl,iface);
1413   FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, dwFlags, idGroup, lpData, lpdwDataSize );
1414   return DP_OK;
1415 }
1416
1417 static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
1418           ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
1419 {
1420   HMODULE hServiceProvider;
1421   typedef DWORD (WINAPI *SP_SPInit)(LPVOID lpCompoundAddress, ...); /* FIXME: How many arguments? */
1422   SP_SPInit SPInit;
1423
1424   ICOM_THIS(IDirectPlay3Impl,iface);
1425
1426   FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpConnection, dwFlags );
1427
1428   if( dwFlags != 0 )
1429   {
1430     return DPERR_INVALIDFLAGS;
1431   }
1432
1433   if( This->dp3->bConnectionInitialized == TRUE )
1434   {
1435     return DPERR_ALREADYINITIALIZED;
1436   }
1437
1438   /* Parse lpConnection as a compound address for the service provider */
1439   /* Take service provider GUID and find the path to it */
1440
1441   /* FIXME: Hard coded to only load the tcp/ip service provider for now... */
1442   hServiceProvider = LoadLibraryA( "dpwsockx.dll" );
1443
1444   if( hServiceProvider == 0 )
1445   {
1446     ERR( "Unable to load service provider\n" );
1447     return DPERR_UNAVAILABLE; 
1448   }
1449   
1450   /* Initialize the service provider by calling SPInit */
1451   SPInit = (SP_SPInit)GetProcAddress( hServiceProvider, "SPInit" );
1452
1453   if( SPInit == NULL )
1454   {
1455     ERR( "Service provider doesn't provide SPInit interface?\n" );
1456   }  
1457
1458 #if 0
1459   /* NOTE: This will crash until I know what parameters/interface this has */
1460   /* FIXME: Take a guess that we just pass the compound address to the SP */
1461   /* Hmmm...how to say which parameters need to be gotten from the SP. They must
1462      come from the compound address, but how do we communicate what's required? */
1463   dwReturnValue = (*SPInit)( lpConnection );
1464 #endif
1465
1466   /* This interface is now initialized */
1467   This->dp3->bConnectionInitialized = TRUE;
1468
1469   return DP_OK;
1470 }
1471
1472 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
1473           ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
1474 {
1475   ICOM_THIS(IDirectPlay3Impl,iface);
1476   FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpConnection, dwFlags );
1477   return DP_OK;
1478 }
1479
1480 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
1481           ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags, LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
1482 {
1483   ICOM_THIS(IDirectPlay3Impl,iface);
1484
1485   FIXME("(%p)->(%p,0x%08lx,%p,%p): stub\n", This, lpsd, dwFlags, lpSecurity, lpCredentials );
1486
1487   IDirectPlayX_EnumSessions( iface, NULL, 0, NULL, NULL, DPENUMSESSIONS_STOPASYNC );
1488
1489   return DP_OK;
1490 }
1491
1492 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
1493           ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags, LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
1494 {   
1495   ICOM_THIS(IDirectPlay3Impl,iface);
1496   FIXME("(%p)->(%p,0x%08lx,%p,%p): stub\n", This, lpsd, dwFlags, lpSecurity, lpCredentials );
1497   return DP_OK;
1498 }
1499
1500 static HRESULT WINAPI DirectPlay3AImpl_SendChatMessage
1501           ( LPDIRECTPLAY3A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
1502 {
1503   ICOM_THIS(IDirectPlay3Impl,iface);
1504   FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
1505   return DP_OK;
1506 }
1507
1508 static HRESULT WINAPI DirectPlay3WImpl_SendChatMessage
1509           ( LPDIRECTPLAY3 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDPCHAT lpChatMessage )
1510 {
1511   ICOM_THIS(IDirectPlay3Impl,iface);
1512   FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p): stub\n", This, idFrom, idTo, dwFlags, lpChatMessage );
1513   return DP_OK;
1514 }
1515
1516 static HRESULT WINAPI DirectPlay3AImpl_SetGroupConnectionSettings
1517           ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
1518 {
1519   ICOM_THIS(IDirectPlay3Impl,iface);
1520   FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
1521   return DP_OK;
1522 }
1523
1524 static HRESULT WINAPI DirectPlay3WImpl_SetGroupConnectionSettings
1525           ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup, LPDPLCONNECTION lpConnection )
1526 {
1527   ICOM_THIS(IDirectPlay3Impl,iface);
1528   FIXME("(%p)->(0x%08lx,0x%08lx,%p): stub\n", This, dwFlags, idGroup, lpConnection );
1529   return DP_OK;
1530 }
1531
1532 static HRESULT WINAPI DirectPlay3AImpl_StartSession
1533           ( LPDIRECTPLAY3A iface, DWORD dwFlags, DPID idGroup )
1534 {
1535   ICOM_THIS(IDirectPlay3Impl,iface);
1536   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
1537   return DP_OK;
1538 }
1539
1540 static HRESULT WINAPI DirectPlay3WImpl_StartSession
1541           ( LPDIRECTPLAY3 iface, DWORD dwFlags, DPID idGroup )
1542 {
1543   ICOM_THIS(IDirectPlay3Impl,iface);
1544   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
1545   return DP_OK;
1546 }
1547  
1548 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
1549           ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
1550 {
1551   ICOM_THIS(IDirectPlay3Impl,iface);
1552   FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
1553   return DP_OK;
1554 }
1555
1556 static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
1557           ( LPDIRECTPLAY3 iface, DPID idGroup, LPDWORD lpdwFlags )
1558 {
1559   ICOM_THIS(IDirectPlay3Impl,iface);
1560   FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpdwFlags );
1561   return DP_OK;
1562 }
1563
1564 static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
1565           ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
1566 {
1567   ICOM_THIS(IDirectPlay3Impl,iface);
1568   FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroup );
1569   return DP_OK;
1570 }
1571
1572 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
1573           ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
1574 {
1575   ICOM_THIS(IDirectPlay3Impl,iface);
1576   FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroup );
1577   return DP_OK;
1578 }
1579
1580 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
1581           ( LPDIRECTPLAY3A iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
1582 {
1583   ICOM_THIS(IDirectPlay3Impl,iface);
1584   FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
1585   return DP_OK;
1586 }
1587
1588 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerAccount
1589           ( LPDIRECTPLAY3 iface, DPID idPlayer, DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
1590 {
1591   ICOM_THIS(IDirectPlay3Impl,iface);
1592   FIXME("(%p)->(0x%08lx,0x%08lx,%p,%p): stub\n", This, idPlayer, dwFlags, lpData, lpdwDataSize );
1593   return DP_OK;
1594 }
1595
1596 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerFlags
1597           ( LPDIRECTPLAY3A iface, DPID idPlayer, LPDWORD lpdwFlags )
1598 {
1599   ICOM_THIS(IDirectPlay3Impl,iface);
1600   FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
1601   return DP_OK;
1602 }
1603
1604 static HRESULT WINAPI DirectPlay3WImpl_GetPlayerFlags
1605           ( LPDIRECTPLAY3 iface, DPID idPlayer, LPDWORD lpdwFlags )
1606 {
1607   ICOM_THIS(IDirectPlay3Impl,iface);
1608   FIXME("(%p)->(0x%08lx,%p): stub\n", This, idPlayer, lpdwFlags );
1609   return DP_OK;
1610 }
1611
1612 static HRESULT WINAPI DirectPlay4AImpl_GetGroupOwner
1613           ( LPDIRECTPLAY4A iface, DPID idGroup, LPDPID lpidGroupOwner )
1614 {
1615   ICOM_THIS(IDirectPlay4Impl,iface);
1616   FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
1617   return DP_OK;
1618 }
1619
1620 static HRESULT WINAPI DirectPlay4WImpl_GetGroupOwner
1621           ( LPDIRECTPLAY4 iface, DPID idGroup, LPDPID lpidGroupOwner )
1622 {
1623   ICOM_THIS(IDirectPlay4Impl,iface);
1624   FIXME("(%p)->(0x%08lx,%p): stub\n", This, idGroup, lpidGroupOwner );
1625   return DP_OK;
1626 }
1627
1628 static HRESULT WINAPI DirectPlay4AImpl_SetGroupOwner
1629           ( LPDIRECTPLAY4A iface, DPID idGroup , DPID idGroupOwner )
1630 {
1631   ICOM_THIS(IDirectPlay4Impl,iface);
1632   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
1633   return DP_OK;
1634 }
1635
1636 static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
1637           ( LPDIRECTPLAY4 iface, DPID idGroup , DPID idGroupOwner )
1638 {
1639   ICOM_THIS(IDirectPlay4Impl,iface);
1640   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, idGroup, idGroupOwner );
1641   return DP_OK;
1642 }
1643
1644 static HRESULT WINAPI DirectPlay4AImpl_SendEx
1645           ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout, LPVOID lpContext, LPDWORD lpdwMsgID )
1646 {
1647   ICOM_THIS(IDirectPlay4Impl,iface);
1648   FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p): stub\n", This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority, dwTimeout, lpContext, lpdwMsgID );
1649   return DP_OK;
1650 }
1651
1652 static HRESULT WINAPI DirectPlay4WImpl_SendEx
1653           ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout, LPVOID lpContext, LPDWORD lpdwMsgID )
1654 {
1655   ICOM_THIS(IDirectPlay4Impl,iface);
1656   FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,0x%08lx,0x%08lx,0x%08lx,%p,%p): stub\n", This, idFrom, idTo, dwFlags, lpData, dwDataSize, dwPriority, dwTimeout, lpContext, lpdwMsgID );
1657   return DP_OK;
1658 }
1659
1660 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
1661           ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
1662 {
1663   ICOM_THIS(IDirectPlay4Impl,iface);
1664   FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p): stub\n", This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes );
1665   return DP_OK;
1666 }
1667
1668 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
1669           ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
1670 {
1671   ICOM_THIS(IDirectPlay4Impl,iface);
1672   FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p): stub\n", This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes );
1673   return DP_OK;
1674 }
1675
1676 static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
1677           ( LPDIRECTPLAY4A iface, DWORD dwMsgID, DWORD dwFlags )
1678 {
1679   ICOM_THIS(IDirectPlay4Impl,iface);
1680   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwMsgID, dwFlags );
1681   return DP_OK;
1682 }
1683
1684 static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
1685           ( LPDIRECTPLAY4 iface, DWORD dwMsgID, DWORD dwFlags )
1686 {
1687   ICOM_THIS(IDirectPlay4Impl,iface);
1688   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwMsgID, dwFlags );
1689   return DP_OK;
1690 }
1691
1692 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
1693           ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority, DWORD dwFlags )
1694 {
1695   ICOM_THIS(IDirectPlay4Impl,iface);
1696   FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx): stub\n", This, dwMinPriority, dwMaxPriority, dwFlags );
1697   return DP_OK;
1698 }
1699
1700 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
1701           ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority, DWORD dwFlags )
1702 {
1703   ICOM_THIS(IDirectPlay4Impl,iface);
1704   FIXME("(%p)->(0x%08lx,0x%08lx,0x%08lx): stub\n", This, dwMinPriority, dwMaxPriority, dwFlags );
1705   return DP_OK;
1706 }
1707
1708 /* Note: Hack so we can reuse the old functions without compiler warnings */
1709 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1710 # define XCAST(fun)     (typeof(directPlay2WVT.fn##fun))
1711 #else
1712 # define XCAST(fun)     (void*)
1713 #endif
1714
1715 static ICOM_VTABLE(IDirectPlay2) directPlay2WVT = 
1716 {
1717   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1718   DirectPlay2W_QueryInterface,
1719   XCAST(AddRef)DirectPlay2AImpl_AddRef,
1720   XCAST(Release)DirectPlay2AImpl_Release,
1721
1722   DirectPlay2WImpl_AddPlayerToGroup,
1723   DirectPlay2WImpl_Close,
1724   DirectPlay2WImpl_CreateGroup,
1725   DirectPlay2WImpl_CreatePlayer,
1726   DirectPlay2WImpl_DeletePlayerFromGroup,
1727   DirectPlay2WImpl_DestroyGroup,
1728   DirectPlay2WImpl_DestroyPlayer,
1729   DirectPlay2WImpl_EnumGroupPlayers,
1730   DirectPlay2WImpl_EnumGroups,
1731   DirectPlay2WImpl_EnumPlayers,
1732   DirectPlay2WImpl_EnumSessions,
1733   DirectPlay2WImpl_GetCaps,
1734   DirectPlay2WImpl_GetGroupData,
1735   DirectPlay2WImpl_GetGroupName,
1736   DirectPlay2WImpl_GetMessageCount,
1737   DirectPlay2WImpl_GetPlayerAddress,
1738   DirectPlay2WImpl_GetPlayerCaps,
1739   DirectPlay2WImpl_GetPlayerData,
1740   DirectPlay2WImpl_GetPlayerName,
1741   DirectPlay2WImpl_GetSessionDesc,
1742   DirectPlay2WImpl_Initialize,
1743   DirectPlay2WImpl_Open,
1744   DirectPlay2WImpl_Receive,
1745   DirectPlay2WImpl_Send,
1746   DirectPlay2WImpl_SetGroupData,
1747   DirectPlay2WImpl_SetGroupName,
1748   DirectPlay2WImpl_SetPlayerData,
1749   DirectPlay2WImpl_SetPlayerName,
1750   DirectPlay2WImpl_SetSessionDesc
1751 };
1752 #undef XCAST
1753
1754 /* Note: Hack so we can reuse the old functions without compiler warnings */
1755 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1756 # define XCAST(fun)     (typeof(directPlay2AVT.fn##fun))
1757 #else
1758 # define XCAST(fun)     (void*)
1759 #endif
1760
1761 static ICOM_VTABLE(IDirectPlay2) directPlay2AVT = 
1762 {
1763   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1764   DirectPlay2A_QueryInterface,
1765   XCAST(AddRef)DirectPlay2AImpl_AddRef,
1766   XCAST(Release)DirectPlay2AImpl_Release,
1767
1768   DirectPlay2AImpl_AddPlayerToGroup,
1769   DirectPlay2AImpl_Close,
1770   DirectPlay2AImpl_CreateGroup,
1771   DirectPlay2AImpl_CreatePlayer,
1772   DirectPlay2AImpl_DeletePlayerFromGroup,
1773   DirectPlay2AImpl_DestroyGroup,
1774   DirectPlay2AImpl_DestroyPlayer,
1775   DirectPlay2AImpl_EnumGroupPlayers,
1776   DirectPlay2AImpl_EnumGroups,
1777   DirectPlay2AImpl_EnumPlayers,
1778   DirectPlay2AImpl_EnumSessions,
1779   DirectPlay2AImpl_GetCaps,
1780   DirectPlay2AImpl_GetGroupData,
1781   DirectPlay2AImpl_GetGroupName,
1782   DirectPlay2AImpl_GetMessageCount,
1783   DirectPlay2AImpl_GetPlayerAddress,
1784   DirectPlay2AImpl_GetPlayerCaps,
1785   DirectPlay2AImpl_GetPlayerData,
1786   DirectPlay2AImpl_GetPlayerName,
1787   DirectPlay2AImpl_GetSessionDesc,
1788   DirectPlay2AImpl_Initialize,
1789   DirectPlay2AImpl_Open,
1790   DirectPlay2AImpl_Receive,
1791   DirectPlay2AImpl_Send,
1792   DirectPlay2AImpl_SetGroupData,
1793   DirectPlay2AImpl_SetGroupName,
1794   DirectPlay2AImpl_SetPlayerData,
1795   DirectPlay2AImpl_SetPlayerName,
1796   DirectPlay2AImpl_SetSessionDesc
1797 };
1798 #undef XCAST
1799
1800
1801 /* Note: Hack so we can reuse the old functions without compiler warnings */
1802 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1803 # define XCAST(fun)     (typeof(directPlay3AVT.fn##fun))
1804 #else
1805 # define XCAST(fun)     (void*)
1806 #endif
1807
1808 static ICOM_VTABLE(IDirectPlay3) directPlay3AVT = 
1809 {
1810   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1811   DirectPlay3AImpl_QueryInterface,
1812   XCAST(AddRef)DirectPlay2AImpl_AddRef,
1813   XCAST(Release)DirectPlay2AImpl_Release,
1814
1815   XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
1816   XCAST(Close)DirectPlay2AImpl_Close,
1817   XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
1818   XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
1819   XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
1820   XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
1821   XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
1822   XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
1823   XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
1824   XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
1825   XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
1826   XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
1827   XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
1828   XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
1829   XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
1830   XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
1831   XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
1832   XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
1833   XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
1834   XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
1835   XCAST(Initialize)DirectPlay2AImpl_Initialize,
1836   XCAST(Open)DirectPlay2AImpl_Open,
1837   XCAST(Receive)DirectPlay2AImpl_Receive,
1838   XCAST(Send)DirectPlay2AImpl_Send,
1839   XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
1840   XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
1841   XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
1842   XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
1843   XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
1844
1845   DirectPlay3AImpl_AddGroupToGroup,
1846   DirectPlay3AImpl_CreateGroupInGroup,
1847   DirectPlay3AImpl_DeleteGroupFromGroup,
1848   DirectPlay3AImpl_EnumConnections,
1849   DirectPlay3AImpl_EnumGroupsInGroup,
1850   DirectPlay3AImpl_GetGroupConnectionSettings,
1851   DirectPlay3AImpl_InitializeConnection,
1852   DirectPlay3AImpl_SecureOpen,
1853   DirectPlay3AImpl_SendChatMessage,
1854   DirectPlay3AImpl_SetGroupConnectionSettings,
1855   DirectPlay3AImpl_StartSession,
1856   DirectPlay3AImpl_GetGroupFlags,
1857   DirectPlay3AImpl_GetGroupParent,
1858   DirectPlay3AImpl_GetPlayerAccount,
1859   DirectPlay3AImpl_GetPlayerFlags
1860 };
1861 #undef XCAST
1862
1863 /* Note: Hack so we can reuse the old functions without compiler warnings */
1864 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1865 # define XCAST(fun)     (typeof(directPlay3WVT.fn##fun))
1866 #else
1867 # define XCAST(fun)     (void*)
1868 #endif
1869 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT = 
1870 {
1871   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1872   DirectPlay3WImpl_QueryInterface,
1873   XCAST(AddRef)DirectPlay2AImpl_AddRef,
1874   XCAST(Release)DirectPlay2AImpl_Release,
1875
1876   XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
1877   XCAST(Close)DirectPlay2WImpl_Close,
1878   XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
1879   XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
1880   XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
1881   XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
1882   XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
1883   XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
1884   XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
1885   XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
1886   XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
1887   XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
1888   XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
1889   XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
1890   XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
1891   XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
1892   XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
1893   XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
1894   XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
1895   XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
1896   XCAST(Initialize)DirectPlay2WImpl_Initialize,
1897   XCAST(Open)DirectPlay2WImpl_Open,
1898   XCAST(Receive)DirectPlay2WImpl_Receive,
1899   XCAST(Send)DirectPlay2WImpl_Send,
1900   XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
1901   XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
1902   XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
1903   XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
1904   XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
1905
1906   DirectPlay3WImpl_AddGroupToGroup,
1907   DirectPlay3WImpl_CreateGroupInGroup,
1908   DirectPlay3WImpl_DeleteGroupFromGroup,
1909   DirectPlay3WImpl_EnumConnections,
1910   DirectPlay3WImpl_EnumGroupsInGroup,
1911   DirectPlay3WImpl_GetGroupConnectionSettings,
1912   DirectPlay3WImpl_InitializeConnection,
1913   DirectPlay3WImpl_SecureOpen,
1914   DirectPlay3WImpl_SendChatMessage,
1915   DirectPlay3WImpl_SetGroupConnectionSettings,
1916   DirectPlay3WImpl_StartSession,
1917   DirectPlay3WImpl_GetGroupFlags,
1918   DirectPlay3WImpl_GetGroupParent,
1919   DirectPlay3WImpl_GetPlayerAccount,
1920   DirectPlay3WImpl_GetPlayerFlags
1921 };
1922 #undef XCAST
1923
1924 /* Note: Hack so we can reuse the old functions without compiler warnings */
1925 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1926 # define XCAST(fun)     (typeof(directPlay4WVT.fn##fun))
1927 #else
1928 # define XCAST(fun)     (void*)
1929 #endif
1930 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
1931 {
1932   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1933   DirectPlay4WImpl_QueryInterface,
1934   XCAST(AddRef)DirectPlay2AImpl_AddRef,
1935   XCAST(Release)DirectPlay2AImpl_Release,
1936
1937   XCAST(AddPlayerToGroup)DirectPlay2WImpl_AddPlayerToGroup,
1938   XCAST(Close)DirectPlay2WImpl_Close,
1939   XCAST(CreateGroup)DirectPlay2WImpl_CreateGroup,
1940   XCAST(CreatePlayer)DirectPlay2WImpl_CreatePlayer,
1941   XCAST(DeletePlayerFromGroup)DirectPlay2WImpl_DeletePlayerFromGroup,
1942   XCAST(DestroyGroup)DirectPlay2WImpl_DestroyGroup,
1943   XCAST(DestroyPlayer)DirectPlay2WImpl_DestroyPlayer,
1944   XCAST(EnumGroupPlayers)DirectPlay2WImpl_EnumGroupPlayers,
1945   XCAST(EnumGroups)DirectPlay2WImpl_EnumGroups,
1946   XCAST(EnumPlayers)DirectPlay2WImpl_EnumPlayers,
1947   XCAST(EnumSessions)DirectPlay2WImpl_EnumSessions,
1948   XCAST(GetCaps)DirectPlay2WImpl_GetCaps,
1949   XCAST(GetGroupData)DirectPlay2WImpl_GetGroupData,
1950   XCAST(GetGroupName)DirectPlay2WImpl_GetGroupName,
1951   XCAST(GetMessageCount)DirectPlay2WImpl_GetMessageCount,
1952   XCAST(GetPlayerAddress)DirectPlay2WImpl_GetPlayerAddress,
1953   XCAST(GetPlayerCaps)DirectPlay2WImpl_GetPlayerCaps,
1954   XCAST(GetPlayerData)DirectPlay2WImpl_GetPlayerData,
1955   XCAST(GetPlayerName)DirectPlay2WImpl_GetPlayerName,
1956   XCAST(GetSessionDesc)DirectPlay2WImpl_GetSessionDesc,
1957   XCAST(Initialize)DirectPlay2WImpl_Initialize,
1958   XCAST(Open)DirectPlay2WImpl_Open,
1959   XCAST(Receive)DirectPlay2WImpl_Receive,
1960   XCAST(Send)DirectPlay2WImpl_Send,
1961   XCAST(SetGroupData)DirectPlay2WImpl_SetGroupData,
1962   XCAST(SetGroupName)DirectPlay2WImpl_SetGroupName,
1963   XCAST(SetPlayerData)DirectPlay2WImpl_SetPlayerData,
1964   XCAST(SetPlayerName)DirectPlay2WImpl_SetPlayerName,
1965   XCAST(SetSessionDesc)DirectPlay2WImpl_SetSessionDesc,
1966
1967   XCAST(AddGroupToGroup)DirectPlay3WImpl_AddGroupToGroup,
1968   XCAST(CreateGroupInGroup)DirectPlay3WImpl_CreateGroupInGroup,
1969   XCAST(DeleteGroupFromGroup)DirectPlay3WImpl_DeleteGroupFromGroup,
1970   XCAST(EnumConnections)DirectPlay3WImpl_EnumConnections,
1971   XCAST(EnumGroupsInGroup)DirectPlay3WImpl_EnumGroupsInGroup,
1972   XCAST(GetGroupConnectionSettings)DirectPlay3WImpl_GetGroupConnectionSettings,
1973   XCAST(InitializeConnection)DirectPlay3WImpl_InitializeConnection,
1974   XCAST(SecureOpen)DirectPlay3WImpl_SecureOpen,
1975   XCAST(SendChatMessage)DirectPlay3WImpl_SendChatMessage,
1976   XCAST(SetGroupConnectionSettings)DirectPlay3WImpl_SetGroupConnectionSettings,
1977   XCAST(StartSession)DirectPlay3WImpl_StartSession,
1978   XCAST(GetGroupFlags)DirectPlay3WImpl_GetGroupFlags,
1979   XCAST(GetGroupParent)DirectPlay3WImpl_GetGroupParent,
1980   XCAST(GetPlayerAccount)DirectPlay3WImpl_GetPlayerAccount,
1981   XCAST(GetPlayerFlags)DirectPlay3WImpl_GetPlayerFlags,
1982
1983   DirectPlay4WImpl_GetGroupOwner,
1984   DirectPlay4WImpl_SetGroupOwner,
1985   DirectPlay4WImpl_SendEx,
1986   DirectPlay4WImpl_GetMessageQueue,
1987   DirectPlay4WImpl_CancelMessage,
1988   DirectPlay4WImpl_CancelPriority
1989 };
1990 #undef XCAST
1991
1992
1993 /* Note: Hack so we can reuse the old functions without compiler warnings */
1994 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1995 # define XCAST(fun)     (typeof(directPlay4AVT.fn##fun))
1996 #else
1997 # define XCAST(fun)     (void*)
1998 #endif
1999 static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
2000 {
2001   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2002   DirectPlay4AImpl_QueryInterface,
2003   XCAST(AddRef)DirectPlay2AImpl_AddRef,
2004   XCAST(Release)DirectPlay2AImpl_Release,
2005
2006   XCAST(AddPlayerToGroup)DirectPlay2AImpl_AddPlayerToGroup,
2007   XCAST(Close)DirectPlay2AImpl_Close,
2008   XCAST(CreateGroup)DirectPlay2AImpl_CreateGroup,
2009   XCAST(CreatePlayer)DirectPlay2AImpl_CreatePlayer,
2010   XCAST(DeletePlayerFromGroup)DirectPlay2AImpl_DeletePlayerFromGroup,
2011   XCAST(DestroyGroup)DirectPlay2AImpl_DestroyGroup,
2012   XCAST(DestroyPlayer)DirectPlay2AImpl_DestroyPlayer,
2013   XCAST(EnumGroupPlayers)DirectPlay2AImpl_EnumGroupPlayers,
2014   XCAST(EnumGroups)DirectPlay2AImpl_EnumGroups,
2015   XCAST(EnumPlayers)DirectPlay2AImpl_EnumPlayers,
2016   XCAST(EnumSessions)DirectPlay2AImpl_EnumSessions,
2017   XCAST(GetCaps)DirectPlay2AImpl_GetCaps,
2018   XCAST(GetGroupData)DirectPlay2AImpl_GetGroupData,
2019   XCAST(GetGroupName)DirectPlay2AImpl_GetGroupName,
2020   XCAST(GetMessageCount)DirectPlay2AImpl_GetMessageCount,
2021   XCAST(GetPlayerAddress)DirectPlay2AImpl_GetPlayerAddress,
2022   XCAST(GetPlayerCaps)DirectPlay2AImpl_GetPlayerCaps,
2023   XCAST(GetPlayerData)DirectPlay2AImpl_GetPlayerData,
2024   XCAST(GetPlayerName)DirectPlay2AImpl_GetPlayerName,
2025   XCAST(GetSessionDesc)DirectPlay2AImpl_GetSessionDesc,
2026   XCAST(Initialize)DirectPlay2AImpl_Initialize,
2027   XCAST(Open)DirectPlay2AImpl_Open,
2028   XCAST(Receive)DirectPlay2AImpl_Receive,
2029   XCAST(Send)DirectPlay2AImpl_Send,
2030   XCAST(SetGroupData)DirectPlay2AImpl_SetGroupData,
2031   XCAST(SetGroupName)DirectPlay2AImpl_SetGroupName,
2032   XCAST(SetPlayerData)DirectPlay2AImpl_SetPlayerData,
2033   XCAST(SetPlayerName)DirectPlay2AImpl_SetPlayerName,
2034   XCAST(SetSessionDesc)DirectPlay2AImpl_SetSessionDesc,
2035
2036   XCAST(AddGroupToGroup)DirectPlay3AImpl_AddGroupToGroup,
2037   XCAST(CreateGroupInGroup)DirectPlay3AImpl_CreateGroupInGroup,
2038   XCAST(DeleteGroupFromGroup)DirectPlay3AImpl_DeleteGroupFromGroup,
2039   XCAST(EnumConnections)DirectPlay3AImpl_EnumConnections,
2040   XCAST(EnumGroupsInGroup)DirectPlay3AImpl_EnumGroupsInGroup,
2041   XCAST(GetGroupConnectionSettings)DirectPlay3AImpl_GetGroupConnectionSettings,
2042   XCAST(InitializeConnection)DirectPlay3AImpl_InitializeConnection,
2043   XCAST(SecureOpen)DirectPlay3AImpl_SecureOpen,
2044   XCAST(SendChatMessage)DirectPlay3AImpl_SendChatMessage,
2045   XCAST(SetGroupConnectionSettings)DirectPlay3AImpl_SetGroupConnectionSettings,
2046   XCAST(StartSession)DirectPlay3AImpl_StartSession,
2047   XCAST(GetGroupFlags)DirectPlay3AImpl_GetGroupFlags,
2048   XCAST(GetGroupParent)DirectPlay3AImpl_GetGroupParent,
2049   XCAST(GetPlayerAccount)DirectPlay3AImpl_GetPlayerAccount,
2050   XCAST(GetPlayerFlags)DirectPlay3AImpl_GetPlayerFlags,
2051
2052   DirectPlay4AImpl_GetGroupOwner,
2053   DirectPlay4AImpl_SetGroupOwner,
2054   DirectPlay4AImpl_SendEx,
2055   DirectPlay4AImpl_GetMessageQueue,
2056   DirectPlay4AImpl_CancelMessage,
2057   DirectPlay4AImpl_CancelPriority
2058 };
2059 #undef XCAST
2060
2061
2062 /***************************************************************************
2063  *  DirectPlayEnumerateA (DPLAYX.2) 
2064  *
2065  *  The pointer to the structure lpContext will be filled with the 
2066  *  appropriate data for each service offered by the OS. These services are
2067  *  not necessarily available on this particular machine but are defined
2068  *  as simple service providers under the "Service Providers" registry key.
2069  *  This structure is then passed to lpEnumCallback for each of the different 
2070  *  services. 
2071  *
2072  *  This API is useful only for applications written using DirectX3 or
2073  *  worse. It is superceeded by IDirectPlay3::EnumConnections which also
2074  *  gives information on the actual connections.
2075  *
2076  * defn of a service provider:
2077  * A dynamic-link library used by DirectPlay to communicate over a network. 
2078  * The service provider contains all the network-specific code required
2079  * to send and receive messages. Online services and network operators can
2080  * supply service providers to use specialized hardware, protocols, communications
2081  * media, and network resources. 
2082  *
2083  * TODO: Allocate string buffer space from the heap (length from reg)
2084  *       Pass real device driver numbers...
2085  *       Get the GUID properly...
2086  */
2087 HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
2088                                      LPVOID lpContext )
2089 {
2090
2091   HKEY   hkResult; 
2092   LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
2093   DWORD  dwIndex;
2094   DWORD  sizeOfSubKeyName=50;
2095   char   subKeyName[51]; 
2096   FILETIME filetime;
2097
2098   TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
2099
2100   if( !lpEnumCallback || !*lpEnumCallback )
2101   {
2102      return DPERR_INVALIDPARAMS;
2103   }
2104
2105   /* Need to loop over the service providers in the registry */
2106   if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
2107                        0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
2108   {
2109     /* Hmmm. Does this mean that there are no service providers? */ 
2110     ERR(": no service providers?\n");
2111     return DP_OK; 
2112   }
2113
2114   /* Traverse all the service providers we have available */
2115   for( dwIndex=0;
2116        RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 
2117                       NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
2118        ++dwIndex, sizeOfSubKeyName=50 )
2119   {
2120     LPSTR    majVerDataSubKey = "dwReserved1";  
2121     LPSTR    minVerDataSubKey = "dwReserved2";  
2122     LPSTR    guidDataSubKey   = "Guid";
2123     HKEY     hkServiceProvider;
2124     GUID     serviceProviderGUID;
2125     DWORD    returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
2126     char     returnBuffer[51];
2127     DWORD    majVersionNum , minVersionNum = 0;
2128     LPWSTR   lpWGUIDString; 
2129
2130     TRACE(" this time through: %s\n", subKeyName );
2131
2132     /* Get a handle for this particular service provider */
2133     if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
2134                          &hkServiceProvider ) != ERROR_SUCCESS )
2135     {
2136       ERR(": what the heck is going on?\n" );
2137       continue;
2138     }
2139
2140     /* Get the GUID, Device major number and device minor number 
2141      * from the registry. 
2142      */
2143     if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
2144                             NULL, &returnTypeGUID, returnBuffer,
2145                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
2146     {
2147       ERR(": missing GUID registry data members\n" );
2148       continue; 
2149     }
2150
2151     /* FIXME: Check return types to ensure we're interpreting data right */
2152     lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
2153     CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID ); 
2154     HeapFree( GetProcessHeap(), 0, lpWGUIDString );
2155
2156     /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
2157
2158     sizeOfReturnBuffer = 50;
2159     if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
2160                             NULL, &returnTypeReserved, returnBuffer,
2161                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
2162     {
2163       ERR(": missing dwReserved1 registry data members\n") ;
2164       continue; 
2165     }
2166
2167     majVersionNum = GET_DWORD( returnBuffer );
2168
2169     sizeOfReturnBuffer = 50;
2170     if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
2171                             NULL, &returnTypeReserved, returnBuffer,
2172                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
2173     {
2174       ERR(": missing dwReserved2 registry data members\n") ;
2175       continue;
2176     }
2177
2178     minVersionNum = GET_DWORD( returnBuffer );
2179
2180
2181     /* The enumeration will return FALSE if we are not to continue */
2182     if( !lpEnumCallback( &serviceProviderGUID , subKeyName,
2183                          majVersionNum, minVersionNum, lpContext ) )
2184     {
2185       WARN("lpEnumCallback returning FALSE\n" );
2186       break;
2187     }
2188   }
2189
2190   return DP_OK;
2191
2192 }
2193
2194 /***************************************************************************
2195  *  DirectPlayEnumerateW (DPLAYX.3)
2196  *
2197  */
2198 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
2199 {
2200
2201   FIXME(":stub\n");
2202
2203   return DPERR_OUTOFMEMORY; 
2204
2205 }
2206
2207 /***************************************************************************
2208  *  DirectPlayCreate (DPLAYX.1) (DPLAY.1)
2209  *
2210  */
2211 HRESULT WINAPI DirectPlayCreate
2212 ( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk)
2213 {
2214   TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
2215
2216   if( pUnk != NULL )
2217   {
2218     return CLASS_E_NOAGGREGATION;
2219   }
2220
2221
2222   /* Create an IDirectPlay object. We don't support that so we'll cheat and
2223      give them an IDirectPlay2A object and hope that doesn't cause problems */
2224   if( directPlay_QueryInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
2225   {
2226     return DPERR_UNAVAILABLE;
2227   } 
2228
2229   if( IsEqualGUID( &GUID_NULL, lpGUID ) )
2230   {
2231     /* The GUID_NULL means don't bind a service provider. Just return the
2232        interface */ 
2233     return DP_OK;
2234   }
2235
2236
2237   /* Bind the desired service provider */
2238   if( ( IsEqualGUID( lpGUID, &DPSPGUID_MODEM ) ) ||
2239       ( IsEqualGUID( lpGUID, &DPSPGUID_SERIAL ) ) ||
2240       ( IsEqualGUID( lpGUID, &DPSPGUID_TCPIP ) ) ||
2241       ( IsEqualGUID( lpGUID, &DPSPGUID_IPX ) ) 
2242     )
2243   {
2244      FIXME( "Service provider binding not supported yet\n" );
2245      IDirectPlayX_Release( *lplpDP );
2246      *lplpDP = NULL;
2247      return DPERR_INVALIDPARAMS; 
2248   }
2249
2250   ERR( "unknown Service Provider %s\n", debugstr_guid(lpGUID) );
2251
2252   IDirectPlayX_Release( *lplpDP );
2253   *lplpDP = NULL;
2254
2255   return DPERR_INVALIDPARAMS;
2256 }