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