Removed a few dependencies on kernel32 functions.
[wine] / dlls / dplayx / dplaysp.c
1 /* This contains the implementation of the interface Service
2  * Providers require to communicate with Direct Play 
3  *
4  * Copyright 2000 Peter Hunnisett <hunnise@nortelnetworks.com>
5  */
6
7 #include "heap.h"
8 #include "winerror.h"
9 #include "debugtools.h"
10
11 #include "dpinit.h"
12 #include "dplaysp.h"
13 #include "dplay_global.h"
14 #include "name_server.h"
15 #include "dplayx_messages.h"
16
17 #include "dplayx_global.h" /* FIXME: For global hack */
18
19 /* FIXME: Need to add interface locking inside procedures */
20
21 DEFAULT_DEBUG_CHANNEL(dplay)
22
23 /* Prototypes */
24 static BOOL DPSP_CreateIUnknown( LPVOID lpSP );
25 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP );
26 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp );
27 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP );
28
29
30 /* Predefine the interface */
31 typedef struct IDirectPlaySPImpl IDirectPlaySPImpl;
32
33 typedef struct tagDirectPlaySPIUnknownData
34 {
35   ULONG             ulObjRef;
36   CRITICAL_SECTION  DPSP_lock;
37 } DirectPlaySPIUnknownData;
38
39 typedef struct tagDirectPlaySPData
40 {
41   LPVOID lpSpRemoteData;
42   DWORD  dwSpRemoteDataSize; /* Size of data pointed to by lpSpRemoteData */
43
44   LPVOID lpSpLocalData;
45   DWORD  dwSpLocalDataSize; /* Size of data pointed to by lpSpLocalData */
46
47   IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
48
49   LPVOID lpPlayerData; /* FIXME: Need to figure out how this actually behaves */
50   DWORD dwPlayerDataSize;
51 } DirectPlaySPData;
52
53 #define DPSP_IMPL_FIELDS \
54    ULONG ulInterfaceRef; \
55    DirectPlaySPIUnknownData* unk; \
56    DirectPlaySPData* sp;
57
58 struct IDirectPlaySPImpl
59 {
60   ICOM_VFIELD(IDirectPlaySP);
61   DPSP_IMPL_FIELDS
62 };
63
64 /* Forward declaration of virtual tables */
65 static ICOM_VTABLE(IDirectPlaySP) directPlaySPVT;
66
67
68
69 /* Create the SP interface */
70 extern
71 HRESULT DPSP_CreateInterface( REFIID riid, LPVOID* ppvObj, IDirectPlay2Impl* dp )
72 {
73   TRACE( " for %s\n", debugstr_guid( riid ) );
74
75   *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
76                        sizeof( IDirectPlaySPImpl ) );
77
78   if( *ppvObj == NULL )
79   {
80     return DPERR_OUTOFMEMORY;
81   }
82  
83   if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
84   {
85     ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
86     ICOM_VTBL(This) = &directPlaySPVT;
87   }
88   else
89   {
90     /* Unsupported interface */
91     HeapFree( GetProcessHeap(), 0, *ppvObj );
92     *ppvObj = NULL;
93
94     return E_NOINTERFACE;
95   }
96
97   /* Initialize it */
98   if( DPSP_CreateIUnknown( *ppvObj ) &&
99       DPSP_CreateDirectPlaySP( *ppvObj, dp )
100     )
101   {
102     IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
103     return S_OK;
104   }
105
106   /* Initialize failed, destroy it */
107   DPSP_DestroyDirectPlaySP( *ppvObj );
108   DPSP_DestroyIUnknown( *ppvObj );
109
110   HeapFree( GetProcessHeap(), 0, *ppvObj );
111   *ppvObj = NULL;
112
113   return DPERR_NOMEMORY;
114 }
115
116 static BOOL DPSP_CreateIUnknown( LPVOID lpSP )
117 {
118   ICOM_THIS(IDirectPlaySPImpl,lpSP);
119
120   This->unk = (DirectPlaySPIUnknownData*)HeapAlloc( GetProcessHeap(), 
121                                                     HEAP_ZERO_MEMORY,
122                                                     sizeof( *(This->unk) ) );
123
124   if ( This->unk == NULL )
125   {
126     return FALSE;
127   }
128
129   InitializeCriticalSection( &This->unk->DPSP_lock );
130
131   return TRUE;
132 }
133
134 static BOOL DPSP_DestroyIUnknown( LPVOID lpSP )
135 {
136   ICOM_THIS(IDirectPlaySPImpl,lpSP);
137  
138   DeleteCriticalSection( &This->unk->DPSP_lock );
139   HeapFree( GetProcessHeap(), 0, This->unk );
140
141   return TRUE;
142 }
143
144
145 static BOOL DPSP_CreateDirectPlaySP( LPVOID lpSP, IDirectPlay2Impl* dp )
146 {
147   ICOM_THIS(IDirectPlaySPImpl,lpSP);
148
149   This->sp = (DirectPlaySPData*)HeapAlloc( GetProcessHeap(),
150                                            HEAP_ZERO_MEMORY,
151                                            sizeof( *(This->sp) ) );
152
153   if ( This->sp == NULL )
154   {
155     return FALSE;
156   }
157
158   This->sp->dplay = dp;
159
160   /* Normally we should be keeping a reference, but since only the dplay
161    * interface that created us can destroy us, we do not keep a reference
162    * to it (ie we'd be stuck with always having one reference to the dplay
163    * object, and hence us, around).
164    * NOTE: The dp object does reference count us.
165    */
166   /* IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp ); */
167
168   return TRUE;
169 }
170
171 static BOOL DPSP_DestroyDirectPlaySP( LPVOID lpSP )
172 {
173   ICOM_THIS(IDirectPlaySPImpl,lpSP);
174
175   /* Normally we should be keeping a reference, but since only the dplay
176    * interface that created us can destroy us, we do not keep a reference
177    * to it (ie we'd be stuck with always having one reference to the dplay
178    * object, and hence us, around).
179    * NOTE: The dp object does reference count us.
180    */
181   /*IDirectPlayX_Release( (LPDIRECTPLAY2)This->sp->dplay ); */
182
183   HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
184   HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
185
186   /* FIXME: Need to delete player queue */
187
188   HeapFree( GetProcessHeap(), 0, This->sp );
189   return TRUE;
190 }
191
192 /* Interface implementation */
193
194 static HRESULT WINAPI DPSP_QueryInterface
195 ( LPDIRECTPLAYSP iface,
196   REFIID riid,
197   LPVOID* ppvObj )
198 {
199   ICOM_THIS(IDirectPlaySPImpl,iface);
200   TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
201
202   *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
203                        sizeof( IDirectPlaySPImpl ) );
204
205   if( *ppvObj == NULL )
206   {
207     return DPERR_OUTOFMEMORY;
208   }
209
210   CopyMemory( *ppvObj, iface, sizeof( IDirectPlaySPImpl )  );
211   (*(IDirectPlaySPImpl**)ppvObj)->ulInterfaceRef = 0;
212
213   if( IsEqualGUID( &IID_IDirectPlaySP, riid ) )
214   {
215     ICOM_THIS(IDirectPlaySPImpl,*ppvObj);
216     ICOM_VTBL(This) = &directPlaySPVT;
217   }
218   else
219   {
220     /* Unsupported interface */
221     HeapFree( GetProcessHeap(), 0, *ppvObj );
222     *ppvObj = NULL;
223
224     return E_NOINTERFACE;
225   }
226  
227   IDirectPlaySP_AddRef( (LPDIRECTPLAYSP)*ppvObj );
228
229   return S_OK;
230
231
232 static ULONG WINAPI DPSP_AddRef
233 ( LPDIRECTPLAYSP iface )
234 {
235   ULONG ulInterfaceRefCount, ulObjRefCount;
236   ICOM_THIS(IDirectPlaySPImpl,iface);
237
238   ulObjRefCount       = InterlockedIncrement( &This->unk->ulObjRef );
239   ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
240
241   TRACE( "ref count incremented to %lu:%lu for %p\n",
242          ulInterfaceRefCount, ulObjRefCount, This );
243
244   return ulObjRefCount;
245 }
246
247 static ULONG WINAPI DPSP_Release
248 ( LPDIRECTPLAYSP iface )
249 {
250   ULONG ulInterfaceRefCount, ulObjRefCount;
251   ICOM_THIS(IDirectPlaySPImpl,iface);
252
253   ulObjRefCount       = InterlockedDecrement( &This->unk->ulObjRef );
254   ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
255
256   TRACE( "ref count decremented to %lu:%lu for %p\n",
257          ulInterfaceRefCount, ulObjRefCount, This );
258
259   /* Deallocate if this is the last reference to the object */
260   if( ulObjRefCount == 0 )
261   {
262      DPSP_DestroyDirectPlaySP( This );
263      DPSP_DestroyIUnknown( This );
264   }
265
266   if( ulInterfaceRefCount == 0 )
267   {
268     HeapFree( GetProcessHeap(), 0, This );
269   }
270
271   return ulInterfaceRefCount;
272 }
273
274 static HRESULT WINAPI IDirectPlaySPImpl_AddMRUEntry
275 ( LPDIRECTPLAYSP iface,
276   LPCWSTR lpSection,
277   LPCWSTR lpKey,
278   LPCVOID lpData, 
279   DWORD   dwDataSize, 
280   DWORD   dwMaxEntries
281 )
282 {
283   ICOM_THIS(IDirectPlaySPImpl,iface);
284
285   FIXME( "(%p)->(%p,%p%p,0x%08lx,0x%08lx): stub\n", 
286          This, lpSection, lpKey, lpData, dwDataSize, dwMaxEntries );
287
288   return DP_OK;
289 }
290
291 static HRESULT WINAPI IDirectPlaySPImpl_CreateAddress
292 ( LPDIRECTPLAYSP iface,
293   REFGUID guidSP, 
294   REFGUID guidDataType, 
295   LPCVOID lpData, 
296   DWORD   dwDataSize, 
297   LPVOID  lpAddress,
298   LPDWORD lpdwAddressSize
299 )
300 {
301   ICOM_THIS(IDirectPlaySPImpl,iface);
302
303   FIXME( "(%p)->(%s,%s,%p,0x%08lx,%p,%p): stub\n", 
304          This, debugstr_guid(guidSP), debugstr_guid(guidDataType),
305          lpData, dwDataSize, lpAddress, lpdwAddressSize );
306
307   return DP_OK;
308 }
309
310 static HRESULT WINAPI IDirectPlaySPImpl_EnumAddress
311 ( LPDIRECTPLAYSP iface,
312   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, 
313   LPCVOID lpAddress, 
314   DWORD dwAddressSize, 
315   LPVOID lpContext
316 )
317 {
318   ICOM_THIS(IDirectPlaySPImpl,iface);
319
320   TRACE( "(%p)->(%p,%p,0x%08lx,%p)\n", 
321          This, lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
322
323   DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
324
325   return DP_OK;
326 }
327
328 static HRESULT WINAPI IDirectPlaySPImpl_EnumMRUEntries
329 ( LPDIRECTPLAYSP iface,
330   LPCWSTR lpSection, 
331   LPCWSTR lpKey, 
332   LPENUMMRUCALLBACK lpEnumMRUCallback, 
333   LPVOID lpContext
334 )
335 {
336   ICOM_THIS(IDirectPlaySPImpl,iface);
337
338   FIXME( "(%p)->(%p,%p,%p,%p,): stub\n", 
339          This, lpSection, lpKey, lpEnumMRUCallback, lpContext );
340
341   return DP_OK;
342 }
343
344 static HRESULT WINAPI IDirectPlaySPImpl_GetPlayerFlags
345 ( LPDIRECTPLAYSP iface,
346   DPID idPlayer, 
347   LPDWORD lpdwPlayerFlags
348 )
349 {
350   ICOM_THIS(IDirectPlaySPImpl,iface);
351
352   FIXME( "(%p)->(0x%08lx,%p): stub\n", 
353          This, idPlayer, lpdwPlayerFlags );
354
355   return DP_OK;
356 }
357
358 static HRESULT WINAPI IDirectPlaySPImpl_GetSPPlayerData
359 ( LPDIRECTPLAYSP iface,
360   DPID idPlayer, 
361   LPVOID* lplpData, 
362   LPDWORD lpdwDataSize, 
363   DWORD dwFlags
364 )
365 {
366   ICOM_THIS(IDirectPlaySPImpl,iface);
367
368   TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
369   FIXME( "(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n", 
370          This, idPlayer, lplpData, lpdwDataSize, dwFlags );
371
372   /* What to do in the case where there is nothing set yet? */
373
374   *lplpData     = This->sp->lpPlayerData;
375   *lpdwDataSize = This->sp->dwPlayerDataSize;
376
377   return DP_OK;
378 }
379
380 static HRESULT WINAPI IDirectPlaySPImpl_HandleMessage
381 ( LPDIRECTPLAYSP iface,
382   LPVOID lpMessageBody, 
383   DWORD  dwMessageBodySize, 
384   LPVOID lpMessageHeader
385 )
386 {
387   LPDPMSG_SENDENVELOPE lpMsg = (LPDPMSG_SENDENVELOPE)lpMessageBody;
388   HRESULT hr = DPERR_GENERIC;
389   WORD wCommandId;
390   WORD wVersion;
391
392   ICOM_THIS(IDirectPlaySPImpl,iface);
393
394   TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
395   FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n", 
396          This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
397
398   wCommandId = lpMsg->wCommandId;
399   wVersion   = lpMsg->wVersion;
400
401   TRACE( "Incomming message has envelope of 0x%08lx, %u, %u\n", 
402          lpMsg->dwMagic, wCommandId, wVersion );
403
404   if( lpMsg->dwMagic != DPMSGMAGIC_DPLAYMSG )
405   {
406     ERR( "Unknown magic 0x%08lx!\n", lpMsg->dwMagic );
407   }
408
409   switch( lpMsg->wCommandId )
410   {
411     /* Name server needs to handle this request */
412     case DPMSGCMD_ENUMSESSIONSREQUEST:
413     {
414       DPSP_REPLYDATA data;
415
416       data.lpSPMessageHeader = lpMessageHeader;
417       data.idNameServer      = 0;
418       data.lpISP             = iface;
419  
420       NS_ReplyToEnumSessionsRequest( lpMessageBody, &data, This->sp->dplay );
421
422       hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
423
424       if( FAILED(hr) )
425       {
426         ERR( "Reply failed 0x%08lx\n", hr );
427       }
428
429       break;
430     }
431
432     /* Name server needs to handle this request */
433     case DPMSGCMD_ENUMSESSIONSREPLY:
434     {
435       NS_SetRemoteComputerAsNameServer( lpMessageHeader, 
436                                         This->sp->dplay->dp2->spData.dwSPHeaderSize,
437                                         (LPDPMSG_ENUMSESSIONSREPLY)lpMessageBody,
438                                         This->sp->dplay->dp2->lpNameServerData );
439
440       /* No reply expected */
441
442       break;
443     }
444
445     case DPMSGCMD_GETNAMETABLE:
446     case DPMSGCMD_GETNAMETABLEREPLY:
447     case DPMSGCMD_NEWPLAYERIDREPLY:
448     case DPMSGCMD_REQUESTNEWPLAYERID:
449     {
450       DPSP_REPLYDATA data;
451       
452       data.lpMessage     = NULL;
453       data.dwMessageSize = 0;
454
455       /* Pass this message to the dplay interface to handle */
456       DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
457                         lpMessageHeader, wCommandId, wVersion, 
458                         &data.lpMessage, &data.dwMessageSize );
459
460       /* Do we want a reply? */
461       if( data.lpMessage != NULL )
462       {
463         HRESULT hr;
464
465         data.lpSPMessageHeader = lpMessageHeader;
466         data.idNameServer      = 0;
467         data.lpISP             = iface;
468
469         hr = (This->sp->dplay->dp2->spData.lpCB->Reply)( &data );
470
471         if( FAILED(hr) )
472         {
473           ERR( "Reply failed %s\n", DPLAYX_HresultToString(hr) );
474         }
475       }
476
477       break;
478     }
479
480     default:
481       FIXME( "Unknown Command of %u and size 0x%08lx\n", 
482              lpMsg->wCommandId, dwMessageBodySize );
483   }
484
485 #if 0
486   HRESULT hr = DP_OK;
487   HANDLE  hReceiveEvent = 0;
488   /* FIXME: Aquire some sort of interface lock */
489   /* FIXME: Need some sort of context for this callback. Need to determine
490    *        how this is actually done with the SP
491    */
492   /* FIXME: Who needs to delete the message when done? */
493   switch( lpMsg->dwType )
494   {
495     case DPSYS_CREATEPLAYERORGROUP:
496     {
497       LPDPMSG_CREATEPLAYERORGROUP msg = (LPDPMSG_CREATEPLAYERORGROUP)lpMsg;
498
499       if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
500       {
501         hr = DP_IF_CreatePlayer( This, lpMessageHeader, msg->dpId, 
502                                  &msg->dpnName, 0, msg->lpData, 
503                                  msg->dwDataSize, msg->dwFlags, ... );
504       }
505       else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
506       {
507         /* Group in group situation? */
508         if( msg->dpIdParent == DPID_NOPARENT_GROUP )
509         {
510           hr = DP_IF_CreateGroup( This, lpMessageHeader, msg->dpId, 
511                                   &msg->dpnName, 0, msg->lpData, 
512                                   msg->dwDataSize, msg->dwFlags, ... );
513         }
514         else /* Group in Group */
515         {
516           hr = DP_IF_CreateGroupInGroup( This, lpMessageHeader, msg->dpIdParent,
517                                          &msg->dpnName, 0, msg->lpData, 
518                                          msg->dwDataSize, msg->dwFlags, ... );
519         }
520       }
521       else /* Hmmm? */
522       {
523         ERR( "Corrupt msg->dwPlayerType for DPSYS_CREATEPLAYERORGROUP\n" );
524         return;
525       }
526
527       break;
528     }
529
530     case DPSYS_DESTROYPLAYERORGROUP:
531     {
532       LPDPMSG_DESTROYPLAYERORGROUP msg = (LPDPMSG_DESTROYPLAYERORGROUP)lpMsg;
533
534       if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
535       {
536         hr = DP_IF_DestroyPlayer( This, msg->dpId, ... );
537       }
538       else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
539       {
540         hr = DP_IF_DestroyGroup( This, msg->dpId, ... );
541       }
542       else /* Hmmm? */
543       {
544         ERR( "Corrupt msg->dwPlayerType for DPSYS_DESTROYPLAYERORGROUP\n" );
545         return;
546       }
547
548       break;
549     }
550
551     case DPSYS_ADDPLAYERTOGROUP:
552     {
553       LPDPMSG_ADDPLAYERTOGROUP msg = (LPDPMSG_ADDPLAYERTOGROUP)lpMsg;
554
555       hr = DP_IF_AddPlayerToGroup( This, msg->dpIdGroup, msg->dpIdPlayer, ... );
556       break;
557     }
558
559     case DPSYS_DELETEPLAYERFROMGROUP:
560     {
561       LPDPMSG_DELETEPLAYERFROMGROUP msg = (LPDPMSG_DELETEPLAYERFROMGROUP)lpMsg;
562
563       hr = DP_IF_DeletePlayerFromGroup( This, msg->dpIdGroup, msg->dpIdPlayer,
564                                         ... );
565
566       break;
567     }
568
569     case DPSYS_SESSIONLOST:
570     {
571       LPDPMSG_SESSIONLOST msg = (LPDPMSG_SESSIONLOST)lpMsg;
572
573       FIXME( "DPSYS_SESSIONLOST not handled\n" );
574
575       break;
576     }
577
578     case DPSYS_HOST:
579     {
580       LPDPMSG_HOST msg = (LPDPMSG_HOST)lpMsg;
581
582       FIXME( "DPSYS_HOST not handled\n" );
583
584       break;
585     }
586
587     case DPSYS_SETPLAYERORGROUPDATA:
588     {
589       LPDPMSG_SETPLAYERORGROUPDATA msg = (LPDPMSG_SETPLAYERORGROUPDATA)lpMsg;
590
591       if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
592       {
593         hr = DP_IF_SetPlayerData( This, msg->dpId, msg->lpData, msg->dwDataSize,                                  DPSET_REMOTE, ... );
594       }
595       else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
596       {
597         hr = DP_IF_SetGroupData( This, msg->dpId, msg->lpData, msg->dwDataSize,
598                                  DPSET_REMOTE, ... );
599       }
600       else /* Hmmm? */
601       {
602         ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
603         return;
604       }
605
606       break;
607     }
608
609     case DPSYS_SETPLAYERORGROUPNAME:
610     {
611       LPDPMSG_SETPLAYERORGROUPNAME msg = (LPDPMSG_SETPLAYERORGROUPNAME)lpMsg;
612
613       if( msg->dwPlayerType == DPPLAYERTYPE_PLAYER )
614       {
615         hr = DP_IF_SetPlayerName( This, msg->dpId, msg->dpnName, ... );
616       }
617       else if( msg->dwPlayerType == DPPLAYERTYPE_GROUP )
618       {
619         hr = DP_IF_SetGroupName( This, msg->dpId, msg->dpnName, ... );
620       }
621       else /* Hmmm? */
622       {
623         ERR( "Corrupt msg->dwPlayerType for LPDPMSG_SETPLAYERORGROUPDATA\n" );
624         return;
625       }
626
627       break;
628     }
629
630     case DPSYS_SETSESSIONDESC;
631     {
632       LPDPMSG_SETSESSIONDESC msg = (LPDPMSG_SETSESSIONDESC)lpMsg;
633
634       hr = DP_IF_SetSessionDesc( This, &msg->dpDesc );
635
636       break;
637     }
638
639     case DPSYS_ADDGROUPTOGROUP:
640     {
641       LPDPMSG_ADDGROUPTOGROUP msg = (LPDPMSG_ADDGROUPTOGROUP)lpMsg;
642
643       hr = DP_IF_AddGroupToGroup( This, msg->dpIdParentGroup, msg->dpIdGroup,
644                                   ... );
645
646       break;
647     }
648
649     case DPSYS_DELETEGROUPFROMGROUP:
650     {
651       LPDPMSG_DELETEGROUPFROMGROUP msg = (LPDPMSG_DELETEGROUPFROMGROUP)lpMsg;
652
653       hr = DP_IF_DeleteGroupFromGroup( This, msg->dpIdParentGroup,
654                                        msg->dpIdGroup, ... );
655
656       break;
657     }
658
659     case DPSYS_SECUREMESSAGE:
660     {
661       LPDPMSG_SECUREMESSAGE msg = (LPDPMSG_SECUREMESSAGE)lpMsg;
662
663       FIXME( "DPSYS_SECUREMESSAGE not implemented\n" );
664
665       break;
666     }
667
668     case DPSYS_STARTSESSION:
669     {
670       LPDPMSG_STARTSESSION msg = (LPDPMSG_STARTSESSION)lpMsg;
671
672       FIXME( "DPSYS_STARTSESSION not implemented\n" );
673
674       break;
675     }
676
677     case DPSYS_CHAT:
678     {
679       LPDPMSG_CHAT msg = (LPDPMSG_CHAT)lpMsg;
680
681       FIXME( "DPSYS_CHAT not implemeneted\n" );
682
683       break;
684     }   
685
686     case DPSYS_SETGROUPOWNER:
687     {
688       LPDPMSG_SETGROUPOWNER msg = (LPDPMSG_SETGROUPOWNER)lpMsg;
689
690       FIXME( "DPSYS_SETGROUPOWNER not implemented\n" );
691
692       break;
693     }
694
695     case DPSYS_SENDCOMPLETE:
696     {
697       LPDPMSG_SENDCOMPLETE msg = (LPDPMSG_SENDCOMPLETE)lpMsg;
698
699       FIXME( "DPSYS_SENDCOMPLETE not implemented\n" );
700
701       break;
702     }
703
704     default:
705     {
706       /* NOTE: This should be a user defined type. There is nothing that we
707        *       need to do with it except queue it.
708        */
709       TRACE( "Received user message type(?) 0x%08lx through SP.\n",
710               lpMsg->dwType );
711       break;
712     }
713   }
714
715   FIXME( "Queue message in the receive queue. Need some context data!\n" );
716
717   if( FAILED(hr) )
718   {
719     ERR( "Unable to perform action for msg type 0x%08lx\n", lpMsg->dwType );
720   }
721   /* If a receieve event was registered for this player, invoke it */
722   if( hReceiveEvent )
723   {
724     SetEvent( hReceiveEvent );
725   }
726 #endif
727
728   return hr;
729 }
730
731 static HRESULT WINAPI IDirectPlaySPImpl_SetSPPlayerData
732 ( LPDIRECTPLAYSP iface,
733   DPID idPlayer, 
734   LPVOID lpData, 
735   DWORD dwDataSize, 
736   DWORD dwFlags
737 )
738 {
739   ICOM_THIS(IDirectPlaySPImpl,iface);
740
741   /* FIXME: I'm not sure if this stuff should be associated with the DPlay
742    *        player lists. How else would this stuff get deleted? 
743    */
744
745   TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
746   FIXME( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n", 
747          This, idPlayer, lpData, dwDataSize, dwFlags );
748
749   This->sp->lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); 
750
751   This->sp->dwPlayerDataSize = dwDataSize;
752   CopyMemory( This->sp->lpPlayerData, lpData, dwDataSize );
753
754   return DP_OK;
755 }
756
757 static HRESULT WINAPI IDirectPlaySPImpl_CreateCompoundAddress
758 ( LPDIRECTPLAYSP iface,
759   LPCDPCOMPOUNDADDRESSELEMENT lpElements, 
760   DWORD dwElementCount, 
761   LPVOID lpAddress, 
762   LPDWORD lpdwAddressSize
763 )
764 {
765   ICOM_THIS(IDirectPlaySPImpl,iface);
766
767   FIXME( "(%p)->(%p,0x%08lx,%p,%p): stub\n", 
768          This, lpElements, dwElementCount, lpAddress, lpdwAddressSize );
769
770   return DP_OK;
771 }
772
773 static HRESULT WINAPI IDirectPlaySPImpl_GetSPData
774 ( LPDIRECTPLAYSP iface,
775   LPVOID* lplpData, 
776   LPDWORD lpdwDataSize, 
777   DWORD dwFlags
778 )
779 {
780   ICOM_THIS(IDirectPlaySPImpl,iface);
781
782   TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
783   TRACE( "(%p)->(%p,%p,0x%08lx)\n", 
784          This, lplpData, lpdwDataSize, dwFlags );
785
786 #if 0
787   /* This is what the documentation says... */
788   if( dwFlags != 0 )
789   {
790     return DPERR_INVALIDPARAMS;
791   }
792 #else
793   /* ... but most service providers call this with 1 */
794   /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
795    * thing?
796    */
797   if( dwFlags != 0 )
798   {
799     FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
800   }
801 #endif
802
803   /* FIXME: What to do in the case where this isn't initialized yet? */
804
805   /* Yes, we're supposed to return a pointer to the memory we have stored! */
806   if( dwFlags == DPSET_REMOTE )
807   {
808     *lpdwDataSize = This->sp->dwSpRemoteDataSize;
809     *lplpData     = This->sp->lpSpRemoteData;
810   }
811   else if( dwFlags == DPSET_LOCAL )
812   {
813     *lpdwDataSize = This->sp->dwSpLocalDataSize;
814     *lplpData     = This->sp->lpSpLocalData;
815   }
816
817   return DP_OK;
818 }
819
820 static HRESULT WINAPI IDirectPlaySPImpl_SetSPData
821 ( LPDIRECTPLAYSP iface,
822   LPVOID lpData, 
823   DWORD dwDataSize, 
824   DWORD dwFlags
825 )
826 {
827   LPVOID lpSpData;
828
829   ICOM_THIS(IDirectPlaySPImpl,iface);
830
831   TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
832   TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n", 
833          This, lpData, dwDataSize, dwFlags );
834
835 #if 0
836   /* This is what the documentation says... */
837   if( dwFlags != 0 )
838   {
839     return DPERR_INVALIDPARAMS;
840   }
841 #else
842   /* ... but most service providers call this with 1 */
843   /* Guess that this is using a DPSET_LOCAL or DPSET_REMOTE type of
844    * thing?
845    */
846   if( dwFlags != 0 )
847   {
848     FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
849   }
850 #endif
851
852   if( dwFlags == DPSET_REMOTE )
853   {
854     lpSpData = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY, dwDataSize );
855   }  
856   else
857   {
858     lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize ); 
859   }
860
861   CopyMemory( lpSpData, lpData, dwDataSize );
862
863   /* If we have data already allocated, free it and replace it */
864   if( dwFlags == DPSET_REMOTE )
865   {
866     /* FIXME: This doesn't strictly make sense as there is no means to share
867      *        this shared data. Must be misinterpreting something...
868      */
869     if( This->sp->lpSpRemoteData )
870     {
871       DPLAYX_PrivHeapFree( This->sp->lpSpRemoteData );
872     }
873
874     /* NOTE: dwDataSize is also stored in the heap structure */
875     This->sp->dwSpRemoteDataSize = dwDataSize;
876     This->sp->lpSpRemoteData = lpSpData;
877   }
878   else if ( dwFlags == DPSET_LOCAL )
879   {
880     if( This->sp->lpSpLocalData )
881     {
882       HeapFree( GetProcessHeap(), 0, This->sp->lpSpLocalData );
883     }
884
885     This->sp->lpSpLocalData     = lpSpData;
886     This->sp->dwSpLocalDataSize = dwDataSize;
887   }
888
889   return DP_OK;
890 }
891
892 static VOID WINAPI IDirectPlaySPImpl_SendComplete
893 ( LPDIRECTPLAYSP iface,
894   LPVOID unknownA, 
895   DWORD unknownB
896 )
897 {
898   ICOM_THIS(IDirectPlaySPImpl,iface);
899
900   FIXME( "(%p)->(%p,0x%08lx): stub\n", 
901          This, unknownA, unknownB );
902 }
903
904
905 static struct ICOM_VTABLE(IDirectPlaySP) directPlaySPVT =
906 {
907   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
908
909   DPSP_QueryInterface,
910   DPSP_AddRef,
911   DPSP_Release,
912
913   IDirectPlaySPImpl_AddMRUEntry,
914   IDirectPlaySPImpl_CreateAddress,
915   IDirectPlaySPImpl_EnumAddress,
916   IDirectPlaySPImpl_EnumMRUEntries,
917   IDirectPlaySPImpl_GetPlayerFlags,
918   IDirectPlaySPImpl_GetSPPlayerData,
919   IDirectPlaySPImpl_HandleMessage,
920   IDirectPlaySPImpl_SetSPPlayerData,
921   IDirectPlaySPImpl_CreateCompoundAddress,
922   IDirectPlaySPImpl_GetSPData,
923   IDirectPlaySPImpl_SetSPData,
924   IDirectPlaySPImpl_SendComplete
925 };