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

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

Added ID tags

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