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

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

Updated to latest wine version

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