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