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