Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / dll / directx / wine / dplayx / dplobby.c
1 /* Direct Play Lobby 2 & 3 Implementation
2 *
3 * Copyright 1998,1999,2000 - 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 /* Forward declarations for this module helper methods */
23 HRESULT DPL_CreateCompoundAddress ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
24 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface )DECLSPEC_HIDDEN;
25
26 static HRESULT DPL_CreateAddress( REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData, DWORD dwDataSize,
27 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
28
29
30 /*****************************************************************************
31 * IDirectPlayLobby {1,2,3} implementation structure
32 *
33 * The philosophy behind this extra pointer dereference is that I wanted to
34 * have the same structure for all types of objects without having to do
35 * a lot of casting. I also only wanted to implement an interface in the
36 * object it was "released" with IUnknown interface being implemented in the 1 version.
37 * Of course, with these new interfaces comes the data required to keep the state required
38 * by these interfaces. So, basically, the pointers contain the data associated with
39 * a release. If you use the data associated with release 3 in a release 2 object, you'll
40 * get a run time trap, as that won't have any data.
41 *
42 */
43 struct DPLMSG
44 {
45 DPQ_ENTRY( DPLMSG ) msgs; /* Link to next queued message */
46 };
47 typedef struct DPLMSG* LPDPLMSG;
48
49 typedef struct IDirectPlayLobbyImpl
50 {
51 IDirectPlayLobby IDirectPlayLobby_iface;
52 IDirectPlayLobbyA IDirectPlayLobbyA_iface;
53 IDirectPlayLobby2 IDirectPlayLobby2_iface;
54 IDirectPlayLobby2A IDirectPlayLobby2A_iface;
55 IDirectPlayLobby3 IDirectPlayLobby3_iface;
56 IDirectPlayLobby3A IDirectPlayLobby3A_iface;
57 LONG numIfaces; /* "in use interfaces" refcount */
58 LONG ref, refA, ref2, ref2A, ref3, ref3A;
59 CRITICAL_SECTION lock;
60 HKEY cbkeyhack;
61 DWORD msgtid;
62 DPQ_HEAD( DPLMSG ) msgs; /* List of messages received */
63 } IDirectPlayLobbyImpl;
64
65 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby( IDirectPlayLobby *iface )
66 {
67 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby_iface );
68 }
69
70 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobbyA( IDirectPlayLobbyA *iface )
71 {
72 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobbyA_iface );
73 }
74
75 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby2( IDirectPlayLobby2 *iface )
76 {
77 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby2_iface );
78 }
79
80 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby2A( IDirectPlayLobby2A *iface )
81 {
82 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby2A_iface );
83 }
84
85 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby3( IDirectPlayLobby3 *iface )
86 {
87 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby3_iface );
88 }
89
90 static inline IDirectPlayLobbyImpl *impl_from_IDirectPlayLobby3A( IDirectPlayLobby3A *iface )
91 {
92 return CONTAINING_RECORD( iface, IDirectPlayLobbyImpl, IDirectPlayLobby3A_iface );
93 }
94
95 static void dplobby_destroy(IDirectPlayLobbyImpl *obj)
96 {
97 if ( obj->msgtid )
98 FIXME( "Should kill the msg thread\n" );
99
100 DPQ_DELETEQ( obj->msgs, msgs, LPDPLMSG, cbDeleteElemFromHeap );
101 obj->lock.DebugInfo->Spare[0] = 0;
102 DeleteCriticalSection( &obj->lock );
103 HeapFree( GetProcessHeap(), 0, obj );
104 }
105
106 static HRESULT WINAPI IDirectPlayLobbyAImpl_QueryInterface( IDirectPlayLobbyA *iface, REFIID riid,
107 void **ppv )
108 {
109 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
110 return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv );
111 }
112
113 static HRESULT WINAPI IDirectPlayLobbyImpl_QueryInterface( IDirectPlayLobby *iface, REFIID riid,
114 void **ppv )
115 {
116 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
117 return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv );
118 }
119
120 static HRESULT WINAPI IDirectPlayLobby2AImpl_QueryInterface( IDirectPlayLobby2A *iface, REFIID riid,
121 void **ppv )
122 {
123 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
124 return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv );
125 }
126
127 static HRESULT WINAPI IDirectPlayLobby2Impl_QueryInterface( IDirectPlayLobby2 *iface, REFIID riid,
128 void **ppv )
129 {
130 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
131 return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv );
132 }
133
134 static HRESULT WINAPI IDirectPlayLobby3AImpl_QueryInterface( IDirectPlayLobby3A *iface, REFIID riid,
135 void **ppv )
136 {
137 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
138 return IDirectPlayLobby_QueryInterface( &This->IDirectPlayLobby3_iface, riid, ppv );
139 }
140
141 static HRESULT WINAPI IDirectPlayLobby3Impl_QueryInterface( IDirectPlayLobby3 *iface, REFIID riid,
142 void **ppv )
143 {
144 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
145
146 if ( IsEqualGUID( &IID_IUnknown, riid ) )
147 {
148 TRACE( "(%p)->(IID_IUnknown %p)\n", This, ppv );
149 *ppv = &This->IDirectPlayLobby_iface;
150 }
151 else if ( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
152 {
153 TRACE( "(%p)->(IID_IDirectPlayLobby %p)\n", This, ppv );
154 *ppv = &This->IDirectPlayLobby_iface;
155 }
156 else if ( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
157 {
158 TRACE( "(%p)->(IID_IDirectPlayLobbyA %p)\n", This, ppv );
159 *ppv = &This->IDirectPlayLobbyA_iface;
160 }
161 else if ( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
162 {
163 TRACE( "(%p)->(IID_IDirectPlayLobby2 %p)\n", This, ppv );
164 *ppv = &This->IDirectPlayLobby2_iface;
165 }
166 else if ( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
167 {
168 TRACE( "(%p)->(IID_IDirectPlayLobby2A %p)\n", This, ppv );
169 *ppv = &This->IDirectPlayLobby2A_iface;
170 }
171 else if ( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
172 {
173 TRACE( "(%p)->(IID_IDirectPlay3 %p)\n", This, ppv );
174 *ppv = &This->IDirectPlayLobby3_iface;
175 }
176 else if ( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
177 {
178 TRACE( "(%p)->(IID_IDirectPlayLobby3A %p)\n", This, ppv );
179 *ppv = &This->IDirectPlayLobby3A_iface;
180 }
181 else
182 {
183 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
184 *ppv = NULL;
185 return E_NOINTERFACE;
186 }
187
188 IUnknown_AddRef((IUnknown*)*ppv);
189 return S_OK;
190 }
191
192 static ULONG WINAPI IDirectPlayLobbyAImpl_AddRef( IDirectPlayLobbyA *iface )
193 {
194 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
195 ULONG ref = InterlockedIncrement( &This->refA );
196
197 TRACE( "(%p) refA=%d\n", This, ref );
198
199 if ( ref == 1 )
200 InterlockedIncrement( &This->numIfaces );
201
202 return ref;
203 }
204
205 static ULONG WINAPI IDirectPlayLobbyImpl_AddRef( IDirectPlayLobby *iface )
206 {
207 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
208 ULONG ref = InterlockedIncrement( &This->ref );
209
210 TRACE( "(%p) ref=%d\n", This, ref );
211
212 if ( ref == 1 )
213 InterlockedIncrement( &This->numIfaces );
214
215 return ref;
216 }
217
218 static ULONG WINAPI IDirectPlayLobby2AImpl_AddRef(IDirectPlayLobby2A *iface)
219 {
220 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
221 ULONG ref = InterlockedIncrement( &This->ref2A );
222
223 TRACE( "(%p) ref2A=%d\n", This, ref );
224
225 if ( ref == 1 )
226 InterlockedIncrement( &This->numIfaces );
227
228 return ref;
229 }
230
231 static ULONG WINAPI IDirectPlayLobby2Impl_AddRef(IDirectPlayLobby2 *iface)
232 {
233 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
234 ULONG ref = InterlockedIncrement( &This->ref2 );
235
236 TRACE( "(%p) ref2=%d\n", This, ref );
237
238 if ( ref == 1 )
239 InterlockedIncrement( &This->numIfaces );
240
241 return ref;
242 }
243
244 static ULONG WINAPI IDirectPlayLobby3AImpl_AddRef(IDirectPlayLobby3A *iface)
245 {
246 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
247 ULONG ref = InterlockedIncrement( &This->ref3A );
248
249 TRACE( "(%p) ref3A=%d\n", This, ref );
250
251 if ( ref == 1 )
252 InterlockedIncrement( &This->numIfaces );
253
254 return ref;
255 }
256
257 static ULONG WINAPI IDirectPlayLobby3Impl_AddRef(IDirectPlayLobby3 *iface)
258 {
259 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
260 ULONG ref = InterlockedIncrement( &This->ref3 );
261
262 TRACE( "(%p) ref3=%d\n", This, ref );
263
264 if ( ref == 1 )
265 InterlockedIncrement( &This->numIfaces );
266
267 return ref;
268 }
269
270 static ULONG WINAPI IDirectPlayLobbyAImpl_Release( IDirectPlayLobbyA *iface )
271 {
272 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
273 ULONG ref = InterlockedDecrement( &This->refA );
274
275 TRACE( "(%p) refA=%d\n", This, ref );
276
277 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
278 dplobby_destroy( This );
279
280 return ref;
281 }
282
283 static ULONG WINAPI IDirectPlayLobbyImpl_Release( IDirectPlayLobby *iface )
284 {
285 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
286 ULONG ref = InterlockedDecrement( &This->ref );
287
288 TRACE( "(%p) ref=%d\n", This, ref );
289
290 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
291 dplobby_destroy( This );
292
293 return ref;
294 }
295
296 static ULONG WINAPI IDirectPlayLobby2AImpl_Release(IDirectPlayLobby2A *iface)
297 {
298 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
299 ULONG ref = InterlockedDecrement( &This->ref2A );
300
301 TRACE( "(%p) ref2A=%d\n", This, ref );
302
303 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
304 dplobby_destroy( This );
305
306 return ref;
307 }
308
309 static ULONG WINAPI IDirectPlayLobby2Impl_Release(IDirectPlayLobby2 *iface)
310 {
311 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
312 ULONG ref = InterlockedDecrement( &This->ref2 );
313
314 TRACE( "(%p) ref2=%d\n", This, ref );
315
316 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
317 dplobby_destroy( This );
318
319 return ref;
320 }
321
322 static ULONG WINAPI IDirectPlayLobby3AImpl_Release(IDirectPlayLobby3A *iface)
323 {
324 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
325 ULONG ref = InterlockedDecrement( &This->ref3A );
326
327 TRACE( "(%p) ref3A=%d\n", This, ref );
328
329 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
330 dplobby_destroy( This );
331
332 return ref;
333 }
334
335 static ULONG WINAPI IDirectPlayLobby3Impl_Release(IDirectPlayLobby3 *iface)
336 {
337 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
338 ULONG ref = InterlockedDecrement( &This->ref3 );
339
340 TRACE( "(%p) ref3=%d\n", This, ref );
341
342 if ( !ref && !InterlockedDecrement( &This->numIfaces ) )
343 dplobby_destroy( This );
344
345 return ref;
346 }
347
348
349 /********************************************************************
350 *
351 * Connects an application to the session specified by the DPLCONNECTION
352 * structure currently stored with the DirectPlayLobby object.
353 *
354 * Returns an IDirectPlay interface.
355 *
356 */
357 static HRESULT DPL_ConnectEx( IDirectPlayLobbyImpl *This, DWORD dwFlags, REFIID riid, void **lplpDP,
358 IUnknown* pUnk)
359 {
360 HRESULT hr;
361 DWORD dwOpenFlags = 0;
362 DWORD dwConnSize = 0;
363 LPDPLCONNECTION lpConn;
364
365 FIXME("(%p)->(0x%08x,%p,%p): semi stub\n", This, dwFlags, lplpDP, pUnk );
366
367 if( pUnk )
368 {
369 return DPERR_INVALIDPARAMS;
370 }
371
372 /* Backwards compatibility */
373 if( dwFlags == 0 )
374 {
375 dwFlags = DPCONNECT_RETURNSTATUS;
376 }
377
378 if ( ( hr = dplay_create( riid, lplpDP ) ) != DP_OK )
379 {
380 ERR( "error creating interface for %s:%s.\n",
381 debugstr_guid( riid ), DPLAYX_HresultToString( hr ) );
382 return hr;
383 }
384
385 /* FIXME: Is it safe/correct to use appID of 0? */
386 hr = IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface,
387 0, NULL, &dwConnSize );
388 if( hr != DPERR_BUFFERTOOSMALL )
389 {
390 return hr;
391 }
392
393 lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwConnSize );
394
395 if( lpConn == NULL )
396 {
397 return DPERR_NOMEMORY;
398 }
399
400 /* FIXME: Is it safe/correct to use appID of 0? */
401 hr = IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface,
402 0, lpConn, &dwConnSize );
403 if( FAILED( hr ) )
404 {
405 HeapFree( GetProcessHeap(), 0, lpConn );
406 return hr;
407 }
408
409 #if 0
410 /* - Need to call IDirectPlay::EnumConnections with the service provider to get that good information
411 * - Need to call CreateAddress to create the lpConnection param for IDirectPlay::InitializeConnection
412 * - Call IDirectPlay::InitializeConnection
413 */
414
415 /* Now initialize the Service Provider */
416 hr = IDirectPlayX_InitializeConnection( (*(LPDIRECTPLAY2*)lplpDP),
417 #endif
418
419
420 /* Setup flags to pass into DirectPlay::Open */
421 if( dwFlags & DPCONNECT_RETURNSTATUS )
422 {
423 dwOpenFlags |= DPOPEN_RETURNSTATUS;
424 }
425 dwOpenFlags |= lpConn->dwFlags;
426
427 hr = IDirectPlayX_Open( (*(LPDIRECTPLAY2*)lplpDP), lpConn->lpSessionDesc,
428 dwOpenFlags );
429
430 HeapFree( GetProcessHeap(), 0, lpConn );
431
432 return hr;
433 }
434
435 static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect( IDirectPlayLobbyA *iface, DWORD flags,
436 IDirectPlay2A **dp, IUnknown *unk )
437 {
438 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
439 return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3A_iface, flags, dp, unk );
440 }
441
442 static HRESULT WINAPI IDirectPlayLobbyImpl_Connect( IDirectPlayLobby *iface, DWORD flags,
443 IDirectPlay2A **dp, IUnknown *unk )
444 {
445 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
446 return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3_iface, flags, dp, unk );
447 }
448
449 static HRESULT WINAPI IDirectPlayLobby2AImpl_Connect( IDirectPlayLobby2A *iface, DWORD flags,
450 IDirectPlay2A **dp, IUnknown *unk )
451 {
452 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
453 return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3A_iface, flags, dp, unk );
454 }
455
456 static HRESULT WINAPI IDirectPlayLobby2Impl_Connect( IDirectPlayLobby2 *iface, DWORD flags,
457 IDirectPlay2A **dp, IUnknown *unk )
458 {
459 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
460 return IDirectPlayLobby_Connect( &This->IDirectPlayLobby3_iface, flags, dp, unk );
461 }
462
463 static HRESULT WINAPI IDirectPlayLobby3AImpl_Connect( IDirectPlayLobby3A *iface, DWORD flags,
464 IDirectPlay2A **dp, IUnknown *unk)
465 {
466 return IDirectPlayLobby_ConnectEx( iface, flags, &IID_IDirectPlay2A, (void**)dp, unk );
467 }
468
469 static HRESULT WINAPI IDirectPlayLobby3Impl_Connect( IDirectPlayLobby3 *iface, DWORD flags,
470 IDirectPlay2 **dp, IUnknown *unk)
471 {
472 return IDirectPlayLobby_ConnectEx( iface, flags, &IID_IDirectPlay2A, (void**)dp, unk );
473 }
474
475 /********************************************************************
476 *
477 * Creates a DirectPlay Address, given a service provider-specific network
478 * address.
479 * Returns an address contains the globally unique identifier
480 * (GUID) of the service provider and data that the service provider can
481 * interpret as a network address.
482 *
483 * NOTE: It appears that this method is supposed to be really really stupid
484 * with no error checking on the contents.
485 */
486 static HRESULT WINAPI IDirectPlayLobbyAImpl_CreateAddress( IDirectPlayLobbyA *iface, REFGUID sp,
487 REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize )
488 {
489 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
490 return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3A_iface, sp, datatype, data,
491 datasize, address, addrsize );
492 }
493
494 static HRESULT WINAPI IDirectPlayLobbyImpl_CreateAddress( IDirectPlayLobby *iface, REFGUID sp,
495 REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize )
496 {
497 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
498 return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3_iface, sp, datatype, data,
499 datasize, address, addrsize );
500 }
501
502 static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateAddress( IDirectPlayLobby2A *iface, REFGUID sp,
503 REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize )
504 {
505 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
506 return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3A_iface, sp, datatype, data,
507 datasize, address, addrsize );
508 }
509
510 static HRESULT WINAPI IDirectPlayLobby2Impl_CreateAddress( IDirectPlayLobby2 *iface, REFGUID sp,
511 REFGUID datatype, const void *data, DWORD datasize, void *address, DWORD *addrsize )
512 {
513 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
514 return IDirectPlayLobby_CreateAddress( &This->IDirectPlayLobby3_iface, sp, datatype, data,
515 datasize, address, addrsize );
516 }
517
518 static HRESULT WINAPI IDirectPlayLobby3AImpl_CreateAddress( IDirectPlayLobby3A *iface,
519 REFGUID guidSP, REFGUID guidDataType, const void *lpData, DWORD dwDataSize, void *lpAddress,
520 DWORD *lpdwAddressSize )
521 {
522 return DPL_CreateAddress( guidSP, guidDataType, lpData, dwDataSize,
523 lpAddress, lpdwAddressSize, TRUE );
524 }
525
526 static HRESULT WINAPI IDirectPlayLobby3Impl_CreateAddress( IDirectPlayLobby3 *iface, REFGUID guidSP,
527 REFGUID guidDataType, const void *lpData, DWORD dwDataSize, void *lpAddress,
528 DWORD *lpdwAddressSize )
529 {
530 return DPL_CreateAddress( guidSP, guidDataType, lpData, dwDataSize,
531 lpAddress, lpdwAddressSize, FALSE );
532 }
533
534 static HRESULT DPL_CreateAddress(
535 REFGUID guidSP,
536 REFGUID guidDataType,
537 LPCVOID lpData,
538 DWORD dwDataSize,
539 LPVOID lpAddress,
540 LPDWORD lpdwAddressSize,
541 BOOL bAnsiInterface )
542 {
543 const DWORD dwNumAddElements = 2; /* Service Provide & address data type */
544 DPCOMPOUNDADDRESSELEMENT addressElements[ 2 /* dwNumAddElements */ ];
545
546 TRACE( "(%p)->(%p,%p,0x%08x,%p,%p,%d)\n", guidSP, guidDataType, lpData, dwDataSize,
547 lpAddress, lpdwAddressSize, bAnsiInterface );
548
549 addressElements[ 0 ].guidDataType = DPAID_ServiceProvider;
550 addressElements[ 0 ].dwDataSize = sizeof( GUID );
551 addressElements[ 0 ].lpData = (LPVOID)guidSP;
552
553 addressElements[ 1 ].guidDataType = *guidDataType;
554 addressElements[ 1 ].dwDataSize = dwDataSize;
555 addressElements[ 1 ].lpData = (LPVOID)lpData;
556
557 /* Call CreateCompoundAddress to cut down on code.
558 NOTE: We can do this because we don't support DPL 1 interfaces! */
559 return DPL_CreateCompoundAddress( addressElements, dwNumAddElements,
560 lpAddress, lpdwAddressSize, bAnsiInterface );
561 }
562
563
564
565 /********************************************************************
566 *
567 * Parses out chunks from the DirectPlay Address buffer by calling the
568 * given callback function, with lpContext, for each of the chunks.
569 *
570 */
571 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddress( IDirectPlayLobbyA *iface,
572 LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context )
573 {
574 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
575 return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3A_iface, enumaddrcb, address, size,
576 context );
577 }
578
579 static HRESULT WINAPI IDirectPlayLobbyImpl_EnumAddress( IDirectPlayLobby *iface,
580 LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context )
581 {
582 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
583 return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3_iface, enumaddrcb, address, size,
584 context );
585 }
586
587 static HRESULT WINAPI IDirectPlayLobby2AImpl_EnumAddress( IDirectPlayLobby2A *iface,
588 LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context )
589 {
590 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
591 return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3A_iface, enumaddrcb, address, size,
592 context );
593 }
594
595 static HRESULT WINAPI IDirectPlayLobby2Impl_EnumAddress( IDirectPlayLobby2 *iface,
596 LPDPENUMADDRESSCALLBACK enumaddrcb, const void *address, DWORD size, void *context )
597 {
598 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
599 return IDirectPlayLobby_EnumAddress( &This->IDirectPlayLobby3_iface, enumaddrcb, address, size,
600 context );
601 }
602
603 static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumAddress( IDirectPlayLobby3A *iface,
604 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, const void *lpAddress, DWORD dwAddressSize,
605 void *lpContext )
606 {
607 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
608
609 TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, lpEnumAddressCallback, lpAddress,
610 dwAddressSize, lpContext );
611
612 return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
613 }
614
615 static HRESULT WINAPI IDirectPlayLobby3Impl_EnumAddress( IDirectPlayLobby3 *iface,
616 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, const void *lpAddress, DWORD dwAddressSize,
617 void *lpContext )
618 {
619 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
620
621 TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, lpEnumAddressCallback, lpAddress,
622 dwAddressSize, lpContext );
623
624 return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
625 }
626
627 HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
628 DWORD dwAddressSize, LPVOID lpContext )
629 {
630 DWORD dwTotalSizeEnumerated = 0;
631
632 /* FIXME: First chunk is always the total size chunk - Should we report it? */
633
634 while ( dwTotalSizeEnumerated < dwAddressSize )
635 {
636 const DPADDRESS* lpElements = lpAddress;
637 DWORD dwSizeThisEnumeration;
638
639 /* Invoke the enum method. If false is returned, stop enumeration */
640 if ( !lpEnumAddressCallback( &lpElements->guidDataType,
641 lpElements->dwDataSize,
642 (const BYTE *)lpElements + sizeof( DPADDRESS ),
643 lpContext ) )
644 {
645 break;
646 }
647
648 dwSizeThisEnumeration = sizeof( DPADDRESS ) + lpElements->dwDataSize;
649 lpAddress = (const BYTE*) lpAddress + dwSizeThisEnumeration;
650 dwTotalSizeEnumerated += dwSizeThisEnumeration;
651 }
652
653 return DP_OK;
654 }
655
656 /********************************************************************
657 *
658 * Enumerates all the address types that a given service provider needs to
659 * build the DirectPlay Address.
660 *
661 */
662 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddressTypes( IDirectPlayLobbyA *iface,
663 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
664 {
665 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
666 return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3A_iface, enumaddrtypecb, sp,
667 context, flags );
668 }
669
670 static HRESULT WINAPI IDirectPlayLobbyImpl_EnumAddressTypes( IDirectPlayLobby *iface,
671 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
672 {
673 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
674 return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3_iface, enumaddrtypecb, sp,
675 context, flags );
676 }
677
678 static HRESULT WINAPI IDirectPlayLobby2AImpl_EnumAddressTypes( IDirectPlayLobby2A *iface,
679 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
680 {
681 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
682 return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3A_iface, enumaddrtypecb, sp,
683 context, flags );
684 }
685
686 static HRESULT WINAPI IDirectPlayLobby2Impl_EnumAddressTypes( IDirectPlayLobby2 *iface,
687 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
688 {
689 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
690 return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3_iface, enumaddrtypecb, sp,
691 context, flags );
692 }
693
694 static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumAddressTypes( IDirectPlayLobby3A *iface,
695 LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback, REFGUID guidSP, void *lpContext,
696 DWORD dwFlags )
697 {
698 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
699
700 HKEY hkResult;
701 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
702 DWORD dwIndex, sizeOfSubKeyName=50;
703 char subKeyName[51];
704 FILETIME filetime;
705
706 TRACE(" (%p)->(%p,%p,%p,0x%08x)\n", This, lpEnumAddressTypeCallback, guidSP, lpContext, dwFlags );
707
708 if( dwFlags != 0 )
709 {
710 return DPERR_INVALIDPARAMS;
711 }
712
713 if( !lpEnumAddressTypeCallback )
714 {
715 return DPERR_INVALIDPARAMS;
716 }
717
718 if( guidSP == NULL )
719 {
720 return DPERR_INVALIDOBJECT;
721 }
722
723 /* Need to loop over the service providers in the registry */
724 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
725 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
726 {
727 /* Hmmm. Does this mean that there are no service providers? */
728 ERR(": no service providers?\n");
729 return DP_OK;
730 }
731
732 /* Traverse all the service providers we have available */
733 for( dwIndex=0;
734 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
735 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
736 ++dwIndex, sizeOfSubKeyName=50 )
737 {
738
739 HKEY hkServiceProvider, hkServiceProviderAt;
740 GUID serviceProviderGUID;
741 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
742 char atSubKey[51];
743 char returnBuffer[51];
744 WCHAR buff[51];
745 DWORD dwAtIndex;
746 LPCSTR atKey = "Address Types";
747 LPCSTR guidDataSubKey = "Guid";
748
749 TRACE(" this time through: %s\n", subKeyName );
750
751 /* Get a handle for this particular service provider */
752 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
753 &hkServiceProvider ) != ERROR_SUCCESS )
754 {
755 ERR(": what the heck is going on?\n" );
756 continue;
757 }
758
759 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
760 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
761 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
762 {
763 ERR(": missing GUID registry data members\n" );
764 continue;
765 }
766
767 /* FIXME: Check return types to ensure we're interpreting data right */
768 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
769 CLSIDFromString( buff, &serviceProviderGUID );
770 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
771
772 /* Determine if this is the Service Provider that the user asked for */
773 if( !IsEqualGUID( &serviceProviderGUID, guidSP ) )
774 {
775 continue;
776 }
777
778 /* Get a handle for this particular service provider */
779 if( RegOpenKeyExA( hkServiceProvider, atKey, 0, KEY_READ,
780 &hkServiceProviderAt ) != ERROR_SUCCESS )
781 {
782 TRACE(": No Address Types registry data sub key/members\n" );
783 break;
784 }
785
786 /* Traverse all the address type we have available */
787 for( dwAtIndex=0;
788 RegEnumKeyExA( hkServiceProviderAt, dwAtIndex, atSubKey, &sizeOfSubKeyName,
789 NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
790 ++dwAtIndex, sizeOfSubKeyName=50 )
791 {
792 TRACE( "Found Address Type GUID %s\n", atSubKey );
793
794 /* FIXME: Check return types to ensure we're interpreting data right */
795 MultiByteToWideChar( CP_ACP, 0, atSubKey, -1, buff, sizeof(buff)/sizeof(WCHAR) );
796 CLSIDFromString( buff, &serviceProviderGUID );
797 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
798
799 /* The enumeration will return FALSE if we are not to continue */
800 if( !lpEnumAddressTypeCallback( &serviceProviderGUID, lpContext, 0 ) )
801 {
802 WARN("lpEnumCallback returning FALSE\n" );
803 break; /* FIXME: This most likely has to break from the procedure...*/
804 }
805
806 }
807
808 /* We only enumerate address types for 1 GUID. We've found it, so quit looking */
809 break;
810 }
811
812 return DP_OK;
813 }
814
815 static HRESULT WINAPI IDirectPlayLobby3Impl_EnumAddressTypes( IDirectPlayLobby3 *iface,
816 LPDPLENUMADDRESSTYPESCALLBACK enumaddrtypecb, REFGUID sp, void *context, DWORD flags )
817 {
818 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
819 return IDirectPlayLobby_EnumAddressTypes( &This->IDirectPlayLobby3A_iface, enumaddrtypecb, sp,
820 context, flags );
821 }
822
823 /********************************************************************
824 *
825 * Enumerates what applications are registered with DirectPlay by
826 * invoking the callback function with lpContext.
827 *
828 */
829 static HRESULT WINAPI IDirectPlayLobby3Impl_EnumLocalApplications( IDirectPlayLobby3 *iface,
830 LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback, void *lpContext, DWORD dwFlags )
831 {
832 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
833
834 FIXME("(%p)->(%p,%p,0x%08x):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
835
836 return DPERR_OUTOFMEMORY;
837 }
838
839 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumLocalApplications( IDirectPlayLobbyA *iface,
840 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
841 {
842 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
843 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3A_iface, enumlocalappcb,
844 context, flags );
845 }
846
847 static HRESULT WINAPI IDirectPlayLobbyImpl_EnumLocalApplications( IDirectPlayLobby *iface,
848 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
849 {
850 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
851 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3_iface, enumlocalappcb,
852 context, flags );
853 }
854
855 static HRESULT WINAPI IDirectPlayLobby2AImpl_EnumLocalApplications( IDirectPlayLobby2A *iface,
856 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
857 {
858 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
859 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3A_iface, enumlocalappcb,
860 context, flags );
861 }
862
863 static HRESULT WINAPI IDirectPlayLobby2Impl_EnumLocalApplications( IDirectPlayLobby2 *iface,
864 LPDPLENUMLOCALAPPLICATIONSCALLBACK enumlocalappcb, void *context, DWORD flags )
865 {
866 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
867 return IDirectPlayLobby_EnumLocalApplications( &This->IDirectPlayLobby3_iface, enumlocalappcb,
868 context, flags );
869 }
870
871 static HRESULT WINAPI IDirectPlayLobby3AImpl_EnumLocalApplications( IDirectPlayLobby3A *iface,
872 LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback, void *lpContext, DWORD dwFlags )
873 {
874 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
875
876 HKEY hkResult;
877 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Applications";
878 LPCSTR guidDataSubKey = "Guid";
879 DWORD dwIndex, sizeOfSubKeyName=50;
880 char subKeyName[51];
881 FILETIME filetime;
882
883 TRACE("(%p)->(%p,%p,0x%08x)\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
884
885 if( dwFlags != 0 )
886 {
887 return DPERR_INVALIDPARAMS;
888 }
889
890 if( !lpEnumLocalAppCallback )
891 {
892 return DPERR_INVALIDPARAMS;
893 }
894
895 /* Need to loop over the service providers in the registry */
896 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
897 0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
898 {
899 /* Hmmm. Does this mean that there are no service providers? */
900 ERR(": no service providers?\n");
901 return DP_OK;
902 }
903
904 /* Traverse all registered applications */
905 for( dwIndex=0;
906 RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
907 ++dwIndex, sizeOfSubKeyName=50 )
908 {
909
910 HKEY hkServiceProvider;
911 GUID serviceProviderGUID;
912 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
913 char returnBuffer[51];
914 WCHAR buff[51];
915 DPLAPPINFO dplAppInfo;
916
917 TRACE(" this time through: %s\n", subKeyName );
918
919 /* Get a handle for this particular service provider */
920 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
921 &hkServiceProvider ) != ERROR_SUCCESS )
922 {
923 ERR(": what the heck is going on?\n" );
924 continue;
925 }
926
927 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
928 NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
929 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
930 {
931 ERR(": missing GUID registry data members\n" );
932 continue;
933 }
934
935 /* FIXME: Check return types to ensure we're interpreting data right */
936 MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
937 CLSIDFromString( buff, &serviceProviderGUID );
938 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
939
940 dplAppInfo.dwSize = sizeof( dplAppInfo );
941 dplAppInfo.guidApplication = serviceProviderGUID;
942 dplAppInfo.u.lpszAppNameA = subKeyName;
943
944 EnterCriticalSection( &This->lock );
945
946 memcpy( &This->cbkeyhack, &hkServiceProvider, sizeof( hkServiceProvider ) );
947
948 if( !lpEnumLocalAppCallback( &dplAppInfo, lpContext, dwFlags ) )
949 {
950 LeaveCriticalSection( &This->lock );
951 break;
952 }
953
954 LeaveCriticalSection( &This->lock );
955 }
956
957 return DP_OK;
958 }
959
960 /********************************************************************
961 *
962 * Retrieves the DPLCONNECTION structure that contains all the information
963 * needed to start and connect an application. This was generated using
964 * either the RunApplication or SetConnectionSettings methods.
965 *
966 * NOTES: If lpData is NULL then just return lpdwDataSize. This allows
967 * the data structure to be allocated by our caller which can then
968 * call this procedure/method again with a valid data pointer.
969 */
970 static HRESULT WINAPI IDirectPlayLobbyAImpl_GetConnectionSettings( IDirectPlayLobbyA *iface,
971 DWORD appid, void *data, DWORD *size )
972 {
973 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
974 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3A_iface, appid, data,
975 size );
976 }
977
978 static HRESULT WINAPI IDirectPlayLobbyImpl_GetConnectionSettings( IDirectPlayLobby *iface,
979 DWORD appid, void *data, DWORD *size )
980 {
981 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
982 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface, appid, data,
983 size );
984 }
985
986 static HRESULT WINAPI IDirectPlayLobby2AImpl_GetConnectionSettings( IDirectPlayLobby2A *iface,
987 DWORD appid, void *data, DWORD *size )
988 {
989 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
990 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3A_iface, appid, data,
991 size );
992 }
993
994 static HRESULT WINAPI IDirectPlayLobby2Impl_GetConnectionSettings( IDirectPlayLobby2 *iface,
995 DWORD appid, void *data, DWORD *size )
996 {
997 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
998 return IDirectPlayLobby_GetConnectionSettings( &This->IDirectPlayLobby3_iface, appid, data,
999 size );
1000 }
1001
1002 static HRESULT WINAPI IDirectPlayLobby3AImpl_GetConnectionSettings( IDirectPlayLobby3A *iface,
1003 DWORD dwAppID, void *lpData, DWORD *lpdwDataSize )
1004 {
1005 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
1006 HRESULT hr;
1007
1008 TRACE("(%p)->(0x%08x,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
1009
1010 EnterCriticalSection( &This->lock );
1011
1012 hr = DPLAYX_GetConnectionSettingsA( dwAppID,
1013 lpData,
1014 lpdwDataSize
1015 );
1016
1017 LeaveCriticalSection( &This->lock );
1018
1019 return hr;
1020 }
1021
1022 static HRESULT WINAPI IDirectPlayLobby3Impl_GetConnectionSettings( IDirectPlayLobby3 *iface,
1023 DWORD dwAppID, void *lpData, DWORD *lpdwDataSize )
1024 {
1025 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
1026 HRESULT hr;
1027
1028 TRACE("(%p)->(0x%08x,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
1029
1030 EnterCriticalSection( &This->lock );
1031
1032 hr = DPLAYX_GetConnectionSettingsW( dwAppID,
1033 lpData,
1034 lpdwDataSize
1035 );
1036
1037 LeaveCriticalSection( &This->lock );
1038
1039 return hr;
1040 }
1041
1042 /********************************************************************
1043 *
1044 * Retrieves the message sent between a lobby client and a DirectPlay
1045 * application. All messages are queued until received.
1046 *
1047 */
1048 static HRESULT WINAPI IDirectPlayLobbyAImpl_ReceiveLobbyMessage( IDirectPlayLobbyA *iface,
1049 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
1050 {
1051 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
1052 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid,
1053 msgflags, data, size );
1054 }
1055
1056 static HRESULT WINAPI IDirectPlayLobbyImpl_ReceiveLobbyMessage( IDirectPlayLobby *iface,
1057 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
1058 {
1059 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1060 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid,
1061 msgflags, data, size );
1062 }
1063
1064 static HRESULT WINAPI IDirectPlayLobby2AImpl_ReceiveLobbyMessage( IDirectPlayLobby2A *iface,
1065 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
1066 {
1067 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1068 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid,
1069 msgflags, data, size );
1070 }
1071
1072 static HRESULT WINAPI IDirectPlayLobby2Impl_ReceiveLobbyMessage( IDirectPlayLobby2 *iface,
1073 DWORD flags, DWORD appid, DWORD *msgflags, void *data, DWORD *size )
1074 {
1075 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1076 return IDirectPlayLobby_ReceiveLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid,
1077 msgflags, data, size );
1078 }
1079
1080 static HRESULT WINAPI IDirectPlayLobby3AImpl_ReceiveLobbyMessage( IDirectPlayLobby3A *iface,
1081 DWORD dwFlags, DWORD dwAppID, DWORD *lpdwMessageFlags, void *lpData,
1082 DWORD *lpdwDataSize )
1083 {
1084 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
1085 FIXME(":stub %p %08x %08x %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
1086 lpdwDataSize );
1087 return DPERR_OUTOFMEMORY;
1088 }
1089
1090 static HRESULT WINAPI IDirectPlayLobby3Impl_ReceiveLobbyMessage( IDirectPlayLobby3 *iface,
1091 DWORD dwFlags, DWORD dwAppID, DWORD *lpdwMessageFlags, void *lpData,
1092 DWORD *lpdwDataSize )
1093 {
1094 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
1095 FIXME(":stub %p %08x %08x %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
1096 lpdwDataSize );
1097 return DPERR_OUTOFMEMORY;
1098 }
1099
1100 typedef struct tagRunApplicationEnumStruct
1101 {
1102 IDirectPlayLobbyImpl *This;
1103
1104 GUID appGUID;
1105 LPSTR lpszPath;
1106 LPSTR lpszFileName;
1107 LPSTR lpszCommandLine;
1108 LPSTR lpszCurrentDirectory;
1109 } RunApplicationEnumStruct, *lpRunApplicationEnumStruct;
1110
1111 /* To be called by RunApplication to find how to invoke the function */
1112 static BOOL CALLBACK RunApplicationA_EnumLocalApplications
1113 ( LPCDPLAPPINFO lpAppInfo,
1114 LPVOID lpContext,
1115 DWORD dwFlags )
1116 {
1117 lpRunApplicationEnumStruct lpData = (lpRunApplicationEnumStruct)lpContext;
1118
1119 if( IsEqualGUID( &lpAppInfo->guidApplication, &lpData->appGUID ) )
1120 {
1121 char returnBuffer[200];
1122 DWORD returnType, sizeOfReturnBuffer;
1123 LPCSTR clSubKey = "CommandLine";
1124 LPCSTR cdSubKey = "CurrentDirectory";
1125 LPCSTR fileSubKey = "File";
1126 LPCSTR pathSubKey = "Path";
1127
1128 /* FIXME: Lazy man hack - dplay struct has the present reg key saved */
1129
1130 sizeOfReturnBuffer = 200;
1131
1132 /* Get all the appropriate data from the registry */
1133 if( RegQueryValueExA( lpData->This->cbkeyhack, clSubKey,
1134 NULL, &returnType, (LPBYTE)returnBuffer,
1135 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1136 {
1137 ERR( ": missing CommandLine registry data member\n" );
1138 }
1139 else
1140 {
1141 if ((lpData->lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
1142 strcpy( lpData->lpszCommandLine, returnBuffer );
1143 }
1144
1145 sizeOfReturnBuffer = 200;
1146
1147 if( RegQueryValueExA( lpData->This->cbkeyhack, cdSubKey,
1148 NULL, &returnType, (LPBYTE)returnBuffer,
1149 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1150 {
1151 ERR( ": missing CurrentDirectory registry data member\n" );
1152 }
1153 else
1154 {
1155 if ((lpData->lpszCurrentDirectory = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
1156 strcpy( lpData->lpszCurrentDirectory, returnBuffer );
1157 }
1158
1159 sizeOfReturnBuffer = 200;
1160
1161 if( RegQueryValueExA( lpData->This->cbkeyhack, fileSubKey,
1162 NULL, &returnType, (LPBYTE)returnBuffer,
1163 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1164 {
1165 ERR( ": missing File registry data member\n" );
1166 }
1167 else
1168 {
1169 if ((lpData->lpszFileName = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
1170 strcpy( lpData->lpszFileName, returnBuffer );
1171 }
1172
1173 sizeOfReturnBuffer = 200;
1174
1175 if( RegQueryValueExA( lpData->This->cbkeyhack, pathSubKey,
1176 NULL, &returnType, (LPBYTE)returnBuffer,
1177 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1178 {
1179 ERR( ": missing Path registry data member\n" );
1180 }
1181 else
1182 {
1183 if ((lpData->lpszPath = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
1184 strcpy( lpData->lpszPath, returnBuffer );
1185 }
1186
1187 return FALSE; /* No need to keep going as we found what we wanted */
1188 }
1189
1190 return TRUE; /* Keep enumerating, haven't found the application yet */
1191 }
1192
1193 static BOOL DPL_CreateAndSetLobbyHandles( DWORD dwDestProcessId, HANDLE hDestProcess,
1194 LPHANDLE lphStart, LPHANDLE lphDeath,
1195 LPHANDLE lphRead )
1196 {
1197 /* These are the handles for the created process */
1198 HANDLE hAppStart = 0, hAppDeath = 0, hAppRead = 0;
1199 SECURITY_ATTRIBUTES s_attrib;
1200
1201 s_attrib.nLength = sizeof( s_attrib );
1202 s_attrib.lpSecurityDescriptor = NULL;
1203 s_attrib.bInheritHandle = TRUE;
1204
1205 *lphStart = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
1206 *lphDeath = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
1207 *lphRead = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
1208
1209 if( ( !DuplicateHandle( GetCurrentProcess(), *lphStart,
1210 hDestProcess, &hAppStart,
1211 0, FALSE, DUPLICATE_SAME_ACCESS ) ) ||
1212 ( !DuplicateHandle( GetCurrentProcess(), *lphDeath,
1213 hDestProcess, &hAppDeath,
1214 0, FALSE, DUPLICATE_SAME_ACCESS ) ) ||
1215 ( !DuplicateHandle( GetCurrentProcess(), *lphRead,
1216 hDestProcess, &hAppRead,
1217 0, FALSE, DUPLICATE_SAME_ACCESS ) )
1218 )
1219 {
1220 if (*lphStart) { CloseHandle(*lphStart); *lphStart = 0; }
1221 if (*lphDeath) { CloseHandle(*lphDeath); *lphDeath = 0; }
1222 if (*lphRead) { CloseHandle(*lphRead); *lphRead = 0; }
1223 /* FIXME: Handle leak... */
1224 ERR( "Unable to dup handles\n" );
1225 return FALSE;
1226 }
1227
1228 if( !DPLAYX_SetLobbyHandles( dwDestProcessId,
1229 hAppStart, hAppDeath, hAppRead ) )
1230 {
1231 /* FIXME: Handle leak... */
1232 return FALSE;
1233 }
1234
1235 return TRUE;
1236 }
1237
1238
1239 /********************************************************************
1240 *
1241 * Starts an application and passes to it all the information to
1242 * connect to a session.
1243 *
1244 */
1245 static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication( IDirectPlayLobbyA *iface, DWORD flags,
1246 DWORD *appid, DPLCONNECTION *conn, HANDLE event )
1247 {
1248 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
1249 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3A_iface, flags, appid, conn,
1250 event );
1251 }
1252
1253 static HRESULT WINAPI IDirectPlayLobbyImpl_RunApplication( IDirectPlayLobby *iface, DWORD flags,
1254 DWORD *appid, DPLCONNECTION *conn, HANDLE event )
1255 {
1256 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1257 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3_iface, flags, appid, conn,
1258 event );
1259 }
1260
1261 static HRESULT WINAPI IDirectPlayLobby2AImpl_RunApplication( IDirectPlayLobby2A *iface, DWORD flags,
1262 DWORD *appid, DPLCONNECTION *conn, HANDLE event )
1263 {
1264 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1265 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3A_iface, flags, appid, conn,
1266 event );
1267 }
1268
1269 static HRESULT WINAPI IDirectPlayLobby2Impl_RunApplication( IDirectPlayLobby2 *iface, DWORD flags,
1270 DWORD *appid, DPLCONNECTION *conn, HANDLE event )
1271 {
1272 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1273 return IDirectPlayLobby_RunApplication( &This->IDirectPlayLobby3_iface, flags, appid, conn,
1274 event );
1275 }
1276
1277 static HRESULT WINAPI IDirectPlayLobby3AImpl_RunApplication( IDirectPlayLobby3A *iface,
1278 DWORD dwFlags, DWORD *lpdwAppID, DPLCONNECTION *lpConn, HANDLE hReceiveEvent )
1279 {
1280 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
1281 HRESULT hr;
1282 RunApplicationEnumStruct enumData;
1283 char temp[200];
1284 STARTUPINFOA startupInfo;
1285 PROCESS_INFORMATION newProcessInfo;
1286 LPSTR appName;
1287 DWORD dwSuspendCount;
1288 HANDLE hStart, hDeath, hSettingRead;
1289
1290 TRACE( "(%p)->(0x%08x,%p,%p,%p)\n",
1291 This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
1292
1293 if( dwFlags != 0 )
1294 {
1295 return DPERR_INVALIDPARAMS;
1296 }
1297
1298 if( DPLAYX_AnyLobbiesWaitingForConnSettings() )
1299 {
1300 FIXME( "Waiting lobby not being handled correctly\n" );
1301 }
1302
1303 EnterCriticalSection( &This->lock );
1304
1305 ZeroMemory( &enumData, sizeof( enumData ) );
1306 enumData.This = This;
1307 enumData.appGUID = lpConn->lpSessionDesc->guidApplication;
1308
1309 /* Our callback function will fill up the enumData structure with all the information
1310 required to start a new process */
1311 IDirectPlayLobby_EnumLocalApplications( iface, RunApplicationA_EnumLocalApplications,
1312 (&enumData), 0 );
1313
1314 /* First the application name */
1315 strcpy( temp, enumData.lpszPath );
1316 strcat( temp, "\\" );
1317 strcat( temp, enumData.lpszFileName );
1318 HeapFree( GetProcessHeap(), 0, enumData.lpszPath );
1319 HeapFree( GetProcessHeap(), 0, enumData.lpszFileName );
1320 if ((appName = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 ))) strcpy( appName, temp );
1321
1322 /* Now the command line */
1323 strcat( temp, " " );
1324 strcat( temp, enumData.lpszCommandLine );
1325 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
1326 if ((enumData.lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 )))
1327 strcpy( enumData.lpszCommandLine, temp );
1328
1329 ZeroMemory( &startupInfo, sizeof( startupInfo ) );
1330 startupInfo.cb = sizeof( startupInfo );
1331 /* FIXME: Should any fields be filled in? */
1332
1333 ZeroMemory( &newProcessInfo, sizeof( newProcessInfo ) );
1334
1335 if( !CreateProcessA( appName,
1336 enumData.lpszCommandLine,
1337 NULL,
1338 NULL,
1339 FALSE,
1340 CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_SUSPENDED, /* Creation Flags */
1341 NULL,
1342 enumData.lpszCurrentDirectory,
1343 &startupInfo,
1344 &newProcessInfo
1345 )
1346 )
1347 {
1348 ERR( "Failed to create process for app %s\n", appName );
1349
1350 HeapFree( GetProcessHeap(), 0, appName );
1351 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
1352 HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
1353
1354 LeaveCriticalSection( &This->lock );
1355 return DPERR_CANTCREATEPROCESS;
1356 }
1357
1358 HeapFree( GetProcessHeap(), 0, appName );
1359 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
1360 HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
1361
1362 /* Reserve this global application id! */
1363 if( !DPLAYX_CreateLobbyApplication( newProcessInfo.dwProcessId ) )
1364 {
1365 ERR( "Unable to create global application data for 0x%08x\n",
1366 newProcessInfo.dwProcessId );
1367 }
1368
1369 hr = IDirectPlayLobby_SetConnectionSettings( iface, 0, newProcessInfo.dwProcessId, lpConn );
1370
1371 if( hr != DP_OK )
1372 {
1373 ERR( "SetConnectionSettings failure %s\n", DPLAYX_HresultToString( hr ) );
1374 LeaveCriticalSection( &This->lock );
1375 return hr;
1376 }
1377
1378 /* Setup the handles for application notification */
1379 DPL_CreateAndSetLobbyHandles( newProcessInfo.dwProcessId,
1380 newProcessInfo.hProcess,
1381 &hStart, &hDeath, &hSettingRead );
1382
1383 /* Setup the message thread ID */
1384 This->msgtid = CreateLobbyMessageReceptionThread( hReceiveEvent, hStart, hDeath, hSettingRead );
1385
1386 DPLAYX_SetLobbyMsgThreadId( newProcessInfo.dwProcessId, This->msgtid );
1387
1388 LeaveCriticalSection( &This->lock );
1389
1390 /* Everything seems to have been set correctly, update the dwAppID */
1391 *lpdwAppID = newProcessInfo.dwProcessId;
1392
1393 /* Unsuspend the process - should return the prev suspension count */
1394 if( ( dwSuspendCount = ResumeThread( newProcessInfo.hThread ) ) != 1 )
1395 {
1396 ERR( "ResumeThread failed with 0x%08x\n", dwSuspendCount );
1397 }
1398
1399 return DP_OK;
1400 }
1401
1402 static HRESULT WINAPI IDirectPlayLobby3Impl_RunApplication( IDirectPlayLobby3 *iface, DWORD dwFlags,
1403 DWORD *lpdwAppID, DPLCONNECTION *lpConn, HANDLE hReceiveEvent )
1404 {
1405 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
1406 FIXME( "(%p)->(0x%08x,%p,%p,%p):stub\n", This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
1407 return DPERR_OUTOFMEMORY;
1408 }
1409
1410 /********************************************************************
1411 *
1412 * Sends a message between the application and the lobby client.
1413 * All messages are queued until received.
1414 *
1415 */
1416 static HRESULT WINAPI IDirectPlayLobbyAImpl_SendLobbyMessage( IDirectPlayLobbyA *iface, DWORD flags,
1417 DWORD appid, void *data, DWORD size )
1418 {
1419 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
1420 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid, data,
1421 size );
1422 }
1423
1424 static HRESULT WINAPI IDirectPlayLobbyImpl_SendLobbyMessage( IDirectPlayLobby *iface, DWORD flags,
1425 DWORD appid, void *data, DWORD size )
1426 {
1427 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1428 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid, data,
1429 size );
1430 }
1431
1432 static HRESULT WINAPI IDirectPlayLobby2AImpl_SendLobbyMessage( IDirectPlayLobby2A *iface,
1433 DWORD flags, DWORD appid, void *data, DWORD size )
1434 {
1435 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1436 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3A_iface, flags, appid, data,
1437 size );
1438 }
1439
1440 static HRESULT WINAPI IDirectPlayLobby2Impl_SendLobbyMessage( IDirectPlayLobby2 *iface, DWORD flags,
1441 DWORD appid, void *data, DWORD size )
1442 {
1443 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1444 return IDirectPlayLobby_SendLobbyMessage( &This->IDirectPlayLobby3_iface, flags, appid, data,
1445 size );
1446 }
1447
1448 static HRESULT WINAPI IDirectPlayLobby3AImpl_SendLobbyMessage( IDirectPlayLobby3A *iface,
1449 DWORD flags, DWORD appid, void *data, DWORD size )
1450 {
1451 FIXME(":stub\n");
1452 return DPERR_OUTOFMEMORY;
1453 }
1454
1455 static HRESULT WINAPI IDirectPlayLobby3Impl_SendLobbyMessage( IDirectPlayLobby3 *iface,
1456 DWORD flags, DWORD appid, void *data, DWORD size )
1457 {
1458 FIXME(":stub\n");
1459 return DPERR_OUTOFMEMORY;
1460 }
1461
1462 /********************************************************************
1463 *
1464 * Modifies the DPLCONNECTION structure to contain all information
1465 * needed to start and connect an application.
1466 *
1467 */
1468 static HRESULT WINAPI IDirectPlayLobby3Impl_SetConnectionSettings( IDirectPlayLobby3 *iface,
1469 DWORD dwFlags, DWORD dwAppID, DPLCONNECTION *lpConn )
1470 {
1471 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
1472 HRESULT hr;
1473
1474 TRACE("(%p)->(0x%08x,0x%08x,%p)\n", This, dwFlags, dwAppID, lpConn );
1475
1476 EnterCriticalSection( &This->lock );
1477
1478 hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
1479
1480 /* FIXME: Don't think that this is supposed to fail, but the documentation
1481 is somewhat sketchy. I'll try creating a lobby application
1482 for this... */
1483 if( hr == DPERR_NOTLOBBIED )
1484 {
1485 FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
1486 if( dwAppID == 0 )
1487 {
1488 dwAppID = GetCurrentProcessId();
1489 }
1490 DPLAYX_CreateLobbyApplication( dwAppID );
1491 hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
1492 }
1493
1494 LeaveCriticalSection( &This->lock );
1495
1496 return hr;
1497 }
1498
1499 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetConnectionSettings( IDirectPlayLobbyA *iface,
1500 DWORD flags, DWORD appid, DPLCONNECTION *conn )
1501 {
1502 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
1503 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3A_iface, flags,
1504 appid, conn );
1505 }
1506
1507 static HRESULT WINAPI IDirectPlayLobbyImpl_SetConnectionSettings( IDirectPlayLobby *iface,
1508 DWORD flags, DWORD appid, DPLCONNECTION *conn )
1509 {
1510 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1511 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3_iface, flags,
1512 appid, conn );
1513 }
1514
1515 static HRESULT WINAPI IDirectPlayLobby2AImpl_SetConnectionSettings( IDirectPlayLobby2A *iface,
1516 DWORD flags, DWORD appid, DPLCONNECTION *conn )
1517 {
1518 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1519 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3A_iface, flags,
1520 appid, conn );
1521 }
1522
1523 static HRESULT WINAPI IDirectPlayLobby2Impl_SetConnectionSettings( IDirectPlayLobby2 *iface,
1524 DWORD flags, DWORD appid, DPLCONNECTION *conn )
1525 {
1526 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1527 return IDirectPlayLobby_SetConnectionSettings( &This->IDirectPlayLobby3_iface, flags,
1528 appid, conn );
1529 }
1530
1531 static HRESULT WINAPI IDirectPlayLobby3AImpl_SetConnectionSettings( IDirectPlayLobby3A *iface,
1532 DWORD dwFlags, DWORD dwAppID, DPLCONNECTION *lpConn )
1533 {
1534 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
1535 HRESULT hr;
1536
1537 TRACE("(%p)->(0x%08x,0x%08x,%p)\n", This, dwFlags, dwAppID, lpConn );
1538
1539 EnterCriticalSection( &This->lock );
1540
1541 hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
1542
1543 /* FIXME: Don't think that this is supposed to fail, but the documentation
1544 is somewhat sketchy. I'll try creating a lobby application
1545 for this... */
1546 if( hr == DPERR_NOTLOBBIED )
1547 {
1548 FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
1549 dwAppID = GetCurrentProcessId();
1550 DPLAYX_CreateLobbyApplication( dwAppID );
1551 hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
1552 }
1553
1554 LeaveCriticalSection( &This->lock );
1555
1556 return hr;
1557 }
1558
1559 /********************************************************************
1560 *
1561 * Registers an event that will be set when a lobby message is received.
1562 *
1563 */
1564 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetLobbyMessageEvent( IDirectPlayLobbyA *iface,
1565 DWORD flags, DWORD appid, HANDLE event )
1566 {
1567 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobbyA( iface );
1568 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3A_iface, flags, appid,
1569 event );
1570 }
1571
1572 static HRESULT WINAPI IDirectPlayLobbyImpl_SetLobbyMessageEvent( IDirectPlayLobby *iface,
1573 DWORD flags, DWORD appid, HANDLE event )
1574 {
1575 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby( iface );
1576 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3_iface, flags, appid,
1577 event );
1578 }
1579
1580 static HRESULT WINAPI IDirectPlayLobby2AImpl_SetLobbyMessageEvent( IDirectPlayLobby2A *iface,
1581 DWORD flags, DWORD appid, HANDLE event )
1582 {
1583 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1584 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3A_iface, flags, appid,
1585 event );
1586 }
1587
1588 static HRESULT WINAPI IDirectPlayLobby2Impl_SetLobbyMessageEvent( IDirectPlayLobby2 *iface,
1589 DWORD flags, DWORD appid, HANDLE event )
1590 {
1591 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1592 return IDirectPlayLobby_SetLobbyMessageEvent( &This->IDirectPlayLobby3_iface, flags, appid,
1593 event );
1594 }
1595
1596 static HRESULT WINAPI IDirectPlayLobby3AImpl_SetLobbyMessageEvent( IDirectPlayLobby3A *iface,
1597 DWORD flags, DWORD appid, HANDLE event )
1598 {
1599 FIXME(":stub\n");
1600 return DPERR_OUTOFMEMORY;
1601 }
1602
1603 static HRESULT WINAPI IDirectPlayLobby3Impl_SetLobbyMessageEvent( IDirectPlayLobby3 *iface,
1604 DWORD flags, DWORD appid, HANDLE event )
1605 {
1606 FIXME(":stub\n");
1607 return DPERR_OUTOFMEMORY;
1608 }
1609
1610
1611 /* DPL 2 methods */
1612 static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateCompoundAddress( IDirectPlayLobby2A *iface,
1613 const DPCOMPOUNDADDRESSELEMENT *elements, DWORD count, void *address, DWORD *size )
1614 {
1615 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2A( iface );
1616 return IDirectPlayLobby_CreateCompoundAddress( &This->IDirectPlayLobby3A_iface, elements,
1617 count, address, size );
1618 }
1619
1620 static HRESULT WINAPI IDirectPlayLobby2Impl_CreateCompoundAddress( IDirectPlayLobby2 *iface,
1621 const DPCOMPOUNDADDRESSELEMENT *elements, DWORD count, void *address, DWORD *size )
1622 {
1623 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby2( iface );
1624 return IDirectPlayLobby_CreateCompoundAddress( &This->IDirectPlayLobby3_iface, elements,
1625 count, address, size );
1626 }
1627
1628 static HRESULT WINAPI IDirectPlayLobby3Impl_CreateCompoundAddress( IDirectPlayLobby3 *iface,
1629 const DPCOMPOUNDADDRESSELEMENT *lpElements, DWORD dwElementCount, void *lpAddress,
1630 DWORD *lpdwAddressSize )
1631 {
1632 return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, FALSE );
1633 }
1634
1635 static HRESULT WINAPI IDirectPlayLobby3AImpl_CreateCompoundAddress( IDirectPlayLobby3A *iface,
1636 const DPCOMPOUNDADDRESSELEMENT *lpElements, DWORD dwElementCount, void *lpAddress,
1637 DWORD *lpdwAddressSize )
1638 {
1639 return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, TRUE );
1640 }
1641
1642 HRESULT DPL_CreateCompoundAddress
1643 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1644 DWORD dwElementCount,
1645 LPVOID lpAddress,
1646 LPDWORD lpdwAddressSize,
1647 BOOL bAnsiInterface )
1648 {
1649 DWORD dwSizeRequired = 0;
1650 DWORD dwElements;
1651 LPCDPCOMPOUNDADDRESSELEMENT lpOrigElements = lpElements;
1652
1653 TRACE("(%p,0x%08x,%p,%p)\n", lpElements, dwElementCount, lpAddress, lpdwAddressSize );
1654
1655 /* Parameter check */
1656 if( ( lpElements == NULL ) ||
1657 ( dwElementCount == 0 ) /* FIXME: Not sure if this is a failure case */
1658 )
1659 {
1660 return DPERR_INVALIDPARAMS;
1661 }
1662
1663 /* Add the total size chunk */
1664 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DWORD );
1665
1666 /* Calculate the size of the buffer required */
1667 for ( dwElements = dwElementCount; dwElements > 0; --dwElements, ++lpElements )
1668 {
1669 if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
1670 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
1671 )
1672 {
1673 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( GUID );
1674 }
1675 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
1676 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
1677 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
1678 )
1679 {
1680 if( !bAnsiInterface )
1681 {
1682 ERR( "Ansi GUIDs used for unicode interface\n" );
1683 return DPERR_INVALIDFLAGS;
1684 }
1685
1686 dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize;
1687 }
1688 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
1689 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
1690 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
1691 )
1692 {
1693 if( bAnsiInterface )
1694 {
1695 ERR( "Unicode GUIDs used for ansi interface\n" );
1696 return DPERR_INVALIDFLAGS;
1697 }
1698
1699 FIXME( "Right size for unicode interface?\n" );
1700 dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize * sizeof( WCHAR );
1701 }
1702 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
1703 {
1704 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( WORD );
1705 }
1706 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
1707 {
1708 FIXME( "Right size for unicode interface?\n" );
1709 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DPCOMPORTADDRESS ); /* FIXME: Right size? */
1710 }
1711 else
1712 {
1713 WARN( "Skipping Unknown GUID %s\n", debugstr_guid(&lpElements->guidDataType) );
1714 }
1715 }
1716
1717 /* The user wants to know how big a buffer to allocate for us */
1718 if( ( lpAddress == NULL ) ||
1719 ( *lpdwAddressSize < dwSizeRequired )
1720 )
1721 {
1722 *lpdwAddressSize = dwSizeRequired;
1723 return DPERR_BUFFERTOOSMALL;
1724 }
1725
1726 /* Add the total size chunk */
1727 {
1728 LPDPADDRESS lpdpAddress = lpAddress;
1729
1730 lpdpAddress->guidDataType = DPAID_TotalSize;
1731 lpdpAddress->dwDataSize = sizeof( DWORD );
1732 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1733
1734 *(LPDWORD)lpAddress = dwSizeRequired;
1735 lpAddress = (char *) lpAddress + sizeof( DWORD );
1736 }
1737
1738 /* Calculate the size of the buffer required */
1739 for( dwElements = dwElementCount, lpElements = lpOrigElements;
1740 dwElements > 0;
1741 --dwElements, ++lpElements )
1742 {
1743 if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
1744 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
1745 )
1746 {
1747 LPDPADDRESS lpdpAddress = lpAddress;
1748
1749 lpdpAddress->guidDataType = lpElements->guidDataType;
1750 lpdpAddress->dwDataSize = sizeof( GUID );
1751 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1752
1753 CopyMemory( lpAddress, lpElements->lpData, sizeof( GUID ) );
1754 lpAddress = (char *) lpAddress + sizeof( GUID );
1755 }
1756 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
1757 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
1758 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
1759 )
1760 {
1761 LPDPADDRESS lpdpAddress = lpAddress;
1762
1763 lpdpAddress->guidDataType = lpElements->guidDataType;
1764 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1765 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1766
1767 lstrcpynA( lpAddress, lpElements->lpData, lpElements->dwDataSize );
1768 lpAddress = (char *) lpAddress + lpElements->dwDataSize;
1769 }
1770 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
1771 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
1772 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
1773 )
1774 {
1775 LPDPADDRESS lpdpAddress = lpAddress;
1776
1777 lpdpAddress->guidDataType = lpElements->guidDataType;
1778 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1779 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1780
1781 lstrcpynW( lpAddress, lpElements->lpData, lpElements->dwDataSize );
1782 lpAddress = (char *) lpAddress + lpElements->dwDataSize * sizeof( WCHAR );
1783 }
1784 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
1785 {
1786 LPDPADDRESS lpdpAddress = lpAddress;
1787
1788 lpdpAddress->guidDataType = lpElements->guidDataType;
1789 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1790 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1791
1792 *((LPWORD)lpAddress) = *((LPWORD)lpElements->lpData);
1793 lpAddress = (char *) lpAddress + sizeof( WORD );
1794 }
1795 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
1796 {
1797 LPDPADDRESS lpdpAddress = lpAddress;
1798
1799 lpdpAddress->guidDataType = lpElements->guidDataType;
1800 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1801 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1802
1803 CopyMemory( lpAddress, lpElements->lpData, sizeof( DPADDRESS ) );
1804 lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
1805 }
1806 }
1807
1808 return DP_OK;
1809 }
1810
1811 /* DPL 3 methods */
1812
1813 static HRESULT WINAPI IDirectPlayLobby3Impl_ConnectEx( IDirectPlayLobby3 *iface, DWORD dwFlags,
1814 REFIID riid, LPVOID* lplpDP, IUnknown* pUnk )
1815 {
1816 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3( iface );
1817 return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk );
1818 }
1819
1820 static HRESULT WINAPI IDirectPlayLobby3AImpl_ConnectEx( IDirectPlayLobby3A *iface, DWORD dwFlags,
1821 REFIID riid, void **lplpDP, IUnknown *pUnk )
1822 {
1823 IDirectPlayLobbyImpl *This = impl_from_IDirectPlayLobby3A( iface );
1824 return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk );
1825 }
1826
1827 static HRESULT WINAPI IDirectPlayLobby3Impl_RegisterApplication( IDirectPlayLobby3 *iface,
1828 DWORD flags, DPAPPLICATIONDESC *appdesc )
1829 {
1830 FIXME(":stub\n");
1831 return DP_OK;
1832 }
1833
1834 static HRESULT WINAPI IDirectPlayLobby3AImpl_RegisterApplication( IDirectPlayLobby3A *iface,
1835 DWORD flags, DPAPPLICATIONDESC *appdesc )
1836 {
1837 FIXME(":stub\n");
1838 return DP_OK;
1839 }
1840
1841 static HRESULT WINAPI IDirectPlayLobby3Impl_UnregisterApplication( IDirectPlayLobby3 *iface,
1842 DWORD flags, REFGUID appdesc )
1843 {
1844 FIXME(":stub\n");
1845 return DP_OK;
1846 }
1847
1848 static HRESULT WINAPI IDirectPlayLobby3AImpl_UnregisterApplication( IDirectPlayLobby3A *iface,
1849 DWORD flags, REFGUID appdesc )
1850 {
1851 FIXME(":stub\n");
1852 return DP_OK;
1853 }
1854
1855 static HRESULT WINAPI IDirectPlayLobby3Impl_WaitForConnectionSettings( IDirectPlayLobby3 *iface,
1856 DWORD dwFlags )
1857 {
1858 HRESULT hr = DP_OK;
1859 BOOL bStartWait = !(dwFlags & DPLWAIT_CANCEL);
1860
1861 TRACE( "(%p)->(0x%08x)\n", iface, dwFlags );
1862
1863 if( DPLAYX_WaitForConnectionSettings( bStartWait ) )
1864 {
1865 /* FIXME: What is the correct error return code? */
1866 hr = DPERR_NOTLOBBIED;
1867 }
1868
1869 return hr;
1870 }
1871
1872 static HRESULT WINAPI IDirectPlayLobby3AImpl_WaitForConnectionSettings( IDirectPlayLobby3A *iface,
1873 DWORD dwFlags )
1874 {
1875 HRESULT hr = DP_OK;
1876 BOOL bStartWait = !(dwFlags & DPLWAIT_CANCEL);
1877
1878 TRACE( "(%p)->(0x%08x)\n", iface, dwFlags );
1879
1880 if( DPLAYX_WaitForConnectionSettings( bStartWait ) )
1881 {
1882 /* FIXME: What is the correct error return code? */
1883 hr = DPERR_NOTLOBBIED;
1884 }
1885
1886 return hr;
1887 }
1888
1889 static const IDirectPlayLobbyVtbl dplA_vt =
1890 {
1891 IDirectPlayLobbyAImpl_QueryInterface,
1892 IDirectPlayLobbyAImpl_AddRef,
1893 IDirectPlayLobbyAImpl_Release,
1894 IDirectPlayLobbyAImpl_Connect,
1895 IDirectPlayLobbyAImpl_CreateAddress,
1896 IDirectPlayLobbyAImpl_EnumAddress,
1897 IDirectPlayLobbyAImpl_EnumAddressTypes,
1898 IDirectPlayLobbyAImpl_EnumLocalApplications,
1899 IDirectPlayLobbyAImpl_GetConnectionSettings,
1900 IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
1901 IDirectPlayLobbyAImpl_RunApplication,
1902 IDirectPlayLobbyAImpl_SendLobbyMessage,
1903 IDirectPlayLobbyAImpl_SetConnectionSettings,
1904 IDirectPlayLobbyAImpl_SetLobbyMessageEvent
1905 };
1906
1907 static const IDirectPlayLobbyVtbl dpl_vt =
1908 {
1909 IDirectPlayLobbyImpl_QueryInterface,
1910 IDirectPlayLobbyImpl_AddRef,
1911 IDirectPlayLobbyImpl_Release,
1912 IDirectPlayLobbyImpl_Connect,
1913 IDirectPlayLobbyImpl_CreateAddress,
1914 IDirectPlayLobbyImpl_EnumAddress,
1915 IDirectPlayLobbyImpl_EnumAddressTypes,
1916 IDirectPlayLobbyImpl_EnumLocalApplications,
1917 IDirectPlayLobbyImpl_GetConnectionSettings,
1918 IDirectPlayLobbyImpl_ReceiveLobbyMessage,
1919 IDirectPlayLobbyImpl_RunApplication,
1920 IDirectPlayLobbyImpl_SendLobbyMessage,
1921 IDirectPlayLobbyImpl_SetConnectionSettings,
1922 IDirectPlayLobbyImpl_SetLobbyMessageEvent
1923 };
1924
1925 static const IDirectPlayLobby2Vtbl dpl2A_vt =
1926 {
1927 IDirectPlayLobby2AImpl_QueryInterface,
1928 IDirectPlayLobby2AImpl_AddRef,
1929 IDirectPlayLobby2AImpl_Release,
1930 IDirectPlayLobby2AImpl_Connect,
1931 IDirectPlayLobby2AImpl_CreateAddress,
1932 IDirectPlayLobby2AImpl_EnumAddress,
1933 IDirectPlayLobby2AImpl_EnumAddressTypes,
1934 IDirectPlayLobby2AImpl_EnumLocalApplications,
1935 IDirectPlayLobby2AImpl_GetConnectionSettings,
1936 IDirectPlayLobby2AImpl_ReceiveLobbyMessage,
1937 IDirectPlayLobby2AImpl_RunApplication,
1938 IDirectPlayLobby2AImpl_SendLobbyMessage,
1939 IDirectPlayLobby2AImpl_SetConnectionSettings,
1940 IDirectPlayLobby2AImpl_SetLobbyMessageEvent,
1941 IDirectPlayLobby2AImpl_CreateCompoundAddress
1942 };
1943
1944 static const IDirectPlayLobby2Vtbl dpl2_vt =
1945 {
1946 IDirectPlayLobby2Impl_QueryInterface,
1947 IDirectPlayLobby2Impl_AddRef,
1948 IDirectPlayLobby2Impl_Release,
1949 IDirectPlayLobby2Impl_Connect,
1950 IDirectPlayLobby2Impl_CreateAddress,
1951 IDirectPlayLobby2Impl_EnumAddress,
1952 IDirectPlayLobby2Impl_EnumAddressTypes,
1953 IDirectPlayLobby2Impl_EnumLocalApplications,
1954 IDirectPlayLobby2Impl_GetConnectionSettings,
1955 IDirectPlayLobby2Impl_ReceiveLobbyMessage,
1956 IDirectPlayLobby2Impl_RunApplication,
1957 IDirectPlayLobby2Impl_SendLobbyMessage,
1958 IDirectPlayLobby2Impl_SetConnectionSettings,
1959 IDirectPlayLobby2Impl_SetLobbyMessageEvent,
1960 IDirectPlayLobby2Impl_CreateCompoundAddress
1961 };
1962
1963 static const IDirectPlayLobby3Vtbl dpl3A_vt =
1964 {
1965 IDirectPlayLobby3AImpl_QueryInterface,
1966 IDirectPlayLobby3AImpl_AddRef,
1967 IDirectPlayLobby3AImpl_Release,
1968 IDirectPlayLobby3AImpl_Connect,
1969 IDirectPlayLobby3AImpl_CreateAddress,
1970 IDirectPlayLobby3AImpl_EnumAddress,
1971 IDirectPlayLobby3AImpl_EnumAddressTypes,
1972 IDirectPlayLobby3AImpl_EnumLocalApplications,
1973 IDirectPlayLobby3AImpl_GetConnectionSettings,
1974 IDirectPlayLobby3AImpl_ReceiveLobbyMessage,
1975 IDirectPlayLobby3AImpl_RunApplication,
1976 IDirectPlayLobby3AImpl_SendLobbyMessage,
1977 IDirectPlayLobby3AImpl_SetConnectionSettings,
1978 IDirectPlayLobby3AImpl_SetLobbyMessageEvent,
1979 IDirectPlayLobby3AImpl_CreateCompoundAddress,
1980 IDirectPlayLobby3AImpl_ConnectEx,
1981 IDirectPlayLobby3AImpl_RegisterApplication,
1982 IDirectPlayLobby3AImpl_UnregisterApplication,
1983 IDirectPlayLobby3AImpl_WaitForConnectionSettings
1984 };
1985
1986 static const IDirectPlayLobby3Vtbl dpl3_vt =
1987 {
1988 IDirectPlayLobby3Impl_QueryInterface,
1989 IDirectPlayLobby3Impl_AddRef,
1990 IDirectPlayLobby3Impl_Release,
1991 IDirectPlayLobby3Impl_Connect,
1992 IDirectPlayLobby3Impl_CreateAddress,
1993 IDirectPlayLobby3Impl_EnumAddress,
1994 IDirectPlayLobby3Impl_EnumAddressTypes,
1995 IDirectPlayLobby3Impl_EnumLocalApplications,
1996 IDirectPlayLobby3Impl_GetConnectionSettings,
1997 IDirectPlayLobby3Impl_ReceiveLobbyMessage,
1998 IDirectPlayLobby3Impl_RunApplication,
1999 IDirectPlayLobby3Impl_SendLobbyMessage,
2000 IDirectPlayLobby3Impl_SetConnectionSettings,
2001 IDirectPlayLobby3Impl_SetLobbyMessageEvent,
2002 IDirectPlayLobby3Impl_CreateCompoundAddress,
2003 IDirectPlayLobby3Impl_ConnectEx,
2004 IDirectPlayLobby3Impl_RegisterApplication,
2005 IDirectPlayLobby3Impl_UnregisterApplication,
2006 IDirectPlayLobby3Impl_WaitForConnectionSettings
2007 };
2008
2009 HRESULT dplobby_create( REFIID riid, void **ppv )
2010 {
2011 IDirectPlayLobbyImpl *obj;
2012 HRESULT hr;
2013
2014 TRACE( "(%s, %p)\n", debugstr_guid( riid ), ppv );
2015
2016 *ppv = NULL;
2017 obj = HeapAlloc( GetProcessHeap(), 0, sizeof( *obj ) );
2018 if ( !obj )
2019 return DPERR_OUTOFMEMORY;
2020
2021 obj->IDirectPlayLobby_iface.lpVtbl = &dpl_vt;
2022 obj->IDirectPlayLobbyA_iface.lpVtbl = &dplA_vt;
2023 obj->IDirectPlayLobby2_iface.lpVtbl = &dpl2_vt;
2024 obj->IDirectPlayLobby2A_iface.lpVtbl = &dpl2A_vt;
2025 obj->IDirectPlayLobby3_iface.lpVtbl = &dpl3_vt;
2026 obj->IDirectPlayLobby3A_iface.lpVtbl = &dpl3A_vt;
2027 obj->numIfaces = 1;
2028 obj->msgtid = 0;
2029 obj->ref = 0;
2030 obj->refA = 0;
2031 obj->ref2 = 0;
2032 obj->ref2A = 0;
2033 obj->ref3 = 1;
2034 obj->ref3A = 0;
2035
2036 InitializeCriticalSection( &obj->lock );
2037 obj->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayLobbyImpl.lock");
2038 DPQ_INIT( obj->msgs );
2039
2040 hr = IDirectPlayLobby_QueryInterface( &obj->IDirectPlayLobby3_iface, riid, ppv );
2041 IDirectPlayLobby_Release( &obj->IDirectPlayLobby3_iface );
2042
2043 return hr;
2044 }
2045
2046
2047
2048 /***************************************************************************
2049 * DirectPlayLobbyCreateA (DPLAYX.4)
2050 *
2051 */
2052 HRESULT WINAPI DirectPlayLobbyCreateA( GUID *lpGUIDDSP, IDirectPlayLobbyA **lplpDPL,
2053 IUnknown *lpUnk, void *lpData, DWORD dwDataSize )
2054 {
2055 TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08x\n",
2056 lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
2057
2058 /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
2059 * equal 0. These fields are mostly for future expansion.
2060 */
2061 if ( lpGUIDDSP || lpData || dwDataSize )
2062 {
2063 *lplpDPL = NULL;
2064 return DPERR_INVALIDPARAMS;
2065 }
2066
2067 if( lpUnk )
2068 {
2069 *lplpDPL = NULL;
2070 ERR("Bad parameters!\n" );
2071 return CLASS_E_NOAGGREGATION;
2072 }
2073
2074 return dplobby_create( &IID_IDirectPlayLobbyA, (void**)lplpDPL );
2075 }
2076
2077 /***************************************************************************
2078 * DirectPlayLobbyCreateW (DPLAYX.5)
2079 *
2080 */
2081 HRESULT WINAPI DirectPlayLobbyCreateW( GUID *lpGUIDDSP, IDirectPlayLobby **lplpDPL,
2082 IUnknown *lpUnk, void *lpData, DWORD dwDataSize )
2083 {
2084 TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08x\n",
2085 lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
2086
2087 /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
2088 * equal 0. These fields are mostly for future expansion.
2089 */
2090 if ( lpGUIDDSP || lpData || dwDataSize )
2091 {
2092 *lplpDPL = NULL;
2093 ERR("Bad parameters!\n" );
2094 return DPERR_INVALIDPARAMS;
2095 }
2096
2097 if( lpUnk )
2098 {
2099 *lplpDPL = NULL;
2100 ERR("Bad parameters!\n" );
2101 return CLASS_E_NOAGGREGATION;
2102 }
2103
2104 return dplobby_create( &IID_IDirectPlayLobby, (void**)lplpDPL );
2105 }