ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dplobby.c
Go to the documentation of this file.
00001 /* Direct Play Lobby 2 & 3 Implementation
00002  *
00003  * Copyright 1998,1999,2000 - Peter Hunnisett
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 #include <stdarg.h>
00020 #include <string.h>
00021 
00022 #define NONAMELESSUNION
00023 #define NONAMELESSSTRUCT
00024 #include "windef.h"
00025 #include "winbase.h"
00026 #include "winerror.h"
00027 #include "winreg.h"
00028 #include "winnls.h"
00029 #include "wine/debug.h"
00030 
00031 #include "dplayx_global.h"
00032 #include "dplayx_messages.h"
00033 #include "dplayx_queue.h"
00034 #include "dplobby.h"
00035 #include "dpinit.h"
00036 
00037 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
00038 
00039 /*****************************************************************************
00040  * Predeclare the interface implementation structures
00041  */
00042 typedef struct IDirectPlayLobbyImpl  IDirectPlayLobbyAImpl;
00043 typedef struct IDirectPlayLobbyImpl  IDirectPlayLobbyWImpl;
00044 typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2AImpl;
00045 typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2WImpl;
00046 typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3AImpl;
00047 typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3WImpl;
00048 
00049 /* Forward declarations for this module helper methods */
00050 HRESULT DPL_CreateCompoundAddress ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
00051                                     LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
00052 
00053 HRESULT DPL_CreateAddress( REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData, DWORD dwDataSize,
00054                            LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
00055 
00056 
00057 
00058 extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
00059                                 DWORD dwAddressSize, LPVOID lpContext );
00060 
00061 static HRESULT WINAPI DPL_ConnectEx( IDirectPlayLobbyAImpl* This,
00062                                      DWORD dwFlags, REFIID riid,
00063                                      LPVOID* lplpDP, IUnknown* pUnk );
00064 
00065 BOOL DPL_CreateAndSetLobbyHandles( DWORD dwDestProcessId, HANDLE hDestProcess,
00066                                    LPHANDLE lphStart, LPHANDLE lphDeath,
00067                                    LPHANDLE lphRead );
00068 
00069 
00070 /*****************************************************************************
00071  * IDirectPlayLobby {1,2,3} implementation structure
00072  *
00073  * The philosophy behind this extra pointer dereference is that I wanted to
00074  * have the same structure for all types of objects without having to do
00075  * a lot of casting. I also only wanted to implement an interface in the
00076  * object it was "released" with IUnknown interface being implemented in the 1 version.
00077  * Of course, with these new interfaces comes the data required to keep the state required
00078  * by these interfaces. So, basically, the pointers contain the data associated with
00079  * a release. If you use the data associated with release 3 in a release 2 object, you'll
00080  * get a run time trap, as that won't have any data.
00081  *
00082  */
00083 struct DPLMSG
00084 {
00085   DPQ_ENTRY( DPLMSG ) msgs;  /* Link to next queued message */
00086 };
00087 typedef struct DPLMSG* LPDPLMSG;
00088 
00089 typedef struct tagDirectPlayLobbyIUnknownData
00090 {
00091   LONG              ulObjRef;
00092   CRITICAL_SECTION  DPL_lock;
00093 } DirectPlayLobbyIUnknownData;
00094 
00095 typedef struct tagDirectPlayLobbyData
00096 {
00097   HKEY  hkCallbackKeyHack;
00098   DWORD dwMsgThread;
00099   DPQ_HEAD( DPLMSG ) msgs;  /* List of messages received */
00100 } DirectPlayLobbyData;
00101 
00102 typedef struct tagDirectPlayLobby2Data
00103 {
00104   BOOL dummy;
00105 } DirectPlayLobby2Data;
00106 
00107 typedef struct tagDirectPlayLobby3Data
00108 {
00109   BOOL dummy;
00110 } DirectPlayLobby3Data;
00111 
00112 #define DPL_IMPL_FIELDS \
00113  LONG ulInterfaceRef; \
00114  DirectPlayLobbyIUnknownData*  unk; \
00115  DirectPlayLobbyData*          dpl; \
00116  DirectPlayLobby2Data*         dpl2; \
00117  DirectPlayLobby3Data*         dpl3;
00118 
00119 struct IDirectPlayLobbyImpl
00120 {
00121     const IDirectPlayLobbyVtbl *lpVtbl;
00122     DPL_IMPL_FIELDS
00123 };
00124 
00125 struct IDirectPlayLobby2Impl
00126 {
00127     const IDirectPlayLobby2Vtbl *lpVtbl;
00128     DPL_IMPL_FIELDS
00129 };
00130 
00131 struct IDirectPlayLobby3Impl
00132 {
00133     const IDirectPlayLobby3Vtbl *lpVtbl;
00134     DPL_IMPL_FIELDS
00135 };
00136 
00137 /* Forward declarations of virtual tables */
00138 static const IDirectPlayLobbyVtbl  directPlayLobbyWVT;
00139 static const IDirectPlayLobby2Vtbl directPlayLobby2WVT;
00140 static const IDirectPlayLobby3Vtbl directPlayLobby3WVT;
00141 
00142 static const IDirectPlayLobbyVtbl  directPlayLobbyAVT;
00143 static const IDirectPlayLobby2Vtbl directPlayLobby2AVT;
00144 static const IDirectPlayLobby3Vtbl directPlayLobby3AVT;
00145 
00146 static BOOL DPL_CreateIUnknown( LPVOID lpDPL )
00147 {
00148   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
00149 
00150   This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
00151   if ( This->unk == NULL )
00152   {
00153     return FALSE;
00154   }
00155 
00156   InitializeCriticalSection( &This->unk->DPL_lock );
00157 
00158   return TRUE;
00159 }
00160 
00161 static BOOL DPL_DestroyIUnknown( LPVOID lpDPL )
00162 {
00163   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
00164 
00165   DeleteCriticalSection( &This->unk->DPL_lock );
00166   HeapFree( GetProcessHeap(), 0, This->unk );
00167 
00168   return TRUE;
00169 }
00170 
00171 static BOOL DPL_CreateLobby1( LPVOID lpDPL )
00172 {
00173   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
00174 
00175   This->dpl = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dpl) ) );
00176   if ( This->dpl == NULL )
00177   {
00178     return FALSE;
00179   }
00180 
00181   DPQ_INIT( This->dpl->msgs );
00182 
00183   return TRUE;
00184 }
00185 
00186 static BOOL DPL_DestroyLobby1( LPVOID lpDPL )
00187 {
00188   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
00189 
00190   if( This->dpl->dwMsgThread )
00191   {
00192     FIXME( "Should kill the msg thread\n" );
00193   }
00194 
00195   DPQ_DELETEQ( This->dpl->msgs, msgs, LPDPLMSG, cbDeleteElemFromHeap );
00196 
00197   /* Delete the contents */
00198   HeapFree( GetProcessHeap(), 0, This->dpl );
00199 
00200   return TRUE;
00201 }
00202 
00203 static BOOL DPL_CreateLobby2( LPVOID lpDPL )
00204 {
00205   IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)lpDPL;
00206 
00207   This->dpl2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dpl2) ) );
00208   if ( This->dpl2 == NULL )
00209   {
00210     return FALSE;
00211   }
00212 
00213   return TRUE;
00214 }
00215 
00216 static BOOL DPL_DestroyLobby2( LPVOID lpDPL )
00217 {
00218   IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)lpDPL;
00219 
00220   HeapFree( GetProcessHeap(), 0, This->dpl2 );
00221 
00222   return TRUE;
00223 }
00224 
00225 static BOOL DPL_CreateLobby3( LPVOID lpDPL )
00226 {
00227   IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)lpDPL;
00228 
00229   This->dpl3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dpl3) ) );
00230   if ( This->dpl3 == NULL )
00231   {
00232     return FALSE;
00233   }
00234 
00235   return TRUE;
00236 }
00237 
00238 static BOOL DPL_DestroyLobby3( LPVOID lpDPL )
00239 {
00240   IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)lpDPL;
00241 
00242   HeapFree( GetProcessHeap(), 0, This->dpl3 );
00243 
00244   return TRUE;
00245 }
00246 
00247 
00248 /* The COM interface for upversioning an interface
00249  * We've been given a GUID (riid) and we need to replace the present
00250  * interface with that of the requested interface.
00251  *
00252  * Snip from some Microsoft document:
00253  * There are four requirements for implementations of QueryInterface (In these
00254  * cases, "must succeed" means "must succeed barring catastrophic failure."):
00255  *
00256  *  * The set of interfaces accessible on an object through
00257  *    IUnknown::QueryInterface must be static, not dynamic. This means that
00258  *    if a call to QueryInterface for a pointer to a specified interface
00259  *    succeeds the first time, it must succeed again, and if it fails the
00260  *    first time, it must fail on all subsequent queries.
00261  *  * It must be symmetric ~W if a client holds a pointer to an interface on
00262  *    an object, and queries for that interface, the call must succeed.
00263  *  * It must be reflexive ~W if a client holding a pointer to one interface
00264  *    queries successfully for another, a query through the obtained pointer
00265  *    for the first interface must succeed.
00266  *  * It must be transitive ~W if a client holding a pointer to one interface
00267  *    queries successfully for a second, and through that pointer queries
00268  *    successfully for a third interface, a query for the first interface
00269  *    through the pointer for the third interface must succeed.
00270  */
00271 extern
00272 HRESULT DPL_CreateInterface
00273          ( REFIID riid, LPVOID* ppvObj )
00274 {
00275   TRACE( " for %s\n", debugstr_guid( riid ) );
00276 
00277   *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
00278                        sizeof( IDirectPlayLobbyWImpl ) );
00279 
00280   if( *ppvObj == NULL )
00281   {
00282     return DPERR_OUTOFMEMORY;
00283   }
00284 
00285   if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
00286   {
00287     IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)*ppvObj;
00288     This->lpVtbl = &directPlayLobbyWVT;
00289   }
00290   else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
00291   {
00292     IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)*ppvObj;
00293     This->lpVtbl = &directPlayLobbyAVT;
00294   }
00295   else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
00296   {
00297     IDirectPlayLobby2WImpl *This = (IDirectPlayLobby2WImpl *)*ppvObj;
00298     This->lpVtbl = &directPlayLobby2WVT;
00299   }
00300   else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
00301   {
00302     IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)*ppvObj;
00303     This->lpVtbl = &directPlayLobby2AVT;
00304   }
00305   else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
00306   {
00307     IDirectPlayLobby3WImpl *This = (IDirectPlayLobby3WImpl *)*ppvObj;
00308     This->lpVtbl = &directPlayLobby3WVT;
00309   }
00310   else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
00311   {
00312     IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)*ppvObj;
00313     This->lpVtbl = &directPlayLobby3AVT;
00314   }
00315   else
00316   {
00317     /* Unsupported interface */
00318     HeapFree( GetProcessHeap(), 0, *ppvObj );
00319     *ppvObj = NULL;
00320 
00321     return E_NOINTERFACE;
00322   }
00323 
00324   /* Initialize it */
00325   if ( DPL_CreateIUnknown( *ppvObj ) &&
00326        DPL_CreateLobby1( *ppvObj ) &&
00327        DPL_CreateLobby2( *ppvObj ) &&
00328        DPL_CreateLobby3( *ppvObj )
00329      )
00330   {
00331     IDirectPlayLobby_AddRef( (LPDIRECTPLAYLOBBY)*ppvObj );
00332     return S_OK;
00333   }
00334 
00335   /* Initialize failed, destroy it */
00336   DPL_DestroyLobby3( *ppvObj );
00337   DPL_DestroyLobby2( *ppvObj );
00338   DPL_DestroyLobby1( *ppvObj );
00339   DPL_DestroyIUnknown( *ppvObj );
00340   HeapFree( GetProcessHeap(), 0, *ppvObj );
00341 
00342   *ppvObj = NULL;
00343   return DPERR_NOMEMORY;
00344 }
00345 
00346 static HRESULT WINAPI DPL_QueryInterface
00347 ( LPDIRECTPLAYLOBBYA iface,
00348   REFIID riid,
00349   LPVOID* ppvObj )
00350 {
00351   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
00352   TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
00353 
00354   *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
00355                        sizeof( *This ) );
00356 
00357   if( *ppvObj == NULL )
00358   {
00359     return DPERR_OUTOFMEMORY;
00360   }
00361 
00362   CopyMemory( *ppvObj, This, sizeof( *This )  );
00363   (*(IDirectPlayLobbyAImpl**)ppvObj)->ulInterfaceRef = 0;
00364 
00365   if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
00366   {
00367     IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)*ppvObj;
00368     This->lpVtbl = &directPlayLobbyWVT;
00369   }
00370   else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
00371   {
00372     IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)*ppvObj;
00373     This->lpVtbl = &directPlayLobbyAVT;
00374   }
00375   else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
00376   {
00377     IDirectPlayLobby2WImpl *This = (IDirectPlayLobby2WImpl *)*ppvObj;
00378     This->lpVtbl = &directPlayLobby2WVT;
00379   }
00380   else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
00381   {
00382     IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)*ppvObj;
00383     This->lpVtbl = &directPlayLobby2AVT;
00384   }
00385   else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
00386   {
00387     IDirectPlayLobby3WImpl *This = (IDirectPlayLobby3WImpl *)*ppvObj;
00388     This->lpVtbl = &directPlayLobby3WVT;
00389   }
00390   else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
00391   {
00392     IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)*ppvObj;
00393     This->lpVtbl = &directPlayLobby3AVT;
00394   }
00395   else
00396   {
00397     /* Unsupported interface */
00398     HeapFree( GetProcessHeap(), 0, *ppvObj );
00399     *ppvObj = NULL;
00400 
00401     return E_NOINTERFACE;
00402   }
00403 
00404   IDirectPlayLobby_AddRef( (LPDIRECTPLAYLOBBY)*ppvObj );
00405 
00406   return S_OK;
00407 }
00408 
00409 /*
00410  * Simple procedure. Just increment the reference count to this
00411  * structure and return the new reference count.
00412  */
00413 static ULONG WINAPI DPL_AddRef
00414 ( LPDIRECTPLAYLOBBY iface )
00415 {
00416   ULONG ulInterfaceRefCount, ulObjRefCount;
00417   IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
00418 
00419   ulObjRefCount       = InterlockedIncrement( &This->unk->ulObjRef );
00420   ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
00421 
00422   TRACE( "ref count incremented to %lu:%lu for %p\n",
00423          ulInterfaceRefCount, ulObjRefCount, This );
00424 
00425   return ulObjRefCount;
00426 }
00427 
00428 /*
00429  * Simple COM procedure. Decrease the reference count to this object.
00430  * If the object no longer has any reference counts, free up the associated
00431  * memory.
00432  */
00433 static ULONG WINAPI DPL_Release
00434 ( LPDIRECTPLAYLOBBYA iface )
00435 {
00436   ULONG ulInterfaceRefCount, ulObjRefCount;
00437   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
00438 
00439   ulObjRefCount       = InterlockedDecrement( &This->unk->ulObjRef );
00440   ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
00441 
00442   TRACE( "ref count decremented to %lu:%lu for %p\n",
00443          ulInterfaceRefCount, ulObjRefCount, This );
00444 
00445   /* Deallocate if this is the last reference to the object */
00446   if( ulObjRefCount == 0 )
00447   {
00448      DPL_DestroyLobby3( This );
00449      DPL_DestroyLobby2( This );
00450      DPL_DestroyLobby1( This );
00451      DPL_DestroyIUnknown( This );
00452   }
00453 
00454   if( ulInterfaceRefCount == 0 )
00455   {
00456     HeapFree( GetProcessHeap(), 0, This );
00457   }
00458 
00459   return ulInterfaceRefCount;
00460 }
00461 
00462 
00463 /********************************************************************
00464  *
00465  * Connects an application to the session specified by the DPLCONNECTION
00466  * structure currently stored with the DirectPlayLobby object.
00467  *
00468  * Returns an IDirectPlay interface.
00469  *
00470  */
00471 static HRESULT WINAPI DPL_ConnectEx
00472 ( IDirectPlayLobbyAImpl* This,
00473   DWORD     dwFlags,
00474   REFIID    riid,
00475   LPVOID*   lplpDP,
00476   IUnknown* pUnk)
00477 {
00478   HRESULT         hr;
00479   DWORD           dwOpenFlags = 0;
00480   DWORD           dwConnSize = 0;
00481   LPDPLCONNECTION lpConn;
00482 
00483   FIXME("(%p)->(0x%08lx,%p,%p): semi stub\n", This, dwFlags, lplpDP, pUnk );
00484 
00485   if( pUnk )
00486   {
00487      return DPERR_INVALIDPARAMS;
00488   }
00489 
00490   /* Backwards compatibility */
00491   if( dwFlags == 0 )
00492   {
00493     dwFlags = DPCONNECT_RETURNSTATUS;
00494   }
00495 
00496   /* Create the DirectPlay interface */
00497   if( ( hr = DP_CreateInterface( riid, lplpDP ) ) != DP_OK )
00498   {
00499      ERR( "error creating interface for %s:%s.\n",
00500           debugstr_guid( riid ), DPLAYX_HresultToString( hr ) );
00501      return hr;
00502   }
00503 
00504   /* FIXME: Is it safe/correct to use appID of 0? */
00505   hr = IDirectPlayLobby_GetConnectionSettings( (LPDIRECTPLAYLOBBY)This,
00506                                                0, NULL, &dwConnSize );
00507   if( hr != DPERR_BUFFERTOOSMALL )
00508   {
00509     return hr;
00510   }
00511 
00512   lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwConnSize );
00513 
00514   if( lpConn == NULL )
00515   {
00516     return DPERR_NOMEMORY;
00517   }
00518 
00519   /* FIXME: Is it safe/correct to use appID of 0? */
00520   hr = IDirectPlayLobby_GetConnectionSettings( (LPDIRECTPLAYLOBBY)This,
00521                                                0, lpConn, &dwConnSize );
00522   if( FAILED( hr ) )
00523   {
00524     HeapFree( GetProcessHeap(), 0, lpConn );
00525     return hr;
00526   }
00527 
00528 #if 0
00529   /* - Need to call IDirectPlay::EnumConnections with the service provider to get that good information
00530    * - Need to call CreateAddress to create the lpConnection param for IDirectPlay::InitializeConnection
00531    * - Call IDirectPlay::InitializeConnection
00532    */
00533 
00534   /* Now initialize the Service Provider */
00535   hr = IDirectPlayX_InitializeConnection( (*(LPDIRECTPLAY2*)lplpDP),
00536 #endif
00537 
00538 
00539   /* Setup flags to pass into DirectPlay::Open */
00540   if( dwFlags & DPCONNECT_RETURNSTATUS )
00541   {
00542     dwOpenFlags |= DPOPEN_RETURNSTATUS;
00543   }
00544   dwOpenFlags |= lpConn->dwFlags;
00545 
00546   hr = IDirectPlayX_Open( (*(LPDIRECTPLAY2*)lplpDP), lpConn->lpSessionDesc,
00547                           dwOpenFlags );
00548 
00549   HeapFree( GetProcessHeap(), 0, lpConn );
00550 
00551   return hr;
00552 }
00553 
00554 static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect
00555 ( LPDIRECTPLAYLOBBYA iface,
00556   DWORD dwFlags,
00557   LPDIRECTPLAY2A* lplpDP,
00558   IUnknown* pUnk)
00559 {
00560   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
00561   return DPL_ConnectEx( This, dwFlags, &IID_IDirectPlay2A,
00562                         (LPVOID)lplpDP, pUnk );
00563 }
00564 
00565 static HRESULT WINAPI IDirectPlayLobbyWImpl_Connect
00566 ( LPDIRECTPLAYLOBBY iface,
00567   DWORD dwFlags,
00568   LPDIRECTPLAY2* lplpDP,
00569   IUnknown* pUnk)
00570 {
00571   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface; /* Yes cast to A */
00572   return DPL_ConnectEx( This, dwFlags, &IID_IDirectPlay2,
00573                         (LPVOID)lplpDP, pUnk );
00574 }
00575 
00576 /********************************************************************
00577  *
00578  * Creates a DirectPlay Address, given a service provider-specific network
00579  * address.
00580  * Returns an address contains the globally unique identifier
00581  * (GUID) of the service provider and data that the service provider can
00582  * interpret as a network address.
00583  *
00584  * NOTE: It appears that this method is supposed to be really really stupid
00585  *       with no error checking on the contents.
00586  */
00587 static HRESULT WINAPI IDirectPlayLobbyAImpl_CreateAddress
00588 ( LPDIRECTPLAYLOBBYA iface,
00589   REFGUID guidSP,
00590   REFGUID guidDataType,
00591   LPCVOID lpData,
00592   DWORD dwDataSize,
00593   LPVOID lpAddress,
00594   LPDWORD lpdwAddressSize )
00595 {
00596   return DPL_CreateAddress( guidSP, guidDataType, lpData, dwDataSize,
00597                             lpAddress, lpdwAddressSize, TRUE );
00598 }
00599 
00600 static HRESULT WINAPI IDirectPlayLobbyWImpl_CreateAddress
00601 ( LPDIRECTPLAYLOBBY iface,
00602   REFGUID guidSP,
00603   REFGUID guidDataType,
00604   LPCVOID lpData,
00605   DWORD dwDataSize,
00606   LPVOID lpAddress,
00607   LPDWORD lpdwAddressSize )
00608 {
00609   return DPL_CreateAddress( guidSP, guidDataType, lpData, dwDataSize,
00610                             lpAddress, lpdwAddressSize, FALSE );
00611 }
00612 
00613 HRESULT DPL_CreateAddress(
00614   REFGUID guidSP,
00615   REFGUID guidDataType,
00616   LPCVOID lpData,
00617   DWORD dwDataSize,
00618   LPVOID lpAddress,
00619   LPDWORD lpdwAddressSize,
00620   BOOL bAnsiInterface )
00621 {
00622   const DWORD dwNumAddElements = 2; /* Service Provide & address data type */
00623   DPCOMPOUNDADDRESSELEMENT addressElements[ 2 /* dwNumAddElements */ ];
00624 
00625   TRACE( "(%p)->(%p,%p,0x%08lx,%p,%p,%d)\n", guidSP, guidDataType, lpData, dwDataSize,
00626                                              lpAddress, lpdwAddressSize, bAnsiInterface );
00627 
00628   addressElements[ 0 ].guidDataType = DPAID_ServiceProvider;
00629   addressElements[ 0 ].dwDataSize = sizeof( GUID );
00630   addressElements[ 0 ].lpData = (LPVOID)guidSP;
00631 
00632   addressElements[ 1 ].guidDataType = *guidDataType;
00633   addressElements[ 1 ].dwDataSize = dwDataSize;
00634   addressElements[ 1 ].lpData = (LPVOID)lpData;
00635 
00636   /* Call CreateCompoundAddress to cut down on code.
00637      NOTE: We can do this because we don't support DPL 1 interfaces! */
00638   return DPL_CreateCompoundAddress( addressElements, dwNumAddElements,
00639                                     lpAddress, lpdwAddressSize, bAnsiInterface );
00640 }
00641 
00642 
00643 
00644 /********************************************************************
00645  *
00646  * Parses out chunks from the DirectPlay Address buffer by calling the
00647  * given callback function, with lpContext, for each of the chunks.
00648  *
00649  */
00650 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddress
00651 ( LPDIRECTPLAYLOBBYA iface,
00652   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
00653   LPCVOID lpAddress,
00654   DWORD dwAddressSize,
00655   LPVOID lpContext )
00656 {
00657   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
00658 
00659   TRACE("(%p)->(%p,%p,0x%08lx,%p)\n", This, lpEnumAddressCallback, lpAddress,
00660                                       dwAddressSize, lpContext );
00661 
00662   return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
00663 }
00664 
00665 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumAddress
00666 ( LPDIRECTPLAYLOBBY iface,
00667   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
00668   LPCVOID lpAddress,
00669   DWORD dwAddressSize,
00670   LPVOID lpContext )
00671 {
00672   IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
00673 
00674   TRACE("(%p)->(%p,%p,0x%08lx,%p)\n", This, lpEnumAddressCallback, lpAddress,
00675                                       dwAddressSize, lpContext );
00676 
00677   return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
00678 }
00679 
00680 extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
00681                                 DWORD dwAddressSize, LPVOID lpContext )
00682 {
00683   DWORD dwTotalSizeEnumerated = 0;
00684 
00685   /* FIXME: First chunk is always the total size chunk - Should we report it? */
00686 
00687   while ( dwTotalSizeEnumerated < dwAddressSize )
00688   {
00689     const DPADDRESS* lpElements = (const DPADDRESS*)lpAddress;
00690     DWORD dwSizeThisEnumeration;
00691 
00692     /* Invoke the enum method. If false is returned, stop enumeration */
00693     if ( !lpEnumAddressCallback( &lpElements->guidDataType,
00694                                  lpElements->dwDataSize,
00695                                  (BYTE*)lpElements + sizeof( DPADDRESS ),
00696                                  lpContext ) )
00697     {
00698       break;
00699     }
00700 
00701     dwSizeThisEnumeration  = sizeof( DPADDRESS ) + lpElements->dwDataSize;
00702     lpAddress = (const BYTE*) lpAddress + dwSizeThisEnumeration;
00703     dwTotalSizeEnumerated += dwSizeThisEnumeration;
00704   }
00705 
00706   return DP_OK;
00707 }
00708 
00709 /********************************************************************
00710  *
00711  * Enumerates all the address types that a given service provider needs to
00712  * build the DirectPlay Address.
00713  *
00714  */
00715 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddressTypes
00716 ( LPDIRECTPLAYLOBBYA iface,
00717   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
00718   REFGUID guidSP,
00719   LPVOID lpContext,
00720   DWORD dwFlags )
00721 {
00722   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
00723 
00724   HKEY   hkResult;
00725   LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
00726   DWORD  dwIndex, sizeOfSubKeyName=50;
00727   char   subKeyName[51];
00728   FILETIME filetime;
00729 
00730   TRACE(" (%p)->(%p,%p,%p,0x%08lx)\n", This, lpEnumAddressTypeCallback, guidSP, lpContext, dwFlags );
00731 
00732   if( dwFlags != 0 )
00733   {
00734     return DPERR_INVALIDPARAMS;
00735   }
00736 
00737   if( !lpEnumAddressTypeCallback || !*lpEnumAddressTypeCallback )
00738   {
00739      return DPERR_INVALIDPARAMS;
00740   }
00741 
00742   if( guidSP == NULL )
00743   {
00744     return DPERR_INVALIDOBJECT;
00745   }
00746 
00747     /* Need to loop over the service providers in the registry */
00748     if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
00749                          0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
00750     {
00751       /* Hmmm. Does this mean that there are no service providers? */
00752       ERR(": no service providers?\n");
00753       return DP_OK;
00754     }
00755 
00756     /* Traverse all the service providers we have available */
00757     for( dwIndex=0;
00758          RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
00759                         NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
00760          ++dwIndex, sizeOfSubKeyName=50 )
00761     {
00762 
00763       HKEY     hkServiceProvider, hkServiceProviderAt;
00764       GUID     serviceProviderGUID;
00765       DWORD    returnTypeGUID, sizeOfReturnBuffer = 50;
00766       char     atSubKey[51];
00767       char     returnBuffer[51];
00768       WCHAR    buff[51];
00769       DWORD    dwAtIndex;
00770       LPCSTR   atKey = "Address Types";
00771       LPCSTR   guidDataSubKey   = "Guid";
00772       FILETIME filetime;
00773 
00774 
00775       TRACE(" this time through: %s\n", subKeyName );
00776 
00777       /* Get a handle for this particular service provider */
00778       if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
00779                          &hkServiceProvider ) != ERROR_SUCCESS )
00780       {
00781          ERR(": what the heck is going on?\n" );
00782          continue;
00783       }
00784 
00785       if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
00786                             NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
00787                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
00788       {
00789         ERR(": missing GUID registry data members\n" );
00790         continue;
00791       }
00792 
00793       /* FIXME: Check return types to ensure we're interpreting data right */
00794       MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
00795       CLSIDFromString( buff, &serviceProviderGUID );
00796       /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
00797 
00798       /* Determine if this is the Service Provider that the user asked for */
00799       if( !IsEqualGUID( &serviceProviderGUID, guidSP ) )
00800       {
00801         continue;
00802       }
00803 
00804       /* Get a handle for this particular service provider */
00805       if( RegOpenKeyExA( hkServiceProvider, atKey, 0, KEY_READ,
00806                          &hkServiceProviderAt ) != ERROR_SUCCESS )
00807       {
00808         TRACE(": No Address Types registry data sub key/members\n" );
00809         break;
00810       }
00811 
00812       /* Traverse all the address type we have available */
00813       for( dwAtIndex=0;
00814            RegEnumKeyExA( hkServiceProviderAt, dwAtIndex, atSubKey, &sizeOfSubKeyName,
00815                           NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
00816            ++dwAtIndex, sizeOfSubKeyName=50 )
00817       {
00818         TRACE( "Found Address Type GUID %s\n", atSubKey );
00819 
00820         /* FIXME: Check return types to ensure we're interpreting data right */
00821         MultiByteToWideChar( CP_ACP, 0, atSubKey, -1, buff, sizeof(buff)/sizeof(WCHAR) );
00822         CLSIDFromString( buff, &serviceProviderGUID );
00823         /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
00824 
00825         /* The enumeration will return FALSE if we are not to continue */
00826         if( !lpEnumAddressTypeCallback( &serviceProviderGUID, lpContext, 0 ) )
00827         {
00828            WARN("lpEnumCallback returning FALSE\n" );
00829            break; /* FIXME: This most likely has to break from the procedure...*/
00830         }
00831 
00832       }
00833 
00834       /* We only enumerate address types for 1 GUID. We've found it, so quit looking */
00835       break;
00836     }
00837 
00838   return DP_OK;
00839 }
00840 
00841 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumAddressTypes
00842 ( LPDIRECTPLAYLOBBY iface,
00843   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
00844   REFGUID guidSP,
00845   LPVOID lpContext,
00846   DWORD dwFlags )
00847 {
00848   FIXME(":stub\n");
00849   return DPERR_OUTOFMEMORY;
00850 }
00851 
00852 /********************************************************************
00853  *
00854  * Enumerates what applications are registered with DirectPlay by
00855  * invoking the callback function with lpContext.
00856  *
00857  */
00858 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumLocalApplications
00859 ( LPDIRECTPLAYLOBBY iface,
00860   LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback,
00861   LPVOID lpContext,
00862   DWORD dwFlags )
00863 {
00864   IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
00865 
00866   FIXME("(%p)->(%p,%p,0x%08lx):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
00867 
00868   return DPERR_OUTOFMEMORY;
00869 }
00870 
00871 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumLocalApplications
00872 ( LPDIRECTPLAYLOBBYA iface,
00873   LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback,
00874   LPVOID lpContext,
00875   DWORD dwFlags )
00876 {
00877   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
00878 
00879   HKEY hkResult;
00880   LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Applications";
00881   LPCSTR guidDataSubKey  = "Guid";
00882   DWORD dwIndex, sizeOfSubKeyName=50;
00883   char subKeyName[51];
00884   FILETIME filetime;
00885 
00886   TRACE("(%p)->(%p,%p,0x%08lx)\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
00887 
00888   if( dwFlags != 0 )
00889   {
00890     return DPERR_INVALIDPARAMS;
00891   }
00892 
00893   if( !lpEnumLocalAppCallback || !*lpEnumLocalAppCallback )
00894   {
00895      return DPERR_INVALIDPARAMS;
00896   }
00897 
00898   /* Need to loop over the service providers in the registry */
00899   if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
00900                      0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
00901   {
00902     /* Hmmm. Does this mean that there are no service providers? */
00903     ERR(": no service providers?\n");
00904     return DP_OK;
00905   }
00906 
00907   /* Traverse all registered applications */
00908   for( dwIndex=0;
00909        RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
00910        ++dwIndex, sizeOfSubKeyName=50 )
00911   {
00912 
00913     HKEY       hkServiceProvider;
00914     GUID       serviceProviderGUID;
00915     DWORD      returnTypeGUID, sizeOfReturnBuffer = 50;
00916     char       returnBuffer[51];
00917     WCHAR      buff[51];
00918     DPLAPPINFO dplAppInfo;
00919 
00920     TRACE(" this time through: %s\n", subKeyName );
00921 
00922     /* Get a handle for this particular service provider */
00923     if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
00924                        &hkServiceProvider ) != ERROR_SUCCESS )
00925     {
00926        ERR(": what the heck is going on?\n" );
00927        continue;
00928     }
00929 
00930     if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
00931                           NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
00932                           &sizeOfReturnBuffer ) != ERROR_SUCCESS )
00933     {
00934       ERR(": missing GUID registry data members\n" );
00935       continue;
00936     }
00937 
00938     /* FIXME: Check return types to ensure we're interpreting data right */
00939     MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
00940     CLSIDFromString( buff, &serviceProviderGUID );
00941     /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
00942 
00943     dplAppInfo.dwSize               = sizeof( dplAppInfo );
00944     dplAppInfo.guidApplication      = serviceProviderGUID;
00945     dplAppInfo.u.lpszAppNameA = subKeyName;
00946 
00947     EnterCriticalSection( &This->unk->DPL_lock );
00948 
00949     memcpy( &This->dpl->hkCallbackKeyHack, &hkServiceProvider, sizeof( hkServiceProvider ) );
00950 
00951     if( !lpEnumLocalAppCallback( &dplAppInfo, lpContext, dwFlags ) )
00952     {
00953        LeaveCriticalSection( &This->unk->DPL_lock );
00954        break;
00955     }
00956 
00957     LeaveCriticalSection( &This->unk->DPL_lock );
00958   }
00959 
00960   return DP_OK;
00961 }
00962 
00963 /********************************************************************
00964  *
00965  * Retrieves the DPLCONNECTION structure that contains all the information
00966  * needed to start and connect an application. This was generated using
00967  * either the RunApplication or SetConnectionSettings methods.
00968  *
00969  * NOTES: If lpData is NULL then just return lpdwDataSize. This allows
00970  *        the data structure to be allocated by our caller which can then
00971  *        call this procedure/method again with a valid data pointer.
00972  */
00973 static HRESULT WINAPI IDirectPlayLobbyAImpl_GetConnectionSettings
00974 ( LPDIRECTPLAYLOBBYA iface,
00975   DWORD dwAppID,
00976   LPVOID lpData,
00977   LPDWORD lpdwDataSize )
00978 {
00979   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
00980   HRESULT hr;
00981 
00982   TRACE("(%p)->(0x%08lx,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
00983 
00984   EnterCriticalSection( &This->unk->DPL_lock );
00985 
00986   hr = DPLAYX_GetConnectionSettingsA( dwAppID,
00987                                       lpData,
00988                                       lpdwDataSize
00989                                     );
00990 
00991   LeaveCriticalSection( &This->unk->DPL_lock );
00992 
00993   return hr;
00994 }
00995 
00996 static HRESULT WINAPI IDirectPlayLobbyWImpl_GetConnectionSettings
00997 ( LPDIRECTPLAYLOBBY iface,
00998   DWORD dwAppID,
00999   LPVOID lpData,
01000   LPDWORD lpdwDataSize )
01001 {
01002   IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
01003   HRESULT hr;
01004 
01005   TRACE("(%p)->(0x%08lx,%p,%p)\n", This, dwAppID, lpData, lpdwDataSize );
01006 
01007   EnterCriticalSection( &This->unk->DPL_lock );
01008 
01009   hr = DPLAYX_GetConnectionSettingsW( dwAppID,
01010                                       lpData,
01011                                       lpdwDataSize
01012                                     );
01013 
01014   LeaveCriticalSection( &This->unk->DPL_lock );
01015 
01016   return hr;
01017 }
01018 
01019 /********************************************************************
01020  *
01021  * Retrieves the message sent between a lobby client and a DirectPlay
01022  * application. All messages are queued until received.
01023  *
01024  */
01025 static HRESULT WINAPI IDirectPlayLobbyAImpl_ReceiveLobbyMessage
01026 ( LPDIRECTPLAYLOBBYA iface,
01027   DWORD dwFlags,
01028   DWORD dwAppID,
01029   LPDWORD lpdwMessageFlags,
01030   LPVOID lpData,
01031   LPDWORD lpdwDataSize )
01032 {
01033   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
01034   FIXME(":stub %p %08lx %08lx %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
01035          lpdwDataSize );
01036   return DPERR_OUTOFMEMORY;
01037 }
01038 
01039 static HRESULT WINAPI IDirectPlayLobbyWImpl_ReceiveLobbyMessage
01040 ( LPDIRECTPLAYLOBBY iface,
01041   DWORD dwFlags,
01042   DWORD dwAppID,
01043   LPDWORD lpdwMessageFlags,
01044   LPVOID lpData,
01045   LPDWORD lpdwDataSize )
01046 {
01047   IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
01048   FIXME(":stub %p %08lx %08lx %p %p %p\n", This, dwFlags, dwAppID, lpdwMessageFlags, lpData,
01049          lpdwDataSize );
01050   return DPERR_OUTOFMEMORY;
01051 }
01052 
01053 typedef struct tagRunApplicationEnumStruct
01054 {
01055   IDirectPlayLobbyAImpl* This;
01056 
01057   GUID  appGUID;
01058   LPSTR lpszPath;
01059   LPSTR lpszFileName;
01060   LPSTR lpszCommandLine;
01061   LPSTR lpszCurrentDirectory;
01062 } RunApplicationEnumStruct, *lpRunApplicationEnumStruct;
01063 
01064 /* To be called by RunApplication to find how to invoke the function */
01065 static BOOL CALLBACK RunApplicationA_EnumLocalApplications
01066 ( LPCDPLAPPINFO   lpAppInfo,
01067   LPVOID          lpContext,
01068   DWORD           dwFlags )
01069 {
01070   lpRunApplicationEnumStruct lpData = (lpRunApplicationEnumStruct)lpContext;
01071 
01072   if( IsEqualGUID( &lpAppInfo->guidApplication, &lpData->appGUID ) )
01073   {
01074     char  returnBuffer[200];
01075     DWORD returnType, sizeOfReturnBuffer;
01076     LPCSTR clSubKey   = "CommandLine";
01077     LPCSTR cdSubKey   = "CurrentDirectory";
01078     LPCSTR fileSubKey = "File";
01079     LPCSTR pathSubKey = "Path";
01080 
01081     /* FIXME: Lazy man hack - dplay struct has the present reg key saved */
01082 
01083     sizeOfReturnBuffer = 200;
01084 
01085     /* Get all the appropriate data from the registry */
01086     if( RegQueryValueExA( lpData->This->dpl->hkCallbackKeyHack, clSubKey,
01087                           NULL, &returnType, (LPBYTE)returnBuffer,
01088                           &sizeOfReturnBuffer ) != ERROR_SUCCESS )
01089     {
01090        ERR( ": missing CommandLine registry data member\n" );
01091     }
01092     else
01093     {
01094         if ((lpData->lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
01095             strcpy( lpData->lpszCommandLine, returnBuffer );
01096     }
01097 
01098     sizeOfReturnBuffer = 200;
01099 
01100     if( RegQueryValueExA( lpData->This->dpl->hkCallbackKeyHack, cdSubKey,
01101                           NULL, &returnType, (LPBYTE)returnBuffer,
01102                           &sizeOfReturnBuffer ) != ERROR_SUCCESS )
01103     {
01104        ERR( ": missing CurrentDirectory registry data member\n" );
01105     }
01106     else
01107     {
01108         if ((lpData->lpszCurrentDirectory = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
01109             strcpy( lpData->lpszCurrentDirectory, returnBuffer );
01110     }
01111 
01112     sizeOfReturnBuffer = 200;
01113 
01114     if( RegQueryValueExA( lpData->This->dpl->hkCallbackKeyHack, fileSubKey,
01115                           NULL, &returnType, (LPBYTE)returnBuffer,
01116                           &sizeOfReturnBuffer ) != ERROR_SUCCESS )
01117     {
01118        ERR( ": missing File registry data member\n" );
01119     }
01120     else
01121     {
01122         if ((lpData->lpszFileName = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
01123             strcpy( lpData->lpszFileName, returnBuffer );
01124     }
01125 
01126     sizeOfReturnBuffer = 200;
01127 
01128     if( RegQueryValueExA( lpData->This->dpl->hkCallbackKeyHack, pathSubKey,
01129                           NULL, &returnType, (LPBYTE)returnBuffer,
01130                           &sizeOfReturnBuffer ) != ERROR_SUCCESS )
01131     {
01132        ERR( ": missing Path registry data member\n" );
01133     }
01134     else
01135     {
01136         if ((lpData->lpszPath = HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
01137             strcpy( lpData->lpszPath, returnBuffer );
01138     }
01139 
01140     return FALSE; /* No need to keep going as we found what we wanted */
01141   }
01142 
01143   return TRUE; /* Keep enumerating, haven't found the application yet */
01144 }
01145 
01146 BOOL DPL_CreateAndSetLobbyHandles( DWORD dwDestProcessId, HANDLE hDestProcess,
01147                                    LPHANDLE lphStart, LPHANDLE lphDeath,
01148                                    LPHANDLE lphRead )
01149 {
01150   /* These are the handles for the created process */
01151   HANDLE hAppStart = 0, hAppDeath = 0, hAppRead  = 0;
01152   SECURITY_ATTRIBUTES s_attrib;
01153 
01154   s_attrib.nLength              = sizeof( s_attrib );
01155   s_attrib.lpSecurityDescriptor = NULL;
01156   s_attrib.bInheritHandle       = TRUE;
01157 
01158   *lphStart = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
01159   *lphDeath = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
01160   *lphRead  = CreateEventW( &s_attrib, TRUE, FALSE, NULL );
01161 
01162   if( ( !DuplicateHandle( GetCurrentProcess(), *lphStart,
01163                           hDestProcess, &hAppStart,
01164                           0, FALSE, DUPLICATE_SAME_ACCESS ) ) ||
01165       ( !DuplicateHandle( GetCurrentProcess(), *lphDeath,
01166                           hDestProcess, &hAppDeath,
01167                           0, FALSE, DUPLICATE_SAME_ACCESS ) ) ||
01168       ( !DuplicateHandle( GetCurrentProcess(), *lphRead,
01169                           hDestProcess, &hAppRead,
01170                           0, FALSE, DUPLICATE_SAME_ACCESS ) )
01171     )
01172   {
01173     if (*lphStart) { CloseHandle(*lphStart); *lphStart = 0; }
01174     if (*lphDeath) { CloseHandle(*lphDeath); *lphDeath = 0; }
01175     if (*lphRead)  { CloseHandle(*lphRead);  *lphRead  = 0; }
01176     /* FIXME: Handle leak... */
01177     ERR( "Unable to dup handles\n" );
01178     return FALSE;
01179   }
01180 
01181   if( !DPLAYX_SetLobbyHandles( dwDestProcessId,
01182                                hAppStart, hAppDeath, hAppRead ) )
01183   {
01184     /* FIXME: Handle leak... */
01185     return FALSE;
01186   }
01187 
01188   return TRUE;
01189 }
01190 
01191 
01192 /********************************************************************
01193  *
01194  * Starts an application and passes to it all the information to
01195  * connect to a session.
01196  *
01197  */
01198 static HRESULT WINAPI IDirectPlayLobbyAImpl_RunApplication
01199 ( LPDIRECTPLAYLOBBYA iface,
01200   DWORD dwFlags,
01201   LPDWORD lpdwAppID,
01202   LPDPLCONNECTION lpConn,
01203   HANDLE hReceiveEvent )
01204 {
01205   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
01206   HRESULT hr;
01207   RunApplicationEnumStruct enumData;
01208   char temp[200];
01209   STARTUPINFOA startupInfo;
01210   PROCESS_INFORMATION newProcessInfo;
01211   LPSTR appName;
01212   DWORD dwSuspendCount;
01213   HANDLE hStart, hDeath, hSettingRead;
01214 
01215   TRACE( "(%p)->(0x%08lx,%p,%p,%p)\n",
01216          This, dwFlags, lpdwAppID, lpConn, hReceiveEvent );
01217 
01218   if( dwFlags != 0 )
01219   {
01220     return DPERR_INVALIDPARAMS;
01221   }
01222 
01223   if( DPLAYX_AnyLobbiesWaitingForConnSettings() )
01224   {
01225     FIXME( "Waiting lobby not being handled correctly\n" );
01226   }
01227 
01228   EnterCriticalSection( &This->unk->DPL_lock );
01229 
01230   ZeroMemory( &enumData, sizeof( enumData ) );
01231   enumData.This    = This;
01232   enumData.appGUID = lpConn->lpSessionDesc->guidApplication;
01233 
01234   /* Our callback function will fill up the enumData structure with all the information
01235      required to start a new process */
01236   IDirectPlayLobby_EnumLocalApplications( iface, RunApplicationA_EnumLocalApplications,
01237                                           (LPVOID)(&enumData), 0 );
01238 
01239   /* First the application name */
01240   strcpy( temp, enumData.lpszPath );
01241   strcat( temp, "\\" );
01242   strcat( temp, enumData.lpszFileName );
01243   HeapFree( GetProcessHeap(), 0, enumData.lpszPath );
01244   HeapFree( GetProcessHeap(), 0, enumData.lpszFileName );
01245   if ((appName = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 ))) strcpy( appName, temp );
01246 
01247   /* Now the command line */
01248   strcat( temp, " " );
01249   strcat( temp, enumData.lpszCommandLine );
01250   HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
01251   if ((enumData.lpszCommandLine = HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 )))
01252       strcpy( enumData.lpszCommandLine, temp );
01253 
01254   ZeroMemory( &startupInfo, sizeof( startupInfo ) );
01255   startupInfo.cb = sizeof( startupInfo );
01256   /* FIXME: Should any fields be filled in? */
01257 
01258   ZeroMemory( &newProcessInfo, sizeof( newProcessInfo ) );
01259 
01260   if( !CreateProcessA( appName,
01261                        enumData.lpszCommandLine,
01262                        NULL,
01263                        NULL,
01264                        FALSE,
01265                        CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_SUSPENDED, /* Creation Flags */
01266                        NULL,
01267                        enumData.lpszCurrentDirectory,
01268                        &startupInfo,
01269                        &newProcessInfo
01270                      )
01271     )
01272   {
01273     ERR( "Failed to create process for app %s\n", appName );
01274 
01275     HeapFree( GetProcessHeap(), 0, appName );
01276     HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
01277     HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
01278 
01279     LeaveCriticalSection( &This->unk->DPL_lock );
01280     return DPERR_CANTCREATEPROCESS;
01281   }
01282 
01283   HeapFree( GetProcessHeap(), 0, appName );
01284   HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
01285   HeapFree( GetProcessHeap(), 0, enumData.lpszCurrentDirectory );
01286 
01287   /* Reserve this global application id! */
01288   if( !DPLAYX_CreateLobbyApplication( newProcessInfo.dwProcessId ) )
01289   {
01290     ERR( "Unable to create global application data for 0x%08lx\n",
01291            newProcessInfo.dwProcessId );
01292   }
01293 
01294   hr = IDirectPlayLobby_SetConnectionSettings( iface, 0, newProcessInfo.dwProcessId, lpConn );
01295 
01296   if( hr != DP_OK )
01297   {
01298     ERR( "SetConnectionSettings failure %s\n", DPLAYX_HresultToString( hr ) );
01299     LeaveCriticalSection( &This->unk->DPL_lock );
01300     return hr;
01301   }
01302 
01303   /* Setup the handles for application notification */
01304   DPL_CreateAndSetLobbyHandles( newProcessInfo.dwProcessId,
01305                                 newProcessInfo.hProcess,
01306                                 &hStart, &hDeath, &hSettingRead );
01307 
01308   /* Setup the message thread ID */
01309   This->dpl->dwMsgThread =
01310     CreateLobbyMessageReceptionThread( hReceiveEvent, hStart, hDeath, hSettingRead );
01311 
01312   DPLAYX_SetLobbyMsgThreadId( newProcessInfo.dwProcessId, This->dpl->dwMsgThread );
01313 
01314   LeaveCriticalSection( &This->unk->DPL_lock );
01315 
01316   /* Everything seems to have been set correctly, update the dwAppID */
01317   *lpdwAppID = newProcessInfo.dwProcessId;
01318 
01319   /* Unsuspend the process - should return the prev suspension count */
01320   if( ( dwSuspendCount = ResumeThread( newProcessInfo.hThread ) ) != 1 )
01321   {
01322     ERR( "ResumeThread failed with 0x%08lx\n", dwSuspendCount );
01323   }
01324 
01325   return DP_OK;
01326 }
01327 
01328 static HRESULT WINAPI IDirectPlayLobbyWImpl_RunApplication
01329 ( LPDIRECTPLAYLOBBY iface,
01330   DWORD dwFlags,
01331   LPDWORD lpdwAppID,
01332   LPDPLCONNECTION lpConn,
01333   HANDLE hReceiveEvent )
01334 {
01335   IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
01336   FIXME( "(%p)->(0x%08lx,%p,%p,%p):stub\n", This, dwFlags, lpdwAppID, lpConn, (void *)hReceiveEvent );
01337   return DPERR_OUTOFMEMORY;
01338 }
01339 
01340 /********************************************************************
01341  *
01342  * Sends a message between the application and the lobby client.
01343  * All messages are queued until received.
01344  *
01345  */
01346 static HRESULT WINAPI IDirectPlayLobbyAImpl_SendLobbyMessage
01347 ( LPDIRECTPLAYLOBBYA iface,
01348   DWORD dwFlags,
01349   DWORD dwAppID,
01350   LPVOID lpData,
01351   DWORD dwDataSize )
01352 {
01353   FIXME(":stub\n");
01354   return DPERR_OUTOFMEMORY;
01355 }
01356 
01357 static HRESULT WINAPI IDirectPlayLobbyWImpl_SendLobbyMessage
01358 ( LPDIRECTPLAYLOBBY iface,
01359   DWORD dwFlags,
01360   DWORD dwAppID,
01361   LPVOID lpData,
01362   DWORD dwDataSize )
01363 {
01364   FIXME(":stub\n");
01365   return DPERR_OUTOFMEMORY;
01366 }
01367 
01368 /********************************************************************
01369  *
01370  * Modifies the DPLCONNECTION structure to contain all information
01371  * needed to start and connect an application.
01372  *
01373  */
01374 static HRESULT WINAPI IDirectPlayLobbyWImpl_SetConnectionSettings
01375 ( LPDIRECTPLAYLOBBY iface,
01376   DWORD dwFlags,
01377   DWORD dwAppID,
01378   LPDPLCONNECTION lpConn )
01379 {
01380   IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
01381   HRESULT hr;
01382 
01383   TRACE("(%p)->(0x%08lx,0x%08lx,%p)\n", This, dwFlags, dwAppID, lpConn );
01384 
01385   EnterCriticalSection( &This->unk->DPL_lock );
01386 
01387   hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
01388 
01389   /* FIXME: Don't think that this is supposed to fail, but the docuementation
01390             is somewhat sketchy. I'll try creating a lobby application
01391             for this... */
01392   if( hr == DPERR_NOTLOBBIED )
01393   {
01394     FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
01395     if( dwAppID == 0 )
01396     {
01397        dwAppID = GetCurrentProcessId();
01398     }
01399     DPLAYX_CreateLobbyApplication( dwAppID );
01400     hr = DPLAYX_SetConnectionSettingsW( dwFlags, dwAppID, lpConn );
01401   }
01402 
01403   LeaveCriticalSection( &This->unk->DPL_lock );
01404 
01405   return hr;
01406 }
01407 
01408 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetConnectionSettings
01409 ( LPDIRECTPLAYLOBBYA iface,
01410   DWORD dwFlags,
01411   DWORD dwAppID,
01412   LPDPLCONNECTION lpConn )
01413 {
01414   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
01415   HRESULT hr;
01416 
01417   TRACE("(%p)->(0x%08lx,0x%08lx,%p)\n", This, dwFlags, dwAppID, lpConn );
01418 
01419   EnterCriticalSection( &This->unk->DPL_lock );
01420 
01421   hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
01422 
01423   /* FIXME: Don't think that this is supposed to fail, but the docuementation
01424             is somewhat sketchy. I'll try creating a lobby application
01425             for this... */
01426   if( hr == DPERR_NOTLOBBIED )
01427   {
01428     FIXME( "Unlobbied app setting connections. Is this correct behavior?\n" );
01429     dwAppID = GetCurrentProcessId();
01430     DPLAYX_CreateLobbyApplication( dwAppID );
01431     hr = DPLAYX_SetConnectionSettingsA( dwFlags, dwAppID, lpConn );
01432   }
01433 
01434   LeaveCriticalSection( &This->unk->DPL_lock );
01435 
01436   return hr;
01437 }
01438 
01439 /********************************************************************
01440  *
01441  * Registers an event that will be set when a lobby message is received.
01442  *
01443  */
01444 static HRESULT WINAPI IDirectPlayLobbyAImpl_SetLobbyMessageEvent
01445 ( LPDIRECTPLAYLOBBYA iface,
01446   DWORD dwFlags,
01447   DWORD dwAppID,
01448   HANDLE hReceiveEvent )
01449 {
01450   FIXME(":stub\n");
01451   return DPERR_OUTOFMEMORY;
01452 }
01453 
01454 static HRESULT WINAPI IDirectPlayLobbyWImpl_SetLobbyMessageEvent
01455 ( LPDIRECTPLAYLOBBY iface,
01456   DWORD dwFlags,
01457   DWORD dwAppID,
01458   HANDLE hReceiveEvent )
01459 {
01460   FIXME(":stub\n");
01461   return DPERR_OUTOFMEMORY;
01462 }
01463 
01464 
01465 /* DPL 2 methods */
01466 static HRESULT WINAPI IDirectPlayLobby2WImpl_CreateCompoundAddress
01467 ( LPDIRECTPLAYLOBBY2 iface,
01468   LPCDPCOMPOUNDADDRESSELEMENT lpElements,
01469   DWORD dwElementCount,
01470   LPVOID lpAddress,
01471   LPDWORD lpdwAddressSize )
01472 {
01473   return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, FALSE );
01474 }
01475 
01476 static HRESULT WINAPI IDirectPlayLobby2AImpl_CreateCompoundAddress
01477 ( LPDIRECTPLAYLOBBY2A iface,
01478   LPCDPCOMPOUNDADDRESSELEMENT lpElements,
01479   DWORD dwElementCount,
01480   LPVOID lpAddress,
01481   LPDWORD lpdwAddressSize )
01482 {
01483   return DPL_CreateCompoundAddress( lpElements, dwElementCount, lpAddress, lpdwAddressSize, TRUE );
01484 }
01485 
01486 HRESULT DPL_CreateCompoundAddress
01487 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements,
01488   DWORD dwElementCount,
01489   LPVOID lpAddress,
01490   LPDWORD lpdwAddressSize,
01491   BOOL bAnsiInterface )
01492 {
01493   DWORD dwSizeRequired = 0;
01494   DWORD dwElements;
01495   LPCDPCOMPOUNDADDRESSELEMENT lpOrigElements = lpElements;
01496 
01497   TRACE("(%p,0x%08lx,%p,%p)\n", lpElements, dwElementCount, lpAddress, lpdwAddressSize );
01498 
01499   /* Parameter check */
01500   if( ( lpElements == NULL ) ||
01501       ( dwElementCount == 0 )   /* FIXME: Not sure if this is a failure case */
01502     )
01503   {
01504     return DPERR_INVALIDPARAMS;
01505   }
01506 
01507   /* Add the total size chunk */
01508   dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DWORD );
01509 
01510   /* Calculate the size of the buffer required */
01511   for ( dwElements = dwElementCount; dwElements > 0; --dwElements, ++lpElements )
01512   {
01513     if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
01514          ( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
01515        )
01516     {
01517       dwSizeRequired += sizeof( DPADDRESS ) + sizeof( GUID );
01518     }
01519     else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
01520               ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
01521               ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
01522             )
01523     {
01524       if( !bAnsiInterface )
01525       {
01526         ERR( "Ansi GUIDs used for unicode interface\n" );
01527         return DPERR_INVALIDFLAGS;
01528       }
01529 
01530       dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize;
01531     }
01532     else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
01533               ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
01534               ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
01535             )
01536     {
01537       if( bAnsiInterface )
01538       {
01539         ERR( "Unicode GUIDs used for ansi interface\n" );
01540         return DPERR_INVALIDFLAGS;
01541       }
01542 
01543       FIXME( "Right size for unicode interface?\n" );
01544       dwSizeRequired += sizeof( DPADDRESS ) + lpElements->dwDataSize * sizeof( WCHAR );
01545     }
01546     else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
01547     {
01548       dwSizeRequired += sizeof( DPADDRESS ) + sizeof( WORD );
01549     }
01550     else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
01551     {
01552       FIXME( "Right size for unicode interface?\n" );
01553       dwSizeRequired += sizeof( DPADDRESS ) + sizeof( DPCOMPORTADDRESS ); /* FIXME: Right size? */
01554     }
01555     else
01556     {
01557       ERR( "Unknown GUID %s\n", debugstr_guid(&lpElements->guidDataType) );
01558       return DPERR_INVALIDFLAGS;
01559     }
01560   }
01561 
01562   /* The user wants to know how big a buffer to allocate for us */
01563   if( ( lpAddress == NULL ) ||
01564       ( *lpdwAddressSize < dwSizeRequired )
01565     )
01566   {
01567     *lpdwAddressSize = dwSizeRequired;
01568     return DPERR_BUFFERTOOSMALL;
01569   }
01570 
01571   /* Add the total size chunk */
01572   {
01573     LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
01574 
01575     CopyMemory( &lpdpAddress->guidDataType, &DPAID_TotalSize, sizeof( GUID ) );
01576     lpdpAddress->dwDataSize = sizeof( DWORD );
01577     lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
01578 
01579     *(LPDWORD)lpAddress = dwSizeRequired;
01580     lpAddress = (char *) lpAddress + sizeof( DWORD );
01581   }
01582 
01583   /* Calculate the size of the buffer required */
01584   for( dwElements = dwElementCount, lpElements = lpOrigElements;
01585        dwElements > 0;
01586        --dwElements, ++lpElements )
01587   {
01588     if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ServiceProvider ) ) ||
01589          ( IsEqualGUID( &lpElements->guidDataType, &DPAID_LobbyProvider ) )
01590        )
01591     {
01592       LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
01593 
01594       CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
01595                   sizeof( GUID ) );
01596       lpdpAddress->dwDataSize = sizeof( GUID );
01597       lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
01598 
01599       CopyMemory( lpAddress, lpElements->lpData, sizeof( GUID ) );
01600       lpAddress = (char *) lpAddress + sizeof( GUID );
01601     }
01602     else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Phone ) ) ||
01603               ( IsEqualGUID( &lpElements->guidDataType, &DPAID_Modem ) ) ||
01604               ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INet ) )
01605             )
01606     {
01607       LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
01608 
01609       CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
01610                   sizeof( GUID ) );
01611       lpdpAddress->dwDataSize = lpElements->dwDataSize;
01612       lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
01613 
01614       lstrcpynA( (LPSTR)lpAddress,
01615                  (LPCSTR)lpElements->lpData,
01616                  lpElements->dwDataSize );
01617       lpAddress = (char *) lpAddress + lpElements->dwDataSize;
01618     }
01619     else if ( ( IsEqualGUID( &lpElements->guidDataType, &DPAID_PhoneW ) ) ||
01620               ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ModemW ) ) ||
01621               ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetW ) )
01622             )
01623     {
01624       LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
01625 
01626       CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
01627                   sizeof( GUID ) );
01628       lpdpAddress->dwDataSize = lpElements->dwDataSize;
01629       lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
01630 
01631       lstrcpynW( (LPWSTR)lpAddress,
01632                  (LPCWSTR)lpElements->lpData,
01633                  lpElements->dwDataSize );
01634       lpAddress = (char *) lpAddress + lpElements->dwDataSize * sizeof( WCHAR );
01635     }
01636     else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_INetPort ) )
01637     {
01638       LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
01639 
01640       CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
01641                   sizeof( GUID ) );
01642       lpdpAddress->dwDataSize = lpElements->dwDataSize;
01643       lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
01644 
01645       *((LPWORD)lpAddress) = *((LPWORD)lpElements->lpData);
01646       lpAddress = (char *) lpAddress + sizeof( WORD );
01647     }
01648     else if ( IsEqualGUID( &lpElements->guidDataType, &DPAID_ComPort ) )
01649     {
01650       LPDPADDRESS lpdpAddress = (LPDPADDRESS)lpAddress;
01651 
01652       CopyMemory( &lpdpAddress->guidDataType, &lpElements->guidDataType,
01653                   sizeof( GUID ) );
01654       lpdpAddress->dwDataSize = lpElements->dwDataSize;
01655       lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
01656 
01657       CopyMemory( lpAddress, lpElements->lpData, sizeof( DPADDRESS ) );
01658       lpAddress = (char *) lpAddress + sizeof( DPADDRESS );
01659     }
01660   }
01661 
01662   return DP_OK;
01663 }
01664 
01665 /* DPL 3 methods */
01666 
01667 static HRESULT WINAPI IDirectPlayLobby3WImpl_ConnectEx
01668 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, REFIID riid,
01669   LPVOID* lplpDP, IUnknown* pUnk )
01670 {
01671   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface ;
01672   return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk );
01673 }
01674 
01675 static HRESULT WINAPI IDirectPlayLobby3AImpl_ConnectEx
01676 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, REFIID riid,
01677   LPVOID* lplpDP, IUnknown* pUnk )
01678 {
01679   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface ;
01680   return DPL_ConnectEx( This, dwFlags, riid, lplpDP, pUnk );
01681 }
01682 
01683 static HRESULT WINAPI IDirectPlayLobby3WImpl_RegisterApplication
01684 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, LPDPAPPLICATIONDESC lpAppDesc )
01685 {
01686   FIXME(":stub\n");
01687   return DP_OK;
01688 }
01689 
01690 static HRESULT WINAPI IDirectPlayLobby3AImpl_RegisterApplication
01691 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, LPDPAPPLICATIONDESC lpAppDesc )
01692 {
01693   FIXME(":stub\n");
01694   return DP_OK;
01695 }
01696 
01697 static HRESULT WINAPI IDirectPlayLobby3WImpl_UnregisterApplication
01698 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags, REFGUID lpAppDesc )
01699 {
01700   FIXME(":stub\n");
01701   return DP_OK;
01702 }
01703 
01704 static HRESULT WINAPI IDirectPlayLobby3AImpl_UnregisterApplication
01705 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags, REFGUID lpAppDesc )
01706 {
01707   FIXME(":stub\n");
01708   return DP_OK;
01709 }
01710 
01711 static HRESULT WINAPI IDirectPlayLobby3WImpl_WaitForConnectionSettings
01712 ( LPDIRECTPLAYLOBBY3 iface, DWORD dwFlags )
01713 {
01714   HRESULT hr         = DP_OK;
01715   BOOL    bStartWait = (dwFlags & DPLWAIT_CANCEL) ? FALSE : TRUE;
01716 
01717   TRACE( "(%p)->(0x%08lx)\n", iface, dwFlags );
01718 
01719   if( DPLAYX_WaitForConnectionSettings( bStartWait ) )
01720   {
01721     /* FIXME: What is the correct error return code? */
01722     hr = DPERR_NOTLOBBIED;
01723   }
01724 
01725   return hr;
01726 }
01727 
01728 static HRESULT WINAPI IDirectPlayLobby3AImpl_WaitForConnectionSettings
01729 ( LPDIRECTPLAYLOBBY3A iface, DWORD dwFlags )
01730 {
01731   HRESULT hr         = DP_OK;
01732   BOOL    bStartWait = (dwFlags & DPLWAIT_CANCEL) ? FALSE : TRUE;
01733 
01734   TRACE( "(%p)->(0x%08lx)\n", iface, dwFlags );
01735 
01736   if( DPLAYX_WaitForConnectionSettings( bStartWait ) )
01737   {
01738     /* FIXME: What is the correct error return code? */
01739     hr = DPERR_NOTLOBBIED;
01740   }
01741 
01742   return hr;
01743 }
01744 
01745 
01746 /* Virtual Table definitions for DPL{1,2,3}{A,W} */
01747 
01748 /* Note: Hack so we can reuse the old functions without compiler warnings */
01749 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
01750 # define XCAST(fun)     (typeof(directPlayLobbyAVT.fun))
01751 #else
01752 # define XCAST(fun)     (void*)
01753 #endif
01754 
01755 /* Direct Play Lobby 1 (ascii) Virtual Table for methods */
01756 /* All lobby 1 methods are exactly the same except QueryInterface */
01757 static const IDirectPlayLobbyVtbl directPlayLobbyAVT =
01758 {
01759 
01760   XCAST(QueryInterface)DPL_QueryInterface,
01761   XCAST(AddRef)DPL_AddRef,
01762   XCAST(Release)DPL_Release,
01763 
01764   IDirectPlayLobbyAImpl_Connect,
01765   IDirectPlayLobbyAImpl_CreateAddress,
01766   IDirectPlayLobbyAImpl_EnumAddress,
01767   IDirectPlayLobbyAImpl_EnumAddressTypes,
01768   IDirectPlayLobbyAImpl_EnumLocalApplications,
01769   IDirectPlayLobbyAImpl_GetConnectionSettings,
01770   IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
01771   IDirectPlayLobbyAImpl_RunApplication,
01772   IDirectPlayLobbyAImpl_SendLobbyMessage,
01773   IDirectPlayLobbyAImpl_SetConnectionSettings,
01774   IDirectPlayLobbyAImpl_SetLobbyMessageEvent
01775 };
01776 #undef XCAST
01777 
01778 
01779 /* Note: Hack so we can reuse the old functions without compiler warnings */
01780 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
01781 # define XCAST(fun)     (typeof(directPlayLobbyWVT.fun))
01782 #else
01783 # define XCAST(fun)     (void*)
01784 #endif
01785 
01786 /* Direct Play Lobby 1 (unicode) Virtual Table for methods */
01787 static const IDirectPlayLobbyVtbl directPlayLobbyWVT =
01788 {
01789 
01790   XCAST(QueryInterface)DPL_QueryInterface,
01791   XCAST(AddRef)DPL_AddRef,
01792   XCAST(Release)DPL_Release,
01793 
01794   IDirectPlayLobbyWImpl_Connect,
01795   IDirectPlayLobbyWImpl_CreateAddress,
01796   IDirectPlayLobbyWImpl_EnumAddress,
01797   IDirectPlayLobbyWImpl_EnumAddressTypes,
01798   IDirectPlayLobbyWImpl_EnumLocalApplications,
01799   IDirectPlayLobbyWImpl_GetConnectionSettings,
01800   IDirectPlayLobbyWImpl_ReceiveLobbyMessage,
01801   IDirectPlayLobbyWImpl_RunApplication,
01802   IDirectPlayLobbyWImpl_SendLobbyMessage,
01803   IDirectPlayLobbyWImpl_SetConnectionSettings,
01804   IDirectPlayLobbyWImpl_SetLobbyMessageEvent
01805 };
01806 #undef XCAST
01807 
01808 /* Note: Hack so we can reuse the old functions without compiler warnings */
01809 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
01810 # define XCAST(fun)     (typeof(directPlayLobby2AVT.fun))
01811 #else
01812 # define XCAST(fun)     (void*)
01813 #endif
01814 
01815 /* Direct Play Lobby 2 (ascii) Virtual Table for methods */
01816 static const IDirectPlayLobby2Vtbl directPlayLobby2AVT =
01817 {
01818 
01819   XCAST(QueryInterface)DPL_QueryInterface,
01820   XCAST(AddRef)DPL_AddRef,
01821   XCAST(Release)DPL_Release,
01822 
01823   XCAST(Connect)IDirectPlayLobbyAImpl_Connect,
01824   XCAST(CreateAddress)IDirectPlayLobbyAImpl_CreateAddress,
01825   XCAST(EnumAddress)IDirectPlayLobbyAImpl_EnumAddress,
01826   XCAST(EnumAddressTypes)IDirectPlayLobbyAImpl_EnumAddressTypes,
01827   XCAST(EnumLocalApplications)IDirectPlayLobbyAImpl_EnumLocalApplications,
01828   XCAST(GetConnectionSettings)IDirectPlayLobbyAImpl_GetConnectionSettings,
01829   XCAST(ReceiveLobbyMessage)IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
01830   XCAST(RunApplication)IDirectPlayLobbyAImpl_RunApplication,
01831   XCAST(SendLobbyMessage)IDirectPlayLobbyAImpl_SendLobbyMessage,
01832   XCAST(SetConnectionSettings)IDirectPlayLobbyAImpl_SetConnectionSettings,
01833   XCAST(SetLobbyMessageEvent)IDirectPlayLobbyAImpl_SetLobbyMessageEvent,
01834 
01835   IDirectPlayLobby2AImpl_CreateCompoundAddress
01836 };
01837 #undef XCAST
01838 
01839 /* Note: Hack so we can reuse the old functions without compiler warnings */
01840 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
01841 # define XCAST(fun)     (typeof(directPlayLobby2AVT.fun))
01842 #else
01843 # define XCAST(fun)     (void*)
01844 #endif
01845 
01846 /* Direct Play Lobby 2 (unicode) Virtual Table for methods */
01847 static const IDirectPlayLobby2Vtbl directPlayLobby2WVT =
01848 {
01849 
01850   XCAST(QueryInterface)DPL_QueryInterface,
01851   XCAST(AddRef)DPL_AddRef,
01852   XCAST(Release)DPL_Release,
01853 
01854   XCAST(Connect)IDirectPlayLobbyWImpl_Connect,
01855   XCAST(CreateAddress)IDirectPlayLobbyWImpl_CreateAddress,
01856   XCAST(EnumAddress)IDirectPlayLobbyWImpl_EnumAddress,
01857   XCAST(EnumAddressTypes)IDirectPlayLobbyWImpl_EnumAddressTypes,
01858   XCAST(EnumLocalApplications)IDirectPlayLobbyWImpl_EnumLocalApplications,
01859   XCAST(GetConnectionSettings)IDirectPlayLobbyWImpl_GetConnectionSettings,
01860   XCAST(ReceiveLobbyMessage)IDirectPlayLobbyWImpl_ReceiveLobbyMessage,
01861   XCAST(RunApplication)IDirectPlayLobbyWImpl_RunApplication,
01862   XCAST(SendLobbyMessage)IDirectPlayLobbyWImpl_SendLobbyMessage,
01863   XCAST(SetConnectionSettings)IDirectPlayLobbyWImpl_SetConnectionSettings,
01864   XCAST(SetLobbyMessageEvent)IDirectPlayLobbyWImpl_SetLobbyMessageEvent,
01865 
01866   IDirectPlayLobby2WImpl_CreateCompoundAddress
01867 };
01868 #undef XCAST
01869 
01870 /* Direct Play Lobby 3 (ascii) Virtual Table for methods */
01871 
01872 /* Note: Hack so we can reuse the old functions without compiler warnings */
01873 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
01874 # define XCAST(fun)     (typeof(directPlayLobby3AVT.fun))
01875 #else
01876 # define XCAST(fun)     (void*)
01877 #endif
01878 
01879 static const IDirectPlayLobby3Vtbl directPlayLobby3AVT =
01880 {
01881   XCAST(QueryInterface)DPL_QueryInterface,
01882   XCAST(AddRef)DPL_AddRef,
01883   XCAST(Release)DPL_Release,
01884 
01885   XCAST(Connect)IDirectPlayLobbyAImpl_Connect,
01886   XCAST(CreateAddress)IDirectPlayLobbyAImpl_CreateAddress,
01887   XCAST(EnumAddress)IDirectPlayLobbyAImpl_EnumAddress,
01888   XCAST(EnumAddressTypes)IDirectPlayLobbyAImpl_EnumAddressTypes,
01889   XCAST(EnumLocalApplications)IDirectPlayLobbyAImpl_EnumLocalApplications,
01890   XCAST(GetConnectionSettings)IDirectPlayLobbyAImpl_GetConnectionSettings,
01891   XCAST(ReceiveLobbyMessage)IDirectPlayLobbyAImpl_ReceiveLobbyMessage,
01892   XCAST(RunApplication)IDirectPlayLobbyAImpl_RunApplication,
01893   XCAST(SendLobbyMessage)IDirectPlayLobbyAImpl_SendLobbyMessage,
01894   XCAST(SetConnectionSettings)IDirectPlayLobbyAImpl_SetConnectionSettings,
01895   XCAST(SetLobbyMessageEvent)IDirectPlayLobbyAImpl_SetLobbyMessageEvent,
01896 
01897   XCAST(CreateCompoundAddress)IDirectPlayLobby2AImpl_CreateCompoundAddress,
01898 
01899   IDirectPlayLobby3AImpl_ConnectEx,
01900   IDirectPlayLobby3AImpl_RegisterApplication,
01901   IDirectPlayLobby3AImpl_UnregisterApplication,
01902   IDirectPlayLobby3AImpl_WaitForConnectionSettings
01903 };
01904 #undef XCAST
01905 
01906 /* Direct Play Lobby 3 (unicode) Virtual Table for methods */
01907 
01908 /* Note: Hack so we can reuse the old functions without compiler warnings */
01909 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
01910 # define XCAST(fun)     (typeof(directPlayLobby3WVT.fun))
01911 #else
01912 # define XCAST(fun)     (void*)
01913 #endif
01914 
01915 static const IDirectPlayLobby3Vtbl directPlayLobby3WVT =
01916 {
01917   XCAST(QueryInterface)DPL_QueryInterface,
01918   XCAST(AddRef)DPL_AddRef,
01919   XCAST(Release)DPL_Release,
01920 
01921   XCAST(Connect)IDirectPlayLobbyWImpl_Connect,
01922   XCAST(CreateAddress)IDirectPlayLobbyWImpl_CreateAddress,
01923   XCAST(EnumAddress)IDirectPlayLobbyWImpl_EnumAddress,
01924   XCAST(EnumAddressTypes)IDirectPlayLobbyWImpl_EnumAddressTypes,
01925   XCAST(EnumLocalApplications)IDirectPlayLobbyWImpl_EnumLocalApplications,
01926   XCAST(GetConnectionSettings)IDirectPlayLobbyWImpl_GetConnectionSettings,
01927   XCAST(ReceiveLobbyMessage)IDirectPlayLobbyWImpl_ReceiveLobbyMessage,
01928   XCAST(RunApplication)IDirectPlayLobbyWImpl_RunApplication,
01929   XCAST(SendLobbyMessage)IDirectPlayLobbyWImpl_SendLobbyMessage,
01930   XCAST(SetConnectionSettings)IDirectPlayLobbyWImpl_SetConnectionSettings,
01931   XCAST(SetLobbyMessageEvent)IDirectPlayLobbyWImpl_SetLobbyMessageEvent,
01932 
01933   XCAST(CreateCompoundAddress)IDirectPlayLobby2WImpl_CreateCompoundAddress,
01934 
01935   IDirectPlayLobby3WImpl_ConnectEx,
01936   IDirectPlayLobby3WImpl_RegisterApplication,
01937   IDirectPlayLobby3WImpl_UnregisterApplication,
01938   IDirectPlayLobby3WImpl_WaitForConnectionSettings
01939 };
01940 #undef XCAST
01941 
01942 
01943 /*********************************************************
01944  *
01945  * Direct Play Lobby Interface Implementation
01946  *
01947  *********************************************************/
01948 
01949 /***************************************************************************
01950  *  DirectPlayLobbyCreateA   (DPLAYX.4)
01951  *
01952  */
01953 HRESULT WINAPI DirectPlayLobbyCreateA( LPGUID lpGUIDDSP,
01954                                        LPDIRECTPLAYLOBBYA *lplpDPL,
01955                                        IUnknown *lpUnk,
01956                                        LPVOID lpData,
01957                                        DWORD dwDataSize )
01958 {
01959   TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\n",
01960         lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
01961 
01962   /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
01963    * equal 0. These fields are mostly for future expansion.
01964    */
01965   if ( lpGUIDDSP || lpData || dwDataSize )
01966   {
01967      *lplpDPL = NULL;
01968      return DPERR_INVALIDPARAMS;
01969   }
01970 
01971   if( lpUnk )
01972   {
01973      *lplpDPL = NULL;
01974      ERR("Bad parameters!\n" );
01975      return CLASS_E_NOAGGREGATION;
01976   }
01977 
01978   return DPL_CreateInterface( &IID_IDirectPlayLobbyA, (void**)lplpDPL );
01979 }
01980 
01981 /***************************************************************************
01982  *  DirectPlayLobbyCreateW   (DPLAYX.5)
01983  *
01984  */
01985 HRESULT WINAPI DirectPlayLobbyCreateW( LPGUID lpGUIDDSP,
01986                                        LPDIRECTPLAYLOBBY *lplpDPL,
01987                                        IUnknown *lpUnk,
01988                                        LPVOID lpData,
01989                                        DWORD dwDataSize )
01990 {
01991   TRACE("lpGUIDDSP=%p lplpDPL=%p lpUnk=%p lpData=%p dwDataSize=%08lx\n",
01992         lpGUIDDSP,lplpDPL,lpUnk,lpData,dwDataSize);
01993 
01994   /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must
01995    * equal 0. These fields are mostly for future expansion.
01996    */
01997   if ( lpGUIDDSP || lpData || dwDataSize )
01998   {
01999      *lplpDPL = NULL;
02000      ERR("Bad parameters!\n" );
02001      return DPERR_INVALIDPARAMS;
02002   }
02003 
02004   if( lpUnk )
02005   {
02006      *lplpDPL = NULL;
02007      ERR("Bad parameters!\n" );
02008      return CLASS_E_NOAGGREGATION;
02009   }
02010 
02011   return DPL_CreateInterface( &IID_IDirectPlayLobby, (void**)lplpDPL );
02012 }

Generated on Sun May 27 2012 04:21:38 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.