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