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