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