~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/dplayx/dplobby.c

Version: ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /* Direct Play Lobby 2 & 3 Implementation
  2  *
  3  * Copyright 1998,1999,2000 - Peter Hunnisett
  4  *
  5  * This library is free software; you can redistribute it and/or
  6  * modify it under the terms of the GNU Lesser General Public
  7  * License as published by the Free Software Foundation; either
  8  * version 2.1 of the License, or (at your option) any later version.
  9  *
 10  * This library is distributed in the hope that it will be useful,
 11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  * Lesser General Public License for more details.
 14  *
 15  * You should have received a copy of the GNU Lesser General Public
 16  * License along with this library; if not, write to the Free Software
 17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 18  */
 19 #include <stdarg.h>
 20 #include <string.h>
 21 
 22 #define NONAMELESSUNION
 23 #define NONAMELESSSTRUCT
 24 #include "windef.h"
 25 #include "winbase.h"
 26 #include "winerror.h"
 27 #include "winreg.h"
 28 #include "winnls.h"
 29 #include "wine/debug.h"
 30 
 31 #include "dplayx_global.h"
 32 #include "dplayx_messages.h"
 33 #include "dplayx_queue.h"
 34 #include "dplobby.h"
 35 #include "dpinit.h"
 36 
 37 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
 38 
 39 /*****************************************************************************
 40  * Predeclare the interface implementation structures
 41  */
 42 typedef struct IDirectPlayLobbyImpl  IDirectPlayLobbyAImpl;
 43 typedef struct IDirectPlayLobbyImpl  IDirectPlayLobbyWImpl;
 44 typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2AImpl;
 45 typedef struct IDirectPlayLobby2Impl IDirectPlayLobby2WImpl;
 46 typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3AImpl;
 47 typedef struct IDirectPlayLobby3Impl IDirectPlayLobby3WImpl;
 48 
 49 /* Forward declarations for this module helper methods */
 50 HRESULT DPL_CreateCompoundAddress ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
 51                                     LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
 52 
 53 static HRESULT DPL_CreateAddress( REFGUID guidSP, REFGUID guidDataType, LPCVOID lpData, DWORD dwDataSize,
 54                            LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
 55 
 56 
 57 
 58 extern HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
 59                                 DWORD dwAddressSize, LPVOID lpContext );
 60 
 61 static HRESULT WINAPI DPL_ConnectEx( IDirectPlayLobbyAImpl* This,
 62                                      DWORD dwFlags, REFIID riid,
 63                                      LPVOID* lplpDP, IUnknown* pUnk );
 64 
 65 static BOOL DPL_CreateAndSetLobbyHandles( DWORD dwDestProcessId, HANDLE hDestProcess,
 66                                    LPHANDLE lphStart, LPHANDLE lphDeath,
 67                                    LPHANDLE lphRead );
 68 
 69 
 70 /*****************************************************************************
 71  * IDirectPlayLobby {1,2,3} implementation structure
 72  *
 73  * The philosophy behind this extra pointer dereference is that I wanted to
 74  * have the same structure for all types of objects without having to do
 75  * a lot of casting. I also only wanted to implement an interface in the
 76  * object it was "released" with IUnknown interface being implemented in the 1 version.
 77  * Of course, with these new interfaces comes the data required to keep the state required
 78  * by these interfaces. So, basically, the pointers contain the data associated with
 79  * a release. If you use the data associated with release 3 in a release 2 object, you'll
 80  * get a run time trap, as that won't have any data.
 81  *
 82  */
 83 struct DPLMSG
 84 {
 85   DPQ_ENTRY( DPLMSG ) msgs;  /* Link to next queued message */
 86 };
 87 typedef struct DPLMSG* LPDPLMSG;
 88 
 89 typedef struct tagDirectPlayLobbyIUnknownData
 90 {
 91   LONG              ulObjRef;
 92   CRITICAL_SECTION  DPL_lock;
 93 } DirectPlayLobbyIUnknownData;
 94 
 95 typedef struct tagDirectPlayLobbyData
 96 {
 97   HKEY  hkCallbackKeyHack;
 98   DWORD dwMsgThread;
 99   DPQ_HEAD( DPLMSG ) msgs;  /* List of messages received */
100 } DirectPlayLobbyData;
101 
102 typedef struct tagDirectPlayLobby2Data
103 {
104   BOOL dummy;
105 } DirectPlayLobby2Data;
106 
107 typedef struct tagDirectPlayLobby3Data
108 {
109   BOOL dummy;
110 } DirectPlayLobby3Data;
111 
112 #define DPL_IMPL_FIELDS \
113  LONG ulInterfaceRef; \
114  DirectPlayLobbyIUnknownData*  unk; \
115  DirectPlayLobbyData*          dpl; \
116  DirectPlayLobby2Data*         dpl2; \
117  DirectPlayLobby3Data*         dpl3;
118 
119 struct IDirectPlayLobbyImpl
120 {
121     const IDirectPlayLobbyVtbl *lpVtbl;
122     DPL_IMPL_FIELDS
123 };
124 
125 struct IDirectPlayLobby2Impl
126 {
127     const IDirectPlayLobby2Vtbl *lpVtbl;
128     DPL_IMPL_FIELDS
129 };
130 
131 struct IDirectPlayLobby3Impl
132 {
133     const IDirectPlayLobby3Vtbl *lpVtbl;
134     DPL_IMPL_FIELDS
135 };
136 
137 /* Forward declarations of virtual tables */
138 static const IDirectPlayLobbyVtbl  directPlayLobbyWVT;
139 static const IDirectPlayLobby2Vtbl directPlayLobby2WVT;
140 static const IDirectPlayLobby3Vtbl directPlayLobby3WVT;
141 
142 static const IDirectPlayLobbyVtbl  directPlayLobbyAVT;
143 static const IDirectPlayLobby2Vtbl directPlayLobby2AVT;
144 static const IDirectPlayLobby3Vtbl directPlayLobby3AVT;
145 
146 static BOOL DPL_CreateIUnknown( LPVOID lpDPL )
147 {
148   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
149 
150   This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
151   if ( This->unk == NULL )
152   {
153     return FALSE;
154   }
155 
156   InitializeCriticalSection( &This->unk->DPL_lock );
157   This->unk->DPL_lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectPlayLobbyAImpl*->DirectPlayLobbyIUnknownData*->DPL_lock");
158 
159   return TRUE;
160 }
161 
162 static BOOL DPL_DestroyIUnknown( LPVOID lpDPL )
163 {
164   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
165 
166   This->unk->DPL_lock.DebugInfo->Spare[0] = 0;
167   DeleteCriticalSection( &This->unk->DPL_lock );
168   HeapFree( GetProcessHeap(), 0, This->unk );
169 
170   return TRUE;
171 }
172 
173 static BOOL DPL_CreateLobby1( LPVOID lpDPL )
174 {
175   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
176 
177   This->dpl = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dpl) ) );
178   if ( This->dpl == NULL )
179   {
180     return FALSE;
181   }
182 
183   DPQ_INIT( This->dpl->msgs );
184 
185   return TRUE;
186 }
187 
188 static BOOL DPL_DestroyLobby1( LPVOID lpDPL )
189 {
190   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)lpDPL;
191 
192   if( This->dpl->dwMsgThread )
193   {
194     FIXME( "Should kill the msg thread\n" );
195   }
196 
197   DPQ_DELETEQ( This->dpl->msgs, msgs, LPDPLMSG, cbDeleteElemFromHeap );
198 
199   /* Delete the contents */
200   HeapFree( GetProcessHeap(), 0, This->dpl );
201 
202   return TRUE;
203 }
204 
205 static BOOL DPL_CreateLobby2( LPVOID lpDPL )
206 {
207   IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)lpDPL;
208 
209   This->dpl2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dpl2) ) );
210   if ( This->dpl2 == NULL )
211   {
212     return FALSE;
213   }
214 
215   return TRUE;
216 }
217 
218 static BOOL DPL_DestroyLobby2( LPVOID lpDPL )
219 {
220   IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)lpDPL;
221 
222   HeapFree( GetProcessHeap(), 0, This->dpl2 );
223 
224   return TRUE;
225 }
226 
227 static BOOL DPL_CreateLobby3( LPVOID lpDPL )
228 {
229   IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)lpDPL;
230 
231   This->dpl3 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dpl3) ) );
232   if ( This->dpl3 == NULL )
233   {
234     return FALSE;
235   }
236 
237   return TRUE;
238 }
239 
240 static BOOL DPL_DestroyLobby3( LPVOID lpDPL )
241 {
242   IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)lpDPL;
243 
244   HeapFree( GetProcessHeap(), 0, This->dpl3 );
245 
246   return TRUE;
247 }
248 
249 
250 /* The COM interface for upversioning an interface
251  * We've been given a GUID (riid) and we need to replace the present
252  * interface with that of the requested interface.
253  *
254  * Snip from some Microsoft document:
255  * There are four requirements for implementations of QueryInterface (In these
256  * cases, "must succeed" means "must succeed barring catastrophic failure."):
257  *
258  *  * The set of interfaces accessible on an object through
259  *    IUnknown::QueryInterface must be static, not dynamic. This means that
260  *    if a call to QueryInterface for a pointer to a specified interface
261  *    succeeds the first time, it must succeed again, and if it fails the
262  *    first time, it must fail on all subsequent queries.
263  *  * It must be symmetric ~W if a client holds a pointer to an interface on
264  *    an object, and queries for that interface, the call must succeed.
265  *  * It must be reflexive ~W if a client holding a pointer to one interface
266  *    queries successfully for another, a query through the obtained pointer
267  *    for the first interface must succeed.
268  *  * It must be transitive ~W if a client holding a pointer to one interface
269  *    queries successfully for a second, and through that pointer queries
270  *    successfully for a third interface, a query for the first interface
271  *    through the pointer for the third interface must succeed.
272  */
273 HRESULT DPL_CreateInterface
274          ( REFIID riid, LPVOID* ppvObj )
275 {
276   TRACE( " for %s\n", debugstr_guid( riid ) );
277 
278   *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
279                        sizeof( IDirectPlayLobbyWImpl ) );
280 
281   if( *ppvObj == NULL )
282   {
283     return DPERR_OUTOFMEMORY;
284   }
285 
286   if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
287   {
288     IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)*ppvObj;
289     This->lpVtbl = &directPlayLobbyWVT;
290   }
291   else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
292   {
293     IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)*ppvObj;
294     This->lpVtbl = &directPlayLobbyAVT;
295   }
296   else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
297   {
298     IDirectPlayLobby2WImpl *This = (IDirectPlayLobby2WImpl *)*ppvObj;
299     This->lpVtbl = &directPlayLobby2WVT;
300   }
301   else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
302   {
303     IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)*ppvObj;
304     This->lpVtbl = &directPlayLobby2AVT;
305   }
306   else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
307   {
308     IDirectPlayLobby3WImpl *This = (IDirectPlayLobby3WImpl *)*ppvObj;
309     This->lpVtbl = &directPlayLobby3WVT;
310   }
311   else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
312   {
313     IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)*ppvObj;
314     This->lpVtbl = &directPlayLobby3AVT;
315   }
316   else
317   {
318     /* Unsupported interface */
319     HeapFree( GetProcessHeap(), 0, *ppvObj );
320     *ppvObj = NULL;
321 
322     return E_NOINTERFACE;
323   }
324 
325   /* Initialize it */
326   if ( DPL_CreateIUnknown( *ppvObj ) &&
327        DPL_CreateLobby1( *ppvObj ) &&
328        DPL_CreateLobby2( *ppvObj ) &&
329        DPL_CreateLobby3( *ppvObj )
330      )
331   {
332     IDirectPlayLobby_AddRef( (LPDIRECTPLAYLOBBY)*ppvObj );
333     return S_OK;
334   }
335 
336   /* Initialize failed, destroy it */
337   DPL_DestroyLobby3( *ppvObj );
338   DPL_DestroyLobby2( *ppvObj );
339   DPL_DestroyLobby1( *ppvObj );
340   DPL_DestroyIUnknown( *ppvObj );
341   HeapFree( GetProcessHeap(), 0, *ppvObj );
342 
343   *ppvObj = NULL;
344   return DPERR_NOMEMORY;
345 }
346 
347 static HRESULT WINAPI DPL_QueryInterface
348 ( LPDIRECTPLAYLOBBYA iface,
349   REFIID riid,
350   LPVOID* ppvObj )
351 {
352   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
353   TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
354 
355   *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
356                        sizeof( *This ) );
357 
358   if( *ppvObj == NULL )
359   {
360     return DPERR_OUTOFMEMORY;
361   }
362 
363   CopyMemory( *ppvObj, This, sizeof( *This )  );
364   (*(IDirectPlayLobbyAImpl**)ppvObj)->ulInterfaceRef = 0;
365 
366   if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
367   {
368     IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)*ppvObj;
369     This->lpVtbl = &directPlayLobbyWVT;
370   }
371   else if( IsEqualGUID( &IID_IDirectPlayLobbyA, riid ) )
372   {
373     IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)*ppvObj;
374     This->lpVtbl = &directPlayLobbyAVT;
375   }
376   else if( IsEqualGUID( &IID_IDirectPlayLobby2, riid ) )
377   {
378     IDirectPlayLobby2WImpl *This = (IDirectPlayLobby2WImpl *)*ppvObj;
379     This->lpVtbl = &directPlayLobby2WVT;
380   }
381   else if( IsEqualGUID( &IID_IDirectPlayLobby2A, riid ) )
382   {
383     IDirectPlayLobby2AImpl *This = (IDirectPlayLobby2AImpl *)*ppvObj;
384     This->lpVtbl = &directPlayLobby2AVT;
385   }
386   else if( IsEqualGUID( &IID_IDirectPlayLobby3, riid ) )
387   {
388     IDirectPlayLobby3WImpl *This = (IDirectPlayLobby3WImpl *)*ppvObj;
389     This->lpVtbl = &directPlayLobby3WVT;
390   }
391   else if( IsEqualGUID( &IID_IDirectPlayLobby3A, riid ) )
392   {
393     IDirectPlayLobby3AImpl *This = (IDirectPlayLobby3AImpl *)*ppvObj;
394     This->lpVtbl = &directPlayLobby3AVT;
395   }
396   else
397   {
398     /* Unsupported interface */
399     HeapFree( GetProcessHeap(), 0, *ppvObj );
400     *ppvObj = NULL;
401 
402     return E_NOINTERFACE;
403   }
404 
405   IDirectPlayLobby_AddRef( (LPDIRECTPLAYLOBBY)*ppvObj );
406 
407   return S_OK;
408 }
409 
410 /*
411  * Simple procedure. Just increment the reference count to this
412  * structure and return the new reference count.
413  */
414 static ULONG WINAPI DPL_AddRef
415 ( LPDIRECTPLAYLOBBY iface )
416 {
417   ULONG ulInterfaceRefCount, ulObjRefCount;
418   IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
419 
420   ulObjRefCount       = InterlockedIncrement( &This->unk->ulObjRef );
421   ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
422 
423   TRACE( "ref count incremented to %u:%u for %p\n",
424          ulInterfaceRefCount, ulObjRefCount, This );
425 
426   return ulObjRefCount;
427 }
428 
429 /*
430  * Simple COM procedure. Decrease the reference count to this object.
431  * If the object no longer has any reference counts, free up the associated
432  * memory.
433  */
434 static ULONG WINAPI DPL_Release
435 ( LPDIRECTPLAYLOBBYA iface )
436 {
437   ULONG ulInterfaceRefCount, ulObjRefCount;
438   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
439 
440   ulObjRefCount       = InterlockedDecrement( &This->unk->ulObjRef );
441   ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );
442 
443   TRACE( "ref count decremented to %u:%u for %p\n",
444          ulInterfaceRefCount, ulObjRefCount, This );
445 
446   /* Deallocate if this is the last reference to the object */
447   if( ulObjRefCount == 0 )
448   {
449      DPL_DestroyLobby3( This );
450      DPL_DestroyLobby2( This );
451      DPL_DestroyLobby1( This );
452      DPL_DestroyIUnknown( This );
453   }
454 
455   if( ulInterfaceRefCount == 0 )
456   {
457     HeapFree( GetProcessHeap(), 0, This );
458   }
459 
460   return ulInterfaceRefCount;
461 }
462 
463 
464 /********************************************************************
465  *
466  * Connects an application to the session specified by the DPLCONNECTION
467  * structure currently stored with the DirectPlayLobby object.
468  *
469  * Returns an IDirectPlay interface.
470  *
471  */
472 static HRESULT WINAPI DPL_ConnectEx
473 ( IDirectPlayLobbyAImpl* This,
474   DWORD     dwFlags,
475   REFIID    riid,
476   LPVOID*   lplpDP,
477   IUnknown* pUnk)
478 {
479   HRESULT         hr;
480   DWORD           dwOpenFlags = 0;
481   DWORD           dwConnSize = 0;
482   LPDPLCONNECTION lpConn;
483 
484   FIXME("(%p)->(0x%08x,%p,%p): semi stub\n", This, dwFlags, lplpDP, pUnk );
485 
486   if( pUnk )
487   {
488      return DPERR_INVALIDPARAMS;
489   }
490 
491   /* Backwards compatibility */
492   if( dwFlags == 0 )
493   {
494     dwFlags = DPCONNECT_RETURNSTATUS;
495   }
496 
497   /* Create the DirectPlay interface */
498   if( ( hr = DP_CreateInterface( riid, lplpDP ) ) != DP_OK )
499   {
500      ERR( "error creating interface for %s:%s.\n",
501           debugstr_guid( riid ), DPLAYX_HresultToString( hr ) );
502      return hr;
503   }
504 
505   /* FIXME: Is it safe/correct to use appID of 0? */
506   hr = IDirectPlayLobby_GetConnectionSettings( (LPDIRECTPLAYLOBBY)This,
507                                                0, NULL, &dwConnSize );
508   if( hr != DPERR_BUFFERTOOSMALL )
509   {
510     return hr;
511   }
512 
513   lpConn = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwConnSize );
514 
515   if( lpConn == NULL )
516   {
517     return DPERR_NOMEMORY;
518   }
519 
520   /* FIXME: Is it safe/correct to use appID of 0? */
521   hr = IDirectPlayLobby_GetConnectionSettings( (LPDIRECTPLAYLOBBY)This,
522                                                0, lpConn, &dwConnSize );
523   if( FAILED( hr ) )
524   {
525     HeapFree( GetProcessHeap(), 0, lpConn );
526     return hr;
527   }
528 
529 #if 0
530   /* - Need to call IDirectPlay::EnumConnections with the service provider to get that good information
531    * - Need to call CreateAddress to create the lpConnection param for IDirectPlay::InitializeConnection
532    * - Call IDirectPlay::InitializeConnection
533    */
534 
535   /* Now initialize the Service Provider */
536   hr = IDirectPlayX_InitializeConnection( (*(LPDIRECTPLAY2*)lplpDP),
537 #endif
538 
539 
540   /* Setup flags to pass into DirectPlay::Open */
541   if( dwFlags & DPCONNECT_RETURNSTATUS )
542   {
543     dwOpenFlags |= DPOPEN_RETURNSTATUS;
544   }
545   dwOpenFlags |= lpConn->dwFlags;
546 
547   hr = IDirectPlayX_Open( (*(LPDIRECTPLAY2*)lplpDP), lpConn->lpSessionDesc,
548                           dwOpenFlags );
549 
550   HeapFree( GetProcessHeap(), 0, lpConn );
551 
552   return hr;
553 }
554 
555 static HRESULT WINAPI IDirectPlayLobbyAImpl_Connect
556 ( LPDIRECTPLAYLOBBYA iface,
557   DWORD dwFlags,
558   LPDIRECTPLAY2A* lplpDP,
559   IUnknown* pUnk)
560 {
561   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
562   return DPL_ConnectEx( This, dwFlags, &IID_IDirectPlay2A,
563                         (LPVOID)lplpDP, pUnk );
564 }
565 
566 static HRESULT WINAPI IDirectPlayLobbyWImpl_Connect
567 ( LPDIRECTPLAYLOBBY iface,
568   DWORD dwFlags,
569   LPDIRECTPLAY2* lplpDP,
570   IUnknown* pUnk)
571 {
572   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface; /* Yes cast to A */
573   return DPL_ConnectEx( This, dwFlags, &IID_IDirectPlay2,
574                         (LPVOID)lplpDP, pUnk );
575 }
576 
577 /********************************************************************
578  *
579  * Creates a DirectPlay Address, given a service provider-specific network
580  * address.
581  * Returns an address contains the globally unique identifier
582  * (GUID) of the service provider and data that the service provider can
583  * interpret as a network address.
584  *
585  * NOTE: It appears that this method is supposed to be really really stupid
586  *       with no error checking on the contents.
587  */
588 static HRESULT WINAPI IDirectPlayLobbyAImpl_CreateAddress
589 ( LPDIRECTPLAYLOBBYA iface,
590   REFGUID guidSP,
591   REFGUID guidDataType,
592   LPCVOID lpData,
593   DWORD dwDataSize,
594   LPVOID lpAddress,
595   LPDWORD lpdwAddressSize )
596 {
597   return DPL_CreateAddress( guidSP, guidDataType, lpData, dwDataSize,
598                             lpAddress, lpdwAddressSize, TRUE );
599 }
600 
601 static HRESULT WINAPI IDirectPlayLobbyWImpl_CreateAddress
602 ( LPDIRECTPLAYLOBBY iface,
603   REFGUID guidSP,
604   REFGUID guidDataType,
605   LPCVOID lpData,
606   DWORD dwDataSize,
607   LPVOID lpAddress,
608   LPDWORD lpdwAddressSize )
609 {
610   return DPL_CreateAddress( guidSP, guidDataType, lpData, dwDataSize,
611                             lpAddress, lpdwAddressSize, FALSE );
612 }
613 
614 static HRESULT DPL_CreateAddress(
615   REFGUID guidSP,
616   REFGUID guidDataType,
617   LPCVOID lpData,
618   DWORD dwDataSize,
619   LPVOID lpAddress,
620   LPDWORD lpdwAddressSize,
621   BOOL bAnsiInterface )
622 {
623   const DWORD dwNumAddElements = 2; /* Service Provide & address data type */
624   DPCOMPOUNDADDRESSELEMENT addressElements[ 2 /* dwNumAddElements */ ];
625 
626   TRACE( "(%p)->(%p,%p,0x%08x,%p,%p,%d)\n", guidSP, guidDataType, lpData, dwDataSize,
627                                              lpAddress, lpdwAddressSize, bAnsiInterface );
628 
629   addressElements[ 0 ].guidDataType = DPAID_ServiceProvider;
630   addressElements[ 0 ].dwDataSize = sizeof( GUID );
631   addressElements[ 0 ].lpData = (LPVOID)guidSP;
632 
633   addressElements[ 1 ].guidDataType = *guidDataType;
634   addressElements[ 1 ].dwDataSize = dwDataSize;
635   addressElements[ 1 ].lpData = (LPVOID)lpData;
636 
637   /* Call CreateCompoundAddress to cut down on code.
638      NOTE: We can do this because we don't support DPL 1 interfaces! */
639   return DPL_CreateCompoundAddress( addressElements, dwNumAddElements,
640                                     lpAddress, lpdwAddressSize, bAnsiInterface );
641 }
642 
643 
644 
645 /********************************************************************
646  *
647  * Parses out chunks from the DirectPlay Address buffer by calling the
648  * given callback function, with lpContext, for each of the chunks.
649  *
650  */
651 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddress
652 ( LPDIRECTPLAYLOBBYA iface,
653   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
654   LPCVOID lpAddress,
655   DWORD dwAddressSize,
656   LPVOID lpContext )
657 {
658   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
659 
660   TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, lpEnumAddressCallback, lpAddress,
661                                       dwAddressSize, lpContext );
662 
663   return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
664 }
665 
666 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumAddress
667 ( LPDIRECTPLAYLOBBY iface,
668   LPDPENUMADDRESSCALLBACK lpEnumAddressCallback,
669   LPCVOID lpAddress,
670   DWORD dwAddressSize,
671   LPVOID lpContext )
672 {
673   IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
674 
675   TRACE("(%p)->(%p,%p,0x%08x,%p)\n", This, lpEnumAddressCallback, lpAddress,
676                                       dwAddressSize, lpContext );
677 
678   return DPL_EnumAddress( lpEnumAddressCallback, lpAddress, dwAddressSize, lpContext );
679 }
680 
681 HRESULT DPL_EnumAddress( LPDPENUMADDRESSCALLBACK lpEnumAddressCallback, LPCVOID lpAddress,
682                          DWORD dwAddressSize, LPVOID lpContext )
683 {
684   DWORD dwTotalSizeEnumerated = 0;
685 
686   /* FIXME: First chunk is always the total size chunk - Should we report it? */
687 
688   while ( dwTotalSizeEnumerated < dwAddressSize )
689   {
690     const DPADDRESS* lpElements = (const DPADDRESS*)lpAddress;
691     DWORD dwSizeThisEnumeration;
692 
693     /* Invoke the enum method. If false is returned, stop enumeration */
694     if ( !lpEnumAddressCallback( &lpElements->guidDataType,
695                                  lpElements->dwDataSize,
696                                  (const BYTE *)lpElements + sizeof( DPADDRESS ),
697                                  lpContext ) )
698     {
699       break;
700     }
701 
702     dwSizeThisEnumeration  = sizeof( DPADDRESS ) + lpElements->dwDataSize;
703     lpAddress = (const BYTE*) lpAddress + dwSizeThisEnumeration;
704     dwTotalSizeEnumerated += dwSizeThisEnumeration;
705   }
706 
707   return DP_OK;
708 }
709 
710 /********************************************************************
711  *
712  * Enumerates all the address types that a given service provider needs to
713  * build the DirectPlay Address.
714  *
715  */
716 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumAddressTypes
717 ( LPDIRECTPLAYLOBBYA iface,
718   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
719   REFGUID guidSP,
720   LPVOID lpContext,
721   DWORD dwFlags )
722 {
723   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
724 
725   HKEY   hkResult;
726   LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
727   DWORD  dwIndex, sizeOfSubKeyName=50;
728   char   subKeyName[51];
729   FILETIME filetime;
730 
731   TRACE(" (%p)->(%p,%p,%p,0x%08x)\n", This, lpEnumAddressTypeCallback, guidSP, lpContext, dwFlags );
732 
733   if( dwFlags != 0 )
734   {
735     return DPERR_INVALIDPARAMS;
736   }
737 
738   if( !lpEnumAddressTypeCallback )
739   {
740      return DPERR_INVALIDPARAMS;
741   }
742 
743   if( guidSP == NULL )
744   {
745     return DPERR_INVALIDOBJECT;
746   }
747 
748     /* Need to loop over the service providers in the registry */
749     if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
750                          0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
751     {
752       /* Hmmm. Does this mean that there are no service providers? */
753       ERR(": no service providers?\n");
754       return DP_OK;
755     }
756 
757     /* Traverse all the service providers we have available */
758     for( dwIndex=0;
759          RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
760                         NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
761          ++dwIndex, sizeOfSubKeyName=50 )
762     {
763 
764       HKEY     hkServiceProvider, hkServiceProviderAt;
765       GUID     serviceProviderGUID;
766       DWORD    returnTypeGUID, sizeOfReturnBuffer = 50;
767       char     atSubKey[51];
768       char     returnBuffer[51];
769       WCHAR    buff[51];
770       DWORD    dwAtIndex;
771       LPCSTR   atKey = "Address Types";
772       LPCSTR   guidDataSubKey   = "Guid";
773       FILETIME filetime;
774 
775 
776       TRACE(" this time through: %s\n", subKeyName );
777 
778       /* Get a handle for this particular service provider */
779       if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
780                          &hkServiceProvider ) != ERROR_SUCCESS )
781       {
782          ERR(": what the heck is going on?\n" );
783          continue;
784       }
785 
786       if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
787                             NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
788                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
789       {
790         ERR(": missing GUID registry data members\n" );
791         continue;
792       }
793 
794       /* FIXME: Check return types to ensure we're interpreting data right */
795       MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
796       CLSIDFromString( buff, &serviceProviderGUID );
797       /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
798 
799       /* Determine if this is the Service Provider that the user asked for */
800       if( !IsEqualGUID( &serviceProviderGUID, guidSP ) )
801       {
802         continue;
803       }
804 
805       /* Get a handle for this particular service provider */
806       if( RegOpenKeyExA( hkServiceProvider, atKey, 0, KEY_READ,
807                          &hkServiceProviderAt ) != ERROR_SUCCESS )
808       {
809         TRACE(": No Address Types registry data sub key/members\n" );
810         break;
811       }
812 
813       /* Traverse all the address type we have available */
814       for( dwAtIndex=0;
815            RegEnumKeyExA( hkServiceProviderAt, dwAtIndex, atSubKey, &sizeOfSubKeyName,
816                           NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
817            ++dwAtIndex, sizeOfSubKeyName=50 )
818       {
819         TRACE( "Found Address Type GUID %s\n", atSubKey );
820 
821         /* FIXME: Check return types to ensure we're interpreting data right */
822         MultiByteToWideChar( CP_ACP, 0, atSubKey, -1, buff, sizeof(buff)/sizeof(WCHAR) );
823         CLSIDFromString( buff, &serviceProviderGUID );
824         /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
825 
826         /* The enumeration will return FALSE if we are not to continue */
827         if( !lpEnumAddressTypeCallback( &serviceProviderGUID, lpContext, 0 ) )
828         {
829            WARN("lpEnumCallback returning FALSE\n" );
830            break; /* FIXME: This most likely has to break from the procedure...*/
831         }
832 
833       }
834 
835       /* We only enumerate address types for 1 GUID. We've found it, so quit looking */
836       break;
837     }
838 
839   return DP_OK;
840 }
841 
842 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumAddressTypes
843 ( LPDIRECTPLAYLOBBY iface,
844   LPDPLENUMADDRESSTYPESCALLBACK lpEnumAddressTypeCallback,
845   REFGUID guidSP,
846   LPVOID lpContext,
847   DWORD dwFlags )
848 {
849   FIXME(":stub\n");
850   return DPERR_OUTOFMEMORY;
851 }
852 
853 /********************************************************************
854  *
855  * Enumerates what applications are registered with DirectPlay by
856  * invoking the callback function with lpContext.
857  *
858  */
859 static HRESULT WINAPI IDirectPlayLobbyWImpl_EnumLocalApplications
860 ( LPDIRECTPLAYLOBBY iface,
861   LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback,
862   LPVOID lpContext,
863   DWORD dwFlags )
864 {
865   IDirectPlayLobbyWImpl *This = (IDirectPlayLobbyWImpl *)iface;
866 
867   FIXME("(%p)->(%p,%p,0x%08x):stub\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
868 
869   return DPERR_OUTOFMEMORY;
870 }
871 
872 static HRESULT WINAPI IDirectPlayLobbyAImpl_EnumLocalApplications
873 ( LPDIRECTPLAYLOBBYA iface,
874   LPDPLENUMLOCALAPPLICATIONSCALLBACK lpEnumLocalAppCallback,
875   LPVOID lpContext,
876   DWORD dwFlags )
877 {
878   IDirectPlayLobbyAImpl *This = (IDirectPlayLobbyAImpl *)iface;
879 
880   HKEY hkResult;
881   LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Applications";
882   LPCSTR guidDataSubKey  = "Guid";
883   DWORD dwIndex, sizeOfSubKeyName=50;
884   char subKeyName[51];
885   FILETIME filetime;
886 
887   TRACE("(%p)->(%p,%p,0x%08x)\n", This, lpEnumLocalAppCallback, lpContext, dwFlags );
888 
889   if( dwFlags != 0 )
890   {
891     return DPERR_INVALIDPARAMS;
892   }
893 
894   if( !lpEnumLocalAppCallback )
895   {
896      return DPERR_INVALIDPARAMS;
897   }
898 
899   /* Need to loop over the service providers in the registry */
900   if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
901                      0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
902   {
903     /* Hmmm. Does this mean that there are no service providers? */
904     ERR(": no service providers?\n");
905     return DP_OK;
906   }
907 
908   /* Traverse all registered applications */
909   for( dwIndex=0;
910        RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
911        ++dwIndex, sizeOfSubKeyName=50 )
912   {
913 
914     HKEY       hkServiceProvider;
915     GUID       serviceProviderGUID;
916     DWORD      returnTypeGUID, sizeOfReturnBuffer = 50;
917     char       returnBuffer[51];
918     WCHAR      buff[51];
919     DPLAPPINFO dplAppInfo;
920 
921     TRACE(" this time through: %s\n", subKeyName );
922 
923     /* Get a handle for this particular service provider */
924     if( RegOpenKeyExA( hkResult, subKeyName, 0, KEY_READ,
925                        &hkServiceProvider ) != ERROR_SUCCESS )
926     {
927        ERR(": what the heck is going on?\n" );
928        continue;
929     }
930 
931     if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
932                           NULL, &returnTypeGUID, (LPBYTE)returnBuffer,
933                           &sizeOfReturnBuffer ) != ERROR_SUCCESS )
934     {
935       ERR(": missing GUID registry data members\n" );
936       continue;
937     }
938 
939     /* FIXME: Check return types to ensure we're interpreting data right */
940     MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
941     CLSIDFromString( buff, &serviceProviderGUID );
942     /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
943 
944     dplAppInfo.dwSize               = sizeof( dplAppInfo );
945     dplAppInfo.guidApplication      = serviceProviderGUID;
946     dplAppInfo.u.lpszAppNameA = subKeyName;
947 
948     EnterCriticalSection( &This->unk->DPL_lock );
949 
950     memcpy( &This->dpl->hkCallbackKeyHack, &hkServiceProvider, sizeof( hkServiceProvider ) );
951 
952     if( !lpEnumLocalAppCallback( &dplAppInfo, lpContext, dwFlags ) )
953     {
954        LeaveCriticalSection( &This->unk->DPL_lock );
955        break;
956     }
957 
958     LeaveCriticalSection( &This->unk->DPL_lock );
959   }
960 
961   return DP_OK;
962 }
963 
964 /********************************************************************
965  *
966  * Retrieves the DPLCONNECTION structure that contains all the information
967  * needed