source: trunk/src/DPlayX/dplobby.cpp@ 4446

Last change on this file since 4446 was 4446, checked in by hugh, 25 years ago

Updated to latest WINE

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