Sync up with trunk r61578.
[reactos.git] / dll / directx / wine / dplayx / dplay.c
1 /* Direct Play 2,3,4 Implementation
2 *
3 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #define COBJMACROS
21 #include <config.h>
22 //#include "wine/port.h"
23
24 //#include <stdarg.h>
25 //#include <string.h>
26
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include <windef.h>
30 //#include "winerror.h"
31 //#include "winbase.h"
32 //#include "winnt.h"
33 #include <winreg.h>
34 //#include "winnls.h"
35 #include <wine/unicode.h>
36 #include <wine/debug.h>
37
38 #include "dplayx_global.h"
39 #include "name_server.h"
40 //#include "dplayx_queue.h"
41 //#include "dplaysp.h"
42 //#include "dplay_global.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
45
46 /* FIXME: Should this be externed? */
47 extern HRESULT DPL_CreateCompoundAddress
48 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
49 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
50
51
52 /* Local function prototypes */
53 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid );
54 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi );
55 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
56 LPVOID lpData, DWORD dwDataSize );
57 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
58 static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
59 DWORD dwPlayerType,
60 LPCDPNAME lpName,
61 DWORD dwFlags,
62 LPVOID lpContext );
63 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid );
64
65 /* Helper methods for player/group interfaces */
66 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
67 DWORD dwFlags, BOOL bInitial, BOOL bAnsi );
68 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
69 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID );
70 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
71 LPDWORD lpdwBufSize );
72
73 static DPID DP_GetRemoteNextObjectId(void);
74
75 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi );
76 static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
77 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
78
79
80 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
81 #define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
82 we don't have to change much */
83 #define DPID_NAME_SERVER 0x19a9d65b /* Don't ask me why */
84
85 /* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
86 #define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )
87
88 /* Strip out all dwFlags values for CREATEPLAYER msg */
89 #define DPMSG_CREATEPLAYER_DWFLAGS(x) 0
90
91 static LONG kludgePlayerGroupId = 1000;
92
93
94 static inline IDirectPlayImpl *impl_from_IDirectPlay( IDirectPlay *iface )
95 {
96 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay_iface );
97 }
98
99 static inline IDirectPlayImpl *impl_from_IDirectPlay2( IDirectPlay2 *iface )
100 {
101 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2_iface );
102 }
103
104 static inline IDirectPlayImpl *impl_from_IDirectPlay2A( IDirectPlay2A *iface )
105 {
106 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay2A_iface );
107 }
108
109 static inline IDirectPlayImpl *impl_from_IDirectPlay3A( IDirectPlay3A *iface )
110 {
111 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3A_iface );
112 }
113
114 static inline IDirectPlayImpl *impl_from_IDirectPlay3( IDirectPlay3 *iface )
115 {
116 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay3_iface );
117 }
118
119 static inline IDirectPlayImpl *impl_from_IDirectPlay4A( IDirectPlay4A *iface )
120 {
121 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4A_iface );
122 }
123
124 static inline IDirectPlayImpl *impl_from_IDirectPlay4( IDirectPlay4 *iface )
125 {
126 return CONTAINING_RECORD( iface, IDirectPlayImpl, IDirectPlay4_iface );
127 }
128
129 static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
130 {
131 IDirectPlayImpl *This = lpDP;
132
133 This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
134 if ( This->dp2 == NULL )
135 {
136 return FALSE;
137 }
138
139 This->dp2->bConnectionOpen = FALSE;
140
141 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
142 This->dp2->dwEnumSessionLock = 0;
143
144 This->dp2->bHostInterface = FALSE;
145
146 DPQ_INIT(This->dp2->receiveMsgs);
147 DPQ_INIT(This->dp2->sendMsgs);
148 DPQ_INIT(This->dp2->repliesExpected);
149
150 if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
151 {
152 /* FIXME: Memory leak */
153 return FALSE;
154 }
155
156 /* Provide an initial session desc with nothing in it */
157 This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
158 HEAP_ZERO_MEMORY,
159 sizeof( *This->dp2->lpSessionDesc ) );
160 if( This->dp2->lpSessionDesc == NULL )
161 {
162 /* FIXME: Memory leak */
163 return FALSE;
164 }
165 This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );
166
167 /* We are emulating a dp 6 implementation */
168 This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;
169
170 This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
171 sizeof( *This->dp2->spData.lpCB ) );
172 This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
173 This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
174
175 /* This is the pointer to the service provider */
176 if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
177 (LPVOID*)&This->dp2->spData.lpISP, This ) )
178 )
179 {
180 /* FIXME: Memory leak */
181 return FALSE;
182 }
183
184 /* Setup lobby provider information */
185 This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
186 This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
187 sizeof( *This->dp2->dplspData.lpCB ) );
188 This->dp2->dplspData.lpCB->dwSize = sizeof( *This->dp2->dplspData.lpCB );
189
190 if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
191 (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
192 )
193 {
194 /* FIXME: Memory leak */
195 return FALSE;
196 }
197
198 return TRUE;
199 }
200
201 /* Definition of the global function in dplayx_queue.h. #
202 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
203 DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
204 {
205 HeapFree( GetProcessHeap(), 0, elem );
206 }
207
208 static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
209 {
210 IDirectPlayImpl *This = lpDP;
211
212 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
213 {
214 TerminateThread( This->dp2->hEnumSessionThread, 0 );
215 CloseHandle( This->dp2->hEnumSessionThread );
216 }
217
218 /* Finish with the SP - have it shutdown */
219 if( This->dp2->spData.lpCB->ShutdownEx )
220 {
221 DPSP_SHUTDOWNDATA data;
222
223 TRACE( "Calling SP ShutdownEx\n" );
224
225 data.lpISP = This->dp2->spData.lpISP;
226
227 (*This->dp2->spData.lpCB->ShutdownEx)( &data );
228 }
229 else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
230 {
231 TRACE( "Calling obsolete SP Shutdown\n" );
232 (*This->dp2->spData.lpCB->Shutdown)();
233 }
234
235 /* Unload the SP (if it exists) */
236 if( This->dp2->hServiceProvider != 0 )
237 {
238 FreeLibrary( This->dp2->hServiceProvider );
239 }
240
241 /* Unload the Lobby Provider (if it exists) */
242 if( This->dp2->hDPLobbyProvider != 0 )
243 {
244 FreeLibrary( This->dp2->hDPLobbyProvider );
245 }
246
247 /* FIXME: Need to delete receive and send msgs queue contents */
248
249 NS_DeleteSessionCache( This->dp2->lpNameServerData );
250
251 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
252
253 IDirectPlaySP_Release( This->dp2->spData.lpISP );
254
255 /* Delete the contents */
256 HeapFree( GetProcessHeap(), 0, This->dp2 );
257
258 return TRUE;
259 }
260
261 static void dplay_destroy(IDirectPlayImpl *obj)
262 {
263 DP_DestroyDirectPlay2( obj );
264 obj->lock.DebugInfo->Spare[0] = 0;
265 DeleteCriticalSection( &obj->lock );
266 HeapFree( GetProcessHeap(), 0, obj );
267 }
268
269 static inline DPID DP_NextObjectId(void)
270 {
271 return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
272 }
273
274 /* *lplpReply will be non NULL iff there is something to reply */
275 HRESULT DP_HandleMessage( IDirectPlayImpl *This, const void *lpcMessageBody,
276 DWORD dwMessageBodySize, const void *lpcMessageHeader, WORD wCommandId, WORD wVersion,
277 void **lplpReply, DWORD *lpdwMsgSize )
278 {
279 TRACE( "(%p)->(%p,0x%08x,%p,%u,%u)\n",
280 This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
281 wVersion );
282
283 switch( wCommandId )
284 {
285 /* Name server needs to handle this request */
286 case DPMSGCMD_ENUMSESSIONSREQUEST:
287 /* Reply expected */
288 NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
289 break;
290
291 /* Name server needs to handle this request */
292 case DPMSGCMD_ENUMSESSIONSREPLY:
293 /* No reply expected */
294 NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
295 This->dp2->spData.dwSPHeaderSize,
296 lpcMessageBody,
297 This->dp2->lpNameServerData );
298 break;
299
300 case DPMSGCMD_REQUESTNEWPLAYERID:
301 {
302 LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = lpcMessageBody;
303
304 LPDPMSG_NEWPLAYERIDREPLY lpReply;
305
306 *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
307
308 *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );
309
310 FIXME( "Ignoring dwFlags 0x%08x in request msg\n",
311 lpcMsg->dwFlags );
312
313 /* Setup the reply */
314 lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
315 This->dp2->spData.dwSPHeaderSize );
316
317 lpReply->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
318 lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
319 lpReply->envelope.wVersion = DPMSGVER_DP6;
320
321 lpReply->dpidNewPlayerId = DP_NextObjectId();
322
323 TRACE( "Allocating new playerid 0x%08x from remote request\n",
324 lpReply->dpidNewPlayerId );
325 break;
326 }
327
328 case DPMSGCMD_GETNAMETABLEREPLY:
329 case DPMSGCMD_NEWPLAYERIDREPLY:
330 #if 0
331 if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
332 DebugBreak();
333 #endif
334 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
335 break;
336
337 #if 1
338 case DPMSGCMD_JUSTENVELOPE:
339 TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08x\n", lpcMessageHeader, ((const DWORD *)lpcMessageHeader)[1] );
340 NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
341 DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
342 #endif
343
344 case DPMSGCMD_FORWARDADDPLAYER:
345 #if 0
346 DebugBreak();
347 #endif
348 #if 1
349 TRACE( "Sending message to self to get my addr\n" );
350 DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
351 #endif
352 break;
353
354 case DPMSGCMD_FORWARDADDPLAYERNACK:
355 DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
356 break;
357
358 default:
359 FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
360 DebugBreak();
361 break;
362 }
363
364 /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
365
366 return DP_OK;
367 }
368
369
370 static HRESULT WINAPI IDirectPlayImpl_QueryInterface( IDirectPlay *iface, REFIID riid, void **ppv )
371 {
372 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
373 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
374 }
375
376 static ULONG WINAPI IDirectPlayImpl_AddRef( IDirectPlay *iface )
377 {
378 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
379 ULONG ref = InterlockedIncrement( &This->ref );
380
381 TRACE( "(%p) ref=%d\n", This, ref );
382
383 if ( ref == 1 )
384 InterlockedIncrement( &This->numIfaces );
385
386 return ref;
387 }
388
389 static ULONG WINAPI IDirectPlayImpl_Release( IDirectPlay *iface )
390 {
391 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
392 ULONG ref = InterlockedDecrement( &This->ref );
393
394 TRACE( "(%p) ref=%d\n", This, ref );
395
396 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
397 dplay_destroy( This );
398
399 return ref;
400 }
401
402 static HRESULT WINAPI IDirectPlayImpl_AddPlayerToGroup( IDirectPlay *iface, DPID group,
403 DPID player )
404 {
405 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
406 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
407 return E_NOTIMPL;
408 }
409
410 static HRESULT WINAPI IDirectPlayImpl_Close( IDirectPlay *iface )
411 {
412 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
413 FIXME( "(%p): stub\n", This );
414 return E_NOTIMPL;
415 }
416
417 static HRESULT WINAPI IDirectPlayImpl_CreatePlayer( IDirectPlay *iface, DPID *player,
418 LPSTR name, LPSTR fullname, HANDLE *event )
419 {
420 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
421 FIXME( "(%p)->(%p,%s,%s,%p): stub\n", This, player, debugstr_a( name ), debugstr_a( fullname ),
422 event );
423 return E_NOTIMPL;
424 }
425
426 static HRESULT WINAPI IDirectPlayImpl_CreateGroup( IDirectPlay *iface, DPID *group, LPSTR name,
427 LPSTR fullname )
428 {
429 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
430 FIXME( "(%p)->(%p,%s,%s): stub\n", This, group, debugstr_a( name ), debugstr_a( fullname ) );
431 return E_NOTIMPL;
432 }
433
434 static HRESULT WINAPI IDirectPlayImpl_DeletePlayerFromGroup( IDirectPlay *iface, DPID group,
435 DPID player )
436 {
437 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
438 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, player );
439 return E_NOTIMPL;
440 }
441
442 static HRESULT WINAPI IDirectPlayImpl_DestroyPlayer( IDirectPlay *iface, DPID player )
443 {
444 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
445 FIXME( "(%p)->(0x%08x): stub\n", This, player );
446 return E_NOTIMPL;
447 }
448
449 static HRESULT WINAPI IDirectPlayImpl_DestroyGroup( IDirectPlay *iface, DPID group )
450 {
451 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
452 FIXME( "(%p)->(0x%08x): stub\n", This, group );
453 return E_NOTIMPL;
454 }
455
456 static HRESULT WINAPI IDirectPlayImpl_EnableNewPlayers( IDirectPlay *iface, BOOL enable )
457 {
458 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
459 FIXME( "(%p)->(%d): stub\n", This, enable );
460 return E_NOTIMPL;
461 }
462
463 static HRESULT WINAPI IDirectPlayImpl_EnumGroupPlayers( IDirectPlay *iface, DPID group,
464 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
465 {
466 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
467 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, group, enumplayercb, context, flags );
468 return E_NOTIMPL;
469 }
470
471 static HRESULT WINAPI IDirectPlayImpl_EnumGroups( IDirectPlay *iface, DWORD session,
472 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
473 {
474 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
475 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
476 return E_NOTIMPL;
477 }
478
479 static HRESULT WINAPI IDirectPlayImpl_EnumPlayers( IDirectPlay *iface, DWORD session,
480 LPDPENUMPLAYERSCALLBACK enumplayercb, void *context, DWORD flags )
481 {
482 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
483 FIXME( "(%p)->(0x%08x,%p,%p,0x%08x): stub\n", This, session, enumplayercb, context, flags );
484 return E_NOTIMPL;
485 }
486
487 static HRESULT WINAPI IDirectPlayImpl_EnumSessions( IDirectPlay *iface, DPSESSIONDESC *sdesc,
488 DWORD timeout, LPDPENUMSESSIONSCALLBACK enumsessioncb, void *context, DWORD flags )
489 {
490 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
491 FIXME( "(%p)->(%p,%u,%p,%p,0x%08x): stub\n", This, sdesc, timeout, enumsessioncb, context,
492 flags );
493 return E_NOTIMPL;
494 }
495
496 static HRESULT WINAPI IDirectPlayImpl_GetCaps( IDirectPlay *iface, DPCAPS *caps )
497 {
498 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
499 FIXME( "(%p)->(%p): stub\n", This, caps );
500 return E_NOTIMPL;
501 }
502
503 static HRESULT WINAPI IDirectPlayImpl_GetMessageCount( IDirectPlay *iface, DPID player,
504 DWORD *count )
505 {
506 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
507 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, count );
508 return E_NOTIMPL;
509 }
510
511 static HRESULT WINAPI IDirectPlayImpl_GetPlayerCaps( IDirectPlay *iface, DPID player, DPCAPS *caps )
512 {
513 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
514 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, caps );
515 return E_NOTIMPL;
516 }
517
518 static HRESULT WINAPI IDirectPlayImpl_GetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
519 DWORD *size_name, LPSTR fullname, DWORD *size_fullname )
520 {
521 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
522 FIXME( "(%p)->(0x%08x,%p,%p,%p,%p): stub\n", This, player, name, size_name, fullname,
523 size_fullname );
524 return E_NOTIMPL;
525 }
526
527 static HRESULT WINAPI IDirectPlayImpl_Initialize( IDirectPlay *iface, GUID *guid )
528 {
529 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
530 FIXME( "(%p)->(%p): stub\n", This, guid );
531 return E_NOTIMPL;
532 }
533
534 static HRESULT WINAPI IDirectPlayImpl_Open( IDirectPlay *iface, DPSESSIONDESC *sdesc )
535 {
536 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
537 FIXME( "(%p)->(%p): stub\n", This, sdesc );
538 return E_NOTIMPL;
539 }
540
541 static HRESULT WINAPI IDirectPlayImpl_Receive( IDirectPlay *iface, DPID *from, DPID *to,
542 DWORD flags, void *data, DWORD *size )
543 {
544 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
545 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p): stub\n", This, from, to, flags, data, size );
546 return E_NOTIMPL;
547 }
548
549 static HRESULT WINAPI IDirectPlayImpl_SaveSession( IDirectPlay *iface, LPSTR reserved )
550 {
551 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
552 FIXME( "(%p)->(%p): stub\n", This, reserved );
553 return E_NOTIMPL;
554 }
555
556 static HRESULT WINAPI IDirectPlayImpl_Send( IDirectPlay *iface, DPID from, DPID to, DWORD flags,
557 void *data, DWORD size )
558 {
559 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
560 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%u): stub\n", This, from, to, flags, data, size );
561 return E_NOTIMPL;
562 }
563
564 static HRESULT WINAPI IDirectPlayImpl_SetPlayerName( IDirectPlay *iface, DPID player, LPSTR name,
565 LPSTR fullname )
566 {
567 IDirectPlayImpl *This = impl_from_IDirectPlay( iface );
568 FIXME( "(%p)->(0x%08x,%s,%s): stub\n", This, player, debugstr_a( name ),
569 debugstr_a ( fullname ) );
570 return E_NOTIMPL;
571 }
572
573 static const IDirectPlayVtbl dp_vt =
574 {
575 IDirectPlayImpl_QueryInterface,
576 IDirectPlayImpl_AddRef,
577 IDirectPlayImpl_Release,
578 IDirectPlayImpl_AddPlayerToGroup,
579 IDirectPlayImpl_Close,
580 IDirectPlayImpl_CreatePlayer,
581 IDirectPlayImpl_CreateGroup,
582 IDirectPlayImpl_DeletePlayerFromGroup,
583 IDirectPlayImpl_DestroyPlayer,
584 IDirectPlayImpl_DestroyGroup,
585 IDirectPlayImpl_EnableNewPlayers,
586 IDirectPlayImpl_EnumGroupPlayers,
587 IDirectPlayImpl_EnumGroups,
588 IDirectPlayImpl_EnumPlayers,
589 IDirectPlayImpl_EnumSessions,
590 IDirectPlayImpl_GetCaps,
591 IDirectPlayImpl_GetMessageCount,
592 IDirectPlayImpl_GetPlayerCaps,
593 IDirectPlayImpl_GetPlayerName,
594 IDirectPlayImpl_Initialize,
595 IDirectPlayImpl_Open,
596 IDirectPlayImpl_Receive,
597 IDirectPlayImpl_SaveSession,
598 IDirectPlayImpl_Send,
599 IDirectPlayImpl_SetPlayerName,
600 };
601
602
603 static HRESULT WINAPI IDirectPlay2AImpl_QueryInterface( IDirectPlay2A *iface, REFIID riid,
604 void **ppv )
605 {
606 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
607 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
608 }
609
610 static HRESULT WINAPI IDirectPlay2Impl_QueryInterface( IDirectPlay2 *iface, REFIID riid,
611 void **ppv )
612 {
613 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
614 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
615 }
616
617 static HRESULT WINAPI IDirectPlay3AImpl_QueryInterface( IDirectPlay3A *iface, REFIID riid,
618 void **ppv )
619 {
620 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
621 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
622 }
623
624 static HRESULT WINAPI IDirectPlay3Impl_QueryInterface( IDirectPlay3 *iface, REFIID riid,
625 void **ppv )
626 {
627 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
628 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
629 }
630
631 static HRESULT WINAPI IDirectPlay4AImpl_QueryInterface( IDirectPlay4A *iface, REFIID riid,
632 void **ppv )
633 {
634 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
635 return IDirectPlayX_QueryInterface( &This->IDirectPlay4_iface, riid, ppv );
636 }
637
638 static HRESULT WINAPI IDirectPlay4Impl_QueryInterface( IDirectPlay4 *iface, REFIID riid,
639 void **ppv )
640 {
641 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
642
643 if ( IsEqualGUID( &IID_IUnknown, riid ) )
644 {
645 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv );
646 *ppv = &This->IDirectPlay_iface;
647 }
648 else if ( IsEqualGUID( &IID_IDirectPlay, riid ) )
649 {
650 TRACE( "(%p)->(IID_IDirectPlay %p)\n", This, ppv );
651 *ppv = &This->IDirectPlay_iface;
652 }
653 else if ( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
654 {
655 TRACE( "(%p)->(IID_IDirectPlay2A %p)\n", This, ppv );
656 *ppv = &This->IDirectPlay2A_iface;
657 }
658 else if ( IsEqualGUID( &IID_IDirectPlay2, riid ) )
659 {
660 TRACE( "(%p)->(IID_IDirectPlay2 %p)\n", This, ppv );
661 *ppv = &This->IDirectPlay2_iface;
662 }
663 else if ( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
664 {
665 TRACE( "(%p)->(IID_IDirectPlay3A %p)\n", This, ppv );
666 *ppv = &This->IDirectPlay3A_iface;
667 }
668 else if ( IsEqualGUID( &IID_IDirectPlay3, riid ) )
669 {
670 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv );
671 *ppv = &This->IDirectPlay3_iface;
672 }
673 else if ( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
674 {
675 TRACE( "(%p)->(IID_IDirectPlay4A %p)\n", This, ppv );
676 *ppv = &This->IDirectPlay4A_iface;
677 }
678 else if ( IsEqualGUID( &IID_IDirectPlay4, riid ) )
679 {
680 TRACE( "(%p)->(IID_IDirectPlay4 %p)\n", This, ppv );
681 *ppv = &This->IDirectPlay4_iface;
682 }
683 else
684 {
685 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
686 *ppv = NULL;
687 return E_NOINTERFACE;
688 }
689
690 IUnknown_AddRef((IUnknown*)*ppv);
691 return S_OK;
692 }
693
694 static ULONG WINAPI IDirectPlay2AImpl_AddRef( IDirectPlay2A *iface )
695 {
696 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
697 ULONG ref = InterlockedIncrement( &This->ref2A );
698
699 TRACE( "(%p) ref2A=%d\n", This, ref );
700
701 if ( ref == 1 )
702 InterlockedIncrement( &This->numIfaces );
703
704 return ref;
705 }
706
707 static ULONG WINAPI IDirectPlay2Impl_AddRef( IDirectPlay2 *iface )
708 {
709 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
710 ULONG ref = InterlockedIncrement( &This->ref2 );
711
712 TRACE( "(%p) ref2=%d\n", This, ref );
713
714 if ( ref == 1 )
715 InterlockedIncrement( &This->numIfaces );
716
717 return ref;
718 }
719
720 static ULONG WINAPI IDirectPlay3AImpl_AddRef( IDirectPlay3A *iface )
721 {
722 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
723 ULONG ref = InterlockedIncrement( &This->ref3A );
724
725 TRACE( "(%p) ref3A=%d\n", This, ref );
726
727 if ( ref == 1 )
728 InterlockedIncrement( &This->numIfaces );
729
730 return ref;
731 }
732
733 static ULONG WINAPI IDirectPlay3Impl_AddRef( IDirectPlay3 *iface )
734 {
735 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
736 ULONG ref = InterlockedIncrement( &This->ref3 );
737
738 TRACE( "(%p) ref3=%d\n", This, ref );
739
740 if ( ref == 1 )
741 InterlockedIncrement( &This->numIfaces );
742
743 return ref;
744 }
745
746 static ULONG WINAPI IDirectPlay4AImpl_AddRef(IDirectPlay4A *iface)
747 {
748 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
749 ULONG ref = InterlockedIncrement( &This->ref4A );
750
751 TRACE( "(%p) ref4A=%d\n", This, ref );
752
753 if ( ref == 1 )
754 InterlockedIncrement( &This->numIfaces );
755
756 return ref;
757 }
758
759 static ULONG WINAPI IDirectPlay4Impl_AddRef(IDirectPlay4 *iface)
760 {
761 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
762 ULONG ref = InterlockedIncrement( &This->ref4 );
763
764 TRACE( "(%p) ref4=%d\n", This, ref );
765
766 if ( ref == 1 )
767 InterlockedIncrement( &This->numIfaces );
768
769 return ref;
770 }
771
772 static ULONG WINAPI IDirectPlay2AImpl_Release( IDirectPlay2A *iface )
773 {
774 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
775 ULONG ref = InterlockedDecrement( &This->ref2A );
776
777 TRACE( "(%p) ref2A=%d\n", This, ref );
778
779 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
780 dplay_destroy( This );
781
782 return ref;
783 }
784
785 static ULONG WINAPI IDirectPlay2Impl_Release( IDirectPlay2 *iface )
786 {
787 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
788 ULONG ref = InterlockedDecrement( &This->ref2 );
789
790 TRACE( "(%p) ref2=%d\n", This, ref );
791
792 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
793 dplay_destroy( This );
794
795 return ref;
796 }
797
798 static ULONG WINAPI IDirectPlay3AImpl_Release( IDirectPlay3A *iface )
799 {
800 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
801 ULONG ref = InterlockedDecrement( &This->ref3A );
802
803 TRACE( "(%p) ref3A=%d\n", This, ref );
804
805 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
806 dplay_destroy( This );
807
808 return ref;
809 }
810
811 static ULONG WINAPI IDirectPlay3Impl_Release( IDirectPlay3 *iface )
812 {
813 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
814 ULONG ref = InterlockedDecrement( &This->ref3 );
815
816 TRACE( "(%p) ref3=%d\n", This, ref );
817
818 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
819 dplay_destroy( This );
820
821 return ref;
822 }
823
824 static ULONG WINAPI IDirectPlay4AImpl_Release(IDirectPlay4A *iface)
825 {
826 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
827 ULONG ref = InterlockedDecrement( &This->ref4A );
828
829 TRACE( "(%p) ref4A=%d\n", This, ref );
830
831 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
832 dplay_destroy( This );
833
834 return ref;
835 }
836
837 static ULONG WINAPI IDirectPlay4Impl_Release(IDirectPlay4 *iface)
838 {
839 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
840 ULONG ref = InterlockedDecrement( &This->ref4 );
841
842 TRACE( "(%p) ref4=%d\n", This, ref );
843
844 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
845 dplay_destroy( This );
846
847 return ref;
848 }
849
850 static HRESULT WINAPI IDirectPlay2AImpl_AddPlayerToGroup( IDirectPlay2A *iface, DPID group,
851 DPID player )
852 {
853 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
854 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4A_iface, group, player );
855 }
856
857 static HRESULT WINAPI IDirectPlay2Impl_AddPlayerToGroup( IDirectPlay2 *iface, DPID group,
858 DPID player )
859 {
860 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
861 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
862 }
863
864 static HRESULT WINAPI IDirectPlay3AImpl_AddPlayerToGroup( IDirectPlay3A *iface, DPID group,
865 DPID player )
866 {
867 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
868 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
869 }
870
871 static HRESULT WINAPI IDirectPlay3Impl_AddPlayerToGroup( IDirectPlay3 *iface, DPID group,
872 DPID player )
873 {
874 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
875 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
876 }
877
878 static HRESULT WINAPI IDirectPlay4AImpl_AddPlayerToGroup( IDirectPlay4A *iface, DPID group,
879 DPID player )
880 {
881 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
882 return IDirectPlayX_AddPlayerToGroup( &This->IDirectPlay4_iface, group, player );
883 }
884
885 static HRESULT WINAPI IDirectPlay4Impl_AddPlayerToGroup( IDirectPlay4 *iface, DPID group,
886 DPID player )
887 {
888 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
889 lpGroupData gdata;
890 lpPlayerList plist;
891 lpPlayerList newplist;
892
893 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
894
895 if ( This->dp2->connectionInitialized == NO_PROVIDER )
896 return DPERR_UNINITIALIZED;
897
898 /* Find the group */
899 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
900 return DPERR_INVALIDGROUP;
901
902 /* Find the player */
903 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
904 return DPERR_INVALIDPLAYER;
905
906 /* Create a player list (ie "shortcut" ) */
907 newplist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *newplist ) );
908 if ( !newplist )
909 return DPERR_CANTADDPLAYER;
910
911 /* Add the shortcut */
912 plist->lpPData->uRef++;
913 newplist->lpPData = plist->lpPData;
914
915 /* Add the player to the list of players for this group */
916 DPQ_INSERT(gdata->players, newplist, players);
917
918 /* Let the SP know that we've added a player to the group */
919 if ( This->dp2->spData.lpCB->AddPlayerToGroup )
920 {
921 DPSP_ADDPLAYERTOGROUPDATA data;
922
923 TRACE( "Calling SP AddPlayerToGroup\n" );
924
925 data.idPlayer = player;
926 data.idGroup = group;
927 data.lpISP = This->dp2->spData.lpISP;
928
929 (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
930 }
931
932 /* Inform all other peers of the addition of player to the group. If there are
933 * no peers keep this event quiet.
934 * Also, if this event was the result of another machine sending it to us,
935 * don't bother rebroadcasting it.
936 */
937 if ( This->dp2->lpSessionDesc &&
938 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
939 {
940 DPMSG_ADDPLAYERTOGROUP msg;
941 msg.dwType = DPSYS_ADDPLAYERTOGROUP;
942
943 msg.dpIdGroup = group;
944 msg.dpIdPlayer = player;
945
946 /* FIXME: Correct to just use send effectively? */
947 /* FIXME: Should size include data w/ message or just message "header" */
948 /* FIXME: Check return code */
949 IDirectPlayX_SendEx( iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
950 0, 0, NULL, NULL );
951 }
952
953 return DP_OK;
954 }
955
956 static HRESULT WINAPI IDirectPlay2AImpl_Close( IDirectPlay2A *iface )
957 {
958 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
959 return IDirectPlayX_Close( &This->IDirectPlay4A_iface );
960 }
961
962 static HRESULT WINAPI IDirectPlay2Impl_Close( IDirectPlay2 *iface )
963 {
964 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
965 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
966 }
967
968 static HRESULT WINAPI IDirectPlay3AImpl_Close( IDirectPlay3A *iface )
969 {
970 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
971 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
972 }
973
974 static HRESULT WINAPI IDirectPlay3Impl_Close( IDirectPlay3 *iface )
975 {
976 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
977 return IDirectPlayX_Close( &This->IDirectPlay4_iface );
978 }
979
980 static HRESULT WINAPI IDirectPlay4AImpl_Close( IDirectPlay4A *iface )
981 {
982 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
983 return IDirectPlayX_Close( &This->IDirectPlay4_iface);
984 }
985
986 static HRESULT WINAPI IDirectPlay4Impl_Close( IDirectPlay4 *iface )
987 {
988 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
989 HRESULT hr = DP_OK;
990
991 TRACE( "(%p)\n", This );
992
993 /* FIXME: Need to find a new host I assume (how?) */
994 /* FIXME: Need to destroy all local groups */
995 /* FIXME: Need to migrate all remotely visible players to the new host */
996
997 /* Invoke the SP callback to inform of session close */
998 if( This->dp2->spData.lpCB->CloseEx )
999 {
1000 DPSP_CLOSEDATA data;
1001
1002 TRACE( "Calling SP CloseEx\n" );
1003 data.lpISP = This->dp2->spData.lpISP;
1004 hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
1005 }
1006 else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
1007 {
1008 TRACE( "Calling SP Close (obsolete interface)\n" );
1009 hr = (*This->dp2->spData.lpCB->Close)();
1010 }
1011
1012 return hr;
1013 }
1014
1015 static lpGroupData DP_CreateGroup( IDirectPlayImpl *This, const DPID *lpid, const DPNAME *lpName,
1016 DWORD dwFlags, DPID idParent, BOOL bAnsi )
1017 {
1018 lpGroupData lpGData;
1019
1020 /* Allocate the new space and add to end of high level group list */
1021 lpGData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGData ) );
1022
1023 if( lpGData == NULL )
1024 {
1025 return NULL;
1026 }
1027
1028 DPQ_INIT(lpGData->groups);
1029 DPQ_INIT(lpGData->players);
1030
1031 /* Set the desired player ID - no sanity checking to see if it exists */
1032 lpGData->dpid = *lpid;
1033
1034 DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
1035
1036 /* FIXME: Should we check that the parent exists? */
1037 lpGData->parent = idParent;
1038
1039 /* FIXME: Should we validate the dwFlags? */
1040 lpGData->dwFlags = dwFlags;
1041
1042 TRACE( "Created group id 0x%08x\n", *lpid );
1043
1044 return lpGData;
1045 }
1046
1047 /* This method assumes that all links to it are already deleted */
1048 static void DP_DeleteGroup( IDirectPlayImpl *This, DPID dpid )
1049 {
1050 lpGroupList lpGList;
1051
1052 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1053
1054 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGList );
1055
1056 if( lpGList == NULL )
1057 {
1058 ERR( "DPID 0x%08x not found\n", dpid );
1059 return;
1060 }
1061
1062 if( --(lpGList->lpGData->uRef) )
1063 {
1064 FIXME( "Why is this not the last reference to group?\n" );
1065 DebugBreak();
1066 }
1067
1068 /* Delete player */
1069 DP_DeleteDPNameStruct( &lpGList->lpGData->name );
1070 HeapFree( GetProcessHeap(), 0, lpGList->lpGData );
1071
1072 /* Remove and Delete Player List object */
1073 HeapFree( GetProcessHeap(), 0, lpGList );
1074
1075 }
1076
1077 static lpGroupData DP_FindAnyGroup( IDirectPlayImpl *This, DPID dpid )
1078 {
1079 lpGroupList lpGroups;
1080
1081 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1082
1083 if( dpid == DPID_SYSTEM_GROUP )
1084 {
1085 return This->dp2->lpSysGroup;
1086 }
1087 else
1088 {
1089 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
1090 }
1091
1092 if( lpGroups == NULL )
1093 {
1094 return NULL;
1095 }
1096
1097 return lpGroups->lpGData;
1098 }
1099
1100 static HRESULT DP_IF_CreateGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidGroup,
1101 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
1102 {
1103 lpGroupData lpGData;
1104
1105 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1106 This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
1107 dwFlags, bAnsi );
1108
1109 if( This->dp2->connectionInitialized == NO_PROVIDER )
1110 {
1111 return DPERR_UNINITIALIZED;
1112 }
1113
1114 /* If the name is not specified, we must provide one */
1115 if( DPID_UNKNOWN == *lpidGroup )
1116 {
1117 /* If we are the name server, we decide on the group ids. If not, we
1118 * must ask for one before attempting a creation.
1119 */
1120 if( This->dp2->bHostInterface )
1121 {
1122 *lpidGroup = DP_NextObjectId();
1123 }
1124 else
1125 {
1126 *lpidGroup = DP_GetRemoteNextObjectId();
1127 }
1128 }
1129
1130 lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
1131 DPID_NOPARENT_GROUP, bAnsi );
1132
1133 if( lpGData == NULL )
1134 {
1135 return DPERR_CANTADDPLAYER; /* yes player not group */
1136 }
1137
1138 if( DPID_SYSTEM_GROUP == *lpidGroup )
1139 {
1140 This->dp2->lpSysGroup = lpGData;
1141 TRACE( "Inserting system group\n" );
1142 }
1143 else
1144 {
1145 /* Insert into the system group */
1146 lpGroupList lpGroup = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGroup ) );
1147 lpGroup->lpGData = lpGData;
1148
1149 DPQ_INSERT( This->dp2->lpSysGroup->groups, lpGroup, groups );
1150 }
1151
1152 /* Something is now referencing this data */
1153 lpGData->uRef++;
1154
1155 /* Set all the important stuff for the group */
1156 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
1157
1158 /* FIXME: We should only create the system group if GetCaps returns
1159 * DPCAPS_GROUPOPTIMIZED.
1160 */
1161
1162 /* Let the SP know that we've created this group */
1163 if( This->dp2->spData.lpCB->CreateGroup )
1164 {
1165 DPSP_CREATEGROUPDATA data;
1166 DWORD dwCreateFlags = 0;
1167
1168 TRACE( "Calling SP CreateGroup\n" );
1169
1170 if( *lpidGroup == DPID_NOPARENT_GROUP )
1171 dwCreateFlags |= DPLAYI_GROUP_SYSGROUP;
1172
1173 if( lpMsgHdr == NULL )
1174 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1175
1176 if( dwFlags & DPGROUP_HIDDEN )
1177 dwCreateFlags |= DPLAYI_GROUP_HIDDEN;
1178
1179 data.idGroup = *lpidGroup;
1180 data.dwFlags = dwCreateFlags;
1181 data.lpSPMessageHeader = lpMsgHdr;
1182 data.lpISP = This->dp2->spData.lpISP;
1183
1184 (*This->dp2->spData.lpCB->CreateGroup)( &data );
1185 }
1186
1187 /* Inform all other peers of the creation of a new group. If there are
1188 * no peers keep this event quiet.
1189 * Also if this message was sent to us, don't rebroadcast.
1190 */
1191 if( ( lpMsgHdr == NULL ) &&
1192 This->dp2->lpSessionDesc &&
1193 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1194 {
1195 DPMSG_CREATEPLAYERORGROUP msg;
1196 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1197
1198 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
1199 msg.dpId = *lpidGroup;
1200 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect? */
1201 msg.lpData = lpData;
1202 msg.dwDataSize = dwDataSize;
1203 msg.dpnName = *lpGroupName;
1204 msg.dpIdParent = DPID_NOPARENT_GROUP;
1205 msg.dwFlags = DPMSG_CREATEGROUP_DWFLAGS( dwFlags );
1206
1207 /* FIXME: Correct to just use send effectively? */
1208 /* FIXME: Should size include data w/ message or just message "header" */
1209 /* FIXME: Check return code */
1210 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
1211 sizeof( msg ), 0, 0, NULL, NULL );
1212 }
1213
1214 return DP_OK;
1215 }
1216
1217 static HRESULT WINAPI IDirectPlay2AImpl_CreateGroup( IDirectPlay2A *iface, DPID *lpidGroup,
1218 DPNAME *name, void *data, DWORD size, DWORD flags )
1219 {
1220 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1221 return IDirectPlayX_CreateGroup( &This->IDirectPlay4A_iface, lpidGroup, name, data, size,
1222 flags );
1223 }
1224
1225 static HRESULT WINAPI IDirectPlay2Impl_CreateGroup( IDirectPlay2 *iface, DPID *lpidGroup,
1226 DPNAME *name, void *data, DWORD size, DWORD flags )
1227 {
1228 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1229 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1230 flags );
1231 }
1232
1233 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroup( IDirectPlay3A *iface, DPID *group,
1234 DPNAME *name, void *data, DWORD size, DWORD flags )
1235 {
1236 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1237 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, group, name, data, size,
1238 flags );
1239 }
1240
1241 static HRESULT WINAPI IDirectPlay3Impl_CreateGroup( IDirectPlay3 *iface, DPID *lpidGroup,
1242 DPNAME *name, void *data, DWORD size, DWORD flags )
1243 {
1244 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1245 return IDirectPlayX_CreateGroup( &This->IDirectPlay4_iface, lpidGroup, name, data, size,
1246 flags );
1247 }
1248
1249 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroup( IDirectPlay4A *iface, DPID *lpidGroup,
1250 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1251 {
1252 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1253
1254 *lpidGroup = DPID_UNKNOWN;
1255
1256 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1257 TRUE );
1258 }
1259
1260 static HRESULT WINAPI IDirectPlay4Impl_CreateGroup( IDirectPlay4 *iface, DPID *lpidGroup,
1261 DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1262 {
1263 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1264
1265 *lpidGroup = DPID_UNKNOWN;
1266
1267 return DP_IF_CreateGroup( This, NULL, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags,
1268 FALSE );
1269 }
1270
1271
1272 static void
1273 DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
1274 LPVOID lpData, DWORD dwDataSize )
1275 {
1276 /* Clear out the data with this player */
1277 if( dwFlags & DPSET_LOCAL )
1278 {
1279 if ( lpGData->dwLocalDataSize != 0 )
1280 {
1281 HeapFree( GetProcessHeap(), 0, lpGData->lpLocalData );
1282 lpGData->lpLocalData = NULL;
1283 lpGData->dwLocalDataSize = 0;
1284 }
1285 }
1286 else
1287 {
1288 if( lpGData->dwRemoteDataSize != 0 )
1289 {
1290 HeapFree( GetProcessHeap(), 0, lpGData->lpRemoteData );
1291 lpGData->lpRemoteData = NULL;
1292 lpGData->dwRemoteDataSize = 0;
1293 }
1294 }
1295
1296 /* Reallocate for new data */
1297 if( lpData != NULL )
1298 {
1299 if( dwFlags & DPSET_LOCAL )
1300 {
1301 lpGData->lpLocalData = lpData;
1302 lpGData->dwLocalDataSize = dwDataSize;
1303 }
1304 else
1305 {
1306 lpGData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1307 CopyMemory( lpGData->lpRemoteData, lpData, dwDataSize );
1308 lpGData->dwRemoteDataSize = dwDataSize;
1309 }
1310 }
1311
1312 }
1313
1314 /* This function will just create the storage for the new player. */
1315 static lpPlayerData DP_CreatePlayer( IDirectPlayImpl *This, DPID *lpid, DPNAME *lpName,
1316 DWORD dwFlags, HANDLE hEvent, BOOL bAnsi )
1317 {
1318 lpPlayerData lpPData;
1319
1320 TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
1321
1322 /* Allocate the storage for the player and associate it with list element */
1323 lpPData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPData ) );
1324 if( lpPData == NULL )
1325 {
1326 return NULL;
1327 }
1328
1329 /* Set the desired player ID */
1330 lpPData->dpid = *lpid;
1331
1332 DP_CopyDPNAMEStruct( &lpPData->name, lpName, bAnsi );
1333
1334 lpPData->dwFlags = dwFlags;
1335
1336 /* If we were given an event handle, duplicate it */
1337 if( hEvent != 0 )
1338 {
1339 if( !DuplicateHandle( GetCurrentProcess(), hEvent,
1340 GetCurrentProcess(), &lpPData->hEvent,
1341 0, FALSE, DUPLICATE_SAME_ACCESS )
1342 )
1343 {
1344 /* FIXME: Memory leak */
1345 ERR( "Can't duplicate player msg handle %p\n", hEvent );
1346 }
1347 }
1348
1349 /* Initialize the SP data section */
1350 lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
1351
1352 TRACE( "Created player id 0x%08x\n", *lpid );
1353
1354 if( ~dwFlags & DPLAYI_PLAYER_SYSPLAYER )
1355 This->dp2->lpSessionDesc->dwCurrentPlayers++;
1356
1357 return lpPData;
1358 }
1359
1360 /* Delete the contents of the DPNAME struct */
1361 static void
1362 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
1363 {
1364 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
1365 HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
1366 }
1367
1368 /* This method assumes that all links to it are already deleted */
1369 static void DP_DeletePlayer( IDirectPlayImpl *This, DPID dpid )
1370 {
1371 lpPlayerList lpPList;
1372
1373 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1374
1375 DPQ_REMOVE_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPList );
1376
1377 if( lpPList == NULL )
1378 {
1379 ERR( "DPID 0x%08x not found\n", dpid );
1380 return;
1381 }
1382
1383 /* Verify that this is the last reference to the data */
1384 if( --(lpPList->lpPData->uRef) )
1385 {
1386 FIXME( "Why is this not the last reference to player?\n" );
1387 DebugBreak();
1388 }
1389
1390 /* Delete player */
1391 DP_DeleteDPNameStruct( &lpPList->lpPData->name );
1392
1393 CloseHandle( lpPList->lpPData->hEvent );
1394 HeapFree( GetProcessHeap(), 0, lpPList->lpPData );
1395
1396 /* Delete Player List object */
1397 HeapFree( GetProcessHeap(), 0, lpPList );
1398 }
1399
1400 static lpPlayerList DP_FindPlayer( IDirectPlayImpl *This, DPID dpid )
1401 {
1402 lpPlayerList lpPlayers;
1403
1404 TRACE( "(%p)->(0x%08x)\n", This, dpid );
1405
1406 if(This->dp2->lpSysGroup == NULL)
1407 return NULL;
1408
1409 DPQ_FIND_ENTRY( This->dp2->lpSysGroup->players, players, lpPData->dpid, ==, dpid, lpPlayers );
1410
1411 return lpPlayers;
1412 }
1413
1414 /* Basic area for Dst must already be allocated */
1415 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, const DPNAME *lpSrc, BOOL bAnsi )
1416 {
1417 if( lpSrc == NULL )
1418 {
1419 ZeroMemory( lpDst, sizeof( *lpDst ) );
1420 lpDst->dwSize = sizeof( *lpDst );
1421 return TRUE;
1422 }
1423
1424 if( lpSrc->dwSize != sizeof( *lpSrc) )
1425 {
1426 return FALSE;
1427 }
1428
1429 /* Delete any existing pointers */
1430 HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
1431 HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
1432
1433 /* Copy as required */
1434 CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
1435
1436 if( bAnsi )
1437 {
1438 if( lpSrc->u1.lpszShortNameA )
1439 {
1440 lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
1441 strlen(lpSrc->u1.lpszShortNameA)+1 );
1442 strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
1443 }
1444 if( lpSrc->u2.lpszLongNameA )
1445 {
1446 lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
1447 strlen(lpSrc->u2.lpszLongNameA)+1 );
1448 strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
1449 }
1450 }
1451 else
1452 {
1453 if( lpSrc->u1.lpszShortNameA )
1454 {
1455 lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
1456 (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
1457 strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
1458 }
1459 if( lpSrc->u2.lpszLongNameA )
1460 {
1461 lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
1462 (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
1463 strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
1464 }
1465 }
1466
1467 return TRUE;
1468 }
1469
1470 static void
1471 DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
1472 LPVOID lpData, DWORD dwDataSize )
1473 {
1474 /* Clear out the data with this player */
1475 if( dwFlags & DPSET_LOCAL )
1476 {
1477 if ( lpPData->dwLocalDataSize != 0 )
1478 {
1479 HeapFree( GetProcessHeap(), 0, lpPData->lpLocalData );
1480 lpPData->lpLocalData = NULL;
1481 lpPData->dwLocalDataSize = 0;
1482 }
1483 }
1484 else
1485 {
1486 if( lpPData->dwRemoteDataSize != 0 )
1487 {
1488 HeapFree( GetProcessHeap(), 0, lpPData->lpRemoteData );
1489 lpPData->lpRemoteData = NULL;
1490 lpPData->dwRemoteDataSize = 0;
1491 }
1492 }
1493
1494 /* Reallocate for new data */
1495 if( lpData != NULL )
1496 {
1497
1498 if( dwFlags & DPSET_LOCAL )
1499 {
1500 lpPData->lpLocalData = lpData;
1501 lpPData->dwLocalDataSize = dwDataSize;
1502 }
1503 else
1504 {
1505 lpPData->lpRemoteData = HeapAlloc( GetProcessHeap(), 0, dwDataSize );
1506 CopyMemory( lpPData->lpRemoteData, lpData, dwDataSize );
1507 lpPData->dwRemoteDataSize = dwDataSize;
1508 }
1509 }
1510
1511 }
1512
1513 /* Note: lpMsgHdr is NULL for local creation, non NULL for remote creation */
1514 static HRESULT DP_IF_CreatePlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID *lpidPlayer,
1515 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags,
1516 BOOL bAnsi )
1517 {
1518 HRESULT hr = DP_OK;
1519 lpPlayerData lpPData;
1520 lpPlayerList lpPList;
1521 DWORD dwCreateFlags = 0;
1522
1523 TRACE( "(%p)->(%p,%p,%p,%p,0x%08x,0x%08x,%u)\n",
1524 This, lpidPlayer, lpPlayerName, hEvent, lpData,
1525 dwDataSize, dwFlags, bAnsi );
1526 if( This->dp2->connectionInitialized == NO_PROVIDER )
1527 {
1528 return DPERR_UNINITIALIZED;
1529 }
1530
1531 if( dwFlags == 0 )
1532 {
1533 dwFlags = DPPLAYER_SPECTATOR;
1534 }
1535
1536 if( lpidPlayer == NULL )
1537 {
1538 return DPERR_INVALIDPARAMS;
1539 }
1540
1541
1542 /* Determine the creation flags for the player. These will be passed
1543 * to the name server if requesting a player id and to the SP when
1544 * informing it of the player creation
1545 */
1546 {
1547 if( dwFlags & DPPLAYER_SERVERPLAYER )
1548 {
1549 if( *lpidPlayer == DPID_SERVERPLAYER )
1550 {
1551 /* Server player for the host interface */
1552 dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
1553 }
1554 else if( *lpidPlayer == DPID_NAME_SERVER )
1555 {
1556 /* Name server - master of everything */
1557 dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
1558 }
1559 else
1560 {
1561 /* Server player for a non host interface */
1562 dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
1563 }
1564 }
1565
1566 if( lpMsgHdr == NULL )
1567 dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
1568 }
1569
1570 /* Verify we know how to handle all the flags */
1571 if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
1572 ( dwFlags & DPPLAYER_SPECTATOR )
1573 )
1574 )
1575 {
1576 /* Assume non fatal failure */
1577 ERR( "unknown dwFlags = 0x%08x\n", dwFlags );
1578 }
1579
1580 /* If the name is not specified, we must provide one */
1581 if( *lpidPlayer == DPID_UNKNOWN )
1582 {
1583 /* If we are the session master, we dish out the group/player ids */
1584 if( This->dp2->bHostInterface )
1585 {
1586 *lpidPlayer = DP_NextObjectId();
1587 }
1588 else
1589 {
1590 hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
1591
1592 if( FAILED(hr) )
1593 {
1594 ERR( "Request for ID failed: %s\n", DPLAYX_HresultToString( hr ) );
1595 return hr;
1596 }
1597 }
1598 }
1599 else
1600 {
1601 /* FIXME: Would be nice to perhaps verify that we don't already have
1602 * this player.
1603 */
1604 }
1605
1606 /* We pass creation flags, so we can distinguish sysplayers and not count them in the current
1607 player total */
1608 lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwCreateFlags,
1609 hEvent, bAnsi );
1610
1611 if( lpPData == NULL )
1612 {
1613 return DPERR_CANTADDPLAYER;
1614 }
1615
1616 /* Create the list object and link it in */
1617 lpPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpPList ) );
1618 if( lpPList == NULL )
1619 {
1620 FIXME( "Memory leak\n" );
1621 return DPERR_CANTADDPLAYER;
1622 }
1623
1624 lpPData->uRef = 1;
1625 lpPList->lpPData = lpPData;
1626
1627 /* Add the player to the system group */
1628 DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
1629
1630 /* Update the information and send it to all players in the session */
1631 DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
1632
1633 /* Let the SP know that we've created this player */
1634 if( This->dp2->spData.lpCB->CreatePlayer )
1635 {
1636 DPSP_CREATEPLAYERDATA data;
1637
1638 data.idPlayer = *lpidPlayer;
1639 data.dwFlags = dwCreateFlags;
1640 data.lpSPMessageHeader = lpMsgHdr;
1641 data.lpISP = This->dp2->spData.lpISP;
1642
1643 TRACE( "Calling SP CreatePlayer 0x%08x: dwFlags: 0x%08x lpMsgHdr: %p\n",
1644 *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
1645
1646 hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
1647 }
1648
1649 if( FAILED(hr) )
1650 {
1651 ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
1652 return hr;
1653 }
1654
1655 /* Now let the SP know that this player is a member of the system group */
1656 if( This->dp2->spData.lpCB->AddPlayerToGroup )
1657 {
1658 DPSP_ADDPLAYERTOGROUPDATA data;
1659
1660 data.idPlayer = *lpidPlayer;
1661 data.idGroup = DPID_SYSTEM_GROUP;
1662 data.lpISP = This->dp2->spData.lpISP;
1663
1664 TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
1665
1666 hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
1667 }
1668
1669 if( FAILED(hr) )
1670 {
1671 ERR( "Failed to add player to sys group with sp: %s\n",
1672 DPLAYX_HresultToString(hr) );
1673 return hr;
1674 }
1675
1676 #if 1
1677 if( This->dp2->bHostInterface == FALSE )
1678 {
1679 /* Let the name server know about the creation of this player */
1680 /* FIXME: Is this only to be done for the creation of a server player or
1681 * is this used for regular players? If only for server players, move
1682 * this call to DP_SecureOpen(...);
1683 */
1684 #if 0
1685 TRACE( "Sending message to self to get my addr\n" );
1686 DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
1687 #endif
1688
1689 hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
1690 }
1691 #else
1692 /* Inform all other peers of the creation of a new player. If there are
1693 * no peers keep this quiet.
1694 * Also, if this was a remote event, no need to rebroadcast it.
1695 */
1696 if( ( lpMsgHdr == NULL ) &&
1697 This->dp2->lpSessionDesc &&
1698 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
1699 {
1700 DPMSG_CREATEPLAYERORGROUP msg;
1701 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
1702
1703 msg.dwPlayerType = DPPLAYERTYPE_PLAYER;
1704 msg.dpId = *lpidPlayer;
1705 msg.dwCurrentPlayers = 0; /* FIXME: Incorrect */
1706 msg.lpData = lpData;
1707 msg.dwDataSize = dwDataSize;
1708 msg.dpnName = *lpPlayerName;
1709 msg.dpIdParent = DPID_NOPARENT_GROUP;
1710 msg.dwFlags = DPMSG_CREATEPLAYER_DWFLAGS( dwFlags );
1711
1712 /* FIXME: Correct to just use send effectively? */
1713 /* FIXME: Should size include data w/ message or just message "header" */
1714 /* FIXME: Check return code */
1715 hr = IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0,
1716 &msg, sizeof( msg ), 0, 0, NULL, NULL );
1717 }
1718 #endif
1719
1720 return hr;
1721 }
1722
1723 static HRESULT WINAPI IDirectPlay2AImpl_CreatePlayer( IDirectPlay2A *iface, DPID *lpidPlayer,
1724 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1725 {
1726 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1727 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4A_iface, lpidPlayer, name, event, data,
1728 size, flags );
1729 }
1730
1731 static HRESULT WINAPI IDirectPlay2Impl_CreatePlayer( IDirectPlay2 *iface, DPID *lpidPlayer,
1732 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1733 {
1734 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1735 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1736 size, flags );
1737 }
1738
1739 static HRESULT WINAPI IDirectPlay3AImpl_CreatePlayer( IDirectPlay3A *iface, DPID *lpidPlayer,
1740 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1741 {
1742 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1743 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1744 size, flags );
1745 }
1746
1747 static HRESULT WINAPI IDirectPlay3Impl_CreatePlayer( IDirectPlay3 *iface, DPID *lpidPlayer,
1748 DPNAME *name, HANDLE event, void *data, DWORD size, DWORD flags )
1749 {
1750 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1751 return IDirectPlayX_CreatePlayer( &This->IDirectPlay4_iface, lpidPlayer, name, event, data,
1752 size, flags );
1753 }
1754
1755 static HRESULT WINAPI IDirectPlay4AImpl_CreatePlayer( IDirectPlay4A *iface, DPID *lpidPlayer,
1756 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1757 {
1758 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1759
1760 if( lpidPlayer == NULL )
1761 {
1762 return DPERR_INVALIDPARAMS;
1763 }
1764
1765 if( dwFlags & DPPLAYER_SERVERPLAYER )
1766 {
1767 *lpidPlayer = DPID_SERVERPLAYER;
1768 }
1769 else
1770 {
1771 *lpidPlayer = DPID_UNKNOWN;
1772 }
1773
1774 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1775 lpData, dwDataSize, dwFlags, TRUE );
1776 }
1777
1778 static HRESULT WINAPI IDirectPlay4Impl_CreatePlayer( IDirectPlay4 *iface, DPID *lpidPlayer,
1779 DPNAME *lpPlayerName, HANDLE hEvent, void *lpData, DWORD dwDataSize, DWORD dwFlags )
1780 {
1781 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1782
1783 if( lpidPlayer == NULL )
1784 {
1785 return DPERR_INVALIDPARAMS;
1786 }
1787
1788 if( dwFlags & DPPLAYER_SERVERPLAYER )
1789 {
1790 *lpidPlayer = DPID_SERVERPLAYER;
1791 }
1792 else
1793 {
1794 *lpidPlayer = DPID_UNKNOWN;
1795 }
1796
1797 return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
1798 lpData, dwDataSize, dwFlags, FALSE );
1799 }
1800
1801 static DPID DP_GetRemoteNextObjectId(void)
1802 {
1803 FIXME( ":stub\n" );
1804
1805 /* Hack solution */
1806 return DP_NextObjectId();
1807 }
1808
1809 static HRESULT WINAPI IDirectPlay2AImpl_DeletePlayerFromGroup( IDirectPlay2A *iface, DPID group,
1810 DPID player )
1811 {
1812 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1813 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4A_iface, group, player );
1814 }
1815
1816 static HRESULT WINAPI IDirectPlay2Impl_DeletePlayerFromGroup( IDirectPlay2 *iface, DPID group,
1817 DPID player )
1818 {
1819 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1820 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1821 }
1822
1823 static HRESULT WINAPI IDirectPlay3AImpl_DeletePlayerFromGroup( IDirectPlay3A *iface, DPID group,
1824 DPID player )
1825 {
1826 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1827 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1828 }
1829
1830 static HRESULT WINAPI IDirectPlay3Impl_DeletePlayerFromGroup( IDirectPlay3 *iface, DPID group,
1831 DPID player )
1832 {
1833 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1834 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1835 }
1836
1837 static HRESULT WINAPI IDirectPlay4AImpl_DeletePlayerFromGroup( IDirectPlay4A *iface, DPID group,
1838 DPID player )
1839 {
1840 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
1841 return IDirectPlayX_DeletePlayerFromGroup( &This->IDirectPlay4_iface, group, player );
1842 }
1843
1844 static HRESULT WINAPI IDirectPlay4Impl_DeletePlayerFromGroup( IDirectPlay4 *iface, DPID group,
1845 DPID player )
1846 {
1847 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
1848 HRESULT hr = DP_OK;
1849
1850 lpGroupData gdata;
1851 lpPlayerList plist;
1852
1853 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, group, player );
1854
1855 /* Find the group */
1856 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
1857 return DPERR_INVALIDGROUP;
1858
1859 /* Find the player */
1860 if ( DP_FindPlayer( This, player ) == NULL )
1861 return DPERR_INVALIDPLAYER;
1862
1863 /* Remove the player shortcut from the group */
1864 DPQ_REMOVE_ENTRY( gdata->players, players, lpPData->dpid, ==, player, plist );
1865
1866 if ( !plist )
1867 return DPERR_INVALIDPLAYER;
1868
1869 /* One less reference */
1870 plist->lpPData->uRef--;
1871
1872 /* Delete the Player List element */
1873 HeapFree( GetProcessHeap(), 0, plist );
1874
1875 /* Inform the SP if they care */
1876 if ( This->dp2->spData.lpCB->RemovePlayerFromGroup )
1877 {
1878 DPSP_REMOVEPLAYERFROMGROUPDATA data;
1879
1880 TRACE( "Calling SP RemovePlayerFromGroup\n" );
1881 data.idPlayer = player;
1882 data.idGroup = group;
1883 data.lpISP = This->dp2->spData.lpISP;
1884 hr = (*This->dp2->spData.lpCB->RemovePlayerFromGroup)( &data );
1885 }
1886
1887 /* Need to send a DELETEPLAYERFROMGROUP message */
1888 FIXME( "Need to send a message\n" );
1889
1890 return hr;
1891 }
1892
1893 typedef struct _DPRGOPContext
1894 {
1895 IDirectPlayImpl *This;
1896 BOOL bAnsi;
1897 DPID idGroup;
1898 } DPRGOPContext, *lpDPRGOPContext;
1899
1900 static BOOL CALLBACK
1901 cbRemoveGroupOrPlayer(
1902 DPID dpId,
1903 DWORD dwPlayerType,
1904 LPCDPNAME lpName,
1905 DWORD dwFlags,
1906 LPVOID lpContext )
1907 {
1908 lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
1909
1910 TRACE( "Removing element:0x%08x (type:0x%08x) from element:0x%08x\n",
1911 dpId, dwPlayerType, lpCtxt->idGroup );
1912
1913 if( dwPlayerType == DPPLAYERTYPE_GROUP )
1914 {
1915 if ( FAILED( IDirectPlayX_DeleteGroupFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1916 lpCtxt->idGroup, dpId ) ) )
1917 ERR( "Unable to delete group 0x%08x from group 0x%08x\n", dpId, lpCtxt->idGroup );
1918 }
1919 else if ( FAILED( IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface,
1920 lpCtxt->idGroup, dpId ) ) )
1921 ERR( "Unable to delete player 0x%08x from grp 0x%08x\n", dpId, lpCtxt->idGroup );
1922
1923 return TRUE; /* Continue enumeration */
1924 }
1925
1926 static HRESULT DP_IF_DestroyGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idGroup, BOOL bAnsi )
1927 {
1928 lpGroupData lpGData;
1929 DPRGOPContext context;
1930
1931 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
1932 This, lpMsgHdr, idGroup, bAnsi );
1933
1934 /* Find the group */
1935 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
1936 {
1937 return DPERR_INVALIDPLAYER; /* yes player */
1938 }
1939
1940 context.This = This;
1941 context.bAnsi = bAnsi;
1942 context.idGroup = idGroup;
1943
1944 /* Remove all players that this group has */
1945 IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1946 &context, 0 );
1947
1948 /* Remove all links to groups that this group has since this is dp3 */
1949 IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, idGroup, NULL, cbRemoveGroupOrPlayer,
1950 (void*)&context, 0 );
1951
1952 /* Remove this group from the parent group - if it has one */
1953 if( ( idGroup != DPID_SYSTEM_GROUP ) && ( lpGData->parent != DPID_SYSTEM_GROUP ) )
1954 IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, lpGData->parent, idGroup );
1955
1956 /* Now delete this group data and list from the system group */
1957 DP_DeleteGroup( This, idGroup );
1958
1959 /* Let the SP know that we've destroyed this group */
1960 if( This->dp2->spData.lpCB->DeleteGroup )
1961 {
1962 DPSP_DELETEGROUPDATA data;
1963
1964 FIXME( "data.dwFlags is incorrect\n" );
1965
1966 data.idGroup = idGroup;
1967 data.dwFlags = 0;
1968 data.lpISP = This->dp2->spData.lpISP;
1969
1970 (*This->dp2->spData.lpCB->DeleteGroup)( &data );
1971 }
1972
1973 FIXME( "Send out a DESTORYPLAYERORGROUP message\n" );
1974
1975 return DP_OK;
1976 }
1977
1978 static HRESULT WINAPI IDirectPlay2AImpl_DestroyGroup( IDirectPlay2A *iface, DPID group )
1979 {
1980 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
1981 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4A_iface, group );
1982 }
1983
1984 static HRESULT WINAPI IDirectPlay2Impl_DestroyGroup( IDirectPlay2 *iface, DPID group )
1985 {
1986 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
1987 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1988 }
1989
1990 static HRESULT WINAPI IDirectPlay3AImpl_DestroyGroup( IDirectPlay3A *iface, DPID group )
1991 {
1992 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
1993 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
1994 }
1995
1996 static HRESULT WINAPI IDirectPlay3Impl_DestroyGroup( IDirectPlay3 *iface, DPID group )
1997 {
1998 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
1999 return IDirectPlayX_DestroyGroup( &This->IDirectPlay4_iface, group );
2000 }
2001
2002 static HRESULT WINAPI IDirectPlay4AImpl_DestroyGroup( IDirectPlay4A *iface, DPID idGroup )
2003 {
2004 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2005 return DP_IF_DestroyGroup( This, NULL, idGroup, TRUE );
2006 }
2007
2008 static HRESULT WINAPI IDirectPlay4Impl_DestroyGroup( IDirectPlay4 *iface, DPID idGroup )
2009 {
2010 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2011 return DP_IF_DestroyGroup( This, NULL, idGroup, FALSE );
2012 }
2013
2014 typedef struct _DPFAGContext
2015 {
2016 IDirectPlayImpl *This;
2017 DPID idPlayer;
2018 BOOL bAnsi;
2019 } DPFAGContext, *lpDPFAGContext;
2020
2021 static HRESULT DP_IF_DestroyPlayer( IDirectPlayImpl *This, void *lpMsgHdr, DPID idPlayer,
2022 BOOL bAnsi )
2023 {
2024 DPFAGContext cbContext;
2025
2026 FIXME( "(%p)->(%p,0x%08x,%u): semi stub\n",
2027 This, lpMsgHdr, idPlayer, bAnsi );
2028
2029 if( This->dp2->connectionInitialized == NO_PROVIDER )
2030 {
2031 return DPERR_UNINITIALIZED;
2032 }
2033
2034 if( DP_FindPlayer( This, idPlayer ) == NULL )
2035 {
2036 return DPERR_INVALIDPLAYER;
2037 }
2038
2039 /* FIXME: If the player is remote, we must be the host to delete this */
2040
2041 cbContext.This = This;
2042 cbContext.idPlayer = idPlayer;
2043 cbContext.bAnsi = bAnsi;
2044
2045 /* Find each group and call DeletePlayerFromGroup if the player is a
2046 member of the group */
2047 IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, NULL, cbDeletePlayerFromAllGroups, &cbContext,
2048 DPENUMGROUPS_ALL );
2049
2050 /* Now delete player and player list from the sys group */
2051 DP_DeletePlayer( This, idPlayer );
2052
2053 /* Let the SP know that we've destroyed this group */
2054 if( This->dp2->spData.lpCB->DeletePlayer )
2055 {
2056 DPSP_DELETEPLAYERDATA data;
2057
2058 FIXME( "data.dwFlags is incorrect\n" );
2059
2060 data.idPlayer = idPlayer;
2061 data.dwFlags = 0;
2062 data.lpISP = This->dp2->spData.lpISP;
2063
2064 (*This->dp2->spData.lpCB->DeletePlayer)( &data );
2065 }
2066
2067 FIXME( "Send a DELETEPLAYERORGROUP msg\n" );
2068
2069 return DP_OK;
2070 }
2071
2072 static BOOL CALLBACK
2073 cbDeletePlayerFromAllGroups(
2074 DPID dpId,
2075 DWORD dwPlayerType,
2076 LPCDPNAME lpName,
2077 DWORD dwFlags,
2078 LPVOID lpContext )
2079 {
2080 lpDPFAGContext lpCtxt = (lpDPFAGContext)lpContext;
2081
2082 if( dwPlayerType == DPPLAYERTYPE_GROUP )
2083 {
2084 IDirectPlayX_DeletePlayerFromGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, lpCtxt->idPlayer );
2085
2086 /* Enumerate all groups in this group since this will normally only
2087 * be called for top level groups
2088 */
2089 IDirectPlayX_EnumGroupsInGroup( &lpCtxt->This->IDirectPlay4_iface, dpId, NULL,
2090 cbDeletePlayerFromAllGroups, lpContext, DPENUMGROUPS_ALL);
2091
2092 }
2093 else
2094 {
2095 ERR( "Group callback has dwPlayerType = 0x%08x\n", dwPlayerType );
2096 }
2097
2098 return TRUE;
2099 }
2100
2101 static HRESULT WINAPI IDirectPlay2AImpl_DestroyPlayer( IDirectPlay2A *iface, DPID player )
2102 {
2103 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2104 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4A_iface, player );
2105 }
2106
2107 static HRESULT WINAPI IDirectPlay2Impl_DestroyPlayer( IDirectPlay2 *iface, DPID player )
2108 {
2109 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2110 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2111 }
2112
2113 static HRESULT WINAPI IDirectPlay3AImpl_DestroyPlayer( IDirectPlay3A *iface, DPID player )
2114 {
2115 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2116 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2117 }
2118
2119 static HRESULT WINAPI IDirectPlay3Impl_DestroyPlayer( IDirectPlay3 *iface, DPID player )
2120 {
2121 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2122 return IDirectPlayX_DestroyPlayer( &This->IDirectPlay4_iface, player );
2123 }
2124
2125 static HRESULT WINAPI IDirectPlay4AImpl_DestroyPlayer( IDirectPlay4A *iface, DPID idPlayer )
2126 {
2127 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2128 return DP_IF_DestroyPlayer( This, NULL, idPlayer, TRUE );
2129 }
2130
2131 static HRESULT WINAPI IDirectPlay4Impl_DestroyPlayer( IDirectPlay4 *iface, DPID idPlayer )
2132 {
2133 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2134 return DP_IF_DestroyPlayer( This, NULL, idPlayer, FALSE );
2135 }
2136
2137 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroupPlayers( IDirectPlay2A *iface, DPID group,
2138 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2139 {
2140 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2141 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4A_iface, group, instance,
2142 enumplayercb, context, flags );
2143 }
2144
2145 static HRESULT WINAPI IDirectPlay2Impl_EnumGroupPlayers( IDirectPlay2 *iface, DPID group,
2146 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2147 {
2148 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2149 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2150 enumplayercb, context, flags );
2151 }
2152
2153 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupPlayers( IDirectPlay3A *iface, DPID group,
2154 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2155 {
2156 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2157 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2158 enumplayercb, context, flags );
2159 }
2160
2161 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupPlayers( IDirectPlay3 *iface, DPID group,
2162 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2163 {
2164 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2165 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance,
2166 enumplayercb, context, flags );
2167 }
2168
2169 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupPlayers( IDirectPlay4A *iface, DPID group,
2170 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2171 {
2172 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2173 return IDirectPlayX_EnumGroupPlayers( &This->IDirectPlay4_iface, group, instance, enumplayercb,
2174 context, flags );
2175 }
2176
2177 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupPlayers( IDirectPlay4 *iface, DPID group,
2178 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2179 {
2180 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2181 lpGroupData gdata;
2182 lpPlayerList plist;
2183
2184 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
2185 context, flags );
2186
2187 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2188 return DPERR_UNINITIALIZED;
2189
2190 /* Find the group */
2191 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2192 return DPERR_INVALIDGROUP;
2193
2194 if ( DPQ_IS_EMPTY( gdata->players ) )
2195 return DP_OK;
2196
2197 /* Walk the players in this group */
2198 for( plist = DPQ_FIRST( gdata->players ); ; plist = DPQ_NEXT( plist->players ) )
2199 {
2200 /* We do not enum the name server or app server as they are of no
2201 * consequence to the end user.
2202 */
2203 if ( ( plist->lpPData->dpid != DPID_NAME_SERVER ) &&
2204 ( plist->lpPData->dpid != DPID_SERVERPLAYER ) )
2205 {
2206 /* FIXME: Need to add stuff for flags checking */
2207 if ( !enumplayercb( plist->lpPData->dpid, DPPLAYERTYPE_PLAYER,
2208 &plist->lpPData->name, plist->lpPData->dwFlags, context ) )
2209 /* User requested break */
2210 return DP_OK;
2211 }
2212
2213 if ( DPQ_IS_ENDOFLIST( plist->players ) )
2214 break;
2215 }
2216 return DP_OK;
2217 }
2218
2219 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
2220 static HRESULT WINAPI IDirectPlay2AImpl_EnumGroups( IDirectPlay2A *iface, GUID *instance,
2221 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2222 {
2223 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2224 return IDirectPlayX_EnumGroups( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2225 flags );
2226 }
2227
2228 static HRESULT WINAPI IDirectPlay2Impl_EnumGroups( IDirectPlay2 *iface, GUID *instance,
2229 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2230 {
2231 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2232 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2233 flags );
2234 }
2235
2236 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroups( IDirectPlay3A *iface, GUID *instance,
2237 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2238 {
2239 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2240 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2241 flags );
2242 }
2243
2244 static HRESULT WINAPI IDirectPlay3Impl_EnumGroups( IDirectPlay3 *iface, GUID *instance,
2245 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2246 {
2247 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2248 return IDirectPlayX_EnumGroups( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2249 flags );
2250 }
2251
2252 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroups( IDirectPlay4A *iface, GUID *instance,
2253 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2254 {
2255 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2256 context, flags );
2257 }
2258
2259 static HRESULT WINAPI IDirectPlay4Impl_EnumGroups ( IDirectPlay4 *iface, GUID *instance,
2260 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2261 {
2262 return IDirectPlayX_EnumGroupsInGroup( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2263 context, flags );
2264 }
2265
2266 static HRESULT WINAPI IDirectPlay2AImpl_EnumPlayers( IDirectPlay2A *iface, GUID *instance,
2267 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2268 {
2269 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2270 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4A_iface, instance, enumplayercb, context,
2271 flags );
2272 }
2273
2274 static HRESULT WINAPI IDirectPlay2Impl_EnumPlayers( IDirectPlay2 *iface, GUID *instance,
2275 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2276 {
2277 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2278 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2279 flags );
2280 }
2281
2282 static HRESULT WINAPI IDirectPlay3AImpl_EnumPlayers( IDirectPlay3A *iface, GUID *instance,
2283 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2284 {
2285 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2286 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2287 flags );
2288 }
2289
2290 static HRESULT WINAPI IDirectPlay3Impl_EnumPlayers( IDirectPlay3 *iface, GUID *instance,
2291 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2292 {
2293 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2294 return IDirectPlayX_EnumPlayers( &This->IDirectPlay4_iface, instance, enumplayercb, context,
2295 flags );
2296 }
2297
2298 static HRESULT WINAPI IDirectPlay4AImpl_EnumPlayers( IDirectPlay4A *iface, GUID *instance,
2299 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2300 {
2301 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2302 context, flags );
2303 }
2304
2305 static HRESULT WINAPI IDirectPlay4Impl_EnumPlayers( IDirectPlay4 *iface, GUID *instance,
2306 LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
2307 {
2308 return IDirectPlayX_EnumGroupPlayers( iface, DPID_SYSTEM_GROUP, instance, enumplayercb,
2309 context, flags );
2310 }
2311
2312 /* This function should call the registered callback function that the user
2313 passed into EnumSessions for each entry available.
2314 */
2315 static void DP_InvokeEnumSessionCallbacks
2316 ( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
2317 LPVOID lpNSInfo,
2318 DWORD dwTimeout,
2319 LPVOID lpContext )
2320 {
2321 LPDPSESSIONDESC2 lpSessionDesc;
2322
2323 FIXME( ": not checking for conditions\n" );
2324
2325 /* Not sure if this should be pruning but it's convenient */
2326 NS_PruneSessionCache( lpNSInfo );
2327
2328 NS_ResetSessionEnumeration( lpNSInfo );
2329
2330 /* Enumerate all sessions */
2331 /* FIXME: Need to indicate ANSI */
2332 while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
2333 {
2334 TRACE( "EnumSessionsCallback2 invoked\n" );
2335 if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
2336 {
2337 return;
2338 }
2339 }
2340
2341 /* Invoke one last time to indicate that there is no more to come */
2342 lpEnumSessionsCallback2( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext );
2343 }
2344
2345 static DWORD CALLBACK DP_EnumSessionsSendAsyncRequestThread( LPVOID lpContext )
2346 {
2347 EnumSessionAsyncCallbackData* data = lpContext;
2348 HANDLE hSuicideRequest = data->hSuicideRequest;
2349 DWORD dwTimeout = data->dwTimeout;
2350
2351 TRACE( "Thread started with timeout = 0x%08x\n", dwTimeout );
2352
2353 for( ;; )
2354 {
2355 HRESULT hr;
2356
2357 /* Sleep up to dwTimeout waiting for request to terminate thread */
2358 if( WaitForSingleObject( hSuicideRequest, dwTimeout ) == WAIT_OBJECT_0 )
2359 {
2360 TRACE( "Thread terminating on terminate request\n" );
2361 break;
2362 }
2363
2364 /* Now resend the enum request */
2365 hr = NS_SendSessionRequestBroadcast( &data->requestGuid,
2366 data->dwEnumSessionFlags,
2367 data->lpSpData );
2368
2369 if( FAILED(hr) )
2370 {
2371 ERR( "Enum broadcase request failed: %s\n", DPLAYX_HresultToString(hr) );
2372 /* FIXME: Should we kill this thread? How to inform the main thread? */
2373 }
2374
2375 }
2376
2377 TRACE( "Thread terminating\n" );
2378
2379 /* Clean up the thread data */
2380 CloseHandle( hSuicideRequest );
2381 HeapFree( GetProcessHeap(), 0, lpContext );
2382
2383 /* FIXME: Need to have some notification to main app thread that this is
2384 * dead. It would serve two purposes. 1) allow sync on termination
2385 * so that we don't actually send something to ourselves when we
2386 * become name server (race condition) and 2) so that if we die
2387 * abnormally something else will be able to tell.
2388 */
2389
2390 return 1;
2391 }
2392
2393 static void DP_KillEnumSessionThread( IDirectPlayImpl *This )
2394 {
2395 /* Does a thread exist? If so we were doing an async enum session */
2396 if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
2397 {
2398 TRACE( "Killing EnumSession thread %p\n",
2399 This->dp2->hEnumSessionThread );
2400
2401 /* Request that the thread kill itself nicely */
2402 SetEvent( This->dp2->hKillEnumSessionThreadEvent );
2403 CloseHandle( This->dp2->hKillEnumSessionThreadEvent );
2404
2405 /* We no longer need to know about the thread */
2406 CloseHandle( This->dp2->hEnumSessionThread );
2407
2408 This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;
2409 }
2410 }
2411
2412 static HRESULT WINAPI IDirectPlay2AImpl_EnumSessions( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
2413 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2414 {
2415 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2416 return IDirectPlayX_EnumSessions( &This->IDirectPlay4A_iface, sdesc, timeout, enumsessioncb,
2417 context, flags );
2418 }
2419
2420 static HRESULT WINAPI IDirectPlay2Impl_EnumSessions( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
2421 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2422 {
2423 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2424 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2425 context, flags );
2426 }
2427
2428 static HRESULT WINAPI IDirectPlay3AImpl_EnumSessions( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
2429 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2430 {
2431 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2432 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2433 context, flags );
2434 }
2435
2436 static HRESULT WINAPI IDirectPlay3Impl_EnumSessions( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
2437 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2438 {
2439 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2440 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2441 context, flags );
2442 }
2443
2444 static HRESULT WINAPI IDirectPlay4AImpl_EnumSessions( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
2445 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2446 {
2447 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2448 return IDirectPlayX_EnumSessions( &This->IDirectPlay4_iface, sdesc, timeout, enumsessioncb,
2449 context, flags );
2450 }
2451
2452 static HRESULT WINAPI IDirectPlay4Impl_EnumSessions( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
2453 DWORD timeout, LPDPENUMSESSIONSCALLBACK2 enumsessioncb, void *context, DWORD flags )
2454 {
2455 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2456 void *connection;
2457 DWORD size;
2458 HRESULT hr = DP_OK;
2459
2460 TRACE( "(%p)->(%p,0x%08x,%p,%p,0x%08x)\n", This, sdesc, timeout, enumsessioncb,
2461 context, flags );
2462
2463 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2464 return DPERR_UNINITIALIZED;
2465
2466 /* Can't enumerate if the interface is already open */
2467 if ( This->dp2->bConnectionOpen )
2468 return DPERR_GENERIC;
2469
2470 /* The loading of a lobby provider _seems_ to require a backdoor loading
2471 * of the service provider to also associate with this DP object. This is
2472 * because the app doesn't seem to have to call EnumConnections and
2473 * InitializeConnection for the SP before calling this method. As such
2474 * we'll do their dirty work for them with a quick hack so as to always
2475 * load the TCP/IP service provider.
2476 *
2477 * The correct solution would seem to involve creating a dialog box which
2478 * contains the possible SPs. These dialog boxes most likely follow SDK
2479 * examples.
2480 */
2481 if ( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
2482 {
2483 WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
2484
2485 if ( !DP_BuildSPCompoundAddr( (GUID*)&DPSPGUID_TCPIP, &connection, &size ) )
2486 {
2487 ERR( "Can't build compound addr\n" );
2488 return DPERR_GENERIC;
2489 }
2490
2491 hr = IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, 0 );
2492 if ( FAILED(hr) )
2493 return hr;
2494
2495 HeapFree( GetProcessHeap(), 0, connection );
2496 This->dp2->bSPInitialized = TRUE;
2497 }
2498
2499
2500 /* Use the service provider default? */
2501 if ( !timeout )
2502 {
2503 DPCAPS caps;
2504 caps.dwSize = sizeof( caps );
2505
2506 IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, &caps, 0 );
2507 timeout = caps.dwTimeout;
2508 if ( !timeout )
2509 timeout = DPMSG_WAIT_5_SECS; /* Provide the TCP/IP default */
2510 }
2511
2512 if ( flags & DPENUMSESSIONS_STOPASYNC )
2513 {
2514 DP_KillEnumSessionThread( This );
2515 return hr;
2516 }
2517
2518 if ( flags & DPENUMSESSIONS_ASYNC )
2519 {
2520 /* Enumerate everything presently in the local session cache */
2521 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2522 context );
2523
2524 if ( This->dp2->dwEnumSessionLock )
2525 return DPERR_CONNECTING;
2526
2527 /* See if we've already created a thread to service this interface */
2528 if ( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
2529 {
2530 DWORD tid;
2531 This->dp2->dwEnumSessionLock++;
2532
2533 /* Send the first enum request inline since the user may cancel a dialog
2534 * if one is presented. Also, may also have a connecting return code.
2535 */
2536 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags,
2537 &This->dp2->spData );
2538
2539 if ( SUCCEEDED(hr) )
2540 {
2541 EnumSessionAsyncCallbackData* data = HeapAlloc( GetProcessHeap(),
2542 HEAP_ZERO_MEMORY, sizeof( *data ) );
2543 /* FIXME: need to kill the thread on object deletion */
2544 data->lpSpData = &This->dp2->spData;
2545 data->requestGuid = sdesc->guidApplication;
2546 data->dwEnumSessionFlags = flags;
2547 data->dwTimeout = timeout;
2548
2549 This->dp2->hKillEnumSessionThreadEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
2550 if ( !DuplicateHandle( GetCurrentProcess(), This->dp2->hKillEnumSessionThreadEvent,
2551 GetCurrentProcess(), &data->hSuicideRequest, 0, FALSE,
2552 DUPLICATE_SAME_ACCESS ) )
2553 ERR( "Can't duplicate thread killing handle\n" );
2554
2555 TRACE( ": creating EnumSessionsRequest thread\n" );
2556 This->dp2->hEnumSessionThread = CreateThread( NULL, 0,
2557 DP_EnumSessionsSendAsyncRequestThread, data, 0, &tid );
2558 }
2559 This->dp2->dwEnumSessionLock--;
2560 }
2561 }
2562 else
2563 {
2564 /* Invalidate the session cache for the interface */
2565 NS_InvalidateSessionCache( This->dp2->lpNameServerData );
2566 /* Send the broadcast for session enumeration */
2567 hr = NS_SendSessionRequestBroadcast( &sdesc->guidApplication, flags, &This->dp2->spData );
2568 SleepEx( timeout, FALSE );
2569 DP_InvokeEnumSessionCallbacks( enumsessioncb, This->dp2->lpNameServerData, timeout,
2570 context );
2571 }
2572
2573 return hr;
2574 }
2575
2576 static HRESULT WINAPI IDirectPlay2AImpl_GetCaps( IDirectPlay2A *iface, DPCAPS *caps, DWORD flags )
2577 {
2578 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2579 return IDirectPlayX_GetCaps( &This->IDirectPlay4A_iface, caps, flags );
2580 }
2581
2582 static HRESULT WINAPI IDirectPlay2Impl_GetCaps( IDirectPlay2 *iface, DPCAPS *caps, DWORD flags )
2583 {
2584 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2585 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2586 }
2587
2588 static HRESULT WINAPI IDirectPlay3AImpl_GetCaps( IDirectPlay3A *iface, DPCAPS *caps, DWORD flags )
2589 {
2590 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2591 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2592 }
2593
2594 static HRESULT WINAPI IDirectPlay3Impl_GetCaps( IDirectPlay3 *iface, DPCAPS *caps, DWORD flags )
2595 {
2596 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2597 return IDirectPlayX_GetCaps( &This->IDirectPlay4_iface, caps, flags );
2598 }
2599
2600 static HRESULT WINAPI IDirectPlay4AImpl_GetCaps( IDirectPlay4A *iface, DPCAPS *caps, DWORD flags )
2601 {
2602 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2603 }
2604
2605 static HRESULT WINAPI IDirectPlay4Impl_GetCaps( IDirectPlay4 *iface, DPCAPS *caps, DWORD flags )
2606 {
2607 return IDirectPlayX_GetPlayerCaps( iface, DPID_ALLPLAYERS, caps, flags );
2608 }
2609
2610 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupData( IDirectPlay2A *iface, DPID group, void *data,
2611 DWORD *size, DWORD flags )
2612 {
2613 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2614 return IDirectPlayX_GetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
2615 }
2616
2617 static HRESULT WINAPI IDirectPlay2Impl_GetGroupData( IDirectPlay2 *iface, DPID group, void *data,
2618 DWORD *size, DWORD flags )
2619 {
2620 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2621 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2622 }
2623
2624 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupData( IDirectPlay3A *iface, DPID group, void *data,
2625 DWORD *size, DWORD flags )
2626 {
2627 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2628 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2629 }
2630
2631 static HRESULT WINAPI IDirectPlay3Impl_GetGroupData( IDirectPlay3 *iface, DPID group, void *data,
2632 DWORD *size, DWORD flags )
2633 {
2634 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2635 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2636 }
2637
2638 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupData( IDirectPlay4A *iface, DPID group,
2639 void *data, DWORD *size, DWORD flags )
2640 {
2641 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2642 return IDirectPlayX_GetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
2643 }
2644
2645 static HRESULT WINAPI IDirectPlay4Impl_GetGroupData( IDirectPlay4 *iface, DPID group,
2646 void *data, DWORD *size, DWORD flags )
2647 {
2648 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2649 lpGroupData gdata;
2650 DWORD bufsize;
2651 void *src;
2652
2653 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, group, data, size, flags );
2654
2655 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
2656 return DPERR_INVALIDGROUP;
2657
2658 /* How much buffer is required? */
2659 if ( flags & DPSET_LOCAL )
2660 {
2661 bufsize = gdata->dwLocalDataSize;
2662 src = gdata->lpLocalData;
2663 }
2664 else
2665 {
2666 bufsize = gdata->dwRemoteDataSize;
2667 src = gdata->lpRemoteData;
2668 }
2669
2670 /* Is the user requesting to know how big a buffer is required? */
2671 if ( !data || *size < bufsize )
2672 {
2673 *size = bufsize;
2674 return DPERR_BUFFERTOOSMALL;
2675 }
2676
2677 CopyMemory( data, src, bufsize );
2678
2679 return DP_OK;
2680 }
2681
2682 static HRESULT DP_IF_GetGroupName( IDirectPlayImpl *This, DPID idGroup, void *lpData,
2683 DWORD *lpdwDataSize, BOOL bAnsi )
2684 {
2685 lpGroupData lpGData;
2686 LPDPNAME lpName = lpData;
2687 DWORD dwRequiredDataSize;
2688
2689 FIXME("(%p)->(0x%08x,%p,%p,%u) ANSI ignored\n",
2690 This, idGroup, lpData, lpdwDataSize, bAnsi );
2691
2692 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
2693 {
2694 return DPERR_INVALIDGROUP;
2695 }
2696
2697 dwRequiredDataSize = lpGData->name.dwSize;
2698
2699 if( lpGData->name.u1.lpszShortNameA )
2700 {
2701 dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
2702 }
2703
2704 if( lpGData->name.u2.lpszLongNameA )
2705 {
2706 dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
2707 }
2708
2709 if( ( lpData == NULL ) ||
2710 ( *lpdwDataSize < dwRequiredDataSize )
2711 )
2712 {
2713 *lpdwDataSize = dwRequiredDataSize;
2714 return DPERR_BUFFERTOOSMALL;
2715 }
2716
2717 /* Copy the structure */
2718 CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
2719
2720 if( lpGData->name.u1.lpszShortNameA )
2721 {
2722 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2723 lpGData->name.u1.lpszShortNameA );
2724 }
2725 else
2726 {
2727 lpName->u1.lpszShortNameA = NULL;
2728 }
2729
2730 if( lpGData->name.u1.lpszShortNameA )
2731 {
2732 strcpy( ((char*)lpName)+lpGData->name.dwSize,
2733 lpGData->name.u2.lpszLongNameA );
2734 }
2735 else
2736 {
2737 lpName->u2.lpszLongNameA = NULL;
2738 }
2739
2740 return DP_OK;
2741 }
2742
2743 static HRESULT WINAPI IDirectPlay2AImpl_GetGroupName( IDirectPlay2A *iface, DPID group, void *data,
2744 DWORD *size )
2745 {
2746 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2747 return IDirectPlayX_GetGroupName( &This->IDirectPlay4A_iface, group, data, size );
2748 }
2749
2750 static HRESULT WINAPI IDirectPlay2Impl_GetGroupName( IDirectPlay2 *iface, DPID group, void *data,
2751 DWORD *size )
2752 {
2753 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2754 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2755 }
2756
2757 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupName( IDirectPlay3A *iface, DPID group, void *data,
2758 DWORD *size )
2759 {
2760 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2761 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2762 }
2763
2764 static HRESULT WINAPI IDirectPlay3Impl_GetGroupName( IDirectPlay3 *iface, DPID group, void *data,
2765 DWORD *size )
2766 {
2767 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2768 return IDirectPlayX_GetGroupName( &This->IDirectPlay4_iface, group, data, size );
2769 }
2770
2771 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupName( IDirectPlay4A *iface, DPID idGroup,
2772 void *lpData, DWORD *lpdwDataSize )
2773 {
2774 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2775 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, TRUE );
2776 }
2777
2778 static HRESULT WINAPI IDirectPlay4Impl_GetGroupName( IDirectPlay4 *iface, DPID idGroup,
2779 void *lpData, DWORD *lpdwDataSize )
2780 {
2781 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2782 return DP_IF_GetGroupName( This, idGroup, lpData, lpdwDataSize, FALSE );
2783 }
2784
2785 static HRESULT WINAPI IDirectPlay2AImpl_GetMessageCount( IDirectPlay2A *iface, DPID player,
2786 DWORD *count )
2787 {
2788 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2789 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4A_iface, player, count );
2790 }
2791
2792 static HRESULT WINAPI IDirectPlay2Impl_GetMessageCount( IDirectPlay2 *iface, DPID player,
2793 DWORD *count )
2794 {
2795 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2796 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2797 }
2798
2799 static HRESULT WINAPI IDirectPlay3AImpl_GetMessageCount( IDirectPlay3A *iface, DPID player,
2800 DWORD *count )
2801 {
2802 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2803 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2804 }
2805
2806 static HRESULT WINAPI IDirectPlay3Impl_GetMessageCount( IDirectPlay3 *iface, DPID player,
2807 DWORD *count )
2808 {
2809 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2810 return IDirectPlayX_GetMessageCount( &This->IDirectPlay4_iface, player, count );
2811 }
2812
2813 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageCount( IDirectPlay4A *iface, DPID player,
2814 DWORD *count )
2815 {
2816 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2817 }
2818
2819 static HRESULT WINAPI IDirectPlay4Impl_GetMessageCount( IDirectPlay4 *iface, DPID player,
2820 DWORD *count )
2821 {
2822 return IDirectPlayX_GetMessageQueue( iface, 0, player, DPMESSAGEQUEUE_RECEIVE, count, NULL );
2823 }
2824
2825 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerAddress( IDirectPlay2A *iface, DPID player,
2826 void *data, DWORD *size )
2827 {
2828 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2829 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4A_iface, player, data, size );
2830 }
2831
2832 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerAddress( IDirectPlay2 *iface, DPID player,
2833 void *data, DWORD *size )
2834 {
2835 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2836 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2837 }
2838
2839 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAddress( IDirectPlay3A *iface, DPID player,
2840 void *data, DWORD *size )
2841 {
2842 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2843 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2844 }
2845
2846 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAddress( IDirectPlay3 *iface, DPID player,
2847 void *data, DWORD *size )
2848 {
2849 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2850 return IDirectPlayX_GetPlayerAddress( &This->IDirectPlay4_iface, player, data, size );
2851 }
2852
2853 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAddress( IDirectPlay4A *iface, DPID player,
2854 void *data, DWORD *size )
2855 {
2856 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2857 FIXME("(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2858 return DP_OK;
2859 }
2860
2861 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAddress( IDirectPlay4 *iface, DPID player,
2862 void *data, DWORD *size )
2863 {
2864 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2865 FIXME( "(%p)->(0x%08x,%p,%p): stub\n", This, player, data, size );
2866 return DP_OK;
2867 }
2868
2869 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerCaps( IDirectPlay2A *iface, DPID player,
2870 DPCAPS *caps, DWORD flags )
2871 {
2872 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2873 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4A_iface, player, caps, flags );
2874 }
2875
2876 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerCaps( IDirectPlay2 *iface, DPID player,
2877 DPCAPS *caps, DWORD flags )
2878 {
2879 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2880 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2881 }
2882
2883 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerCaps( IDirectPlay3A *iface, DPID player,
2884 DPCAPS *caps, DWORD flags )
2885 {
2886 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2887 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2888 }
2889
2890 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerCaps( IDirectPlay3 *iface, DPID player,
2891 DPCAPS *caps, DWORD flags )
2892 {
2893 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2894 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2895 }
2896
2897 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerCaps( IDirectPlay4A *iface, DPID player,
2898 DPCAPS *caps, DWORD flags )
2899 {
2900 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2901 return IDirectPlayX_GetPlayerCaps( &This->IDirectPlay4_iface, player, caps, flags );
2902 }
2903
2904 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerCaps( IDirectPlay4 *iface, DPID player,
2905 DPCAPS *caps, DWORD flags )
2906 {
2907 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2908 DPSP_GETCAPSDATA data;
2909
2910 TRACE( "(%p)->(0x%08x,%p,0x%08x)\n", This, player, caps, flags);
2911
2912 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2913 return DPERR_UNINITIALIZED;
2914
2915 /* Query the service provider */
2916 data.idPlayer = player;
2917 data.dwFlags = flags;
2918 data.lpCaps = caps;
2919 data.lpISP = This->dp2->spData.lpISP;
2920
2921 return (*This->dp2->spData.lpCB->GetCaps)( &data );
2922 }
2923
2924 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerData( IDirectPlay2A *iface, DPID player,
2925 void *data, DWORD *size, DWORD flags )
2926 {
2927 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
2928 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
2929 }
2930
2931 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerData( IDirectPlay2 *iface, DPID player,
2932 void *data, DWORD *size, DWORD flags )
2933 {
2934 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
2935 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2936 }
2937
2938 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerData( IDirectPlay3A *iface, DPID player,
2939 void *data, DWORD *size, DWORD flags )
2940 {
2941 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
2942 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2943 }
2944
2945 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerData( IDirectPlay3 *iface, DPID player,
2946 void *data, DWORD *size, DWORD flags )
2947 {
2948 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
2949 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2950 }
2951
2952 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerData( IDirectPlay4A *iface, DPID player,
2953 void *data, DWORD *size, DWORD flags )
2954 {
2955 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
2956 return IDirectPlayX_GetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
2957 }
2958
2959 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerData( IDirectPlay4 *iface, DPID player,
2960 void *data, DWORD *size, DWORD flags )
2961 {
2962 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
2963 lpPlayerList plist;
2964 DWORD bufsize;
2965 void *src;
2966
2967 TRACE( "(%p)->(0x%08x,%p,%p,0x%08x)\n", This, player, data, size, flags );
2968
2969 if ( This->dp2->connectionInitialized == NO_PROVIDER )
2970 return DPERR_UNINITIALIZED;
2971
2972 if ( ( plist = DP_FindPlayer( This, player ) ) == NULL )
2973 return DPERR_INVALIDPLAYER;
2974
2975 if ( flags & DPSET_LOCAL )
2976 {
2977 bufsize = plist->lpPData->dwLocalDataSize;
2978 src = plist->lpPData->lpLocalData;
2979 }
2980 else
2981 {
2982 bufsize = plist->lpPData->dwRemoteDataSize;
2983 src = plist->lpPData->lpRemoteData;
2984 }
2985
2986 /* Is the user requesting to know how big a buffer is required? */
2987 if ( !data || *size < bufsize )
2988 {
2989 *size = bufsize;
2990 return DPERR_BUFFERTOOSMALL;
2991 }
2992
2993 CopyMemory( data, src, bufsize );
2994
2995 return DP_OK;
2996 }
2997
2998 static HRESULT DP_IF_GetPlayerName( IDirectPlayImpl *This, DPID idPlayer, void *lpData,
2999 DWORD *lpdwDataSize, BOOL bAnsi )
3000 {
3001 lpPlayerList lpPList;
3002 LPDPNAME lpName = lpData;
3003 DWORD dwRequiredDataSize;
3004
3005 FIXME( "(%p)->(0x%08x,%p,%p,%u): ANSI\n",
3006 This, idPlayer, lpData, lpdwDataSize, bAnsi );
3007
3008 if( This->dp2->connectionInitialized == NO_PROVIDER )
3009 {
3010 return DPERR_UNINITIALIZED;
3011 }
3012
3013 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3014 {
3015 return DPERR_INVALIDPLAYER;
3016 }
3017
3018 dwRequiredDataSize = lpPList->lpPData->name.dwSize;
3019
3020 if( lpPList->lpPData->name.u1.lpszShortNameA )
3021 {
3022 dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
3023 }
3024
3025 if( lpPList->lpPData->name.u2.lpszLongNameA )
3026 {
3027 dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
3028 }
3029
3030 if( ( lpData == NULL ) ||
3031 ( *lpdwDataSize < dwRequiredDataSize )
3032 )
3033 {
3034 *lpdwDataSize = dwRequiredDataSize;
3035 return DPERR_BUFFERTOOSMALL;
3036 }
3037
3038 /* Copy the structure */
3039 CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
3040
3041 if( lpPList->lpPData->name.u1.lpszShortNameA )
3042 {
3043 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3044 lpPList->lpPData->name.u1.lpszShortNameA );
3045 }
3046 else
3047 {
3048 lpName->u1.lpszShortNameA = NULL;
3049 }
3050
3051 if( lpPList->lpPData->name.u1.lpszShortNameA )
3052 {
3053 strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
3054 lpPList->lpPData->name.u2.lpszLongNameA );
3055 }
3056 else
3057 {
3058 lpName->u2.lpszLongNameA = NULL;
3059 }
3060
3061 return DP_OK;
3062 }
3063
3064 static HRESULT WINAPI IDirectPlay2AImpl_GetPlayerName( IDirectPlay2A *iface, DPID player,
3065 void *data, DWORD *size )
3066 {
3067 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3068 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4A_iface, player, data, size );
3069 }
3070
3071 static HRESULT WINAPI IDirectPlay2Impl_GetPlayerName( IDirectPlay2 *iface, DPID player,
3072 void *data, DWORD *size )
3073 {
3074 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3075 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3076 }
3077
3078 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerName( IDirectPlay3A *iface, DPID player,
3079 void *data, DWORD *size )
3080 {
3081 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3082 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3083 }
3084
3085 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerName( IDirectPlay3 *iface, DPID player,
3086 void *data, DWORD *size )
3087 {
3088 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3089 return IDirectPlayX_GetPlayerName( &This->IDirectPlay4_iface, player, data, size );
3090 }
3091
3092 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3093 void *lpData, DWORD *lpdwDataSize )
3094 {
3095 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3096 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, TRUE );
3097 }
3098
3099 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3100 void *lpData, DWORD *lpdwDataSize )
3101 {
3102 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3103 return DP_IF_GetPlayerName( This, idPlayer, lpData, lpdwDataSize, FALSE );
3104 }
3105
3106 static HRESULT DP_GetSessionDesc( IDirectPlayImpl *This, void *lpData, DWORD *lpdwDataSize,
3107 BOOL bAnsi )
3108 {
3109 DWORD dwRequiredSize;
3110
3111 TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
3112
3113 if( This->dp2->connectionInitialized == NO_PROVIDER )
3114 {
3115 return DPERR_UNINITIALIZED;
3116 }
3117
3118 if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
3119 {
3120 return DPERR_INVALIDPARAMS;
3121 }
3122
3123 /* FIXME: Get from This->dp2->lpSessionDesc */
3124 dwRequiredSize = DP_CalcSessionDescSize( This->dp2->lpSessionDesc, bAnsi );
3125
3126 if ( ( lpData == NULL ) ||
3127 ( *lpdwDataSize < dwRequiredSize )
3128 )
3129 {
3130 *lpdwDataSize = dwRequiredSize;
3131 return DPERR_BUFFERTOOSMALL;
3132 }
3133
3134 DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
3135
3136 return DP_OK;
3137 }
3138
3139 static HRESULT WINAPI IDirectPlay2AImpl_GetSessionDesc( IDirectPlay2A *iface, void *data,
3140 DWORD *size )
3141 {
3142 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3143 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4A_iface, data, size );
3144 }
3145
3146 static HRESULT WINAPI IDirectPlay2Impl_GetSessionDesc( IDirectPlay2 *iface, void *data,
3147 DWORD *size )
3148 {
3149 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3150 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3151 }
3152
3153 static HRESULT WINAPI IDirectPlay3AImpl_GetSessionDesc( IDirectPlay3A *iface, void *data,
3154 DWORD *size )
3155 {
3156 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3157 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3158 }
3159
3160 static HRESULT WINAPI IDirectPlay3Impl_GetSessionDesc( IDirectPlay3 *iface, void *data,
3161 DWORD *size )
3162 {
3163 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3164 return IDirectPlayX_GetSessionDesc( &This->IDirectPlay4_iface, data, size );
3165 }
3166
3167 static HRESULT WINAPI IDirectPlay4AImpl_GetSessionDesc( IDirectPlay4A *iface, void *lpData,
3168 DWORD *lpdwDataSize )
3169 {
3170 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3171 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3172 }
3173
3174 static HRESULT WINAPI IDirectPlay4Impl_GetSessionDesc( IDirectPlay4 *iface, void *lpData,
3175 DWORD *lpdwDataSize )
3176 {
3177 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3178 return DP_GetSessionDesc( This, lpData, lpdwDataSize, TRUE );
3179 }
3180
3181 static HRESULT WINAPI IDirectPlay2AImpl_Initialize( IDirectPlay2A *iface, GUID *guid )
3182 {
3183 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3184 return IDirectPlayX_Initialize( &This->IDirectPlay4A_iface, guid );
3185 }
3186
3187 static HRESULT WINAPI IDirectPlay2Impl_Initialize( IDirectPlay2 *iface, GUID *guid )
3188 {
3189 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3190 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3191 }
3192
3193 static HRESULT WINAPI IDirectPlay3AImpl_Initialize( IDirectPlay3A *iface, GUID *guid )
3194 {
3195 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3196 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3197 }
3198
3199 static HRESULT WINAPI IDirectPlay3Impl_Initialize( IDirectPlay3 *iface, GUID *guid )
3200 {
3201 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3202 return IDirectPlayX_Initialize( &This->IDirectPlay4_iface, guid );
3203 }
3204
3205 /* Intended only for COM compatibility. Always returns an error. */
3206 static HRESULT WINAPI IDirectPlay4AImpl_Initialize( IDirectPlay4A *iface, GUID *guid )
3207 {
3208 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3209 TRACE("(%p)->(%p): no-op\n", This, guid );
3210 return DPERR_ALREADYINITIALIZED;
3211 }
3212
3213 static HRESULT WINAPI IDirectPlay4Impl_Initialize( IDirectPlay4 *iface, GUID *guid )
3214 {
3215 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3216 TRACE( "(%p)->(%p): no-op\n", This, guid );
3217 return DPERR_ALREADYINITIALIZED;
3218 }
3219
3220
3221 static HRESULT DP_SecureOpen( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpsd, DWORD dwFlags,
3222 const DPSECURITYDESC *lpSecurity, const DPCREDENTIALS *lpCredentials, BOOL bAnsi )
3223 {
3224 HRESULT hr = DP_OK;
3225
3226 FIXME( "(%p)->(%p,0x%08x,%p,%p): partial stub\n",
3227 This, lpsd, dwFlags, lpSecurity, lpCredentials );
3228
3229 if( This->dp2->connectionInitialized == NO_PROVIDER )
3230 {
3231 return DPERR_UNINITIALIZED;
3232 }
3233
3234 if( lpsd->dwSize != sizeof(DPSESSIONDESC2) )
3235 {
3236 TRACE( ": rejecting invalid dpsd size (%d).\n", lpsd->dwSize );
3237 return DPERR_INVALIDPARAMS;
3238 }
3239
3240 if( This->dp2->bConnectionOpen )
3241 {
3242 TRACE( ": rejecting already open connection.\n" );
3243 return DPERR_ALREADYINITIALIZED;
3244 }
3245
3246 /* If we're enumerating, kill the thread */
3247 DP_KillEnumSessionThread( This );
3248
3249 if( dwFlags & DPOPEN_CREATE )
3250 {
3251 /* Rightoo - this computer is the host and the local computer needs to be
3252 the name server so that others can join this session */
3253 NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
3254
3255 This->dp2->bHostInterface = TRUE;
3256
3257 hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
3258 if( FAILED( hr ) )
3259 {
3260 ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
3261 return hr;
3262 }
3263 }
3264
3265 /* Invoke the conditional callback for the service provider */
3266 if( This->dp2->spData.lpCB->Open )
3267 {
3268 DPSP_OPENDATA data;
3269
3270 FIXME( "Not all data fields are correct. Need new parameter\n" );
3271
3272 data.bCreate = (dwFlags & DPOPEN_CREATE ) != 0;
3273 data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
3274 : NS_GetNSAddr( This->dp2->lpNameServerData );
3275 data.lpISP = This->dp2->spData.lpISP;
3276 data.bReturnStatus = (dwFlags & DPOPEN_RETURNSTATUS) != 0;
3277 data.dwOpenFlags = dwFlags;
3278 data.dwSessionFlags = This->dp2->lpSessionDesc->dwFlags;
3279
3280 hr = (*This->dp2->spData.lpCB->Open)(&data);
3281 if( FAILED( hr ) )
3282 {
3283 ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
3284 return hr;
3285 }
3286 }
3287
3288 {
3289 /* Create the system group of which everything is a part of */
3290 DPID systemGroup = DPID_SYSTEM_GROUP;
3291
3292 hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
3293 NULL, 0, 0, TRUE );
3294
3295 }
3296
3297 if( dwFlags & DPOPEN_JOIN )
3298 {
3299 DPID dpidServerId = DPID_UNKNOWN;
3300
3301 /* Create the server player for this interface. This way we can receive
3302 * messages for this session.
3303 */
3304 /* FIXME: I suppose that we should be setting an event for a receive
3305 * type of thing. That way the messaging thread could know to wake
3306 * up. DPlay would then trigger the hEvent for the player the
3307 * message is directed to.
3308 */
3309 hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
3310 0,
3311 DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
3312
3313 }
3314 else if( dwFlags & DPOPEN_CREATE )
3315 {
3316 DPID dpidNameServerId = DPID_NAME_SERVER;
3317
3318 hr = DP_IF_CreatePlayer( This, NULL, &dpidNameServerId, NULL, 0, NULL,
3319 0, DPPLAYER_SERVERPLAYER, bAnsi );
3320 }
3321
3322 if( FAILED(hr) )
3323 {
3324 ERR( "Couldn't create name server/system player: %s\n",
3325 DPLAYX_HresultToString(hr) );
3326 }
3327
3328 return hr;
3329 }
3330
3331 static HRESULT WINAPI IDirectPlay2AImpl_Open( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3332 DWORD flags )
3333 {
3334 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3335 return IDirectPlayX_Open( &This->IDirectPlay4A_iface, sdesc, flags );
3336 }
3337
3338 static HRESULT WINAPI IDirectPlay2Impl_Open( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3339 DWORD flags )
3340 {
3341 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3342 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3343 }
3344
3345 static HRESULT WINAPI IDirectPlay3AImpl_Open( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3346 DWORD flags )
3347 {
3348 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3349 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3350 }
3351
3352 static HRESULT WINAPI IDirectPlay3Impl_Open( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3353 DWORD flags )
3354 {
3355 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3356 return IDirectPlayX_Open( &This->IDirectPlay4_iface, sdesc, flags );
3357 }
3358
3359 static HRESULT WINAPI IDirectPlay4AImpl_Open( IDirectPlay4A *iface, DPSESSIONDESC2 *sdesc,
3360 DWORD flags )
3361 {
3362 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3363 }
3364
3365 static HRESULT WINAPI IDirectPlay4Impl_Open( IDirectPlay4 *iface, DPSESSIONDESC2 *sdesc,
3366 DWORD flags )
3367 {
3368 return IDirectPlayX_SecureOpen( iface, sdesc, flags, NULL, NULL );
3369 }
3370
3371 static HRESULT DP_IF_Receive( IDirectPlayImpl *This, DPID *lpidFrom, DPID *lpidTo, DWORD dwFlags,
3372 void *lpData, DWORD *lpdwDataSize, BOOL bAnsi )
3373 {
3374 LPDPMSG lpMsg = NULL;
3375
3376 FIXME( "(%p)->(%p,%p,0x%08x,%p,%p,%u): stub\n",
3377 This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
3378
3379 if( This->dp2->connectionInitialized == NO_PROVIDER )
3380 {
3381 return DPERR_UNINITIALIZED;
3382 }
3383
3384 if( dwFlags == 0 )
3385 {
3386 dwFlags = DPRECEIVE_ALL;
3387 }
3388
3389 /* If the lpData is NULL, we must be peeking the message */
3390 if( ( lpData == NULL ) &&
3391 !( dwFlags & DPRECEIVE_PEEK )
3392 )
3393 {
3394 return DPERR_INVALIDPARAMS;
3395 }
3396
3397 if( dwFlags & DPRECEIVE_ALL )
3398 {
3399 lpMsg = This->dp2->receiveMsgs.lpQHFirst;
3400
3401 if( !( dwFlags & DPRECEIVE_PEEK ) )
3402 {
3403 FIXME( "Remove from queue\n" );
3404 }
3405 }
3406 else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
3407 ( dwFlags & DPRECEIVE_FROMPLAYER )
3408 )
3409 {
3410 FIXME( "Find matching message 0x%08x\n", dwFlags );
3411 }
3412 else
3413 {
3414 ERR( "Hmmm..dwFlags 0x%08x\n", dwFlags );
3415 }
3416
3417 if( lpMsg == NULL )
3418 {
3419 return DPERR_NOMESSAGES;
3420 }
3421
3422 /* Copy into the provided buffer */
3423 if (lpData) CopyMemory( lpData, lpMsg->msg, *lpdwDataSize );
3424
3425 return DP_OK;
3426 }
3427
3428 static HRESULT WINAPI IDirectPlay2AImpl_Receive( IDirectPlay2A *iface, DPID *from, DPID *to,
3429 DWORD flags, void *data, DWORD *size )
3430 {
3431 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3432 return IDirectPlayX_Receive( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3433 }
3434
3435 static HRESULT WINAPI IDirectPlay2Impl_Receive( IDirectPlay2 *iface, DPID *from, DPID *to,
3436 DWORD flags, void *data, DWORD *size )
3437 {
3438 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3439 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3440 }
3441
3442 static HRESULT WINAPI IDirectPlay3AImpl_Receive( IDirectPlay3A *iface, DPID *from, DPID *to,
3443 DWORD flags, void *data, DWORD *size )
3444 {
3445 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3446 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3447 }
3448
3449 static HRESULT WINAPI IDirectPlay3Impl_Receive( IDirectPlay3 *iface, DPID *from, DPID *to,
3450 DWORD flags, void *data, DWORD *size )
3451 {
3452 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3453 return IDirectPlayX_Receive( &This->IDirectPlay4_iface, from, to, flags, data, size );
3454 }
3455
3456 static HRESULT WINAPI IDirectPlay4AImpl_Receive( IDirectPlay4A *iface, DPID *lpidFrom,
3457 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3458 {
3459 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3460 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, TRUE );
3461 }
3462
3463 static HRESULT WINAPI IDirectPlay4Impl_Receive( IDirectPlay4 *iface, DPID *lpidFrom,
3464 DPID *lpidTo, DWORD dwFlags, void *lpData, DWORD *lpdwDataSize )
3465 {
3466 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3467 return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, FALSE );
3468 }
3469
3470 static HRESULT WINAPI IDirectPlay2AImpl_Send( IDirectPlay2A *iface, DPID from, DPID to,
3471 DWORD flags, void *data, DWORD size )
3472 {
3473 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3474 return IDirectPlayX_Send( &This->IDirectPlay4A_iface, from, to, flags, data, size );
3475 }
3476
3477 static HRESULT WINAPI IDirectPlay2Impl_Send( IDirectPlay2 *iface, DPID from, DPID to,
3478 DWORD flags, void *data, DWORD size )
3479 {
3480 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3481 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3482 }
3483
3484 static HRESULT WINAPI IDirectPlay3AImpl_Send( IDirectPlay3A *iface, DPID from, DPID to,
3485 DWORD flags, void *data, DWORD size )
3486 {
3487 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3488 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3489 }
3490
3491 static HRESULT WINAPI IDirectPlay3Impl_Send( IDirectPlay3 *iface, DPID from, DPID to,
3492 DWORD flags, void *data, DWORD size )
3493 {
3494 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3495 return IDirectPlayX_Send( &This->IDirectPlay4_iface, from, to, flags, data, size );
3496 }
3497
3498 static HRESULT WINAPI IDirectPlay4AImpl_Send( IDirectPlay4A *iface, DPID from, DPID to,
3499 DWORD flags, void *data, DWORD size )
3500 {
3501 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3502 }
3503
3504 static HRESULT WINAPI IDirectPlay4Impl_Send( IDirectPlay4 *iface, DPID from, DPID to,
3505 DWORD flags, void *data, DWORD size )
3506 {
3507 return IDirectPlayX_SendEx( iface, from, to, flags, data, size, 0, 0, NULL, NULL );
3508 }
3509
3510 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupData( IDirectPlay2A *iface, DPID group, void *data,
3511 DWORD size, DWORD flags )
3512 {
3513 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3514 return IDirectPlayX_SetGroupData( &This->IDirectPlay4A_iface, group, data, size, flags );
3515 }
3516
3517 static HRESULT WINAPI IDirectPlay2Impl_SetGroupData( IDirectPlay2 *iface, DPID group, void *data,
3518 DWORD size, DWORD flags )
3519 {
3520 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3521 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3522 }
3523
3524 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupData( IDirectPlay3A *iface, DPID group, void *data,
3525 DWORD size, DWORD flags )
3526 {
3527 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3528 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3529 }
3530
3531 static HRESULT WINAPI IDirectPlay3Impl_SetGroupData( IDirectPlay3 *iface, DPID group, void *data,
3532 DWORD size, DWORD flags )
3533 {
3534 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3535 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3536 }
3537
3538 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupData( IDirectPlay4A *iface, DPID group, void *data,
3539 DWORD size, DWORD flags )
3540 {
3541 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3542 return IDirectPlayX_SetGroupData( &This->IDirectPlay4_iface, group, data, size, flags );
3543 }
3544
3545 static HRESULT WINAPI IDirectPlay4Impl_SetGroupData( IDirectPlay4 *iface, DPID group, void *data,
3546 DWORD size, DWORD flags )
3547 {
3548 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3549 lpGroupData gdata;
3550
3551 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, group, data, size, flags );
3552
3553 /* Parameter check */
3554 if ( !data && size )
3555 return DPERR_INVALIDPARAMS;
3556
3557 /* Find the pointer to the data for this player */
3558 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
3559 return DPERR_INVALIDOBJECT;
3560
3561 if ( !(flags & DPSET_LOCAL) )
3562 {
3563 FIXME( "Was this group created by this interface?\n" );
3564 /* FIXME: If this is a remote update need to allow it but not
3565 * send a message.
3566 */
3567 }
3568
3569 DP_SetGroupData( gdata, flags, data, size );
3570
3571 /* FIXME: Only send a message if this group is local to the session otherwise
3572 * it will have been rejected above
3573 */
3574 if ( !(flags & DPSET_LOCAL) )
3575 FIXME( "Send msg?\n" );
3576
3577 return DP_OK;
3578 }
3579
3580 static HRESULT DP_IF_SetGroupName( IDirectPlayImpl *This, DPID idGroup, DPNAME *lpGroupName,
3581 DWORD dwFlags, BOOL bAnsi )
3582 {
3583 lpGroupData lpGData;
3584
3585 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n", This, idGroup,
3586 lpGroupName, dwFlags, bAnsi );
3587
3588 if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
3589 {
3590 return DPERR_INVALIDGROUP;
3591 }
3592
3593 DP_CopyDPNAMEStruct( &lpGData->name, lpGroupName, bAnsi );
3594
3595 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3596 FIXME( "Message not sent and dwFlags ignored\n" );
3597
3598 return DP_OK;
3599 }
3600
3601 static HRESULT WINAPI IDirectPlay2AImpl_SetGroupName( IDirectPlay2A *iface, DPID group,
3602 DPNAME *name, DWORD flags )
3603 {
3604 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3605 return IDirectPlayX_SetGroupName( &This->IDirectPlay4A_iface, group, name, flags );
3606 }
3607
3608 static HRESULT WINAPI IDirectPlay2Impl_SetGroupName( IDirectPlay2 *iface, DPID group,
3609 DPNAME *name, DWORD flags )
3610 {
3611 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3612 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3613 }
3614
3615 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupName( IDirectPlay3A *iface, DPID group,
3616 DPNAME *name, DWORD flags )
3617 {
3618 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3619 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3620 }
3621
3622 static HRESULT WINAPI IDirectPlay3Impl_SetGroupName( IDirectPlay3 *iface, DPID group,
3623 DPNAME *name, DWORD flags )
3624 {
3625 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3626 return IDirectPlayX_SetGroupName( &This->IDirectPlay4_iface, group, name, flags );
3627 }
3628
3629 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupName( IDirectPlay4A *iface, DPID idGroup,
3630 DPNAME *lpGroupName, DWORD dwFlags )
3631 {
3632 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3633 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, TRUE );
3634 }
3635
3636 static HRESULT WINAPI IDirectPlay4Impl_SetGroupName( IDirectPlay4 *iface, DPID idGroup,
3637 DPNAME *lpGroupName, DWORD dwFlags )
3638 {
3639 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3640 return DP_IF_SetGroupName( This, idGroup, lpGroupName, dwFlags, FALSE );
3641 }
3642
3643 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerData( IDirectPlay2A *iface, DPID player,
3644 void *data, DWORD size, DWORD flags )
3645 {
3646 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3647 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4A_iface, player, data, size, flags );
3648 }
3649
3650 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerData( IDirectPlay2 *iface, DPID player,
3651 void *data, DWORD size, DWORD flags )
3652 {
3653 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3654 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3655 }
3656
3657 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerData( IDirectPlay3A *iface, DPID player,
3658 void *data, DWORD size, DWORD flags )
3659 {
3660 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3661 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3662 }
3663
3664 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerData( IDirectPlay3 *iface, DPID player,
3665 void *data, DWORD size, DWORD flags )
3666 {
3667 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3668 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3669 }
3670
3671 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerData( IDirectPlay4A *iface, DPID player,
3672 void *data, DWORD size, DWORD flags )
3673 {
3674 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3675 return IDirectPlayX_SetPlayerData( &This->IDirectPlay4_iface, player, data, size, flags );
3676 }
3677
3678 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerData( IDirectPlay4 *iface, DPID player,
3679 void *data, DWORD size, DWORD flags )
3680 {
3681 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3682 lpPlayerList plist;
3683
3684 TRACE( "(%p)->(0x%08x,%p,0x%08x,0x%08x)\n", This, player, data, size, flags );
3685
3686 if ( This->dp2->connectionInitialized == NO_PROVIDER )
3687 return DPERR_UNINITIALIZED;
3688
3689 /* Parameter check */
3690 if ( !data && size )
3691 return DPERR_INVALIDPARAMS;
3692
3693 /* Find the pointer to the data for this player */
3694 if ( (plist = DP_FindPlayer( This, player )) == NULL )
3695 return DPERR_INVALIDPLAYER;
3696
3697 if ( !(flags & DPSET_LOCAL) )
3698 {
3699 FIXME( "Was this group created by this interface?\n" );
3700 /* FIXME: If this is a remote update need to allow it but not
3701 * send a message.
3702 */
3703 }
3704
3705 DP_SetPlayerData( plist->lpPData, flags, data, size );
3706
3707 if ( !(flags & DPSET_LOCAL) )
3708 FIXME( "Send msg?\n" );
3709
3710 return DP_OK;
3711 }
3712
3713 static HRESULT DP_IF_SetPlayerName( IDirectPlayImpl *This, DPID idPlayer, DPNAME *lpPlayerName,
3714 DWORD dwFlags, BOOL bAnsi )
3715 {
3716 lpPlayerList lpPList;
3717
3718 TRACE( "(%p)->(0x%08x,%p,0x%08x,%u)\n",
3719 This, idPlayer, lpPlayerName, dwFlags, bAnsi );
3720
3721 if( This->dp2->connectionInitialized == NO_PROVIDER )
3722 {
3723 return DPERR_UNINITIALIZED;
3724 }
3725
3726 if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
3727 {
3728 return DPERR_INVALIDGROUP;
3729 }
3730
3731 DP_CopyDPNAMEStruct( &lpPList->lpPData->name, lpPlayerName, bAnsi );
3732
3733 /* Should send a DPMSG_SETPLAYERORGROUPNAME message */
3734 FIXME( "Message not sent and dwFlags ignored\n" );
3735
3736 return DP_OK;
3737 }
3738
3739 static HRESULT WINAPI IDirectPlay2AImpl_SetPlayerName( IDirectPlay2A *iface, DPID player,
3740 DPNAME *name, DWORD flags )
3741 {
3742 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3743 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4A_iface, player, name, flags );
3744 }
3745
3746 static HRESULT WINAPI IDirectPlay2Impl_SetPlayerName( IDirectPlay2 *iface, DPID player,
3747 DPNAME *name, DWORD flags )
3748 {
3749 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3750 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3751 }
3752
3753 static HRESULT WINAPI IDirectPlay3AImpl_SetPlayerName( IDirectPlay3A *iface, DPID player,
3754 DPNAME *name, DWORD flags )
3755 {
3756 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3757 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3758 }
3759
3760 static HRESULT WINAPI IDirectPlay3Impl_SetPlayerName( IDirectPlay3 *iface, DPID player,
3761 DPNAME *name, DWORD flags )
3762 {
3763 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3764 return IDirectPlayX_SetPlayerName( &This->IDirectPlay4_iface, player, name, flags );
3765 }
3766
3767 static HRESULT WINAPI IDirectPlay4AImpl_SetPlayerName( IDirectPlay4A *iface, DPID idPlayer,
3768 DPNAME *lpPlayerName, DWORD dwFlags )
3769 {
3770 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3771 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, TRUE );
3772 }
3773
3774 static HRESULT WINAPI IDirectPlay4Impl_SetPlayerName( IDirectPlay4 *iface, DPID idPlayer,
3775 DPNAME *lpPlayerName, DWORD dwFlags )
3776 {
3777 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3778 return DP_IF_SetPlayerName( This, idPlayer, lpPlayerName, dwFlags, FALSE );
3779 }
3780
3781 static HRESULT DP_SetSessionDesc( IDirectPlayImpl *This, const DPSESSIONDESC2 *lpSessDesc,
3782 DWORD dwFlags, BOOL bInitial, BOOL bAnsi )
3783 {
3784 DWORD dwRequiredSize;
3785 LPDPSESSIONDESC2 lpTempSessDesc;
3786
3787 TRACE( "(%p)->(%p,0x%08x,%u,%u)\n",
3788 This, lpSessDesc, dwFlags, bInitial, bAnsi );
3789
3790 if( This->dp2->connectionInitialized == NO_PROVIDER )
3791 {
3792 return DPERR_UNINITIALIZED;
3793 }
3794
3795 if( dwFlags )
3796 {
3797 return DPERR_INVALIDPARAMS;
3798 }
3799
3800 /* Only the host is allowed to update the session desc */
3801 if( !This->dp2->bHostInterface )
3802 {
3803 return DPERR_ACCESSDENIED;
3804 }
3805
3806 /* FIXME: Copy into This->dp2->lpSessionDesc */
3807 dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
3808 lpTempSessDesc = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwRequiredSize );
3809
3810 if( lpTempSessDesc == NULL )
3811 {
3812 return DPERR_OUTOFMEMORY;
3813 }
3814
3815 /* Free the old */
3816 HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );
3817
3818 This->dp2->lpSessionDesc = lpTempSessDesc;
3819 /* Set the new */
3820 DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
3821 if( bInitial )
3822 {
3823 /*Initializing session GUID*/
3824 CoCreateGuid( &(This->dp2->lpSessionDesc->guidInstance) );
3825 }
3826 /* If this is an external invocation of the interface, we should be
3827 * letting everyone know that things have changed. Otherwise this is
3828 * just an initialization and it doesn't need to be propagated.
3829 */
3830 if( !bInitial )
3831 {
3832 FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
3833 }
3834
3835 return DP_OK;
3836 }
3837
3838 static HRESULT WINAPI IDirectPlay2AImpl_SetSessionDesc( IDirectPlay2A *iface, DPSESSIONDESC2 *sdesc,
3839 DWORD flags )
3840 {
3841 IDirectPlayImpl *This = impl_from_IDirectPlay2A( iface );
3842 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4A_iface, sdesc, flags );
3843 }
3844
3845 static HRESULT WINAPI IDirectPlay2Impl_SetSessionDesc( IDirectPlay2 *iface, DPSESSIONDESC2 *sdesc,
3846 DWORD flags )
3847 {
3848 IDirectPlayImpl *This = impl_from_IDirectPlay2( iface );
3849 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3850 }
3851
3852 static HRESULT WINAPI IDirectPlay3AImpl_SetSessionDesc( IDirectPlay3A *iface, DPSESSIONDESC2 *sdesc,
3853 DWORD flags )
3854 {
3855 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3856 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3857 }
3858
3859 static HRESULT WINAPI IDirectPlay3Impl_SetSessionDesc( IDirectPlay3 *iface, DPSESSIONDESC2 *sdesc,
3860 DWORD flags )
3861 {
3862 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3863 return IDirectPlayX_SetSessionDesc( &This->IDirectPlay4_iface, sdesc, flags );
3864 }
3865
3866 static HRESULT WINAPI IDirectPlay4AImpl_SetSessionDesc( IDirectPlay4A *iface,
3867 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3868 {
3869 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3870 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3871 }
3872
3873 static HRESULT WINAPI IDirectPlay4Impl_SetSessionDesc( IDirectPlay4 *iface,
3874 DPSESSIONDESC2 *lpSessDesc, DWORD dwFlags )
3875 {
3876 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
3877 return DP_SetSessionDesc( This, lpSessDesc, dwFlags, FALSE, TRUE );
3878 }
3879
3880 /* FIXME: See about merging some of this stuff with dplayx_global.c stuff */
3881 static DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
3882 {
3883 DWORD dwSize = 0;
3884
3885 if( lpSessDesc == NULL )
3886 {
3887 /* Hmmm..don't need any size? */
3888 ERR( "NULL lpSessDesc\n" );
3889 return dwSize;
3890 }
3891
3892 dwSize += sizeof( *lpSessDesc );
3893
3894 if( bAnsi )
3895 {
3896 if( lpSessDesc->u1.lpszSessionNameA )
3897 {
3898 dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
3899 }
3900
3901 if( lpSessDesc->u2.lpszPasswordA )
3902 {
3903 dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
3904 }
3905 }
3906 else /* UNICODE */
3907 {
3908 if( lpSessDesc->u1.lpszSessionName )
3909 {
3910 dwSize += sizeof( WCHAR ) *
3911 ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
3912 }
3913
3914 if( lpSessDesc->u2.lpszPassword )
3915 {
3916 dwSize += sizeof( WCHAR ) *
3917 ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
3918 }
3919 }
3920
3921 return dwSize;
3922 }
3923
3924 /* Assumes that contiguous buffers are already allocated. */
3925 static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
3926 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
3927 {
3928 BYTE* lpStartOfFreeSpace;
3929
3930 if( lpSessionDest == NULL )
3931 {
3932 ERR( "NULL lpSessionDest\n" );
3933 return;
3934 }
3935
3936 CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
3937
3938 lpStartOfFreeSpace = ((BYTE*)lpSessionDest) + sizeof( *lpSessionSrc );
3939
3940 if( bAnsi )
3941 {
3942 if( lpSessionSrc->u1.lpszSessionNameA )
3943 {
3944 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3945 lpSessionDest->u1.lpszSessionNameA );
3946 lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
3947 lpStartOfFreeSpace +=
3948 lstrlenA( lpSessionDest->u1.lpszSessionNameA ) + 1;
3949 }
3950
3951 if( lpSessionSrc->u2.lpszPasswordA )
3952 {
3953 lstrcpyA( (LPSTR)lpStartOfFreeSpace,
3954 lpSessionDest->u2.lpszPasswordA );
3955 lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
3956 }
3957 }
3958 else /* UNICODE */
3959 {
3960 if( lpSessionSrc->u1.lpszSessionName )
3961 {
3962 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3963 lpSessionDest->u1.lpszSessionName );
3964 lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
3965 lpStartOfFreeSpace += sizeof(WCHAR) *
3966 ( lstrlenW( lpSessionDest->u1.lpszSessionName ) + 1 );
3967 }
3968
3969 if( lpSessionSrc->u2.lpszPassword )
3970 {
3971 lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
3972 lpSessionDest->u2.lpszPassword );
3973 lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
3974 }
3975 }
3976 }
3977
3978 static HRESULT WINAPI IDirectPlay3AImpl_AddGroupToGroup( IDirectPlay3A *iface, DPID parent,
3979 DPID group )
3980 {
3981 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
3982 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4A_iface, parent, group );
3983 }
3984
3985 static HRESULT WINAPI IDirectPlay3Impl_AddGroupToGroup( IDirectPlay3 *iface, DPID parent,
3986 DPID group )
3987 {
3988 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
3989 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3990 }
3991
3992 static HRESULT WINAPI IDirectPlay4AImpl_AddGroupToGroup( IDirectPlay4A *iface, DPID parent,
3993 DPID group )
3994 {
3995 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
3996 return IDirectPlayX_AddGroupToGroup( &This->IDirectPlay4_iface, parent, group );
3997 }
3998
3999 static HRESULT WINAPI IDirectPlay4Impl_AddGroupToGroup( IDirectPlay4 *iface, DPID parent,
4000 DPID group )
4001 {
4002 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4003 lpGroupData gdata;
4004 lpGroupList glist;
4005
4006 TRACE( "(%p)->(0x%08x,0x%08x)\n", This, parent, group );
4007
4008 if ( This->dp2->connectionInitialized == NO_PROVIDER )
4009 return DPERR_UNINITIALIZED;
4010
4011 if ( !DP_FindAnyGroup(This, parent ) )
4012 return DPERR_INVALIDGROUP;
4013
4014 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
4015 return DPERR_INVALIDGROUP;
4016
4017 /* Create a player list (ie "shortcut" ) */
4018 glist = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *glist ) );
4019 if ( !glist )
4020 return DPERR_CANTADDPLAYER;
4021
4022 /* Add the shortcut */
4023 gdata->uRef++;
4024 glist->lpGData = gdata;
4025
4026 /* Add the player to the list of players for this group */
4027 DPQ_INSERT( gdata->groups, glist, groups );
4028
4029 /* Send a ADDGROUPTOGROUP message */
4030 FIXME( "Not sending message\n" );
4031
4032 return DP_OK;
4033 }
4034
4035 static HRESULT DP_IF_CreateGroupInGroup( IDirectPlayImpl *This, void *lpMsgHdr, DPID idParentGroup,
4036 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags,
4037 BOOL bAnsi )
4038 {
4039 lpGroupData lpGParentData;
4040 lpGroupList lpGList;
4041 lpGroupData lpGData;
4042
4043 TRACE( "(%p)->(0x%08x,%p,%p,%p,0x%08x,0x%08x,%u)\n",
4044 This, idParentGroup, lpidGroup, lpGroupName, lpData,
4045 dwDataSize, dwFlags, bAnsi );
4046
4047 if( This->dp2->connectionInitialized == NO_PROVIDER )
4048 {
4049 return DPERR_UNINITIALIZED;
4050 }
4051
4052 /* Verify that the specified parent is valid */
4053 if( ( lpGParentData = DP_FindAnyGroup(This, idParentGroup ) ) == NULL )
4054 return DPERR_INVALIDGROUP;
4055
4056 lpGData = DP_CreateGroup(This, lpidGroup, lpGroupName, dwFlags, idParentGroup, bAnsi );
4057
4058 if( lpGData == NULL )
4059 {
4060 return DPERR_CANTADDPLAYER; /* yes player not group */
4061 }
4062
4063 /* Something else is referencing this data */
4064 lpGData->uRef++;
4065
4066 DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
4067
4068 /* The list has now been inserted into the interface group list. We now
4069 need to put a "shortcut" to this group in the parent group */
4070 lpGList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpGList ) );
4071 if( lpGList == NULL )
4072 {
4073 FIXME( "Memory leak\n" );
4074 return DPERR_CANTADDPLAYER; /* yes player not group */
4075 }
4076
4077 lpGList->lpGData = lpGData;
4078
4079 DPQ_INSERT( lpGParentData->groups, lpGList, groups );
4080
4081 /* Let the SP know that we've created this group */
4082 if( This->dp2->spData.lpCB->CreateGroup )
4083 {
4084 DPSP_CREATEGROUPDATA data;
4085
4086 TRACE( "Calling SP CreateGroup\n" );
4087
4088 data.idGroup = *lpidGroup;
4089 data.dwFlags = dwFlags;
4090 data.lpSPMessageHeader = lpMsgHdr;
4091 data.lpISP = This->dp2->spData.lpISP;
4092
4093 (*This->dp2->spData.lpCB->CreateGroup)( &data );
4094 }
4095
4096 /* Inform all other peers of the creation of a new group. If there are
4097 * no peers keep this quiet.
4098 */
4099 if( This->dp2->lpSessionDesc &&
4100 ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
4101 {
4102 DPMSG_CREATEPLAYERORGROUP msg;
4103
4104 msg.dwType = DPSYS_CREATEPLAYERORGROUP;
4105 msg.dwPlayerType = DPPLAYERTYPE_GROUP;
4106 msg.dpId = *lpidGroup;
4107 msg.dwCurrentPlayers = idParentGroup; /* FIXME: Incorrect? */
4108 msg.lpData = lpData;
4109 msg.dwDataSize = dwDataSize;
4110 msg.dpnName = *lpGroupName;
4111
4112 /* FIXME: Correct to just use send effectively? */
4113 /* FIXME: Should size include data w/ message or just message "header" */
4114 /* FIXME: Check return code */
4115 IDirectPlayX_SendEx( &This->IDirectPlay4_iface, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
4116 sizeof( msg ), 0, 0, NULL, NULL );
4117 }
4118
4119 return DP_OK;
4120 }
4121
4122 static HRESULT WINAPI IDirectPlay3AImpl_CreateGroupInGroup( IDirectPlay3A *iface, DPID parent,
4123 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4124 {
4125 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4126 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4A_iface, parent, group, name,
4127 data, size, flags );
4128 }
4129
4130 static HRESULT WINAPI IDirectPlay3Impl_CreateGroupInGroup( IDirectPlay3 *iface, DPID parent,
4131 DPID *group, DPNAME *name, void *data, DWORD size, DWORD flags )
4132 {
4133 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4134 return IDirectPlayX_CreateGroupInGroup( &This->IDirectPlay4_iface, parent, group, name,
4135 data, size, flags );
4136 }
4137
4138 static HRESULT WINAPI IDirectPlay4AImpl_CreateGroupInGroup( IDirectPlay4A *iface,
4139 DPID idParentGroup, DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize,
4140 DWORD dwFlags )
4141 {
4142 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4143
4144 *lpidGroup = DPID_UNKNOWN;
4145
4146 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4147 dwDataSize, dwFlags, TRUE );
4148 }
4149
4150 static HRESULT WINAPI IDirectPlay4Impl_CreateGroupInGroup( IDirectPlay4 *iface, DPID idParentGroup,
4151 DPID *lpidGroup, DPNAME *lpGroupName, void *lpData, DWORD dwDataSize, DWORD dwFlags )
4152 {
4153 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4154
4155 *lpidGroup = DPID_UNKNOWN;
4156
4157 return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, lpGroupName, lpData,
4158 dwDataSize, dwFlags, FALSE );
4159 }
4160
4161 static HRESULT WINAPI IDirectPlay3AImpl_DeleteGroupFromGroup( IDirectPlay3A *iface, DPID parent,
4162 DPID group )
4163 {
4164 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4165 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4A_iface, parent, group );
4166 }
4167
4168 static HRESULT WINAPI IDirectPlay3Impl_DeleteGroupFromGroup( IDirectPlay3 *iface, DPID parent,
4169 DPID group )
4170 {
4171 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4172 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4173 }
4174
4175 static HRESULT WINAPI IDirectPlay4AImpl_DeleteGroupFromGroup( IDirectPlay4A *iface, DPID parent,
4176 DPID group )
4177 {
4178 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4179 return IDirectPlayX_DeleteGroupFromGroup( &This->IDirectPlay4_iface, parent, group );
4180 }
4181
4182 static HRESULT WINAPI IDirectPlay4Impl_DeleteGroupFromGroup( IDirectPlay4 *iface, DPID parent,
4183 DPID group )
4184 {
4185 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4186 lpGroupList glist;
4187 lpGroupData parentdata;
4188
4189 TRACE("(%p)->(0x%08x,0x%08x)\n", This, parent, group );
4190
4191 /* Is the parent group valid? */
4192 if ( ( parentdata = DP_FindAnyGroup(This, parent ) ) == NULL )
4193 return DPERR_INVALIDGROUP;
4194
4195 /* Remove the group from the parent group queue */
4196 DPQ_REMOVE_ENTRY( parentdata->groups, groups, lpGData->dpid, ==, group, glist );
4197
4198 if ( glist == NULL )
4199 return DPERR_INVALIDGROUP;
4200
4201 /* Decrement the ref count */
4202 glist->lpGData->uRef--;
4203
4204 /* Free up the list item */
4205 HeapFree( GetProcessHeap(), 0, glist );
4206
4207 /* Should send a DELETEGROUPFROMGROUP message */
4208 FIXME( "message not sent\n" );
4209
4210 return DP_OK;
4211 }
4212
4213 static BOOL DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
4214 LPDWORD lpdwBufSize )
4215 {
4216 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4217 HRESULT hr;
4218
4219 dpCompoundAddress.dwDataSize = sizeof( GUID );
4220 dpCompoundAddress.guidDataType = DPAID_ServiceProvider;
4221 dpCompoundAddress.lpData = lpcSpGuid;
4222
4223 *lplpAddrBuf = NULL;
4224 *lpdwBufSize = 0;
4225
4226 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4227 lpdwBufSize, TRUE );
4228
4229 if( hr != DPERR_BUFFERTOOSMALL )
4230 {
4231 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4232 return FALSE;
4233 }
4234
4235 /* Now allocate the buffer */
4236 *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
4237 *lpdwBufSize );
4238
4239 hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
4240 lpdwBufSize, TRUE );
4241 if( FAILED(hr) )
4242 {
4243 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4244 return FALSE;
4245 }
4246
4247 return TRUE;
4248 }
4249
4250 static HRESULT WINAPI IDirectPlay3AImpl_EnumConnections( IDirectPlay3A *iface,
4251 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4252 {
4253 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4254 return IDirectPlayX_EnumConnections( &This->IDirectPlay4A_iface, application, enumcb, context,
4255 flags );
4256 }
4257
4258 static HRESULT WINAPI IDirectPlay3Impl_EnumConnections( IDirectPlay3 *iface,
4259 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4260 {
4261 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4262 return IDirectPlayX_EnumConnections( &This->IDirectPlay4_iface, application, enumcb, context,
4263 flags );
4264 }
4265
4266 static HRESULT WINAPI IDirectPlay4AImpl_EnumConnections( IDirectPlay4A *iface,
4267 const GUID *lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, void *lpContext,
4268 DWORD dwFlags )
4269 {
4270 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4271 TRACE("(%p)->(%p,%p,%p,0x%08x)\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
4272
4273 /* A default dwFlags (0) is backwards compatible -- DPCONNECTION_DIRECTPLAY */
4274 if( dwFlags == 0 )
4275 {
4276 dwFlags = DPCONNECTION_DIRECTPLAY;
4277 }
4278
4279 if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
4280 ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
4281 )
4282 {
4283 return DPERR_INVALIDFLAGS;
4284 }
4285
4286 if( !lpEnumCallback )
4287 {
4288 return DPERR_INVALIDPARAMS;
4289 }
4290
4291 /* Enumerate DirectPlay service providers */
4292 if( dwFlags & DPCONNECTION_DIRECTPLAY )
4293 {
4294 HKEY hkResult;
4295 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4296 LPCSTR guidDataSubKey = "Guid";
4297 char subKeyName[51];
4298 DWORD dwIndex, sizeOfSubKeyName=50;
4299 FILETIME filetime;
4300
4301 /* Need to loop over the service providers in the registry */
4302 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4303 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4304 {
4305 /* Hmmm. Does this mean that there are no service providers? */
4306 ERR(": no service providers?\n");
4307 return DP_OK;
4308 }
4309
4310
4311 /* Traverse all the service providers we have available */
4312 for( dwIndex=0;
4313 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4314 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4315 ++dwIndex, sizeOfSubKeyName=51 )
4316 {
4317
4318 HKEY hkServiceProvider;
4319 GUID serviceProviderGUID;
4320 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4321 char returnBuffer[51];
4322 WCHAR buff[51];
4323 DPNAME dpName;
4324 BOOL bBuildPass;
4325
4326 LPVOID lpAddressBuffer = NULL;
4327 DWORD dwAddressBufferSize = 0;
4328
4329 TRACE(" this time through: %s\n", subKeyName );
4330
4331 /* Get a handle for this particular service provider */
4332 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4333 &hkServiceProvider ) != ERROR_SUCCESS )
4334 {
4335 ERR(": what the heck is going on?\n" );
4336 continue;
4337 }
4338
4339 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4340 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4341 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4342 {
4343 ERR(": missing GUID registry data members\n" );
4344 RegCloseKey(hkServiceProvider);
4345 continue;
4346 }
4347 RegCloseKey(hkServiceProvider);
4348
4349 /* FIXME: Check return types to ensure we're interpreting data right */
4350 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4351 CLSIDFromString( buff, &serviceProviderGUID );
4352 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4353
4354 /* Fill in the DPNAME struct for the service provider */
4355 dpName.dwSize = sizeof( dpName );
4356 dpName.dwFlags = 0;
4357 dpName.u1.lpszShortNameA = subKeyName;
4358 dpName.u2.lpszLongNameA = NULL;
4359
4360 /* Create the compound address for the service provider.
4361 * NOTE: This is a gruesome architectural scar right now. DP
4362 * uses DPL and DPL uses DP. Nasty stuff. This may be why the
4363 * native dll just gets around this little bit by allocating an
4364 * 80 byte buffer which isn't even filled with a valid compound
4365 * address. Oh well. Creating a proper compound address is the
4366 * way to go anyways despite this method taking slightly more
4367 * heap space and realtime :) */
4368
4369 bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
4370 &lpAddressBuffer,
4371 &dwAddressBufferSize );
4372 if( !bBuildPass )
4373 {
4374 ERR( "Can't build compound addr\n" );
4375 return DPERR_GENERIC;
4376 }
4377
4378 /* The enumeration will return FALSE if we are not to continue */
4379 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4380 &dpName, dwFlags, lpContext ) )
4381 {
4382 return DP_OK;
4383 }
4384 }
4385 }
4386
4387 /* Enumerate DirectPlayLobby service providers */
4388 if( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY )
4389 {
4390 HKEY hkResult;
4391 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4392 LPCSTR guidDataSubKey = "Guid";
4393 char subKeyName[51];
4394 DWORD dwIndex, sizeOfSubKeyName=50;
4395 FILETIME filetime;
4396
4397 /* Need to loop over the service providers in the registry */
4398 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4399 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4400 {
4401 /* Hmmm. Does this mean that there are no service providers? */
4402 ERR(": no service providers?\n");
4403 return DP_OK;
4404 }
4405
4406
4407 /* Traverse all the lobby providers we have available */
4408 for( dwIndex=0;
4409 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4410 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4411 ++dwIndex, sizeOfSubKeyName=51 )
4412 {
4413
4414 HKEY hkServiceProvider;
4415 GUID serviceProviderGUID;
4416 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
4417 char returnBuffer[51];
4418 WCHAR buff[51];
4419 DPNAME dpName;
4420 HRESULT hr;
4421
4422 DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
4423 LPVOID lpAddressBuffer = NULL;
4424 DWORD dwAddressBufferSize = 0;
4425
4426 TRACE(" this time through: %s\n", subKeyName );
4427
4428 /* Get a handle for this particular service provider */
4429 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4430 &hkServiceProvider ) != ERROR_SUCCESS )
4431 {
4432 ERR(": what the heck is going on?\n" );
4433 continue;
4434 }
4435
4436 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4437 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
4438 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4439 {
4440 ERR(": missing GUID registry data members\n" );
4441 RegCloseKey(hkServiceProvider);
4442 continue;
4443 }
4444 RegCloseKey(hkServiceProvider);
4445
4446 /* FIXME: Check return types to ensure we're interpreting data right */
4447 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4448 CLSIDFromString( buff, &serviceProviderGUID );
4449 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4450
4451 /* Fill in the DPNAME struct for the service provider */
4452 dpName.dwSize = sizeof( dpName );
4453 dpName.dwFlags = 0;
4454 dpName.u1.lpszShortNameA = subKeyName;
4455 dpName.u2.lpszLongNameA = NULL;
4456
4457 /* Create the compound address for the service provider.
4458 NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
4459 nast stuff. This may be why the native dll just gets around this little bit by
4460 allocating an 80 byte buffer which isn't even a filled with a valid compound
4461 address. Oh well. Creating a proper compound address is the way to go anyways
4462 despite this method taking slightly more heap space and realtime :) */
4463
4464 dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
4465 dpCompoundAddress.dwDataSize = sizeof( GUID );
4466 dpCompoundAddress.lpData = &serviceProviderGUID;
4467
4468 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4469 &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
4470 {
4471 ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
4472 return hr;
4473 }
4474
4475 /* Now allocate the buffer */
4476 lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
4477
4478 if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
4479 &dwAddressBufferSize, TRUE ) ) != DP_OK )
4480 {
4481 ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
4482 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4483 return hr;
4484 }
4485
4486 /* The enumeration will return FALSE if we are not to continue */
4487 if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
4488 &dpName, dwFlags, lpContext ) )
4489 {
4490 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4491 return DP_OK;
4492 }
4493 HeapFree( GetProcessHeap(), 0, lpAddressBuffer );
4494 }
4495 }
4496
4497 return DP_OK;
4498 }
4499
4500 static HRESULT WINAPI IDirectPlay4Impl_EnumConnections( IDirectPlay4 *iface,
4501 const GUID *application, LPDPENUMCONNECTIONSCALLBACK enumcb, void *context, DWORD flags )
4502 {
4503 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4504 FIXME( "(%p)->(%p,%p,%p,0x%08x): stub\n", This, application, enumcb, context, flags );
4505 return DP_OK;
4506 }
4507
4508 static HRESULT WINAPI IDirectPlay3AImpl_EnumGroupsInGroup( IDirectPlay3A *iface, DPID group,
4509 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4510 {
4511 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4512 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4A_iface, group, instance,
4513 enumplayercb, context, flags );
4514 }
4515
4516 static HRESULT WINAPI IDirectPlay3Impl_EnumGroupsInGroup( IDirectPlay3 *iface, DPID group,
4517 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4518 {
4519 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4520 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4521 enumplayercb, context, flags );
4522 }
4523
4524 static HRESULT WINAPI IDirectPlay4AImpl_EnumGroupsInGroup( IDirectPlay4A *iface, DPID group,
4525 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4526 {
4527 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4528 return IDirectPlayX_EnumGroupsInGroup( &This->IDirectPlay4_iface, group, instance,
4529 enumplayercb, context, flags );
4530 }
4531
4532 static HRESULT WINAPI IDirectPlay4Impl_EnumGroupsInGroup( IDirectPlay4 *iface, DPID group,
4533 GUID *instance, LPDPENUMPLAYERSCALLBACK2 enumplayercb, void *context, DWORD flags )
4534 {
4535 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4536 lpGroupList glist;
4537 lpGroupData gdata;
4538
4539 FIXME( "(%p)->(0x%08x,%p,%p,%p,0x%08x): semi stub\n", This, group, instance, enumplayercb,
4540 context, flags );
4541
4542 if ( This->dp2->connectionInitialized == NO_PROVIDER )
4543 return DPERR_UNINITIALIZED;
4544
4545 if ( ( gdata = DP_FindAnyGroup(This, group ) ) == NULL )
4546 return DPERR_INVALIDGROUP;
4547
4548 if ( DPQ_IS_EMPTY( gdata->groups ) )
4549 return DP_OK;
4550
4551
4552 for( glist = DPQ_FIRST( gdata->groups ); ; glist = DPQ_NEXT( glist->groups ) )
4553 {
4554 /* FIXME: Should check flags for match here */
4555 if ( !(*enumplayercb)( glist->lpGData->dpid, DPPLAYERTYPE_GROUP, &glist->lpGData->name,
4556 flags, context ) )
4557 return DP_OK; /* User requested break */
4558
4559 if ( DPQ_IS_ENDOFLIST( glist->groups ) )
4560 break;
4561 }
4562
4563 return DP_OK;
4564 }
4565
4566 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupConnectionSettings( IDirectPlay3A *iface,
4567 DWORD flags, DPID group, void *data, DWORD *size )
4568 {
4569 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4570 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4571 data, size );
4572 }
4573
4574 static HRESULT WINAPI IDirectPlay3Impl_GetGroupConnectionSettings( IDirectPlay3 *iface,
4575 DWORD flags, DPID group, void *data, DWORD *size )
4576 {
4577 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4578 return IDirectPlayX_GetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4579 data, size );
4580 }
4581
4582 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupConnectionSettings( IDirectPlay4A *iface,
4583 DWORD flags, DPID group, void *data, DWORD *size )
4584 {
4585 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4586 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size );
4587 return DP_OK;
4588 }
4589
4590 static HRESULT WINAPI IDirectPlay4Impl_GetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
4591 DPID group, void *data, DWORD *size )
4592 {
4593 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4594 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, flags, group, data, size );
4595 return DP_OK;
4596 }
4597
4598 static BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
4599 REFGUID guidDataType,
4600 DWORD dwDataSize,
4601 LPCVOID lpData,
4602 LPVOID lpContext )
4603 {
4604 /* Looking for the GUID of the provider to load */
4605 if( ( IsEqualGUID( guidDataType, &DPAID_ServiceProvider ) ) ||
4606 ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
4607 )
4608 {
4609 TRACE( "Found SP/LP (%s) %s (data size = 0x%08x)\n",
4610 debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
4611
4612 if( dwDataSize != sizeof( GUID ) )
4613 {
4614 ERR( "Invalid sp/lp guid size 0x%08x\n", dwDataSize );
4615 }
4616
4617 memcpy( lpContext, lpData, dwDataSize );
4618
4619 /* There shouldn't be more than 1 GUID/compound address */
4620 return FALSE;
4621 }
4622
4623 /* Still waiting for what we want */
4624 return TRUE;
4625 }
4626
4627
4628 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
4629 static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
4630 {
4631 UINT i;
4632 LPCSTR spSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
4633 LPCSTR lpSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
4634 LPCSTR guidDataSubKey = "Guid";
4635 LPCSTR majVerDataSubKey = "dwReserved1";
4636 LPCSTR minVerDataSubKey = "dwReserved2";
4637 LPCSTR pathSubKey = "Path";
4638
4639 TRACE( " request to load %s\n", debugstr_guid( lpcGuid ) );
4640
4641 /* FIXME: Cloned code with a quick hack. */
4642 for( i=0; i<2; i++ )
4643 {
4644 HKEY hkResult;
4645 LPCSTR searchSubKey;
4646 char subKeyName[51];
4647 DWORD dwIndex, sizeOfSubKeyName=50;
4648 FILETIME filetime;
4649
4650 (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
4651 *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
4652
4653
4654 /* Need to loop over the service providers in the registry */
4655 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
4656 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
4657 {
4658 /* Hmmm. Does this mean that there are no service providers? */
4659 ERR(": no service providers?\n");
4660 return 0;
4661 }
4662
4663 /* Traverse all the service providers we have available */
4664 for( dwIndex=0;
4665 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
4666 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
4667 ++dwIndex, sizeOfSubKeyName=51 )
4668 {
4669
4670 HKEY hkServiceProvider;
4671 GUID serviceProviderGUID;
4672 DWORD returnType, sizeOfReturnBuffer = 255;
4673 char returnBuffer[256];
4674 WCHAR buff[51];
4675 DWORD dwTemp, len;
4676
4677 TRACE(" this time through: %s\n", subKeyName );
4678
4679 /* Get a handle for this particular service provider */
4680 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
4681 &hkServiceProvider ) != ERROR_SUCCESS )
4682 {
4683 ERR(": what the heck is going on?\n" );
4684 continue;
4685 }
4686
4687 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
4688 NULL, &returnType, (LPBYTE)returnBuffer,
4689 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4690 {
4691 ERR(": missing GUID registry data members\n" );
4692 continue;
4693 }
4694
4695 /* FIXME: Check return types to ensure we're interpreting data right */
4696 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
4697 CLSIDFromString( buff, &serviceProviderGUID );
4698 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
4699
4700 /* Determine if this is the Service Provider that the user asked for */
4701 if( !IsEqualGUID( &serviceProviderGUID, lpcGuid ) )
4702 {
4703 continue;
4704 }
4705
4706 if( i == 0 ) /* DP SP */
4707 {
4708 len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
4709 lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
4710 MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
4711 }
4712
4713 sizeOfReturnBuffer = 255;
4714
4715 /* Get dwReserved1 */
4716 if( RegQueryValueExA( hkServiceProvider, majVerDataSubKey,
4717 NULL, &returnType, (LPBYTE)returnBuffer,
4718 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4719 {
4720 ERR(": missing dwReserved1 registry data members\n") ;
4721 continue;
4722 }
4723
4724 if( i == 0 )
4725 memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
4726
4727 sizeOfReturnBuffer = 255;
4728
4729 /* Get dwReserved2 */
4730 if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
4731 NULL, &returnType, (LPBYTE)returnBuffer,
4732 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
4733 {
4734 ERR(": missing dwReserved1 registry data members\n") ;
4735 continue;
4736 }
4737
4738 if( i == 0 )
4739 memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
4740
4741 sizeOfReturnBuffer = 255;
4742
4743 /* Get the path for this service provider */
4744 if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
4745 NULL, NULL, (LPBYTE)returnBuffer,
4746 &sizeOfReturnBuffer ) ) != ERROR_SUCCESS )
4747 {
4748 ERR(": missing PATH registry data members: 0x%08x\n", dwTemp );
4749 continue;
4750 }
4751
4752 TRACE( "Loading %s\n", returnBuffer );
4753 return LoadLibraryA( returnBuffer );
4754 }
4755 }
4756
4757 return 0;
4758 }
4759
4760 static HRESULT DP_InitializeDPSP( IDirectPlayImpl *This, HMODULE hServiceProvider )
4761 {
4762 HRESULT hr;
4763 LPDPSP_SPINIT SPInit;
4764
4765 /* Initialize the service provider by calling SPInit */
4766 SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
4767
4768 if( SPInit == NULL )
4769 {
4770 ERR( "Service provider doesn't provide SPInit interface?\n" );
4771 FreeLibrary( hServiceProvider );
4772 return DPERR_UNAVAILABLE;
4773 }
4774
4775 TRACE( "Calling SPInit (DP SP entry point)\n" );
4776
4777 hr = (*SPInit)( &This->dp2->spData );
4778
4779 if( FAILED(hr) )
4780 {
4781 ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4782 FreeLibrary( hServiceProvider );
4783 return hr;
4784 }
4785
4786 /* FIXME: Need to verify the sanity of the returned callback table
4787 * using IsBadCodePtr */
4788 This->dp2->bSPInitialized = TRUE;
4789
4790 /* This interface is now initialized as a DP object */
4791 This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
4792
4793 /* Store the handle of the module so that we can unload it later */
4794 This->dp2->hServiceProvider = hServiceProvider;
4795
4796 return hr;
4797 }
4798
4799 static HRESULT DP_InitializeDPLSP( IDirectPlayImpl *This, HMODULE hLobbyProvider )
4800 {
4801 HRESULT hr;
4802 LPSP_INIT DPLSPInit;
4803
4804 /* Initialize the service provider by calling SPInit */
4805 DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
4806
4807 if( DPLSPInit == NULL )
4808 {
4809 ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
4810 FreeLibrary( hLobbyProvider );
4811 return DPERR_UNAVAILABLE;
4812 }
4813
4814 TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
4815
4816 hr = (*DPLSPInit)( &This->dp2->dplspData );
4817
4818 if( FAILED(hr) )
4819 {
4820 ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
4821 FreeLibrary( hLobbyProvider );
4822 return hr;
4823 }
4824
4825 /* FIXME: Need to verify the sanity of the returned callback table
4826 * using IsBadCodePtr */
4827
4828 This->dp2->bDPLSPInitialized = TRUE;
4829
4830 /* This interface is now initialized as a lobby object */
4831 This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
4832
4833 /* Store the handle of the module so that we can unload it later */
4834 This->dp2->hDPLobbyProvider = hLobbyProvider;
4835
4836 return hr;
4837 }
4838
4839 static HRESULT WINAPI IDirectPlay3AImpl_InitializeConnection( IDirectPlay3A *iface,
4840 void *connection, DWORD flags )
4841 {
4842 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4843 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4A_iface, connection, flags );
4844 }
4845
4846 static HRESULT WINAPI IDirectPlay3Impl_InitializeConnection( IDirectPlay3 *iface,
4847 void *connection, DWORD flags )
4848 {
4849 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4850 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4851 }
4852
4853 static HRESULT WINAPI IDirectPlay4AImpl_InitializeConnection( IDirectPlay4A *iface,
4854 void *connection, DWORD flags )
4855 {
4856 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4857 return IDirectPlayX_InitializeConnection( &This->IDirectPlay4_iface, connection, flags );
4858 }
4859
4860 static HRESULT WINAPI IDirectPlay4Impl_InitializeConnection( IDirectPlay4 *iface,
4861 void *connection, DWORD flags )
4862 {
4863 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4864 HMODULE servprov;
4865 GUID sp;
4866 const DWORD size = 80; /* FIXME: Need to calculate it correctly */
4867 BOOL is_dp_sp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
4868 HRESULT hr;
4869
4870 TRACE( "(%p)->(%p,0x%08x)\n", This, connection, flags );
4871
4872 if ( !connection )
4873 return DPERR_INVALIDPARAMS;
4874
4875 if ( flags )
4876 return DPERR_INVALIDFLAGS;
4877
4878 if ( This->dp2->connectionInitialized != NO_PROVIDER )
4879 return DPERR_ALREADYINITIALIZED;
4880
4881 /* Find out what the requested SP is and how large this buffer is */
4882 hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, connection, size, &sp );
4883
4884 if ( FAILED(hr) )
4885 {
4886 ERR( "Invalid compound address?\n" );
4887 return DPERR_UNAVAILABLE;
4888 }
4889
4890 /* Load the service provider */
4891 servprov = DP_LoadSP( &sp, &This->dp2->spData, &is_dp_sp );
4892
4893 if ( !servprov )
4894 {
4895 ERR( "Unable to load service provider %s\n", debugstr_guid(&sp) );
4896 return DPERR_UNAVAILABLE;
4897 }
4898
4899 if ( is_dp_sp )
4900 {
4901 /* Fill in what we can of the Service Provider required information.
4902 * The rest was be done in DP_LoadSP
4903 */
4904 This->dp2->spData.lpAddress = connection;
4905 This->dp2->spData.dwAddressSize = size;
4906 This->dp2->spData.lpGuid = &sp;
4907 hr = DP_InitializeDPSP( This, servprov );
4908 }
4909 else
4910 {
4911 This->dp2->dplspData.lpAddress = connection;
4912 hr = DP_InitializeDPLSP( This, servprov );
4913 }
4914
4915 if ( FAILED(hr) )
4916 return hr;
4917
4918 return DP_OK;
4919 }
4920
4921 static HRESULT WINAPI IDirectPlay3AImpl_SecureOpen( IDirectPlay3A *iface,
4922 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4923 const DPCREDENTIALS *credentials )
4924 {
4925 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4926 return IDirectPlayX_SecureOpen( &This->IDirectPlay4A_iface, sdesc, flags, security,
4927 credentials );
4928 }
4929
4930 static HRESULT WINAPI IDirectPlay3Impl_SecureOpen( IDirectPlay3 *iface,
4931 const DPSESSIONDESC2 *sdesc, DWORD flags, const DPSECURITYDESC *security,
4932 const DPCREDENTIALS *credentials )
4933 {
4934 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4935 return IDirectPlayX_SecureOpen( &This->IDirectPlay4_iface, sdesc, flags, security,
4936 credentials );
4937 }
4938
4939 static HRESULT WINAPI IDirectPlay4AImpl_SecureOpen( IDirectPlay4A *iface,
4940 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4941 const DPCREDENTIALS *lpCredentials )
4942 {
4943 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4944 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, TRUE );
4945 }
4946
4947 static HRESULT WINAPI IDirectPlay4Impl_SecureOpen( IDirectPlay4 *iface,
4948 const DPSESSIONDESC2 *lpsd, DWORD dwFlags, const DPSECURITYDESC *lpSecurity,
4949 const DPCREDENTIALS *lpCredentials )
4950 {
4951 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4952 return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
4953 }
4954
4955 static HRESULT WINAPI IDirectPlay3AImpl_SendChatMessage( IDirectPlay3A *iface, DPID from, DPID to,
4956 DWORD flags, DPCHAT *chatmsg )
4957 {
4958 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4959 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4A_iface, from, to, flags, chatmsg );
4960 }
4961
4962 static HRESULT WINAPI IDirectPlay3Impl_SendChatMessage( IDirectPlay3 *iface, DPID from, DPID to,
4963 DWORD flags, DPCHAT *chatmsg )
4964 {
4965 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4966 return IDirectPlayX_SendChatMessage( &This->IDirectPlay4_iface, from, to, flags, chatmsg );
4967 }
4968
4969 static HRESULT WINAPI IDirectPlay4AImpl_SendChatMessage( IDirectPlay4A *iface, DPID from,
4970 DPID to, DWORD flags, DPCHAT *chatmsg )
4971 {
4972 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
4973 FIXME("(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg );
4974 return DP_OK;
4975 }
4976
4977 static HRESULT WINAPI IDirectPlay4Impl_SendChatMessage( IDirectPlay4 *iface, DPID from, DPID to,
4978 DWORD flags, DPCHAT *chatmsg )
4979 {
4980 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
4981 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p): stub\n", This, from, to, flags, chatmsg );
4982 return DP_OK;
4983 }
4984
4985 static HRESULT WINAPI IDirectPlay3AImpl_SetGroupConnectionSettings( IDirectPlay3A *iface,
4986 DWORD flags, DPID group, DPLCONNECTION *connection )
4987 {
4988 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
4989 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4A_iface, flags, group,
4990 connection );
4991 }
4992
4993 static HRESULT WINAPI IDirectPlay3Impl_SetGroupConnectionSettings( IDirectPlay3 *iface,
4994 DWORD flags, DPID group, DPLCONNECTION *connection )
4995 {
4996 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
4997 return IDirectPlayX_SetGroupConnectionSettings( &This->IDirectPlay4_iface, flags, group,
4998 connection );
4999 }
5000
5001 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupConnectionSettings( IDirectPlay4A *iface,
5002 DWORD flags, DPID group, DPLCONNECTION *connection )
5003 {
5004 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5005 FIXME("(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection );
5006 return DP_OK;
5007 }
5008
5009 static HRESULT WINAPI IDirectPlay4Impl_SetGroupConnectionSettings( IDirectPlay4 *iface, DWORD flags,
5010 DPID group, DPLCONNECTION *connection )
5011 {
5012 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5013 FIXME( "(%p)->(0x%08x,0x%08x,%p): stub\n", This, flags, group, connection );
5014 return DP_OK;
5015 }
5016
5017 static HRESULT WINAPI IDirectPlay3AImpl_StartSession( IDirectPlay3A *iface, DWORD flags,
5018 DPID group )
5019 {
5020 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5021 return IDirectPlayX_StartSession( &This->IDirectPlay4A_iface, flags, group );
5022 }
5023
5024 static HRESULT WINAPI IDirectPlay3Impl_StartSession( IDirectPlay3 *iface, DWORD flags,
5025 DPID group )
5026 {
5027 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5028 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
5029 }
5030
5031 static HRESULT WINAPI IDirectPlay4AImpl_StartSession( IDirectPlay4A *iface, DWORD flags,
5032 DPID group )
5033 {
5034 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5035 return IDirectPlayX_StartSession( &This->IDirectPlay4_iface, flags, group );
5036 }
5037
5038 static HRESULT WINAPI IDirectPlay4Impl_StartSession( IDirectPlay4 *iface, DWORD flags, DPID group )
5039 {
5040 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5041 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, flags, group );
5042 return DP_OK;
5043 }
5044
5045 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupFlags( IDirectPlay3A *iface, DPID group,
5046 DWORD *flags )
5047 {
5048 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5049 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4A_iface, group, flags );
5050 }
5051
5052 static HRESULT WINAPI IDirectPlay3Impl_GetGroupFlags( IDirectPlay3 *iface, DPID group,
5053 DWORD *flags )
5054 {
5055 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5056 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5057 }
5058
5059 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupFlags( IDirectPlay4A *iface, DPID group,
5060 DWORD *flags )
5061 {
5062 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5063 return IDirectPlayX_GetGroupFlags( &This->IDirectPlay4_iface, group, flags );
5064 }
5065
5066 static HRESULT WINAPI IDirectPlay4Impl_GetGroupFlags( IDirectPlay4 *iface, DPID group,
5067 DWORD *flags )
5068 {
5069 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5070 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, flags );
5071 return DP_OK;
5072 }
5073
5074 static HRESULT WINAPI IDirectPlay3AImpl_GetGroupParent( IDirectPlay3A *iface, DPID group,
5075 DPID *parent )
5076 {
5077 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5078 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4A_iface, group, parent );
5079 }
5080
5081 static HRESULT WINAPI IDirectPlay3Impl_GetGroupParent( IDirectPlay3 *iface, DPID group,
5082 DPID *parent )
5083 {
5084 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5085 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5086 }
5087
5088 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupParent( IDirectPlay4A *iface, DPID group,
5089 DPID *parent )
5090 {
5091 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5092 return IDirectPlayX_GetGroupParent( &This->IDirectPlay4_iface, group, parent );
5093 }
5094
5095 static HRESULT WINAPI IDirectPlay4Impl_GetGroupParent( IDirectPlay4 *iface, DPID group,
5096 DPID *parent )
5097 {
5098 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5099 lpGroupData gdata;
5100
5101 TRACE( "(%p)->(0x%08x,%p)\n", This, group, parent );
5102
5103 if ( ( gdata = DP_FindAnyGroup( This, group ) ) == NULL )
5104 return DPERR_INVALIDGROUP;
5105
5106 *parent = gdata->dpid;
5107
5108 return DP_OK;
5109 }
5110
5111 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerAccount( IDirectPlay3A *iface, DPID player,
5112 DWORD flags, void *data, DWORD *size )
5113 {
5114 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5115 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4A_iface, player, flags, data, size );
5116 }
5117
5118 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerAccount( IDirectPlay3 *iface, DPID player,
5119 DWORD flags, void *data, DWORD *size )
5120 {
5121 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5122 return IDirectPlayX_GetPlayerAccount( &This->IDirectPlay4_iface, player, flags, data, size );
5123 }
5124
5125 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerAccount( IDirectPlay4A *iface, DPID player,
5126 DWORD flags, void *data, DWORD *size )
5127 {
5128 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5129 FIXME("(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size );
5130 return DP_OK;
5131 }
5132
5133 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerAccount( IDirectPlay4 *iface, DPID player,
5134 DWORD flags, void *data, DWORD *size )
5135 {
5136 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5137 FIXME( "(%p)->(0x%08x,0x%08x,%p,%p): stub\n", This, player, flags, data, size );
5138 return DP_OK;
5139 }
5140
5141 static HRESULT WINAPI IDirectPlay3AImpl_GetPlayerFlags( IDirectPlay3A *iface, DPID player,
5142 DWORD *flags )
5143 {
5144 IDirectPlayImpl *This = impl_from_IDirectPlay3A( iface );
5145 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4A_iface, player, flags );
5146 }
5147
5148 static HRESULT WINAPI IDirectPlay3Impl_GetPlayerFlags( IDirectPlay3 *iface, DPID player,
5149 DWORD *flags )
5150 {
5151 IDirectPlayImpl *This = impl_from_IDirectPlay3( iface );
5152 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5153 }
5154
5155 static HRESULT WINAPI IDirectPlay4AImpl_GetPlayerFlags( IDirectPlay4A *iface, DPID player,
5156 DWORD *flags )
5157 {
5158 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5159 return IDirectPlayX_GetPlayerFlags( &This->IDirectPlay4_iface, player, flags );
5160 }
5161
5162 static HRESULT WINAPI IDirectPlay4Impl_GetPlayerFlags( IDirectPlay4 *iface, DPID player,
5163 DWORD *flags )
5164 {
5165 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5166 FIXME( "(%p)->(0x%08x,%p): stub\n", This, player, flags );
5167 return DP_OK;
5168 }
5169
5170 static HRESULT WINAPI IDirectPlay4AImpl_GetGroupOwner( IDirectPlay4A *iface, DPID group,
5171 DPID *owner )
5172 {
5173 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5174 return IDirectPlayX_GetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5175 }
5176
5177 static HRESULT WINAPI IDirectPlay4Impl_GetGroupOwner( IDirectPlay4 *iface, DPID group,
5178 DPID *owner )
5179 {
5180 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5181 FIXME( "(%p)->(0x%08x,%p): stub\n", This, group, owner );
5182 return DP_OK;
5183 }
5184
5185 static HRESULT WINAPI IDirectPlay4AImpl_SetGroupOwner( IDirectPlay4A *iface, DPID group,
5186 DPID owner )
5187 {
5188 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5189 return IDirectPlayX_SetGroupOwner( &This->IDirectPlay4_iface, group, owner );
5190 }
5191
5192 static HRESULT WINAPI IDirectPlay4Impl_SetGroupOwner( IDirectPlay4 *iface, DPID group ,
5193 DPID owner )
5194 {
5195 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5196 FIXME( "(%p)->(0x%08x,0x%08x): stub\n", This, group, owner );
5197 return DP_OK;
5198 }
5199
5200 static HRESULT WINAPI IDirectPlay4AImpl_SendEx( IDirectPlay4A *iface, DPID from, DPID to,
5201 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5202 DWORD *msgid )
5203 {
5204 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5205 return IDirectPlayX_SendEx( &This->IDirectPlay4_iface, from, to, flags, data, size, priority,
5206 timeout, context, msgid );
5207 }
5208
5209 static HRESULT WINAPI IDirectPlay4Impl_SendEx( IDirectPlay4 *iface, DPID from, DPID to,
5210 DWORD flags, void *data, DWORD size, DWORD priority, DWORD timeout, void *context,
5211 DWORD *msgid )
5212 {
5213 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5214
5215 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n",
5216 This, from, to, flags, data, size, priority, timeout, context, msgid );
5217
5218 if ( This->dp2->connectionInitialized == NO_PROVIDER )
5219 return DPERR_UNINITIALIZED;
5220
5221 /* FIXME: Add parameter checking */
5222 /* FIXME: First call to this needs to acquire a message id which will be
5223 * used for multiple sends
5224 */
5225
5226 /* NOTE: Can't send messages to yourself - this will be trapped in receive */
5227
5228 /* Verify that the message is being sent from a valid local player. The
5229 * from player may be anonymous DPID_UNKNOWN
5230 */
5231 if ( from != DPID_UNKNOWN && !DP_FindPlayer( This, from ) )
5232 {
5233 WARN( "INFO: Invalid from player 0x%08x\n", from );
5234 return DPERR_INVALIDPLAYER;
5235 }
5236
5237 /* Verify that the message is being sent to a valid player, group or to
5238 * everyone. If it's valid, send it to those players.
5239 */
5240 if ( to == DPID_ALLPLAYERS )
5241 {
5242 /* See if SP has the ability to multicast. If so, use it */
5243 if ( This->dp2->spData.lpCB->SendToGroupEx )
5244 FIXME( "Use group sendex to group 0\n" );
5245 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5246 FIXME( "Use obsolete group send to group 0\n" );
5247 else /* No multicast, multiplicate */
5248 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5249 }
5250 else if ( DP_FindPlayer( This, to ) )
5251 {
5252 /* Have the service provider send this message */
5253 /* FIXME: Could optimize for local interface sends */
5254 return DP_SP_SendEx( This, flags, data, size, priority, timeout, context, msgid );
5255 }
5256 else if ( DP_FindAnyGroup( This, to ) )
5257 {
5258 /* See if SP has the ability to multicast. If so, use it */
5259 if ( This->dp2->spData.lpCB->SendToGroupEx )
5260 FIXME( "Use group sendex\n" );
5261 else if ( This->dp2->spData.lpCB->SendToGroup ) /* obsolete interface */
5262 FIXME( "Use obsolete group send to group\n" );
5263 else /* No multicast, multiplicate */
5264 FIXME( "Send to all players using EnumPlayersInGroup\n" );
5265
5266 }
5267 else
5268 return DPERR_INVALIDPLAYER;
5269
5270 /* FIXME: Should return what the send returned */
5271 return DP_OK;
5272 }
5273
5274 static HRESULT DP_SP_SendEx( IDirectPlayImpl *This, DWORD dwFlags, void *lpData, DWORD dwDataSize,
5275 DWORD dwPriority, DWORD dwTimeout, void *lpContext, DWORD *lpdwMsgID )
5276 {
5277 LPDPMSG lpMElem;
5278
5279 FIXME( ": stub\n" );
5280
5281 /* FIXME: This queuing should only be for async messages */
5282
5283 lpMElem = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpMElem ) );
5284 lpMElem->msg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
5285
5286 CopyMemory( lpMElem->msg, lpData, dwDataSize );
5287
5288 /* FIXME: Need to queue based on priority */
5289 DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
5290
5291 return DP_OK;
5292 }
5293
5294 static HRESULT WINAPI IDirectPlay4AImpl_GetMessageQueue( IDirectPlay4A *iface, DPID from, DPID to,
5295 DWORD flags, DWORD *msgs, DWORD *bytes )
5296 {
5297 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5298 return IDirectPlayX_GetMessageQueue( &This->IDirectPlay4_iface, from, to, flags, msgs, bytes );
5299 }
5300
5301 static HRESULT WINAPI IDirectPlay4Impl_GetMessageQueue( IDirectPlay4 *iface, DPID from, DPID to,
5302 DWORD flags, DWORD *msgs, DWORD *bytes )
5303 {
5304 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5305 HRESULT hr = DP_OK;
5306
5307 FIXME( "(%p)->(0x%08x,0x%08x,0x%08x,%p,%p): semi-stub\n", This, from, to, flags, msgs, bytes );
5308
5309 /* FIXME: Do we need to do from and to sanity checking here? */
5310 /* FIXME: What about sends which are not immediate? */
5311
5312 if ( This->dp2->spData.lpCB->GetMessageQueue )
5313 {
5314 DPSP_GETMESSAGEQUEUEDATA data;
5315
5316 FIXME( "Calling SP GetMessageQueue - is it right?\n" );
5317
5318 /* FIXME: None of this is documented :( */
5319 data.lpISP = This->dp2->spData.lpISP;
5320 data.dwFlags = flags;
5321 data.idFrom = from;
5322 data.idTo = to;
5323 data.lpdwNumMsgs = msgs;
5324 data.lpdwNumBytes = bytes;
5325
5326 hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
5327 }
5328 else
5329 FIXME( "No SP for GetMessageQueue - fake some data\n" );
5330
5331 return hr;
5332 }
5333
5334 static HRESULT dplay_cancelmsg ( IDirectPlayImpl* This, DWORD msgid, DWORD flags, DWORD minprio,
5335 DWORD maxprio )
5336 {
5337 HRESULT hr = DP_OK;
5338
5339 FIXME( "(%p)->(0x%08x,0x%08x): semi stub\n", This, msgid, flags );
5340
5341 if ( This->dp2->spData.lpCB->Cancel )
5342 {
5343 DPSP_CANCELDATA data;
5344
5345 TRACE( "Calling SP Cancel\n" );
5346
5347 /* FIXME: Undocumented callback */
5348
5349 data.lpISP = This->dp2->spData.lpISP;
5350 data.dwFlags = flags;
5351 data.lprglpvSPMsgID = NULL;
5352 data.cSPMsgID = msgid;
5353 data.dwMinPriority = minprio;
5354 data.dwMaxPriority = maxprio;
5355
5356 hr = (*This->dp2->spData.lpCB->Cancel)( &data );
5357 }
5358 else
5359 FIXME( "SP doesn't implement Cancel\n" );
5360
5361 return hr;
5362 }
5363
5364 static HRESULT WINAPI IDirectPlay4AImpl_CancelMessage( IDirectPlay4A *iface, DWORD msgid,
5365 DWORD flags )
5366 {
5367 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5368 return IDirectPlayX_CancelMessage( &This->IDirectPlay4_iface, msgid, flags );
5369 }
5370
5371 static HRESULT WINAPI IDirectPlay4Impl_CancelMessage( IDirectPlay4 *iface, DWORD msgid,
5372 DWORD flags )
5373 {
5374 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5375
5376 if ( flags != 0 )
5377 return DPERR_INVALIDFLAGS;
5378
5379 if ( msgid == 0 )
5380 flags |= DPCANCELSEND_ALL;
5381
5382 return dplay_cancelmsg( This, msgid, flags, 0, 0 );
5383 }
5384
5385 static HRESULT WINAPI IDirectPlay4AImpl_CancelPriority( IDirectPlay4A *iface, DWORD minprio,
5386 DWORD maxprio, DWORD flags )
5387 {
5388 IDirectPlayImpl *This = impl_from_IDirectPlay4A( iface );
5389 return IDirectPlayX_CancelPriority( &This->IDirectPlay4_iface, minprio, maxprio, flags );
5390 }
5391
5392 static HRESULT WINAPI IDirectPlay4Impl_CancelPriority( IDirectPlay4 *iface, DWORD minprio,
5393 DWORD maxprio, DWORD flags )
5394 {
5395 IDirectPlayImpl *This = impl_from_IDirectPlay4( iface );
5396
5397 if ( flags != 0 )
5398 return DPERR_INVALIDFLAGS;
5399
5400 return dplay_cancelmsg( This, 0, DPCANCELSEND_PRIORITY, minprio, maxprio );
5401 }
5402
5403 static const IDirectPlay2Vtbl dp2_vt =
5404 {
5405 IDirectPlay2Impl_QueryInterface,
5406 IDirectPlay2Impl_AddRef,
5407 IDirectPlay2Impl_Release,
5408 IDirectPlay2Impl_AddPlayerToGroup,
5409 IDirectPlay2Impl_Close,
5410 IDirectPlay2Impl_CreateGroup,
5411 IDirectPlay2Impl_CreatePlayer,
5412 IDirectPlay2Impl_DeletePlayerFromGroup,
5413 IDirectPlay2Impl_DestroyGroup,
5414 IDirectPlay2Impl_DestroyPlayer,
5415 IDirectPlay2Impl_EnumGroupPlayers,
5416 IDirectPlay2Impl_EnumGroups,
5417 IDirectPlay2Impl_EnumPlayers,
5418 IDirectPlay2Impl_EnumSessions,
5419 IDirectPlay2Impl_GetCaps,
5420 IDirectPlay2Impl_GetGroupData,
5421 IDirectPlay2Impl_GetGroupName,
5422 IDirectPlay2Impl_GetMessageCount,
5423 IDirectPlay2Impl_GetPlayerAddress,
5424 IDirectPlay2Impl_GetPlayerCaps,
5425 IDirectPlay2Impl_GetPlayerData,
5426 IDirectPlay2Impl_GetPlayerName,
5427 IDirectPlay2Impl_GetSessionDesc,
5428 IDirectPlay2Impl_Initialize,
5429 IDirectPlay2Impl_Open,
5430 IDirectPlay2Impl_Receive,
5431 IDirectPlay2Impl_Send,
5432 IDirectPlay2Impl_SetGroupData,
5433 IDirectPlay2Impl_SetGroupName,
5434 IDirectPlay2Impl_SetPlayerData,
5435 IDirectPlay2Impl_SetPlayerName,
5436 IDirectPlay2Impl_SetSessionDesc
5437 };
5438
5439 static const IDirectPlay2Vtbl dp2A_vt =
5440 {
5441 IDirectPlay2AImpl_QueryInterface,
5442 IDirectPlay2AImpl_AddRef,
5443 IDirectPlay2AImpl_Release,
5444 IDirectPlay2AImpl_AddPlayerToGroup,
5445 IDirectPlay2AImpl_Close,
5446 IDirectPlay2AImpl_CreateGroup,
5447 IDirectPlay2AImpl_CreatePlayer,
5448 IDirectPlay2AImpl_DeletePlayerFromGroup,
5449 IDirectPlay2AImpl_DestroyGroup,
5450 IDirectPlay2AImpl_DestroyPlayer,
5451 IDirectPlay2AImpl_EnumGroupPlayers,
5452 IDirectPlay2AImpl_EnumGroups,
5453 IDirectPlay2AImpl_EnumPlayers,
5454 IDirectPlay2AImpl_EnumSessions,
5455 IDirectPlay2AImpl_GetCaps,
5456 IDirectPlay2AImpl_GetGroupData,
5457 IDirectPlay2AImpl_GetGroupName,
5458 IDirectPlay2AImpl_GetMessageCount,
5459 IDirectPlay2AImpl_GetPlayerAddress,
5460 IDirectPlay2AImpl_GetPlayerCaps,
5461 IDirectPlay2AImpl_GetPlayerData,
5462 IDirectPlay2AImpl_GetPlayerName,
5463 IDirectPlay2AImpl_GetSessionDesc,
5464 IDirectPlay2AImpl_Initialize,
5465 IDirectPlay2AImpl_Open,
5466 IDirectPlay2AImpl_Receive,
5467 IDirectPlay2AImpl_Send,
5468 IDirectPlay2AImpl_SetGroupData,
5469 IDirectPlay2AImpl_SetGroupName,
5470 IDirectPlay2AImpl_SetPlayerData,
5471 IDirectPlay2AImpl_SetPlayerName,
5472 IDirectPlay2AImpl_SetSessionDesc
5473 };
5474
5475 static const IDirectPlay3Vtbl dp3_vt =
5476 {
5477 IDirectPlay3Impl_QueryInterface,
5478 IDirectPlay3Impl_AddRef,
5479 IDirectPlay3Impl_Release,
5480 IDirectPlay3Impl_AddPlayerToGroup,
5481 IDirectPlay3Impl_Close,
5482 IDirectPlay3Impl_CreateGroup,
5483 IDirectPlay3Impl_CreatePlayer,
5484 IDirectPlay3Impl_DeletePlayerFromGroup,
5485 IDirectPlay3Impl_DestroyGroup,
5486 IDirectPlay3Impl_DestroyPlayer,
5487 IDirectPlay3Impl_EnumGroupPlayers,
5488 IDirectPlay3Impl_EnumGroups,
5489 IDirectPlay3Impl_EnumPlayers,
5490 IDirectPlay3Impl_EnumSessions,
5491 IDirectPlay3Impl_GetCaps,
5492 IDirectPlay3Impl_GetGroupData,
5493 IDirectPlay3Impl_GetGroupName,
5494 IDirectPlay3Impl_GetMessageCount,
5495 IDirectPlay3Impl_GetPlayerAddress,
5496 IDirectPlay3Impl_GetPlayerCaps,
5497 IDirectPlay3Impl_GetPlayerData,
5498 IDirectPlay3Impl_GetPlayerName,
5499 IDirectPlay3Impl_GetSessionDesc,
5500 IDirectPlay3Impl_Initialize,
5501 IDirectPlay3Impl_Open,
5502 IDirectPlay3Impl_Receive,
5503 IDirectPlay3Impl_Send,
5504 IDirectPlay3Impl_SetGroupData,
5505 IDirectPlay3Impl_SetGroupName,
5506 IDirectPlay3Impl_SetPlayerData,
5507 IDirectPlay3Impl_SetPlayerName,
5508 IDirectPlay3Impl_SetSessionDesc,
5509 IDirectPlay3Impl_AddGroupToGroup,
5510 IDirectPlay3Impl_CreateGroupInGroup,
5511 IDirectPlay3Impl_DeleteGroupFromGroup,
5512 IDirectPlay3Impl_EnumConnections,
5513 IDirectPlay3Impl_EnumGroupsInGroup,
5514 IDirectPlay3Impl_GetGroupConnectionSettings,
5515 IDirectPlay3Impl_InitializeConnection,
5516 IDirectPlay3Impl_SecureOpen,
5517 IDirectPlay3Impl_SendChatMessage,
5518 IDirectPlay3Impl_SetGroupConnectionSettings,
5519 IDirectPlay3Impl_StartSession,
5520 IDirectPlay3Impl_GetGroupFlags,
5521 IDirectPlay3Impl_GetGroupParent,
5522 IDirectPlay3Impl_GetPlayerAccount,
5523 IDirectPlay3Impl_GetPlayerFlags
5524 };
5525
5526 static const IDirectPlay3Vtbl dp3A_vt =
5527 {
5528 IDirectPlay3AImpl_QueryInterface,
5529 IDirectPlay3AImpl_AddRef,
5530 IDirectPlay3AImpl_Release,
5531 IDirectPlay3AImpl_AddPlayerToGroup,
5532 IDirectPlay3AImpl_Close,
5533 IDirectPlay3AImpl_CreateGroup,
5534 IDirectPlay3AImpl_CreatePlayer,
5535 IDirectPlay3AImpl_DeletePlayerFromGroup,
5536 IDirectPlay3AImpl_DestroyGroup,
5537 IDirectPlay3AImpl_DestroyPlayer,
5538 IDirectPlay3AImpl_EnumGroupPlayers,
5539 IDirectPlay3AImpl_EnumGroups,
5540 IDirectPlay3AImpl_EnumPlayers,
5541 IDirectPlay3AImpl_EnumSessions,
5542 IDirectPlay3AImpl_GetCaps,
5543 IDirectPlay3AImpl_GetGroupData,
5544 IDirectPlay3AImpl_GetGroupName,
5545 IDirectPlay3AImpl_GetMessageCount,
5546 IDirectPlay3AImpl_GetPlayerAddress,
5547 IDirectPlay3AImpl_GetPlayerCaps,
5548 IDirectPlay3AImpl_GetPlayerData,
5549 IDirectPlay3AImpl_GetPlayerName,
5550 IDirectPlay3AImpl_GetSessionDesc,
5551 IDirectPlay3AImpl_Initialize,
5552 IDirectPlay3AImpl_Open,
5553 IDirectPlay3AImpl_Receive,
5554 IDirectPlay3AImpl_Send,
5555 IDirectPlay3AImpl_SetGroupData,
5556 IDirectPlay3AImpl_SetGroupName,
5557 IDirectPlay3AImpl_SetPlayerData,
5558 IDirectPlay3AImpl_SetPlayerName,
5559 IDirectPlay3AImpl_SetSessionDesc,
5560 IDirectPlay3AImpl_AddGroupToGroup,
5561 IDirectPlay3AImpl_CreateGroupInGroup,
5562 IDirectPlay3AImpl_DeleteGroupFromGroup,
5563 IDirectPlay3AImpl_EnumConnections,
5564 IDirectPlay3AImpl_EnumGroupsInGroup,
5565 IDirectPlay3AImpl_GetGroupConnectionSettings,
5566 IDirectPlay3AImpl_InitializeConnection,
5567 IDirectPlay3AImpl_SecureOpen,
5568 IDirectPlay3AImpl_SendChatMessage,
5569 IDirectPlay3AImpl_SetGroupConnectionSettings,
5570 IDirectPlay3AImpl_StartSession,
5571 IDirectPlay3AImpl_GetGroupFlags,
5572 IDirectPlay3AImpl_GetGroupParent,
5573 IDirectPlay3AImpl_GetPlayerAccount,
5574 IDirectPlay3AImpl_GetPlayerFlags
5575 };
5576
5577 static const IDirectPlay4Vtbl dp4_vt =
5578 {
5579 IDirectPlay4Impl_QueryInterface,
5580 IDirectPlay4Impl_AddRef,
5581 IDirectPlay4Impl_Release,
5582 IDirectPlay4Impl_AddPlayerToGroup,
5583 IDirectPlay4Impl_Close,
5584 IDirectPlay4Impl_CreateGroup,
5585 IDirectPlay4Impl_CreatePlayer,
5586 IDirectPlay4Impl_DeletePlayerFromGroup,
5587 IDirectPlay4Impl_DestroyGroup,
5588 IDirectPlay4Impl_DestroyPlayer,
5589 IDirectPlay4Impl_EnumGroupPlayers,
5590 IDirectPlay4Impl_EnumGroups,
5591 IDirectPlay4Impl_EnumPlayers,
5592 IDirectPlay4Impl_EnumSessions,
5593 IDirectPlay4Impl_GetCaps,
5594 IDirectPlay4Impl_GetGroupData,
5595 IDirectPlay4Impl_GetGroupName,
5596 IDirectPlay4Impl_GetMessageCount,
5597 IDirectPlay4Impl_GetPlayerAddress,
5598 IDirectPlay4Impl_GetPlayerCaps,
5599 IDirectPlay4Impl_GetPlayerData,
5600 IDirectPlay4Impl_GetPlayerName,
5601 IDirectPlay4Impl_GetSessionDesc,
5602 IDirectPlay4Impl_Initialize,
5603 IDirectPlay4Impl_Open,
5604 IDirectPlay4Impl_Receive,
5605 IDirectPlay4Impl_Send,
5606 IDirectPlay4Impl_SetGroupData,
5607 IDirectPlay4Impl_SetGroupName,
5608 IDirectPlay4Impl_SetPlayerData,
5609 IDirectPlay4Impl_SetPlayerName,
5610 IDirectPlay4Impl_SetSessionDesc,
5611 IDirectPlay4Impl_AddGroupToGroup,
5612 IDirectPlay4Impl_CreateGroupInGroup,
5613 IDirectPlay4Impl_DeleteGroupFromGroup,
5614 IDirectPlay4Impl_EnumConnections,
5615 IDirectPlay4Impl_EnumGroupsInGroup,
5616 IDirectPlay4Impl_GetGroupConnectionSettings,
5617 IDirectPlay4Impl_InitializeConnection,
5618 IDirectPlay4Impl_SecureOpen,
5619 IDirectPlay4Impl_SendChatMessage,
5620 IDirectPlay4Impl_SetGroupConnectionSettings,
5621 IDirectPlay4Impl_StartSession,
5622 IDirectPlay4Impl_GetGroupFlags,
5623 IDirectPlay4Impl_GetGroupParent,
5624 IDirectPlay4Impl_GetPlayerAccount,
5625 IDirectPlay4Impl_GetPlayerFlags,
5626 IDirectPlay4Impl_GetGroupOwner,
5627 IDirectPlay4Impl_SetGroupOwner,
5628 IDirectPlay4Impl_SendEx,
5629 IDirectPlay4Impl_GetMessageQueue,
5630 IDirectPlay4Impl_CancelMessage,
5631 IDirectPlay4Impl_CancelPriority
5632 };
5633
5634 static const IDirectPlay4Vtbl dp4A_vt =
5635 {
5636 IDirectPlay4AImpl_QueryInterface,
5637 IDirectPlay4AImpl_AddRef,
5638 IDirectPlay4AImpl_Release,
5639 IDirectPlay4AImpl_AddPlayerToGroup,
5640 IDirectPlay4AImpl_Close,
5641 IDirectPlay4AImpl_CreateGroup,
5642 IDirectPlay4AImpl_CreatePlayer,
5643 IDirectPlay4AImpl_DeletePlayerFromGroup,
5644 IDirectPlay4AImpl_DestroyGroup,
5645 IDirectPlay4AImpl_DestroyPlayer,
5646 IDirectPlay4AImpl_EnumGroupPlayers,
5647 IDirectPlay4AImpl_EnumGroups,
5648 IDirectPlay4AImpl_EnumPlayers,
5649 IDirectPlay4AImpl_EnumSessions,
5650 IDirectPlay4AImpl_GetCaps,
5651 IDirectPlay4AImpl_GetGroupData,
5652 IDirectPlay4AImpl_GetGroupName,
5653 IDirectPlay4AImpl_GetMessageCount,
5654 IDirectPlay4AImpl_GetPlayerAddress,
5655 IDirectPlay4AImpl_GetPlayerCaps,
5656 IDirectPlay4AImpl_GetPlayerData,
5657 IDirectPlay4AImpl_GetPlayerName,
5658 IDirectPlay4AImpl_GetSessionDesc,
5659 IDirectPlay4AImpl_Initialize,
5660 IDirectPlay4AImpl_Open,
5661 IDirectPlay4AImpl_Receive,
5662 IDirectPlay4AImpl_Send,
5663 IDirectPlay4AImpl_SetGroupData,
5664 IDirectPlay4AImpl_SetGroupName,
5665 IDirectPlay4AImpl_SetPlayerData,
5666 IDirectPlay4AImpl_SetPlayerName,
5667 IDirectPlay4AImpl_SetSessionDesc,
5668 IDirectPlay4AImpl_AddGroupToGroup,
5669 IDirectPlay4AImpl_CreateGroupInGroup,
5670 IDirectPlay4AImpl_DeleteGroupFromGroup,
5671 IDirectPlay4AImpl_EnumConnections,
5672 IDirectPlay4AImpl_EnumGroupsInGroup,
5673 IDirectPlay4AImpl_GetGroupConnectionSettings,
5674 IDirectPlay4AImpl_InitializeConnection,
5675 IDirectPlay4AImpl_SecureOpen,
5676 IDirectPlay4AImpl_SendChatMessage,
5677 IDirectPlay4AImpl_SetGroupConnectionSettings,
5678 IDirectPlay4AImpl_StartSession,
5679 IDirectPlay4AImpl_GetGroupFlags,
5680 IDirectPlay4AImpl_GetGroupParent,
5681 IDirectPlay4AImpl_GetPlayerAccount,
5682 IDirectPlay4AImpl_GetPlayerFlags,
5683 IDirectPlay4AImpl_GetGroupOwner,
5684 IDirectPlay4AImpl_SetGroupOwner,
5685 IDirectPlay4AImpl_SendEx,
5686 IDirectPlay4AImpl_GetMessageQueue,
5687 IDirectPlay4AImpl_CancelMessage,
5688 IDirectPlay4AImpl_CancelPriority
5689 };
5690
5691 HRESULT dplay_create( REFIID riid, void **ppv )
5692 {
5693 IDirectPlayImpl *obj;
5694 HRESULT hr;
5695
5696 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv );
5697
5698 *ppv = NULL;
5699 obj = HeapAlloc( GetProcessHeap(), 0, sizeof( *obj ) );
5700 if ( !obj )
5701 return DPERR_OUTOFMEMORY;
5702
5703 obj->IDirectPlay_iface.lpVtbl = &dp_vt;
5704 obj->IDirectPlay2A_iface.lpVtbl = &dp2A_vt;
5705 obj->IDirectPlay2_iface.lpVtbl = &dp2_vt;
5706 obj->IDirectPlay3A_iface.lpVtbl = &dp3A_vt;
5707 obj->IDirectPlay3_iface.lpVtbl = &dp3_vt;
5708 obj->IDirectPlay4A_iface.lpVtbl = &dp4A_vt;
5709 obj->IDirectPlay4_iface.lpVtbl = &dp4_vt;
5710 obj->numIfaces = 1;
5711 obj->ref = 0;
5712 obj->ref2A = 0;
5713 obj->ref2 = 0;
5714 obj->ref3A = 0;
5715 obj->ref3 = 0;
5716 obj->ref4A = 0;
5717 obj->ref4 = 1;
5718
5719 InitializeCriticalSection( &obj->lock );
5720 obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayImpl.lock");
5721
5722 if ( DP_CreateDirectPlay2( obj ) )
5723 hr = IDirectPlayX_QueryInterface( &obj->IDirectPlay4_iface, riid, ppv );
5724 else
5725 hr = DPERR_NOMEMORY;
5726 IDirectPlayX_Release( &obj->IDirectPlay4_iface );
5727
5728 return hr;
5729 }
5730
5731
5732 HRESULT DP_GetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void **lplpData )
5733 {
5734 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5735
5736 if( lpPlayer == NULL )
5737 {
5738 return DPERR_INVALIDPLAYER;
5739 }
5740
5741 *lplpData = lpPlayer->lpPData->lpSPPlayerData;
5742
5743 return DP_OK;
5744 }
5745
5746 HRESULT DP_SetSPPlayerData( IDirectPlayImpl *lpDP, DPID idPlayer, void *lpData )
5747 {
5748 lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
5749
5750 if( lpPlayer == NULL )
5751 {
5752 return DPERR_INVALIDPLAYER;
5753 }
5754
5755 lpPlayer->lpPData->lpSPPlayerData = lpData;
5756
5757 return DP_OK;
5758 }
5759
5760 /***************************************************************************
5761 * DirectPlayEnumerateAW
5762 *
5763 * The pointer to the structure lpContext will be filled with the
5764 * appropriate data for each service offered by the OS. These services are
5765 * not necessarily available on this particular machine but are defined
5766 * as simple service providers under the "Service Providers" registry key.
5767 * This structure is then passed to lpEnumCallback for each of the different
5768 * services.
5769 *
5770 * This API is useful only for applications written using DirectX3 or
5771 * worse. It is superseded by IDirectPlay3::EnumConnections which also
5772 * gives information on the actual connections.
5773 *
5774 * defn of a service provider:
5775 * A dynamic-link library used by DirectPlay to communicate over a network.
5776 * The service provider contains all the network-specific code required
5777 * to send and receive messages. Online services and network operators can
5778 * supply service providers to use specialized hardware, protocols, communications
5779 * media, and network resources.
5780 *
5781 */
5782 static HRESULT DirectPlayEnumerateAW(LPDPENUMDPCALLBACKA lpEnumCallbackA,
5783 LPDPENUMDPCALLBACKW lpEnumCallbackW,
5784 LPVOID lpContext)
5785 {
5786 HKEY hkResult;
5787 static const WCHAR searchSubKey[] = {
5788 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E', '\\',
5789 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', '\\',
5790 'D', 'i', 'r', 'e', 'c', 't', 'P', 'l', 'a', 'y', '\\',
5791 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 's', 0 };
5792 static const WCHAR guidKey[] = { 'G', 'u', 'i', 'd', 0 };
5793 static const WCHAR descW[] = { 'D', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 'W', 0 };
5794
5795 DWORD dwIndex;
5796 FILETIME filetime;
5797
5798 char *descriptionA = NULL;
5799 DWORD max_sizeOfDescriptionA = 0;
5800 WCHAR *descriptionW = NULL;
5801 DWORD max_sizeOfDescriptionW = 0;
5802
5803 if (!lpEnumCallbackA && !lpEnumCallbackW)
5804 {
5805 return DPERR_INVALIDPARAMS;
5806 }
5807
5808 /* Need to loop over the service providers in the registry */
5809 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, searchSubKey,
5810 0, KEY_READ, &hkResult) != ERROR_SUCCESS)
5811 {
5812 /* Hmmm. Does this mean that there are no service providers? */
5813 ERR(": no service provider key in the registry - check your Wine installation !!!\n");
5814 return DPERR_GENERIC;
5815 }
5816
5817 /* Traverse all the service providers we have available */
5818 dwIndex = 0;
5819 while (1)
5820 {
5821 WCHAR subKeyName[255]; /* 255 is the maximum key size according to MSDN */
5822 DWORD sizeOfSubKeyName = sizeof(subKeyName) / sizeof(WCHAR);
5823 HKEY hkServiceProvider;
5824 GUID serviceProviderGUID;
5825 WCHAR guidKeyContent[(2 * 16) + 1 + 6 /* This corresponds to '{....-..-..-..-......}' */ ];
5826 DWORD sizeOfGuidKeyContent = sizeof(guidKeyContent);
5827 LONG ret_value;
5828
5829 ret_value = RegEnumKeyExW(hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
5830 NULL, NULL, NULL, &filetime);
5831 if (ret_value == ERROR_NO_MORE_ITEMS)
5832 break;
5833 else if (ret_value != ERROR_SUCCESS)
5834 {
5835 ERR(": could not enumerate on service provider key.\n");
5836 return DPERR_EXCEPTION;
5837 }
5838 TRACE(" this time through sub-key %s.\n", debugstr_w(subKeyName));
5839
5840 /* Open the key for this service provider */
5841 if (RegOpenKeyExW(hkResult, subKeyName, 0, KEY_READ, &hkServiceProvider) != ERROR_SUCCESS)
5842 {
5843 ERR(": could not open registry key for service provider %s.\n", debugstr_w(subKeyName));
5844 continue;
5845 }
5846
5847 /* Get the GUID from the registry */
5848 if (RegQueryValueExW(hkServiceProvider, guidKey,
5849 NULL, NULL, (LPBYTE) guidKeyContent, &sizeOfGuidKeyContent) != ERROR_SUCCESS)
5850 {
5851 ERR(": missing GUID registry data member for service provider %s.\n", debugstr_w(subKeyName));
5852 continue;
5853 }
5854 if (sizeOfGuidKeyContent != sizeof(guidKeyContent))
5855 {
5856 ERR(": invalid format for the GUID registry data member for service provider %s (%s).\n", debugstr_w(subKeyName), debugstr_w(guidKeyContent));
5857 continue;
5858 }
5859 CLSIDFromString(guidKeyContent, &serviceProviderGUID );
5860
5861 /* The enumeration will return FALSE if we are not to continue.
5862 *
5863 * Note: on my windows box, major / minor version is 6 / 0 for all service providers
5864 * and have no relation to any of the two dwReserved1 and dwReserved2 keys.
5865 * I think that it simply means that they are in-line with DirectX 6.0
5866 */
5867 if (lpEnumCallbackA)
5868 {
5869 DWORD sizeOfDescription = 0;
5870
5871 /* Note that this is the A case of this function, so use the A variant to get the description string */
5872 if (RegQueryValueExA(hkServiceProvider, "DescriptionA",
5873 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5874 {
5875 ERR(": missing 'DescriptionA' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5876 continue;
5877 }
5878 if (sizeOfDescription > max_sizeOfDescriptionA)
5879 {
5880 HeapFree(GetProcessHeap(), 0, descriptionA);
5881 max_sizeOfDescriptionA = sizeOfDescription;
5882 }
5883 descriptionA = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5884 RegQueryValueExA(hkServiceProvider, "DescriptionA",
5885 NULL, NULL, (LPBYTE) descriptionA, &sizeOfDescription);
5886
5887 if (!lpEnumCallbackA(&serviceProviderGUID, descriptionA, 6, 0, lpContext))
5888 goto end;
5889 }
5890 else
5891 {
5892 DWORD sizeOfDescription = 0;
5893
5894 if (RegQueryValueExW(hkServiceProvider, descW,
5895 NULL, NULL, NULL, &sizeOfDescription) != ERROR_SUCCESS)
5896 {
5897 ERR(": missing 'DescriptionW' registry data member for service provider %s.\n", debugstr_w(subKeyName));
5898 continue;
5899 }
5900 if (sizeOfDescription > max_sizeOfDescriptionW)
5901 {
5902 HeapFree(GetProcessHeap(), 0, descriptionW);
5903 max_sizeOfDescriptionW = sizeOfDescription;
5904 }
5905 descriptionW = HeapAlloc(GetProcessHeap(), 0, sizeOfDescription);
5906 RegQueryValueExW(hkServiceProvider, descW,
5907 NULL, NULL, (LPBYTE) descriptionW, &sizeOfDescription);
5908
5909 if (!lpEnumCallbackW(&serviceProviderGUID, descriptionW, 6, 0, lpContext))
5910 goto end;
5911 }
5912
5913 dwIndex++;
5914 }
5915
5916 end:
5917 HeapFree(GetProcessHeap(), 0, descriptionA);
5918 HeapFree(GetProcessHeap(), 0, descriptionW);
5919
5920 return DP_OK;
5921 }
5922
5923 /***************************************************************************
5924 * DirectPlayEnumerate [DPLAYX.9]
5925 * DirectPlayEnumerateA [DPLAYX.2]
5926 */
5927 HRESULT WINAPI DirectPlayEnumerateA(LPDPENUMDPCALLBACKA lpEnumCallback, LPVOID lpContext )
5928 {
5929 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5930
5931 return DirectPlayEnumerateAW(lpEnumCallback, NULL, lpContext);
5932 }
5933
5934 /***************************************************************************
5935 * DirectPlayEnumerateW [DPLAYX.3]
5936 */
5937 HRESULT WINAPI DirectPlayEnumerateW(LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
5938 {
5939 TRACE("(%p,%p)\n", lpEnumCallback, lpContext);
5940
5941 return DirectPlayEnumerateAW(NULL, lpEnumCallback, lpContext);
5942 }
5943
5944 typedef struct tagCreateEnum
5945 {
5946 LPVOID lpConn;
5947 LPCGUID lpGuid;
5948 } CreateEnumData, *lpCreateEnumData;
5949
5950 /* Find and copy the matching connection for the SP guid */
5951 static BOOL CALLBACK cbDPCreateEnumConnections(
5952 LPCGUID lpguidSP,
5953 LPVOID lpConnection,
5954 DWORD dwConnectionSize,
5955 LPCDPNAME lpName,
5956 DWORD dwFlags,
5957 LPVOID lpContext)
5958 {
5959 lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
5960
5961 if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
5962 {
5963 TRACE( "Found SP entry with guid %s\n", debugstr_guid(lpData->lpGuid) );
5964
5965 lpData->lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
5966 dwConnectionSize );
5967 CopyMemory( lpData->lpConn, lpConnection, dwConnectionSize );
5968
5969 /* Found the record that we were looking for */
5970 return FALSE;
5971 }
5972
5973 /* Haven't found what were looking for yet */
5974 return TRUE;
5975 }
5976
5977
5978 /***************************************************************************
5979 * DirectPlayCreate [DPLAYX.1]
5980 *
5981 */
5982 HRESULT WINAPI DirectPlayCreate
5983 ( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk )
5984 {
5985 HRESULT hr;
5986 LPDIRECTPLAY3A lpDP3A;
5987 CreateEnumData cbData;
5988
5989 TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
5990
5991 if( pUnk != NULL )
5992 {
5993 return CLASS_E_NOAGGREGATION;
5994 }
5995
5996 if( (lplpDP == NULL) || (lpGUID == NULL) )
5997 {
5998 return DPERR_INVALIDPARAMS;
5999 }
6000
6001 if ( dplay_create( &IID_IDirectPlay, (void**)lplpDP ) != DP_OK )
6002 return DPERR_UNAVAILABLE;
6003
6004 if( IsEqualGUID( &GUID_NULL, lpGUID ) )
6005 {
6006 /* The GUID_NULL means don't bind a service provider. Just return the
6007 interface as is */
6008 return DP_OK;
6009 }
6010
6011 /* Bind the desired service provider since lpGUID is non NULL */
6012 TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
6013
6014 /* We're going to use a DP3 interface */
6015 hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
6016 (LPVOID*)&lpDP3A );
6017 if( FAILED(hr) )
6018 {
6019 ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
6020 return hr;
6021 }
6022
6023 cbData.lpConn = NULL;
6024 cbData.lpGuid = lpGUID;
6025
6026 /* We were given a service provider, find info about it... */
6027 hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
6028 &cbData, DPCONNECTION_DIRECTPLAY );
6029 if( ( FAILED(hr) ) ||
6030 ( cbData.lpConn == NULL )
6031 )
6032 {
6033 ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
6034 IDirectPlayX_Release( lpDP3A );
6035 return DPERR_UNAVAILABLE;
6036 }
6037
6038 /* Initialize the service provider */
6039 hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
6040 if( FAILED(hr) )
6041 {
6042 ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
6043 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
6044 IDirectPlayX_Release( lpDP3A );
6045 return hr;
6046 }
6047
6048 /* Release our version of the interface now that we're done with it */
6049 IDirectPlayX_Release( lpDP3A );
6050 HeapFree( GetProcessHeap(), 0, cbData.lpConn );
6051
6052 return DP_OK;
6053 }