1 /* Direct Play Lobby 2 & 3 Implementation
3 * Copyright 1998,1999 - Peter Hunnisett
5 * <presently under construction - contact hunnise@nortelnetworks.com>
14 #include "debugtools.h"
18 #include "dplayx_global.h"
20 DEFAULT_DEBUG_CHANNEL(dplay)
23 /* FIXME: All the data structures are presently not needed except for unk */
24 /* FIXME: Move lock from unk to dpl */
26 /* Forward declarations for this module helper methods */
27 static HRESULT DPL_CreateCompoundAddress ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
28 LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
30 static HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
31 DWORD dwAddressSize, LPVOID lpContext );
34 /*****************************************************************************
35 * Predeclare the interface implementation structures
37 typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyAImpl;
38 typedef struct IDirectPlayLobbyImpl IDirectPlayLobbyWImpl;
39 typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2AImpl;
40 typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2WImpl;
41 typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3AImpl;
42 typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3WImpl;
44 /*****************************************************************************
45 * IDirectPlayLobby {1,2,3} implementation structure
47 * The philosophy behind this extra pointer derefernce is that I wanted to
48 * have the same structure for all types of objects without having to do
49 * alot of casting. I also only wanted to implement an interface in the
50 * object it was "released" with IUnknown interface being implemented in the 1 version.
51 * Of course, with these new interfaces comes the data required to keep the state required
52 * by these interfaces. So, basically, the pointers contain the data associated with
53 * a release. If you use the data associated with release 3 in a release 2 object, you'll
54 * get a run time trap, as that won't have any data.
58 typedef struct tagDirectPlayLobbyIUnknownData
61 CRITICAL_SECTION DPL_lock;
62 } DirectPlayLobbyIUnknownData;
64 typedef struct tagDirectPlayLobbyData
66 HKEY hkCallbackKeyHack;
67 } DirectPlayLobbyData;
69 typedef struct tagDirectPlayLobby2Data
72 } DirectPlayLobby2Data;
74 typedef struct tagDirectPlayLobby3Data
77 } DirectPlayLobby3Data;
79 #define LOBBY_IMPL_FIELDS DirectPlayLobbyIUnknownData* unk; \
80 DirectPlayLobbyData* dpl; \
81 DirectPlayLobby2Data* dpl2; \
82 DirectPlayLobby3Data* dpl3;
84 struct IDirectPlayLobbyImpl
86 ICOM_VFIELD(IDirectPlayLobby);
90 struct IDirectPlayLobby2Impl
92 ICOM_VFIELD(IDirectPlayLobby2);
96 struct IDirectPlayLobby3Impl
98 ICOM_VFIELD(IDirectPlayLobby3);
103 /* Forward declarations of virtual tables */
104 static ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyWVT;
105 static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2WVT;
106 static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3WVT;
108 static ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyAVT;
109 static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2AVT;
110 static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3AVT;
115 /* The COM interface for upversioning an interface
116 * We've been given a GUID (riid) and we need to replace the present
117 * interface with that of the requested interface.
119 * Snip from some Microsoft document:
120 * There are four requirements for implementations of QueryInterface (In these
121 * cases, "must succeed" means "must succeed barring catastrophic failure."):
123 * * The set of interfaces accessible on an object through
124 * IUnknown::QueryInterface must be static, not dynamic. This means that
125 * if a call to QueryInterface for a pointer to a specified interface
126 * succeeds the first time, it must succeed again, and if it fails the
127 * first time, it must fail on all subsequent queries.
128 * * It must be symmetric ~W if a client holds a pointer to an interface on
129 * an object, and queries for that interface, the call must succeed.
130 * * It must be reflexive ~W if a client holding a pointer to one interface
131 * queries successfully for another, a query through the obtained pointer
132 * for the first interface must succeed.
133 * * It must be transitive ~W if a client holding a pointer to one interface
134 * queries successfully for a second, and through that pointer queries
135 * successfully for a third interface, a query for the first interface
136 * through the pointer for the third interface must succeed.
138 * As you can see, this interface doesn't qualify but will most likely
139 * be good enough for the time being.
143 BOOL DPL_CreateIUnknown( LPVOID lpDPL )
145 ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
147 This->unk = (DirectPlayLobbyIUnknownData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
148 sizeof( *(This->unk) ) );
149 if ( This->unk != NULL )
151 InitializeCriticalSection( &This->unk->DPL_lock );
153 IDirectPlayLobby_AddRef( (LPDIRECTPLAYLOBBYA)lpDPL );
161 BOOL DPL_DestroyIUnknown( LPVOID lpDPL )
163 ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
165 DeleteCriticalSection( &This->unk->DPL_lock );
166 HeapFree( GetProcessHeap(), 0, This->unk );
171 BOOL DPL_CreateLobby1( LPVOID lpDPL )
173 ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
175 This->dpl = (DirectPlayLobbyData*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
176 sizeof( *(This->dpl) ) );
177 if ( This->dpl == NULL )
185 BOOL DPL_DestroyLobby1( LPVOID lpDPL )
187 ICOM_THIS(IDirectPlayLobbyAImpl,lpDPL);
189 /* Delete the contents */
190 HeapFree( GetProcessHeap(), 0, This->dpl );
195 BOOL DPL_CreateLobby2( LPVOID lpDPL )
197 ICOM_THIS(IDirectPlayLobby2AImpl,lpDPL);
199 This->dpl2 = (DirectPlayLobby2Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
200 sizeof( *(This->dpl2) ) );
201 if ( This->dpl2 == NULL )
209 BOOL DPL_DestroyLobby2( LPVOID lpDPL )
211 ICOM_THIS(IDirectPlayLobby2AImpl,lpDPL);
213 HeapFree( GetProcessHeap(), 0, This->dpl2 );
218 BOOL DPL_CreateLobby3( LPVOID lpDPL )
220 ICOM_THIS(IDirectPlayLobby3AImpl,lpDPL);
222 This->dpl3 = (DirectPlayLobby3Data*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
223 sizeof( *(This->dpl3) ) );
224 if ( This->dpl3 == NULL )
232 BOOL DPL_DestroyLobby3( LPVOID lpDPL )
234 ICOM_THIS(IDirectPlayLobby3AImpl,lpDPL);
236 HeapFree( GetProcessHeap(), 0, This->dpl3 );
242 /* Helper function for DirectPlayLobby QueryInterface */
244 HRESULT directPlayLobby_QueryInterface
245 ( REFIID riid, LPVOID* ppvObj )
247 if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
249 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
250 sizeof( IDirectPlayLobbyWImpl ) );
252 if( *ppvObj == NULL )
254 return E_OUTOFMEMORY;
257 /* new scope for variable declaration */
259 ICOM_THIS(IDirectPlayLobbyWImpl,*ppvObj);
261 ICOM_VTBL(This) = &directPlayLobbyWVT;
263 if ( DPL_CreateIUnknown( (LPVOID)This ) &&
264 DPL_CreateLobby1( (LPVOID)This )
274 else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
276 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
277 sizeof( IDirectPlayLobbyAImpl ) );
279 if( *ppvObj == NULL )
281 return E_OUTOFMEMORY;
285 ICOM_THIS(IDirectPlayLobbyAImpl,*ppvObj);
287 ICOM_VTBL(This) = &directPlayLobbyAVT;
289 if ( DPL_CreateIUnknown( (LPVOID)This ) &&
290 DPL_CreateLobby1( (LPVOID)This )
299 else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
301 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
302 sizeof( IDirectPlayLobby2WImpl ) );
304 if( *ppvObj == NULL )
306 return E_OUTOFMEMORY;
310 ICOM_THIS(IDirectPlayLobby2WImpl,*ppvObj);
312 ICOM_VTBL(This) = &directPlayLobby2WVT;
314 if ( DPL_CreateIUnknown( (LPVOID)This ) &&
315 DPL_CreateLobby1( (LPVOID)This ) &&
316 DPL_CreateLobby2( (LPVOID)This )
325 else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
327 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
328 sizeof( IDirectPlayLobby2AImpl ) );
330 if( *ppvObj == NULL )
332 return E_OUTOFMEMORY;
336 ICOM_THIS(IDirectPlayLobby2AImpl,*ppvObj);
338 ICOM_VTBL(This) = &directPlayLobby2AVT;
340 if ( DPL_CreateIUnknown( (LPVOID)This ) &&
341 DPL_CreateLobby1( (LPVOID)This ) &&
342 DPL_CreateLobby2( (LPVOID)This )
351 else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
353 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
354 sizeof( IDirectPlayLobby3WImpl ) );
356 if( *ppvObj == NULL )
358 return E_OUTOFMEMORY;
362 ICOM_THIS(IDirectPlayLobby3WImpl,*ppvObj);
364 ICOM_VTBL(This) = &directPlayLobby3WVT;
366 if ( DPL_CreateIUnknown( *ppvObj ) &&
367 DPL_CreateLobby1( *ppvObj ) &&
368 DPL_CreateLobby2( *ppvObj ) &&
369 DPL_CreateLobby3( *ppvObj )
378 else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
380 *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
381 sizeof( IDirectPlayLobby3AImpl ) );
383 if( *ppvObj == NULL )
385 return E_OUTOFMEMORY;
389 ICOM_THIS(IDirectPlayLobby3AImpl,*ppvObj);
391 ICOM_VTBL(This) = &directPlayLobby3AVT;
393 if ( DPL_CreateIUnknown( *ppvObj ) &&
394 DPL_CreateLobby1( *ppvObj ) &&
395 DPL_CreateLobby2( *ppvObj ) &&
396 DPL_CreateLobby3( *ppvObj )
406 /* Unsupported interface */
408 return E_NOINTERFACE;
412 DPL_DestroyLobby3( *ppvObj );
413 DPL_DestroyLobby2( *ppvObj );
414 DPL_DestroyLobby1( *ppvObj );
415 DPL_DestroyIUnknown( *ppvObj );
416 HeapFree( GetProcessHeap(), 0, *ppvObj );
419 return DPERR_NOMEMORY;
422 static HRESULT WINAPI IDirectPlayLobbyAImpl_QueryInterface
423 ( LPDIRECTPLAYLOBBYA iface,
427 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
428 TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
430 if( IsEqualGUID( &IID_IUnknown, riid ) ||
431 IsEqualGUID( &IID_IDirectPlayLobbyA, riid )
434 IDirectPlayLobby_AddRef( iface );
439 return directPlayLobby_QueryInterface( riid, ppvObj );
443 static HRESULT WINAPI IDirectPlayLobbyW_QueryInterface
444 ( LPDIRECTPLAYLOBBY iface,
448 ICOM_THIS(IDirectPlayLobbyWImpl,iface);
449 TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
451 if( IsEqualGUID( &IID_IUnknown, riid ) ||
452 IsEqualGUID( &IID_IDirectPlayLobby, riid )
455 IDirectPlayLobby_AddRef( iface );
460 return directPlayLobby_QueryInterface( riid, ppvObj );
464 static HRESULT WINAPI IDirectPlayLobby2AImpl_QueryInterface
465 ( LPDIRECTPLAYLOBBY2A iface,
469 ICOM_THIS(IDirectPlayLobby2AImpl,iface);
470 TRACE("(%p)->(%p,%p)\n", This, riid, ppvObj );
472 /* Compare riids. We know this object is a direct play lobby 2A object.
473 If we are asking about the same type of interface we're fine.
475 if( IsEqualGUID( &IID_IUnknown, riid ) ||
476 IsEqualGUID( &IID_IDirectPlayLobby2A, riid )
479 IDirectPlayLobby_AddRef( iface );
483 return directPlayLobby_QueryInterface( riid, ppvObj );
486 static HRESULT WINAPI IDirectPlayLobby2WImpl_QueryInterface
487 ( LPDIRECTPLAYLOBBY2 iface,
491 ICOM_THIS(IDirectPlayLobby2WImpl,iface);
493 /* Compare riids. We know this object is a direct play lobby 2 object.
494 If we are asking about the same type of interface we're fine.
496 if( IsEqualGUID( &IID_IUnknown, riid ) ||
497 IsEqualGUID( &IID_IDirectPlayLobby2, riid )
500 IDirectPlayLobby_AddRef( iface );
505 return directPlayLobby_QueryInterface( riid, ppvObj );
509 static HRESULT WINAPI IDirectPlayLobby3AImpl_QueryInterface
510 ( LPDIRECTPLAYLOBBY3A iface,
514 ICOM_THIS(IDirectPlayLobby3AImpl,iface);
516 /* Compare riids. We know this object is a direct play lobby 3 object.
517 If we are asking about the same type of interface we're fine.
519 if( IsEqualGUID( &IID_IUnknown, riid ) ||
520 IsEqualGUID( &IID_IDirectPlayLobby3A, riid )
523 IDirectPlayLobby_AddRef( iface );
528 return directPlayLobby_QueryInterface( riid, ppvObj );
532 static HRESULT WINAPI IDirectPlayLobby3WImpl_QueryInterface
533 ( LPDIRECTPLAYLOBBY3 iface,
537 ICOM_THIS(IDirectPlayLobby3WImpl,iface);
539 /* Compare riids. We know this object is a direct play lobby 3 object.
540 If we are asking about the same type of interface we're fine.
542 if( IsEqualGUID( &IID_IUnknown, riid ) ||
543 IsEqualGUID( &IID_IDirectPlayLobby3, riid )
546 IDirectPlayLobby_AddRef( iface );
551 return directPlayLobby_QueryInterface( riid, ppvObj );
556 * Simple procedure. Just increment the reference count to this
557 * structure and return the new reference count.
559 static ULONG WINAPI IDirectPlayLobbyImpl_AddRef
560 ( LPDIRECTPLAYLOBBY iface )
563 ICOM_THIS(IDirectPlayLobbyWImpl,iface);
565 EnterCriticalSection( &This->unk->DPL_lock );
567 refCount = ++(This->unk->ref);
569 LeaveCriticalSection( &This->unk->DPL_lock );
571 TRACE("ref count incremented to %lu for %p\n", refCount, This );
577 * Simple COM procedure. Decrease the reference count to this object.
578 * If the object no longer has any reference counts, free up the associated
581 static ULONG WINAPI IDirectPlayLobbyAImpl_Release
582 ( LPDIRECTPLAYLOBBYA iface )
586 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
588 EnterCriticalSection( &This->unk->DPL_lock );
590 refCount = --(This->unk->ref);
592 LeaveCriticalSection( &This->unk->DPL_lock );
594 TRACE("ref count decremeneted to %lu for %p\n", refCount, This );
596 /* Deallocate if this is the last reference to the object */
599 DPL_DestroyLobby3( This );
600 DPL_DestroyLobby2( This );
601 DPL_DestroyLobby1( This );
602 DPL_DestroyIUnknown( This );
603 HeapFree( GetProcessHeap(), 0, This );
610 /********************************************************************
612 * Connects an application to the session specified by the DPLCONNECTION
613 * structure currently stored with the DirectPlayLobby object.
615 * Returns a IDirectPlay interface.
618 static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect
619 ( LPDIRECTPLAYLOBBYA iface,
621 LPDIRECTPLAY2A* lplpDP,
624 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
626 LPDIRECTPLAY2A lpDirectPlay2A;
627 /* LPDIRECTPLAY3A lpDirectPlay3A; */
628 /* LPDIRECTPLAYLOBBY2A lpDirectPlayLobby2A; */
631 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, dwFlags, lplpDP, pUnk );
633 if( dwFlags || pUnk )
635 return DPERR_INVALIDPARAMS;
638 /* Create the DirectPlay interface */
639 if( ( rc = directPlay_QueryInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) ) != DP_OK )
641 ERR("error creating Direct Play 2A interface. Return Code = 0x%lx.\n", rc );
645 lpDirectPlay2A = *lplpDP;
647 /* - Need to call IDirectPlay::EnumConnections with the service provider to get that good information
648 * - Need to call CreateAddress to create the lpConnection param for IDirectPlay::InitializeConnection
649 * - Call IDirectPlay::InitializeConnection
650 * - Call IDirectPlay::Open
653 IDirectPlayLobby_EnumAddress( iface, RunApplicationA_Callback,
654 lpConn->lpAddress, lpConn->dwAddressSize, NULL );
662 static HRESULT WINAPI IDirectPlayLobbyWImpl_Connect
663 ( LPDIRECTPLAYLOBBY iface,
665 LPDIRECTPLAY2* lplpDP,
668 ICOM_THIS(IDirectPlayLobbyWImpl,iface);
669 LPDIRECTPLAY2* directPlay2W;
672 FIXME("(%p)->(0x%08lx,%p,%p): stub\n", This, dwFlags, lplpDP, pUnk );
674 if( dwFlags || pUnk )
676 return DPERR_INVALIDPARAMS;
679 /* Create the DirectPlay interface */
680 if( ( createRC = directPlay_QueryInterface( &IID_IDirectPlay2, (LPVOID*)lplpDP ) ) != DP_OK )
682 ERR("error creating Direct Play 2W interface. Return Code = 0x%lx.\n", createRC );
686 /* This should invoke IDirectPlay3::InitializeConnection IDirectPlay3::Open */
687 directPlay2W = lplpDP;
693 /********************************************************************
695 * Creates a DirectPlay Address, given a service provider-specific network
697 * Returns an address contains the globally unique identifier
698 * (GUID) of the service provider and data that the service provider can
699 * interpret as a network address.
701 * NOTE: It appears that this method is supposed to be really really stupid
702 * with no error checking on the contents.
704 static HRESULT WINAPI IDirectPlayLobbyAImpl_CreateAddress
705 ( LPDIRECTPLAYLOBBYA iface,
707 REFGUID guidDataType,
711 LPDWORD lpdwAddressSize )
713 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
715 const DWORD dwNumAddElements = 2; /* Service Provide & address data type */
716 DPCOMPOUNDADDRESSELEMENT addressElements[ dwNumAddElements ];
718 TRACE( "(%p)->(%p,%p,%p,0x%08lx,%p,%p)\n", This, guidSP, guidDataType, lpData,
719 dwDataSize, lpAddress, lpdwAddressSize );
721 addressElements[ 0 ].guidDataType = DPAID_ServiceProvider;
722 addressElements[ 0 ].dwDataSize = sizeof( GUID );
723 addressElements[ 0 ].lpData = (LPVOID)guidSP;
725 addressElements[ 1 ].guidDataType = *guidDataType;
726 addressElements[ 1 ].dwDataSize = dwDataSize;
727 addressElements[ 1 ].lpData = (LPVOID)lpData;
729 /* Call CreateCompoundAddress to cut down on code.
730 NOTE: We can do this because we don't support DPL 1 interfaces! */
731 return IDirectPlayLobby_CreateCompoundAddress( (LPDIRECTPLAYLOBBY2A)iface,
732 addressElements, dwNumAddElements,
733 lpAddress, lpdwAddressSize );
736 static HRESULT WINAPI IDirectPlayLobbyWImpl_CreateAddress
737 ( LPDIRECTPLAYLOBBY iface,
739 REFGUID guidDataType,
743 LPDWORD lpdwAddressSize )
745 ICOM_THIS(IDirectPlayLobbyWImpl,iface);
746 const DWORD dwNumAddElements = 2; /* Service Provide & address data type */
747 DPCOMPOUNDADDRESSELEMENT addressElements[ dwNumAddElements ];
749 TRACE( "(%p)->(%p,%p,%p,0x%08lx,%p,%p)\n", This, guidSP, guidDataType, lpData,
750 dwDataSize, lpAddress, lpdwAddressSize );
752 addressElements[ 0 ].guidDataType = DPAID_ServiceProvider;
753 addressElements[ 0 ].dwDataSize = sizeof( GUID );
754 addressElements[ 0 ].lpData = (LPVOID)guidSP;
756 addressElements[ 1 ].guidDataType = *guidDataType;
757 addressElements[ 1 ].dwDataSize = dwDataSize;
758 addressElements[ 1 ].lpData = (LPVOID)lpData;
760 /* Call CreateCompoundAddress to cut down on code.
761 NOTE: We can do this because we don't support DPL 1 interfaces! */
762 return IDirectPlayLobby_CreateCompoundAddress( (LPDIRECTPLAYLOBBY2)iface,
763 addressElements, dwNumAddElements,
764 lpAddress, lpdwAddressSize );
768 /********************************************************************
770 * Parses out chunks from the DirectPlay Address buffer by calling the
771 * given callback function, with lpContext, for each of the chunks.
774 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddress
775 ( LPDIRECTPLAYLOBBYA iface,
776 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
781 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
783 TRACE("(%p)->(%p,%p,0x%08lx,%p)\n", This, lpEnumAddressCallback, lpAddress,
784 dwAddressSize, lpContext );
786 return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
789 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumAddress
790 ( LPDIRECTPLAYLOBBY iface,
791 LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
796 ICOM_THIS(IDirectPlayLobbyWImpl,iface);
798 TRACE("(%p)->(%p,%p,0x%08lx,%p)\n", This, lpEnumAddressCallback, lpAddress,
799 dwAddressSize, lpContext );
801 return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
804 static HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
805 DWORD dwAddressSize, LPVOID lpContext )
807 DWORD dwTotalSizeEnumerated = 0;
809 /* FIXME: First chunk is always the total size chunk - Should we report it? */
811 while ( dwTotalSizeEnumerated < dwAddressSize )
813 LPDPADDRESS lpElements = (LPDPADDRESS)lpAddress;
814 DWORD dwSizeThisEnumeration;
816 /* Invoke the enum method. If false is returned, stop enumeration */
817 if ( !lpEnumAddressCallback( &lpElements->guidDataType, lpElements->dwDataSize,
818 lpElements + sizeof( DPADDRESS ), lpContext ) )
823 dwSizeThisEnumeration = sizeof( DPADDRESS ) + lpElements->dwDataSize;
824 lpAddress += dwSizeThisEnumeration;
825 dwTotalSizeEnumerated += dwSizeThisEnumeration;
831 /********************************************************************
833 * Enumerates all the address types that a given service provider needs to
834 * build the DirectPlay Address.
837 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddressTypes
838 ( LPDIRECTPLAYLOBBYA iface,
839 LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
844 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
847 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
848 DWORD dwIndex, sizeOfSubKeyName=50;
851 TRACE(" (%p)->(%p,%p,%p,0x%08lx)\n", This, lpEnumAddressTypeCallback, guidSP, lpContext, dwFlags );
855 return DPERR_INVALIDPARAMS;
858 if( !lpEnumAddressTypeCallback || !*lpEnumAddressTypeCallback )
860 return DPERR_INVALIDPARAMS;
865 return DPERR_INVALIDOBJECT;
868 /* Need to loop over the service providers in the registry */
869 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
870 0, KEY_ENUMERATE_SUB_KEYS, &hkResult ) != ERROR_SUCCESS )
872 /* Hmmm. Does this mean that there are no service providers? */
873 ERR(": no service providers?\n");
877 /* Traverse all the service providers we have available */
879 RegEnumKeyA( hkResult, dwIndex, subKeyName, sizeOfSubKeyName ) != ERROR_NO_MORE_ITEMS;
883 HKEY hkServiceProvider, hkServiceProviderAt;
884 GUID serviceProviderGUID;
885 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
887 char returnBuffer[51];
888 LPWSTR lpWGUIDString;
890 LPSTR atKey = "Address Types";
891 LPSTR guidDataSubKey = "Guid";
894 TRACE(" this time through: %s\n", subKeyName );
896 /* Get a handle for this particular service provider */
897 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_QUERY_VALUE,
898 &hkServiceProvider ) != ERROR_SUCCESS )
900 ERR(": what the heck is going on?\n" );
904 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
905 NULL, &returnTypeGUID, returnBuffer,
906 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
908 ERR(": missing GUID registry data members\n" );
912 /* FIXME: Check return types to ensure we're interpreting data right */
913 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
914 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
915 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
916 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
918 /* Determine if this is the Service Provider that the user asked for */
919 if( !IsEqualGUID( &serviceProviderGUID, guidSP ) )
924 /* Get a handle for this particular service provider */
925 if( RegOpenKeyExA( hkServiceProvider, atKey, 0, KEY_QUERY_VALUE,
926 &hkServiceProviderAt ) != ERROR_SUCCESS )
928 WARN(": No Address Types registry data sub key/members\n" );
932 /* Traverse all the address type we have available */
934 RegEnumKeyA( hkServiceProviderAt, dwAtIndex, atSubKey, sizeOfSubKeyName ) != ERROR_NO_MORE_ITEMS;
937 TRACE( "Found Address Type GUID %s\n", atSubKey );
939 /* FIXME: Check return types to ensure we're interpreting data right */
940 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, atSubKey );
941 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
942 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
943 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
945 /* The enumeration will return FALSE if we are not to continue */
946 if( !lpEnumAddressTypeCallback( &serviceProviderGUID, lpContext, 0 ) )
948 WARN("lpEnumCallback returning FALSE\n" );
949 break; /* FIXME: This most likely has to break from the procedure...*/
954 /* We only enumerate address types for 1 GUID. We've found it, so quit looking */
961 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumAddressTypes
962 ( LPDIRECTPLAYLOBBY iface,
963 LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
969 return DPERR_OUTOFMEMORY;
972 /********************************************************************
974 * Enumerates what applications are registered with DirectPlay by
975 * invoking the callback function with lpContext.
978 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumLocalApplications
979 ( LPDIRECTPLAYLOBBY iface,
980 LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback,
984 ICOM_THIS(IDirectPlayLobbyWImpl,iface);
986 FIXME("(%p)->(%p,%p,0x%08lx):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
988 return DPERR_OUTOFMEMORY;
991 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumLocalApplications
992 ( LPDIRECTPLAYLOBBYA iface,
993 LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback,
997 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
1000 LPCSTR searchSubKey = "SOFTWARE\\Microsoft\\DirectPlay\\Applications";
1001 LPSTR guidDataSubKey = "Guid";
1002 DWORD dwIndex, sizeOfSubKeyName=50;
1003 char subKeyName[51];
1005 TRACE("(%p)->(%p,%p,0x%08lx)\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
1009 return DPERR_INVALIDPARAMS;
1012 if( !lpEnumLocalAppCallback || !*lpEnumLocalAppCallback )
1014 return DPERR_INVALIDPARAMS;
1017 /* Need to loop over the service providers in the registry */
1018 if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
1019 0, KEY_ENUMERATE_SUB_KEYS, &hkResult ) != ERROR_SUCCESS )
1021 /* Hmmm. Does this mean that there are no service providers? */
1022 ERR(": no service providers?\n");
1026 /* Traverse all registered applications */
1028 RegEnumKeyA( hkResult, dwIndex, subKeyName, sizeOfSubKeyName ) != ERROR_NO_MORE_ITEMS;
1032 HKEY hkServiceProvider;
1033 GUID serviceProviderGUID;
1034 DWORD returnTypeGUID, sizeOfReturnBuffer = 50;
1035 char returnBuffer[51];
1036 LPWSTR lpWGUIDString;
1037 DPLAPPINFO dplAppInfo;
1039 TRACE(" this time through: %s\n", subKeyName );
1041 /* Get a handle for this particular service provider */
1042 if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_QUERY_VALUE,
1043 &hkServiceProvider ) != ERROR_SUCCESS )
1045 ERR(": what the heck is going on?\n" );
1049 if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
1050 NULL, &returnTypeGUID, returnBuffer,
1051 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1053 ERR(": missing GUID registry data members\n" );
1057 /* FIXME: Check return types to ensure we're interpreting data right */
1058 lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
1059 CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
1060 HeapFree( GetProcessHeap(), 0, lpWGUIDString );
1061 /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
1063 dplAppInfo.dwSize = sizeof( dplAppInfo );
1064 dplAppInfo.guidApplication = serviceProviderGUID;
1065 dplAppInfo.appName.lpszAppNameA = subKeyName;
1067 EnterCriticalSection( &This->unk->DPL_lock );
1069 memcpy( &This->dpl->hkCallbackKeyHack, &hkServiceProvider, sizeof( hkServiceProvider ) );
1071 if( !lpEnumLocalAppCallback( &dplAppInfo, lpContext, dwFlags ) )
1073 LeaveCriticalSection( &This->unk->DPL_lock );
1077 LeaveCriticalSection( &This->unk->DPL_lock );
1083 /********************************************************************
1085 * Retrieves the DPLCONNECTION structure that contains all the information
1086 * needed to start and connect an application. This was generated using
1087 * either the RunApplication or SetConnectionSettings methods.
1089 * NOTES: If lpData is NULL then just return lpdwDataSize. This allows
1090 * the data structure to be allocated by our caller which can then
1091 * call this procedure/method again with a valid data pointer.
1093 static HRESULT WINAPI IDirectPlayLobbyAImpl_GetConnectionSettings
1094 ( LPDIRECTPLAYLOBBYA iface,
1097 LPDWORD lpdwDataSize )
1099 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
1102 TRACE("(%p)->(0x%08lx,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
1104 EnterCriticalSection( &This->unk->DPL_lock );
1106 hr = DPLAYX_GetConnectionSettingsA( dwAppID, lpData, lpdwDataSize );
1108 LeaveCriticalSection( &This->unk->DPL_lock );
1113 static HRESULT WINAPI IDirectPlayLobbyWImpl_GetConnectionSettings
1114 ( LPDIRECTPLAYLOBBY iface,
1117 LPDWORD lpdwDataSize )
1119 ICOM_THIS(IDirectPlayLobbyWImpl,iface);
1122 TRACE("(%p)->(0x%08lx,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
1124 EnterCriticalSection( &This->unk->DPL_lock );
1126 hr = DPLAYX_GetConnectionSettingsW( dwAppID, lpData, lpdwDataSize );
1128 LeaveCriticalSection( &This->unk->DPL_lock );
1133 /********************************************************************
1135 * Retrieves the message sent between a lobby client and a DirectPlay
1136 * application. All messages are queued until received.
1139 static HRESULT WINAPI IDirectPlayLobbyAImpl_ReceiveLobbyMessage
1140 ( LPDIRECTPLAYLOBBYA iface,
1143 LPDWORD lpdwMessageFlags,
1145 LPDWORD lpdwDataSize )
1147 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
1148 FIXME(":stub %p %08lx %08lx %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
1150 return DPERR_OUTOFMEMORY;
1153 static HRESULT WINAPI IDirectPlayLobbyWImpl_ReceiveLobbyMessage
1154 ( LPDIRECTPLAYLOBBY iface,
1157 LPDWORD lpdwMessageFlags,
1159 LPDWORD lpdwDataSize )
1161 ICOM_THIS(IDirectPlayLobbyWImpl,iface);
1162 FIXME(":stub %p %08lx %08lx %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
1164 return DPERR_OUTOFMEMORY;
1167 typedef struct tagRunApplicationEnumStruct
1169 IDirectPlayLobbyAImpl* This;
1174 LPSTR lpszCommandLine;
1175 LPSTR lpszCurrentDirectory;
1176 } RunApplicationEnumStruct, *lpRunApplicationEnumStruct;
1178 /* To be called by RunApplication to find how to invoke the function */
1179 static BOOL CALLBACK RunApplicationA_EnumLocalApplications
1180 ( LPCDPLAPPINFO lpAppInfo,
1184 lpRunApplicationEnumStruct lpData = (lpRunApplicationEnumStruct)lpContext;
1186 if( IsEqualGUID( &lpAppInfo->guidApplication, &lpData->appGUID ) )
1188 char returnBuffer[200];
1189 DWORD returnType, sizeOfReturnBuffer;
1190 LPSTR clSubKey = "CommandLine";
1191 LPSTR cdSubKey = "CurrentDirectory";
1192 LPSTR fileSubKey = "File";
1193 LPSTR pathSubKey = "Path";
1195 /* FIXME: Lazy man hack - dplay struct has the present reg key saved */
1197 sizeOfReturnBuffer = 200;
1199 /* Get all the appropriate data from the registry */
1200 if( RegQueryValueExA( lpData->This->dpl->hkCallbackKeyHack, clSubKey,
1201 NULL, &returnType, returnBuffer,
1202 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1204 ERR( ": missing CommandLine registry data member\n" );
1208 lpData->lpszCommandLine = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, returnBuffer );
1211 sizeOfReturnBuffer = 200;
1213 if( RegQueryValueExA( lpData->This->dpl->hkCallbackKeyHack, cdSubKey,
1214 NULL, &returnType, returnBuffer,
1215 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1217 ERR( ": missing CurrentDirectory registry data member\n" );
1221 lpData->lpszCurrentDirectory = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, returnBuffer );
1224 sizeOfReturnBuffer = 200;
1226 if( RegQueryValueExA( lpData->This->dpl->hkCallbackKeyHack, fileSubKey,
1227 NULL, &returnType, returnBuffer,
1228 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1230 ERR( ": missing File registry data member\n" );
1234 lpData->lpszFileName = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, returnBuffer );
1237 sizeOfReturnBuffer = 200;
1239 if( RegQueryValueExA( lpData->This->dpl->hkCallbackKeyHack, pathSubKey,
1240 NULL, &returnType, returnBuffer,
1241 &sizeOfReturnBuffer ) != ERROR_SUCCESS )
1243 ERR( ": missing Path registry data member\n" );
1247 lpData->lpszPath = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, returnBuffer );
1250 return FALSE; /* No need to keep going as we found what we wanted */
1253 return TRUE; /* Keep enumerating, haven't found the application yet */
1256 /********************************************************************
1258 * Starts an application and passes to it all the information to
1259 * connect to a session.
1262 static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication
1263 ( LPDIRECTPLAYLOBBYA iface,
1266 LPDPLCONNECTION lpConn,
1267 HANDLE hReceiveEvent )
1269 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
1271 RunApplicationEnumStruct enumData;
1273 STARTUPINFOA startupInfo;
1274 PROCESS_INFORMATION newProcessInfo;
1277 FIXME( "(%p)->(0x%08lx,%p,%p,%p):semi stub\n", This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
1281 return DPERR_INVALIDPARAMS;
1284 EnterCriticalSection( &This->unk->DPL_lock );
1286 ZeroMemory( &enumData, sizeof( enumData ) );
1287 enumData.This = This;
1288 enumData.appGUID = lpConn->lpSessionDesc->guidApplication;
1290 /* Our callback function will fill up the enumData structure with all the information
1291 required to start a new process */
1292 IDirectPlayLobby_EnumLocalApplications( iface, RunApplicationA_EnumLocalApplications,
1293 (LPVOID)(&enumData), 0 );
1295 /* First the application name */
1296 strcpy( temp, enumData.lpszPath );
1297 strcat( temp, "\\" );
1298 strcat( temp, enumData.lpszFileName );
1299 HeapFree( GetProcessHeap(), 0, enumData.lpszPath );
1300 HeapFree( GetProcessHeap(), 0, enumData.lpszFileName );
1301 appName = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, temp );
1303 /* Now the command line */
1304 strcat( temp, " " );
1305 strcat( temp, enumData.lpszCommandLine );
1306 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
1307 enumData.lpszCommandLine = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, temp );
1309 ZeroMemory( &startupInfo, sizeof( startupInfo ) );
1310 startupInfo.cb = sizeof( startupInfo );
1311 /* FIXME: Should any fields be filled in? */
1313 ZeroMemory( &newProcessInfo, sizeof( newProcessInfo ) );
1315 #if !defined( WORKING_PROCESS_SUSPEND )
1316 DPLAYX_AquireSemaphoreHack();
1319 if( !CreateProcessA( appName,
1320 enumData.lpszCommandLine,
1324 CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_SUSPENDED, /* Creation Flags */
1326 enumData.lpszCurrentDirectory,
1332 FIXME( "Failed to create process for app %s\n", appName );
1335 HeapFree( GetProcessHeap(), 0, appName );
1336 HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
1337 HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
1339 /* Reserve this global application id! */
1340 if( !DPLAYX_CreateLobbyApplication( newProcessInfo.dwProcessId, hReceiveEvent ) )
1342 ERR( "Unable to create global application data\n" );
1345 hr = IDirectPlayLobby_SetConnectionSettings( iface, 0, newProcessInfo.dwProcessId, lpConn );
1349 FIXME( "SetConnectionSettings failure 0x%08lx\n", hr );
1353 /* Everything seems to have been set correctly, update the dwAppID */
1354 *lpdwAppID = newProcessInfo.dwProcessId;
1356 #if !defined( WORKING_PROCESS_SUSPEND )
1357 FIXME( ": It would be at this point that we would allow the process to resume\n" );
1358 DPLAYX_ReleaseSemaphoreHack();
1360 ResumeThread( newProcessInfo.dwThreadId );
1363 LeaveCriticalSection( &This->unk->DPL_lock );
1368 static HRESULT WINAPI IDirectPlayLobbyWImpl_RunApplication
1369 ( LPDIRECTPLAYLOBBY iface,
1372 LPDPLCONNECTION lpConn,
1373 HANDLE hReceiveEvent )
1375 ICOM_THIS(IDirectPlayLobbyWImpl,iface);
1376 FIXME( "(%p)->(0x%08lx,%p,%p,%p):stub\n", This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
1377 return DPERR_OUTOFMEMORY;
1380 /********************************************************************
1382 * Sends a message between the application and the lobby client.
1383 * All messages are queued until received.
1386 static HRESULT WINAPI IDirectPlayLobbyAImpl_SendLobbyMessage
1387 ( LPDIRECTPLAYLOBBYA iface,
1394 return DPERR_OUTOFMEMORY;
1397 static HRESULT WINAPI IDirectPlayLobbyWImpl_SendLobbyMessage
1398 ( LPDIRECTPLAYLOBBY iface,
1405 return DPERR_OUTOFMEMORY;
1408 /********************************************************************
1410 * Modifies the DPLCONNECTION structure to contain all information
1411 * needed to start and connect an application.
1414 static HRESULT WINAPI IDirectPlayLobbyWImpl_SetConnectionSettings
1415 ( LPDIRECTPLAYLOBBY iface,
1418 LPDPLCONNECTION lpConn )
1420 ICOM_THIS(IDirectPlayLobbyWImpl,iface);
1423 TRACE("(%p)->(0x%08lx,0x%08lx,%p)\n", This, dwFlags, dwAppID, lpConn );
1425 EnterCriticalSection( &This->unk->DPL_lock );
1427 hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
1429 LeaveCriticalSection( &This->unk->DPL_lock );
1434 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetConnectionSettings
1435 ( LPDIRECTPLAYLOBBYA iface,
1438 LPDPLCONNECTION lpConn )
1440 ICOM_THIS(IDirectPlayLobbyAImpl,iface);
1443 TRACE("(%p)->(0x%08lx,0x%08lx,%p)\n", This, dwFlags, dwAppID, lpConn );
1445 EnterCriticalSection( &This->unk->DPL_lock );
1447 hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
1449 LeaveCriticalSection( &This->unk->DPL_lock );
1454 /********************************************************************
1456 * Registers an event that will be set when a lobby message is received.
1459 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetLobbyMessageEvent
1460 ( LPDIRECTPLAYLOBBYA iface,
1463 HANDLE hReceiveEvent )
1466 return DPERR_OUTOFMEMORY;
1469 static HRESULT WINAPI IDirectPlayLobbyWImpl_SetLobbyMessageEvent
1470 ( LPDIRECTPLAYLOBBY iface,
1473 HANDLE hReceiveEvent )
1476 return DPERR_OUTOFMEMORY;
1482 /********************************************************************
1484 * Registers an event that will be set when a lobby message is received.
1487 static HRESULT WINAPI IDirectPlayLobby2WImpl_CreateCompoundAddress
1488 ( LPDIRECTPLAYLOBBY2 iface,
1489 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1490 DWORD dwElementCount,
1492 LPDWORD lpdwAddressSize )
1494 return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, FALSE );
1497 static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateCompoundAddress
1498 ( LPDIRECTPLAYLOBBY2A iface,
1499 LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1500 DWORD dwElementCount,
1502 LPDWORD lpdwAddressSize )
1504 return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, TRUE );
1507 static HRESULT DPL_CreateCompoundAddress
1508 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements,
1509 DWORD dwElementCount,
1511 LPDWORD lpdwAddressSize,
1512 BOOL bAnsiInterface )
1514 DWORD dwSizeRequired = 0;
1516 LPCDPCOMPOUNDADDRESSELEMENT lpOrigElements = lpElements;
1518 TRACE("(%p,0x%08lx,%p,%p)\n", lpElements, dwElementCount, lpAddress, lpdwAddressSize );
1520 /* Parameter check */
1521 if( ( lpElements == NULL ) ||
1522 ( dwElementCount == 0 ) /* FIXME: Not sure if this is a failure case */
1525 return DPERR_INVALIDPARAMS;
1528 /* Add the total size chunk */
1529 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DWORD );
1531 /* Calculate the size of the buffer required */
1532 for ( dwElements = dwElementCount; dwElements > 0; --dwElements, ++lpElements )
1534 if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
1535 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
1538 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( GUID );
1540 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
1541 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
1542 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
1545 if( !bAnsiInterface )
1547 ERR( "Ansi GUIDs used for unicode interface\n" );
1548 return DPERR_INVALIDFLAGS;
1551 dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize;
1553 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
1554 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
1555 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
1558 if( bAnsiInterface )
1560 ERR( "Unicode GUIDs used for ansi interface\n" );
1561 return DPERR_INVALIDFLAGS;
1564 FIXME( "Right size for unicode interface?\n" );
1565 dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize * sizeof( WCHAR );
1567 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
1569 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( WORD );
1571 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
1573 FIXME( "Right size for unicode interface?\n" );
1574 dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DPCOMPORTADDRESS ); /* FIXME: Right size? */
1578 char lpGUIDString[51];
1579 WINE_StringFromCLSID( &lpElements->guidDataType, &lpGUIDString[0] );
1581 ERR( "Unknown GUID %s\n", &lpGUIDString[0] );
1583 return DPERR_INVALIDFLAGS;
1587 /* The user wants to know how big a buffer to allocate for us */
1588 if( ( lpAddress == NULL ) ||
1589 ( *lpdwAddressSize < dwSizeRequired )
1592 *lpdwAddressSize = dwSizeRequired;
1593 return DPERR_BUFFERTOOSMALL;
1596 /* Add the total size chunk */
1598 LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
1600 lpdpAddress->guidDataType = DPAID_TotalSize;
1601 lpdpAddress->dwDataSize = sizeof( DWORD );
1602 lpAddress += sizeof( DPADDRESS );
1604 *(LPDWORD)lpAddress = dwSizeRequired;
1605 lpAddress += sizeof( DWORD );
1608 /* Calculate the size of the buffer required */
1609 for( dwElements = dwElementCount, lpElements = lpOrigElements;
1611 --dwElements, ++lpElements )
1613 if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
1614 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
1617 LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
1619 lpdpAddress->guidDataType = lpElements->guidDataType;
1620 lpdpAddress->dwDataSize = sizeof( GUID );
1621 lpAddress += sizeof( DPADDRESS );
1623 *((LPGUID)lpAddress) = *((LPGUID)lpElements->lpData);
1624 lpAddress += sizeof( GUID );
1626 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
1627 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
1628 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
1631 LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
1633 lpdpAddress->guidDataType = lpElements->guidDataType;
1634 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1635 lpAddress += sizeof( DPADDRESS );
1637 lstrcpynA( (LPSTR)lpAddress,
1638 (LPCSTR)lpElements->lpData,
1639 lpElements->dwDataSize );
1640 lpAddress += lpElements->dwDataSize;
1642 else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
1643 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
1644 ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
1647 LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
1649 lpdpAddress->guidDataType = lpElements->guidDataType;
1650 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1651 lpAddress += sizeof( DPADDRESS );
1653 lstrcpynW( (LPWSTR)lpAddress,
1654 (LPCWSTR)lpElements->lpData,
1655 lpElements->dwDataSize );
1656 lpAddress += lpElements->dwDataSize * sizeof( WCHAR );
1658 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
1660 LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
1662 lpdpAddress->guidDataType = lpElements->guidDataType;
1663 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1664 lpAddress += sizeof( DPADDRESS );
1666 *((LPWORD)lpAddress) = *((LPWORD)lpElements->lpData);
1667 lpAddress += sizeof( WORD );
1669 else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
1671 LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
1673 lpdpAddress->guidDataType = lpElements->guidDataType;
1674 lpdpAddress->dwDataSize = lpElements->dwDataSize;
1675 lpAddress += sizeof( DPADDRESS );
1677 memcpy( lpAddress, lpElements->lpData, sizeof( DPADDRESS ) );
1678 lpAddress += sizeof( DPADDRESS );
1687 static HRESULT WINAPI IDirectPlayLobby3WImpl_ConnectEx
1688 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, REFIID riid, LPVOID* lplpDP, IUnknown* pUnk )
1694 static HRESULT WINAPI IDirectPlayLobby3AImpl_ConnectEx
1695 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, REFIID riid, LPVOID* lplpDP, IUnknown* pUnk )
1701 static HRESULT WINAPI IDirectPlayLobby3WImpl_RegisterApplication
1702 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, LPDPAPPLICATIONDESC lpAppDesc )
1708 static HRESULT WINAPI IDirectPlayLobby3AImpl_RegisterApplication
1709 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, LPDPAPPLICATIONDESC lpAppDesc )
1715 static HRESULT WINAPI IDirectPlayLobby3WImpl_UnregisterApplication
1716 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, REFGUID lpAppDesc )
1722 static HRESULT WINAPI IDirectPlayLobby3AImpl_UnregisterApplication
1723 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, REFGUID lpAppDesc )
1729 static HRESULT WINAPI IDirectPlayLobby3WImpl_WaitForConnectionSettings
1730 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags )
1736 static HRESULT WINAPI IDirectPlayLobby3AImpl_WaitForConnectionSettings
1737 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags )
1744 /* Virtual Table definitions for DPL{1,2,3}{A,W} */
1746 /* Note: Hack so we can reuse the old functions without compiler warnings */
1747 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1748 # define XCAST(fun) (typeof(directPlayLobbyAVT.fn##fun))
1750 # define XCAST(fun) (void*)
1753 /* Direct Play Lobby 1 (ascii) Virtual Table for methods */
1754 /* All lobby 1 methods are exactly the same except QueryInterface */
1755 static struct ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyAVT =
1757 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1759 IDirectPlayLobbyAImpl_QueryInterface,
1760 XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
1761 XCAST(Release)IDirectPlayLobbyAImpl_Release,
1763 IDirectPlayLobbyAImpl_Connect,
1764 IDirectPlayLobbyAImpl_CreateAddress,
1765 IDirectPlayLobbyAImpl_EnumAddress,
1766 IDirectPlayLobbyAImpl_EnumAddressTypes,
1767 IDirectPlayLobbyAImpl_EnumLocalApplications,
1768 IDirectPlayLobbyAImpl_GetConnectionSettings,
1769 IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
1770 IDirectPlayLobbyAImpl_RunApplication,
1771 IDirectPlayLobbyAImpl_SendLobbyMessage,
1772 IDirectPlayLobbyAImpl_SetConnectionSettings,
1773 IDirectPlayLobbyAImpl_SetLobbyMessageEvent
1778 /* Note: Hack so we can reuse the old functions without compiler warnings */
1779 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1780 # define XCAST(fun) (typeof(directPlayLobbyWVT.fn##fun))
1782 # define XCAST(fun) (void*)
1785 /* Direct Play Lobby 1 (unicode) Virtual Table for methods */
1786 static ICOM_VTABLE(IDirectPlayLobby) directPlayLobbyWVT =
1788 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1790 IDirectPlayLobbyW_QueryInterface,
1791 XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
1792 XCAST(Release)IDirectPlayLobbyAImpl_Release,
1794 IDirectPlayLobbyWImpl_Connect,
1795 IDirectPlayLobbyWImpl_CreateAddress,
1796 IDirectPlayLobbyWImpl_EnumAddress,
1797 IDirectPlayLobbyWImpl_EnumAddressTypes,
1798 IDirectPlayLobbyWImpl_EnumLocalApplications,
1799 IDirectPlayLobbyWImpl_GetConnectionSettings,
1800 IDirectPlayLobbyWImpl_ReceiveLobbyMessage,
1801 IDirectPlayLobbyWImpl_RunApplication,
1802 IDirectPlayLobbyWImpl_SendLobbyMessage,
1803 IDirectPlayLobbyWImpl_SetConnectionSettings,
1804 IDirectPlayLobbyWImpl_SetLobbyMessageEvent
1808 /* Note: Hack so we can reuse the old functions without compiler warnings */
1809 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1810 # define XCAST(fun) (typeof(directPlayLobby2AVT.fn##fun))
1812 # define XCAST(fun) (void*)
1815 /* Direct Play Lobby 2 (ascii) Virtual Table for methods */
1816 static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2AVT =
1818 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1820 IDirectPlayLobby2AImpl_QueryInterface,
1821 XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
1822 XCAST(Release)IDirectPlayLobbyAImpl_Release,
1824 XCAST(Connect)IDirectPlayLobbyAImpl_Connect,
1825 XCAST(CreateAddress)IDirectPlayLobbyAImpl_CreateAddress,
1826 XCAST(EnumAddress)IDirectPlayLobbyAImpl_EnumAddress,
1827 XCAST(EnumAddressTypes)IDirectPlayLobbyAImpl_EnumAddressTypes,
1828 XCAST(EnumLocalApplications)IDirectPlayLobbyAImpl_EnumLocalApplications,
1829 XCAST(GetConnectionSettings)IDirectPlayLobbyAImpl_GetConnectionSettings,
1830 XCAST(ReceiveLobbyMessage)IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
1831 XCAST(RunApplication)IDirectPlayLobbyAImpl_RunApplication,
1832 XCAST(SendLobbyMessage)IDirectPlayLobbyAImpl_SendLobbyMessage,
1833 XCAST(SetConnectionSettings)IDirectPlayLobbyAImpl_SetConnectionSettings,
1834 XCAST(SetLobbyMessageEvent)IDirectPlayLobbyAImpl_SetLobbyMessageEvent,
1836 IDirectPlayLobby2AImpl_CreateCompoundAddress
1840 /* Note: Hack so we can reuse the old functions without compiler warnings */
1841 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1842 # define XCAST(fun) (typeof(directPlayLobby2AVT.fn##fun))
1844 # define XCAST(fun) (void*)
1847 /* Direct Play Lobby 2 (unicode) Virtual Table for methods */
1848 static ICOM_VTABLE(IDirectPlayLobby2) directPlayLobby2WVT =
1850 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1852 IDirectPlayLobby2WImpl_QueryInterface,
1853 XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
1854 XCAST(Release)IDirectPlayLobbyAImpl_Release,
1856 XCAST(Connect)IDirectPlayLobbyWImpl_Connect,
1857 XCAST(CreateAddress)IDirectPlayLobbyWImpl_CreateAddress,
1858 XCAST(EnumAddress)IDirectPlayLobbyWImpl_EnumAddress,
1859 XCAST(EnumAddressTypes)IDirectPlayLobbyWImpl_EnumAddressTypes,
1860 XCAST(EnumLocalApplications)IDirectPlayLobbyWImpl_EnumLocalApplications,
1861 XCAST(GetConnectionSettings)IDirectPlayLobbyWImpl_GetConnectionSettings,
1862 XCAST(ReceiveLobbyMessage)IDirectPlayLobbyWImpl_ReceiveLobbyMessage,
1863 XCAST(RunApplication)IDirectPlayLobbyWImpl_RunApplication,
1864 XCAST(SendLobbyMessage)IDirectPlayLobbyWImpl_SendLobbyMessage,
1865 XCAST(SetConnectionSettings)IDirectPlayLobbyWImpl_SetConnectionSettings,
1866 XCAST(SetLobbyMessageEvent)IDirectPlayLobbyWImpl_SetLobbyMessageEvent,
1868 IDirectPlayLobby2WImpl_CreateCompoundAddress
1872 /* Direct Play Lobby 3 (ascii) Virtual Table for methods */
1874 /* Note: Hack so we can reuse the old functions without compiler warnings */
1875 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1876 # define XCAST(fun) (typeof(directPlayLobby3AVT.fn##fun))
1878 # define XCAST(fun) (void*)
1881 static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3AVT =
1883 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1884 IDirectPlayLobby3AImpl_QueryInterface,
1885 XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
1886 XCAST(Release)IDirectPlayLobbyAImpl_Release,
1888 XCAST(Connect)IDirectPlayLobbyAImpl_Connect,
1889 XCAST(CreateAddress)IDirectPlayLobbyAImpl_CreateAddress,
1890 XCAST(EnumAddress)IDirectPlayLobbyAImpl_EnumAddress,
1891 XCAST(EnumAddressTypes)IDirectPlayLobbyAImpl_EnumAddressTypes,
1892 XCAST(EnumLocalApplications)IDirectPlayLobbyAImpl_EnumLocalApplications,
1893 XCAST(GetConnectionSettings)IDirectPlayLobbyAImpl_GetConnectionSettings,
1894 XCAST(ReceiveLobbyMessage)IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
1895 XCAST(RunApplication)IDirectPlayLobbyAImpl_RunApplication,
1896 XCAST(SendLobbyMessage)IDirectPlayLobbyAImpl_SendLobbyMessage,
1897 XCAST(SetConnectionSettings)IDirectPlayLobbyAImpl_SetConnectionSettings,
1898 XCAST(SetLobbyMessageEvent)IDirectPlayLobbyAImpl_SetLobbyMessageEvent,
1900 XCAST(CreateCompoundAddress)IDirectPlayLobby2AImpl_CreateCompoundAddress,
1902 IDirectPlayLobby3AImpl_ConnectEx,
1903 IDirectPlayLobby3AImpl_RegisterApplication,
1904 IDirectPlayLobby3AImpl_UnregisterApplication,
1905 IDirectPlayLobby3AImpl_WaitForConnectionSettings
1909 /* Direct Play Lobby 3 (unicode) Virtual Table for methods */
1911 /* Note: Hack so we can reuse the old functions without compiler warnings */
1912 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1913 # define XCAST(fun) (typeof(directPlayLobby3WVT.fn##fun))
1915 # define XCAST(fun) (void*)
1918 static ICOM_VTABLE(IDirectPlayLobby3) directPlayLobby3WVT =
1920 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1921 IDirectPlayLobby3WImpl_QueryInterface,
1922 XCAST(AddRef)IDirectPlayLobbyImpl_AddRef,
1923 XCAST(Release)IDirectPlayLobbyAImpl_Release,
1925 XCAST(Connect)IDirectPlayLobbyWImpl_Connect,
1926 XCAST(CreateAddress)IDirectPlayLobbyWImpl_CreateAddress,
1927 XCAST(EnumAddress)IDirectPlayLobbyWImpl_EnumAddress,
1928 XCAST(EnumAddressTypes)IDirectPlayLobbyWImpl_EnumAddressTypes,
1929 XCAST(EnumLocalApplications)IDirectPlayLobbyWImpl_EnumLocalApplications,
1930 XCAST(GetConnectionSettings)IDirectPlayLobbyWImpl_GetConnectionSettings,
1931 XCAST(ReceiveLobbyMessage)IDirectPlayLobbyWImpl_ReceiveLobbyMessage,
1932 XCAST(RunApplication)IDirectPlayLobbyWImpl_RunApplication,
1933 XCAST(SendLobbyMessage)IDirectPlayLobbyWImpl_SendLobbyMessage,
1934 XCAST(SetConnectionSettings)IDirectPlayLobbyWImpl_SetConnectionSettings,
1935 XCAST(SetLobbyMessageEvent)IDirectPlayLobbyWImpl_SetLobbyMessageEvent,
1937 XCAST(CreateCompoundAddress)IDirectPlayLobby2WImpl_CreateCompoundAddress,
1939 IDirectPlayLobby3WImpl_ConnectEx,
1940 IDirectPlayLobby3WImpl_RegisterApplication,
1941 IDirectPlayLobby3WImpl_UnregisterApplication,
1942 IDirectPlayLobby3WImpl_WaitForConnectionSettings
1947 /*********************************************************
1949 * Direct Play and Direct Play Lobby Interface Implementation
1951 *********************************************************/
1953 /***************************************************************************
1954 * DirectPlayLobbyCreateA (DPLAYX.4)
1957 HRESULT WINAPI DirectPlayLobbyCreateA( LPGUID lpGUIDDSP,
1958 LPDIRECTPLAYLOBBYA *lplpDPL,
1963 TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\n",
1964 lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
1966 /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
1967 * equal 0. These fields are mostly for future expansion.
1969 if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
1972 return DPERR_INVALIDPARAMS;
1975 return directPlayLobby_QueryInterface( &IID_IDirectPlayLobbyA, (void**)lplpDPL );
1978 /***************************************************************************
1979 * DirectPlayLobbyCreateW (DPLAYX.5)
1982 HRESULT WINAPI DirectPlayLobbyCreateW( LPGUID lpGUIDDSP,
1983 LPDIRECTPLAYLOBBY *lplpDPL,
1988 TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\n",
1989 lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
1991 /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
1992 * equal 0. These fields are mostly for future expansion.
1994 if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
1997 ERR("Bad parameters!\n" );
1998 return DPERR_INVALIDPARAMS;
2001 return directPlayLobby_QueryInterface( &IID_IDirectPlayLobby, (void**)lplpDPL );