Provide stub for SetupDiGetClassDevsW.
[wine] / dlls / dplayx / dplay.c
index cec6ac4..edefc77 100644 (file)
@@ -1,18 +1,38 @@
 /* Direct Play 2,3,4 Implementation
  *
- * Copyright 1998,1999,2000 - Peter Hunnisett
+ * Copyright 1998,1999,2000,2001 - Peter Hunnisett
  *
  * <presently under construction - contact hunnise@nortelnetworks.com>
  *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <string.h>
+
 #include "windef.h"
 #include "winerror.h"
 #include "winbase.h"
 #include "winnt.h"
 #include "winreg.h"
+#include "winnls.h"
+#include "wine/unicode.h"
 #include "dplay.h"
-#include "heap.h"
-#include "debugtools.h"
+#include "wine/debug.h"
 
 #include "dpinit.h"
 #include "dplayx_global.h"
 #include "dplaysp.h"
 #include "dplay_global.h"
 
-DEFAULT_DEBUG_CHANNEL(dplay)
+WINE_DEFAULT_DEBUG_CHANNEL(dplay);
 
 /* FIXME: Should this be externed? */
-extern HRESULT DPL_CreateCompoundAddress 
+extern HRESULT DPL_CreateCompoundAddress
 ( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
   LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );
 
 
 /* Local function prototypes */
 static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
-static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid, 
+static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
                                      LPDPNAME lpName, DWORD dwFlags,
                                      HANDLE hEvent, BOOL bAnsi );
 static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
@@ -39,52 +59,52 @@ static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
                               LPVOID lpData, DWORD dwDataSize );
 
 static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
-                                   LPDPNAME lpName, DWORD dwFlags, 
+                                   LPDPNAME lpName, DWORD dwFlags,
                                    DPID idParent, BOOL bAnsi );
 static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
                              LPVOID lpData, DWORD dwDataSize );
 static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
 static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
-static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId, 
-                                                  DWORD dwPlayerType, 
-                                                  LPCDPNAME lpName, 
-                                                  DWORD dwFlags, 
+static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
+                                                  DWORD dwPlayerType,
+                                                  LPCDPNAME lpName,
+                                                  DWORD dwFlags,
                                                   LPVOID lpContext );
 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
-static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType, 
-                                            LPCDPNAME lpName, DWORD dwFlags, 
+static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
+                                            LPCDPNAME lpName, DWORD dwFlags,
                                             LPVOID lpContext );
 static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );
 
 /* Helper methods for player/group interfaces */
 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
-          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, 
+          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
             DPID idPlayer, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_CreatePlayer
-          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer, 
-            LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData, 
+          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
+            LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
             DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_DestroyGroup
           ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_DestroyPlayer
           ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_EnumGroupPlayers
-          ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance, 
+          ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
             LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_EnumGroups
-          ( IDirectPlay2Impl* This, LPGUID lpguidInstance, 
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 
+          ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_EnumPlayers
-          ( IDirectPlay2Impl* This, LPGUID lpguidInstance, 
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 
+          ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_GetGroupData
-          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 
+          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
             LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_GetGroupName
-          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 
+          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
             LPDWORD lpdwDataSize, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_GetPlayerData
           ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
@@ -93,31 +113,31 @@ static HRESULT WINAPI DP_IF_GetPlayerName
           ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
             LPDWORD lpdwDataSize, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_SetGroupName
-          ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName, 
+          ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
             DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_SetPlayerData
-          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData, 
+          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
             DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_SetPlayerName
-          ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName, 
+          ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
             DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_AddGroupToGroup
           ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
 static HRESULT WINAPI DP_IF_CreateGroup
-          ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup, 
-            LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, 
+          ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
+            LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
             DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_CreateGroupInGroup
-          ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup, 
-            LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, 
+          ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
+            LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
             DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_AddPlayerToGroup
-          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, 
+          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
             DPID idPlayer, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
           ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
 static HRESULT WINAPI DP_SetSessionDesc
-          ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc, 
+          ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
             DWORD dwFlags, BOOL bInitial, BOOL bAnsi  );
 static HRESULT WINAPI DP_SecureOpen
           ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
@@ -149,7 +169,7 @@ static HRESULT WINAPI DP_IF_CancelMessage
             DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
           ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
 static HRESULT WINAPI DP_IF_GetGroupParent
           ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
@@ -160,9 +180,13 @@ static HRESULT WINAPI DP_IF_EnumSessions
           ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
             LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
             LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
+static HRESULT WINAPI DP_IF_InitializeConnection
+          ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
 static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
     LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
     DWORD dwFlags, LPVOID lpContext );
+static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
+                                           LPDWORD lpdwBufSize );
 
 
 
@@ -170,18 +194,21 @@ static inline DPID DP_NextObjectId(void);
 static DPID DP_GetRemoteNextObjectId(void);
 
 
-static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc, 
+static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
                                 LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );
 
 
-static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData );
+static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
+static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
+static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
+
 
 
 
 
 
 #define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
-#define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported 
+#define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
                                                  we don't have to change much */
 #define DPID_NAME_SERVER 0x19a9d65b  /* Don't ask me why */
 
@@ -241,6 +268,7 @@ static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
 
   DPQ_INIT(This->dp2->receiveMsgs);
   DPQ_INIT(This->dp2->sendMsgs);
+  DPQ_INIT(This->dp2->replysExpected);
 
   if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
   {
@@ -249,8 +277,8 @@ static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
   }
 
   /* Provide an initial session desc with nothing in it */
-  This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(), 
-                               HEAP_ZERO_MEMORY, 
+  This->dp2->lpSessionDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
+                               HEAP_ZERO_MEMORY,
                                sizeof( *This->dp2->lpSessionDesc ) );
   if( This->dp2->lpSessionDesc == NULL )
   {
@@ -266,9 +294,9 @@ static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
                                       sizeof( *This->dp2->spData.lpCB ) );
   This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
   This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;
-  
+
   /* This is the pointer to the service provider */
-  if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP, 
+  if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
                                     (LPVOID*)&This->dp2->spData.lpISP, This ) )
     )
   {
@@ -276,6 +304,20 @@ static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
     return FALSE;
   }
 
+  /* Setup lobby provider information */
+  This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
+  This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                         sizeof( *This->dp2->dplspData.lpCB ) );
+  This->dp2->dplspData.lpCB->dwSize = sizeof(  *This->dp2->dplspData.lpCB );
+
+  if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
+                                     (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
+    )
+  {
+    /* FIXME: Memory leak */
+    return FALSE;
+  }
+
   return TRUE;
 }
 
@@ -295,8 +337,8 @@ DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
 DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
 {
-  DPQ_DELETEQ( elem->lpGData->groups, groups, 
-               lpGroupList, cbDeleteElemFromHeap ); 
+  DPQ_DELETEQ( elem->lpGData->groups, groups,
+               lpGroupList, cbDeleteElemFromHeap );
   DPQ_DELETEQ( elem->lpGData->players, players,
                lpPlayerList, cbDeleteElemFromHeap );
   HeapFree( GetProcessHeap(), 0, elem->lpGData );
@@ -340,12 +382,17 @@ static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
     (*This->dp2->spData.lpCB->Shutdown)();
   }
 
-  /* Unload the SP */
+  /* Unload the SP (if it exists) */
   if( This->dp2->hServiceProvider != 0 )
   {
     FreeLibrary( This->dp2->hServiceProvider );
   }
 
+  /* Unload the Lobby Provider (if it exists) */
+  if( This->dp2->hDPLobbyProvider != 0 )
+  {
+    FreeLibrary( This->dp2->hDPLobbyProvider );
+  }
 
 #if 0
   DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
@@ -415,9 +462,9 @@ static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
 }
 
 
-/* Create a new interface */ 
-extern 
-HRESULT DP_CreateInterface 
+/* Create a new interface */
+extern
+HRESULT DP_CreateInterface
          ( REFIID riid, LPVOID* ppvObj )
 {
   TRACE( " for %s\n", debugstr_guid( riid ) );
@@ -434,7 +481,7 @@ HRESULT DP_CreateInterface
   {
     ICOM_THIS(IDirectPlay2Impl,*ppvObj);
     ICOM_VTBL(This) = &directPlay2WVT;
-  } 
+  }
   else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
   {
     ICOM_THIS(IDirectPlay2AImpl,*ppvObj);
@@ -504,14 +551,14 @@ static HRESULT WINAPI DP_QueryInterface
   TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );
 
   *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                       sizeof( IDirectPlay2Impl ) );
+                       sizeof( *This ) );
 
   if( *ppvObj == NULL )
   {
     return DPERR_OUTOFMEMORY;
   }
 
-  CopyMemory( *ppvObj, iface, sizeof( IDirectPlay2Impl )  );
+  CopyMemory( *ppvObj, This, sizeof( *This )  );
   (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
 
   if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
@@ -568,7 +615,7 @@ static ULONG WINAPI DP_AddRef
   ulObjRefCount       = InterlockedIncrement( &This->unk->ulObjRef );
   ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );
 
-  TRACE( "ref count incremented to %lu:%lu for %p\n", 
+  TRACE( "ref count incremented to %lu:%lu for %p\n",
          ulInterfaceRefCount, ulObjRefCount, This );
 
   return ulObjRefCount;
@@ -597,7 +644,7 @@ static ULONG WINAPI DP_Release
      DP_DestroyDirectPlay2( This );
      DP_DestroyIUnknown( This );
   }
-  
+
   /* Deallocate the interface */
   if( ulInterfaceRefCount == 0 )
   {
@@ -613,91 +660,132 @@ static inline DPID DP_NextObjectId(void)
 }
 
 /* *lplpReply will be non NULL iff there is something to reply */
-HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
-                          DWORD  dwMessageBodySize, LPCVOID lpMessageHeader,
-                          WORD wCommandId, WORD wVersion, 
+HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpcMessageBody,
+                          DWORD  dwMessageBodySize, LPCVOID lpcMessageHeader,
+                          WORD wCommandId, WORD wVersion,
                           LPVOID* lplpReply, LPDWORD lpdwMsgSize )
 {
   TRACE( "(%p)->(%p,0x%08lx,%p,%u,%u)\n",
-         This, lpMessageBody, dwMessageBodySize, lpMessageHeader, wCommandId, 
+         This, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
          wVersion );
 
   switch( wCommandId )
   {
+    /* Name server needs to handle this request */
+    case DPMSGCMD_ENUMSESSIONSREQUEST:
+    {
+      /* Reply expected */
+      NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );
+
+      break;
+    }
+
+    /* Name server needs to handle this request */
+    case DPMSGCMD_ENUMSESSIONSREPLY:
+    {
+      /* No reply expected */
+      NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
+                                        This->dp2->spData.dwSPHeaderSize,
+                                        (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
+                                        This->dp2->lpNameServerData );
+      break;
+    }
+
     case DPMSGCMD_REQUESTNEWPLAYERID:
     {
-#if 0
-      LPCDPMSG_REQUESTNEWPLAYERID lpcMsg = 
-        (LPCDPMSG_REQUESTNEWPLAYERID)lpMessageBody;
-#endif
+      LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
+        (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
+
       LPDPMSG_NEWPLAYERIDREPLY lpReply;
 
       *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );
 
-      *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(), 
+      *lplpReply = (LPDPMSG_NEWPLAYERIDREPLY)HeapAlloc( GetProcessHeap(),
                                                         HEAP_ZERO_MEMORY,
                                                         *lpdwMsgSize );
 
-      FIXME( "Ignoring dwFlags in msg\n" );
+      FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
+             lpcMsg->dwFlags );
 
       /* Setup the reply */
-      lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) + 
+      lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
                                             This->dp2->spData.dwSPHeaderSize );
 
       lpReply->envelope.dwMagic    = DPMSGMAGIC_DPLAYMSG;
-      lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY; 
-      lpReply->envelope.wVersion   = DPMSGVER_DP6; 
+      lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
+      lpReply->envelope.wVersion   = DPMSGVER_DP6;
 
-#if 0
-      /* FIXME: Need to know the proper contents of the message! */
       lpReply->dpidNewPlayerId = DP_NextObjectId();
-#endif
+
+      TRACE( "Allocating new playerid 0x%08lx from remote request\n",
+             lpReply->dpidNewPlayerId );
 
       break;
     }
 
+    case DPMSGCMD_GETNAMETABLEREPLY:
     case DPMSGCMD_NEWPLAYERIDREPLY:
     {
 
-      DebugBreak(); 
+#if 0
+      if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
+        DebugBreak();
+#endif
+      DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
 
-      if( This->dp2->hMsgReceipt )
-      {
-        /* This is a hack only */
-        This->dp2->lpMsgReceived = HeapAlloc( GetProcessHeap(), 
-                                              HEAP_ZERO_MEMORY,
-                                              dwMessageBodySize );
-        CopyMemory( This->dp2->lpMsgReceived, lpMessageBody, dwMessageBodySize );
-        SetEvent( This->dp2->hMsgReceipt );
-      }
-      else
-      {
-        ERR( "No receipt event set\n" );
-      }
+      break;
+    }
+
+#if 1
+    case DPMSGCMD_JUSTENVELOPE:
+    {
+      TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
+      NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
+      DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
+    }
+#endif
+
+    case DPMSGCMD_FORWARDADDPLAYER:
+    {
+#if 0
+      DebugBreak();
+#endif
+#if 1
+    TRACE( "Sending message to self to get my addr\n" );
+    DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
+#endif
+      break;
+    }
+
+    case DPMSGCMD_FORWARDADDPLAYERNACK:
+    {
+      DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
       break;
     }
 
     default:
     {
       FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
+      DebugBreak();
       break;
     }
   }
 
+  /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */
+
   return DP_OK;
 }
 
 
 static HRESULT WINAPI DP_IF_AddPlayerToGroup
-          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, 
+          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
             DPID idPlayer, BOOL bAnsi )
 {
   lpGroupData  lpGData;
   lpPlayerList lpPList;
   lpPlayerList lpNewPList;
 
-  TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n", 
+  TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
          This, lpMsgHdr, idGroup, idPlayer, bAnsi );
 
   /* Find the group */
@@ -715,10 +803,10 @@ static HRESULT WINAPI DP_IF_AddPlayerToGroup
   /* Create a player list (ie "shortcut" ) */
   lpNewPList = (lpPlayerList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                                         sizeof( *lpNewPList ) );
-  if( lpNewPList == NULL ) 
+  if( lpNewPList == NULL )
   {
     return DPERR_CANTADDPLAYER;
-  }   
+  }
 
   /* Add the shortcut */
   lpPList->lpPData->uRef++;
@@ -731,7 +819,7 @@ static HRESULT WINAPI DP_IF_AddPlayerToGroup
   if( This->dp2->spData.lpCB->AddPlayerToGroup )
   {
     DPSP_ADDPLAYERTOGROUPDATA data;
-   
+
     TRACE( "Calling SP AddPlayerToGroup\n" );
 
     data.idPlayer = idPlayer;
@@ -751,7 +839,7 @@ static HRESULT WINAPI DP_IF_AddPlayerToGroup
       ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
   {
     DPMSG_ADDPLAYERTOGROUP msg;
-    msg.dwType = DPSYS_ADDPLAYERTOGROUP; 
+    msg.dwType = DPSYS_ADDPLAYERTOGROUP;
 
     msg.dpIdGroup  = idGroup;
     msg.dpIdPlayer = idPlayer;
@@ -797,9 +885,9 @@ static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi )
     TRACE( "Calling SP CloseEx\n" );
 
     data.lpISP = This->dp2->spData.lpISP;
+
     hr = (*This->dp2->spData.lpCB->CloseEx)( &data );
-        
+
   }
   else if ( This->dp2->spData.lpCB->Close ) /* Try obsolete version */
   {
@@ -827,7 +915,7 @@ static HRESULT WINAPI DirectPlay2WImpl_Close
 
 static
 lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
-                            LPDPNAME lpName, DWORD dwFlags, 
+                            LPDPNAME lpName, DWORD dwFlags,
                             DPID idParent, BOOL bAnsi )
 {
   lpGroupData lpGData;
@@ -848,18 +936,20 @@ lpGroupData DP_CreateGroup( IDirectPlay2AImpl* This, LPDPID lpid,
   lpGData->dpid = *lpid;
 
   DP_CopyDPNAMEStruct( &lpGData->name, lpName, bAnsi );
+
   /* FIXME: Should we check that the parent exists? */
   lpGData->parent  = idParent;
 
   /* FIXME: Should we validate the dwFlags? */
   lpGData->dwFlags = dwFlags;
 
+  TRACE( "Created group id 0x%08lx\n", *lpid );
+
   return lpGData;
 }
 
 /* This method assumes that all links to it are already deleted */
-static void 
+static void
 DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
 {
   lpGroupList lpGList;
@@ -886,7 +976,7 @@ DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid )
 
   /* Remove and Delete Player List object */
   HeapFree( GetProcessHeap(), 0, lpGList );
+
 }
 
 static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
@@ -903,7 +993,7 @@ static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
   {
     DPQ_FIND_ENTRY( This->dp2->lpSysGroup->groups, groups, lpGData->dpid, ==, dpid, lpGroups );
   }
-  
+
   if( lpGroups == NULL )
   {
     return NULL;
@@ -913,14 +1003,14 @@ static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid )
 }
 
 static HRESULT WINAPI DP_IF_CreateGroup
-          ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup, 
-            LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, 
+          ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
+            LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
             DWORD dwFlags, BOOL bAnsi )
 {
   lpGroupData lpGData;
 
-  TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n", 
-         This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize, 
+  TRACE( "(%p)->(%p,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
+         This, lpMsgHdr, lpidGroup, lpGroupName, lpData, dwDataSize,
          dwFlags, bAnsi );
 
   /* If the name is not specified, we must provide one */
@@ -938,7 +1028,7 @@ static HRESULT WINAPI DP_IF_CreateGroup
       *lpidGroup = DP_GetRemoteNextObjectId();
     }
   }
+
   lpGData = DP_CreateGroup( This, lpidGroup, lpGroupName, dwFlags,
                             DPID_NOPARENT_GROUP, bAnsi );
 
@@ -949,12 +1039,13 @@ static HRESULT WINAPI DP_IF_CreateGroup
 
   if( DPID_SYSTEM_GROUP == *lpidGroup )
   {
-    This->dp2->lpSysGroup = lpGData; 
+    This->dp2->lpSysGroup = lpGData;
+    TRACE( "Inserting system group\n" );
   }
   else
   {
     /* Insert into the system group */
-    lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(), 
+    lpGroupList lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(),
                                                    HEAP_ZERO_MEMORY,
                                                    sizeof( *lpGroup ) );
     lpGroup->lpGData = lpGData;
@@ -997,12 +1088,12 @@ static HRESULT WINAPI DP_IF_CreateGroup
     (*This->dp2->spData.lpCB->CreateGroup)( &data );
   }
 
-  /* Inform all other peers of the creation of a new group. If there are 
-   * no peers keep this event quiet. 
+  /* Inform all other peers of the creation of a new group. If there are
+   * no peers keep this event quiet.
    * Also if this message was sent to us, don't rebroadcast.
    */
   if( ( lpMsgHdr == NULL ) &&
-      This->dp2->lpSessionDesc && 
+      This->dp2->lpSessionDesc &&
       ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
   {
     DPMSG_CREATEPLAYERORGROUP msg;
@@ -1033,23 +1124,23 @@ static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
 {
   *lpidGroup = DPID_UNKNOWN;
 
-  return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup, 
+  return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
                             lpGroupName, lpData, dwDataSize, dwFlags, TRUE );
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
-          ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName, 
+          ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName,
             LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
 {
   *lpidGroup = DPID_UNKNOWN;
 
-  return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup, 
+  return DP_IF_CreateGroup( (IDirectPlay2AImpl*)iface, NULL, lpidGroup,
                             lpGroupName, lpData, dwDataSize, dwFlags, FALSE );
 }
 
 
 static void
-DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags, 
+DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
                  LPVOID lpData, DWORD dwDataSize )
 {
   /* Clear out the data with this player */
@@ -1093,9 +1184,9 @@ DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
 }
 
 /* This function will just create the storage for the new player.  */
-static 
-lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid, 
-                              LPDPNAME lpName, DWORD dwFlags, 
+static
+lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
+                              LPDPNAME lpName, DWORD dwFlags,
                               HANDLE hEvent, BOOL bAnsi )
 {
   lpPlayerData lpPData;
@@ -1103,7 +1194,7 @@ lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
   TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
 
   /* Allocate the storage for the player and associate it with list element */
-  lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(), 
+  lpPData = (lpPlayerData) HeapAlloc( GetProcessHeap(),
                                       HEAP_ZERO_MEMORY,
                                       sizeof( *lpPData ) );
   if( lpPData == NULL )
@@ -1131,6 +1222,11 @@ lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
     }
   }
 
+  /* Initialize the SP data section */
+  lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
+
+  TRACE( "Created player id 0x%08lx\n", *lpid );
+
   return lpPData;
 }
 
@@ -1138,8 +1234,8 @@ lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* This, LPDPID lpid,
 static void
 DP_DeleteDPNameStruct( LPDPNAME lpDPName )
 {
-  HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->psn.lpszShortNameA ); 
-  HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->pln.lpszLongNameA ); 
+  HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u1.lpszShortNameA );
+  HeapFree( GetProcessHeap(), HEAP_ZERO_MEMORY, lpDPName->u2.lpszLongNameA );
 }
 
 /* This method assumes that all links to it are already deleted */
@@ -1162,9 +1258,9 @@ DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid )
   if( --(lpPList->lpPData->uRef) )
   {
     FIXME( "Why is this not the last reference to player?\n" );
-    DebugBreak(); 
+    DebugBreak();
   }
+
   /* Delete player */
   DP_DeleteDPNameStruct( &lpPList->lpPData->name );
 
@@ -1196,61 +1292,61 @@ static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
     return TRUE;
   }
 
-  if( lpSrc->dwSize != sizeof( *lpSrc) )   
+  if( lpSrc->dwSize != sizeof( *lpSrc) )
   {
     return FALSE;
   }
 
   /* Delete any existing pointers */
-  if( lpDst->psn.lpszShortNameA )
+  if( lpDst->u1.lpszShortNameA )
   {
-    HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
+    HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
   }
 
-  if( lpDst->pln.lpszLongNameA )
+  if( lpDst->u2.lpszLongNameA )
   {
-    HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
+    HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
   }
 
   /* Copy as required */
-  CopyMemory( lpDst, lpSrc, lpSrc->dwSize ); 
+  CopyMemory( lpDst, lpSrc, lpSrc->dwSize );
 
   if( bAnsi )
   {
-    if( lpSrc->psn.lpszShortNameA )
+    if( lpSrc->u1.lpszShortNameA )
     {
-      lpDst->psn.lpszShortNameA = 
-        HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, 
-                        lpSrc->psn.lpszShortNameA );
+        lpDst->u1.lpszShortNameA = HeapAlloc( GetProcessHeap(), 0,
+                                             strlen(lpSrc->u1.lpszShortNameA)+1 );
+        strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
     }
-    if( lpSrc->pln.lpszLongNameA )
+    if( lpSrc->u2.lpszLongNameA )
     {
-      lpDst->pln.lpszLongNameA =
-        HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                        lpSrc->pln.lpszLongNameA );
+        lpDst->u2.lpszLongNameA = HeapAlloc( GetProcessHeap(), 0,
+                                              strlen(lpSrc->u2.lpszLongNameA)+1 );
+        strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
     }
   }
   else
   {
-    if( lpSrc->psn.lpszShortNameA )
+    if( lpSrc->u1.lpszShortNameA )
     {
-      lpDst->psn.lpszShortName = 
-        HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                        lpSrc->psn.lpszShortName );
+        lpDst->u1.lpszShortName = HeapAlloc( GetProcessHeap(), 0,
+                                              (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
+        strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
     }
-    if( lpSrc->pln.lpszLongNameA )
+    if( lpSrc->u2.lpszLongNameA )
     {
-      lpDst->pln.lpszLongName =
-        HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                        lpSrc->pln.lpszLongName );
+        lpDst->u2.lpszLongName = HeapAlloc( GetProcessHeap(), 0,
+                                             (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
+        strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
     }
   }
 
   return TRUE;
 }
 
-static void 
-DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags, 
+static void
+DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
                   LPVOID lpData, DWORD dwDataSize )
 {
   /* Clear out the data with this player */
@@ -1293,25 +1389,27 @@ DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
 
 }
 
-static HRESULT WINAPI DP_IF_CreatePlayer 
-( IDirectPlay2Impl* This, 
+static HRESULT WINAPI DP_IF_CreatePlayer
+( IDirectPlay2Impl* This,
   LPVOID lpMsgHdr, /* NULL for local creation, non NULL for remote creation */
-  LPDPID lpidPlayer, 
-  LPDPNAME lpPlayerName, 
-  HANDLE hEvent, 
-  LPVOID lpData, 
-  DWORD dwDataSize, 
+  LPDPID lpidPlayer,
+  LPDPNAME lpPlayerName,
+  HANDLE hEvent,
+  LPVOID lpData,
+  DWORD dwDataSize,
   DWORD dwFlags,
   BOOL bAnsi )
 {
+  HANDLE hr = DP_OK;
   lpPlayerData lpPData;
   lpPlayerList lpPList;
+  DWORD dwCreateFlags = 0;
 
-  TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n", 
-         This, lpidPlayer, lpPlayerName, hEvent, lpData, 
+  TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
+         This, lpidPlayer, lpPlayerName, hEvent, lpData,
          dwDataSize, dwFlags, bAnsi );
 
-  if( dwFlags == 0 ) 
+  if( dwFlags == 0 )
   {
     dwFlags = DPPLAYER_SPECTATOR;
   }
@@ -1321,6 +1419,35 @@ static HRESULT WINAPI DP_IF_CreatePlayer
     return DPERR_INVALIDPARAMS;
   }
 
+
+  /* Determine the creation flags for the player. These will be passed
+   * to the name server if requesting a player id and to the SP when
+   * informing it of the player creation
+   */
+  {
+    if( dwFlags & DPPLAYER_SERVERPLAYER )
+    {
+      if( *lpidPlayer == DPID_SERVERPLAYER )
+      {
+        /* Server player for the host interface */
+        dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
+      }
+      else if( *lpidPlayer == DPID_NAME_SERVER )
+      {
+        /* Name server - master of everything */
+        dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
+      }
+      else
+      {
+        /* Server player for a non host interface */
+        dwCreateFlags |= DPLAYI_PLAYER_SYSPLAYER;
+      }
+    }
+
+    if( lpMsgHdr == NULL )
+      dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
+  }
+
   /* Verify we know how to handle all the flags */
   if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
          ( dwFlags & DPPLAYER_SPECTATOR )
@@ -1341,7 +1468,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer
     }
     else
     {
-      HRESULT hr = DP_MSG_SendRequestPlayerId( This, dwFlags, lpidPlayer );
+      hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
 
       if( FAILED(hr) )
       {
@@ -1357,6 +1484,7 @@ static HRESULT WINAPI DP_IF_CreatePlayer
      */
   }
 
+  /* FIXME: Should we be storing these dwFlags or the creation ones? */
   lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
                              hEvent, bAnsi );
 
@@ -1381,39 +1509,69 @@ static HRESULT WINAPI DP_IF_CreatePlayer
   DPQ_INSERT( This->dp2->lpSysGroup->players, lpPList, players );
 
   /* Update the information and send it to all players in the session */
-  DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );  
+  DP_SetPlayerData( lpPData, DPSET_REMOTE, lpData, dwDataSize );
 
   /* Let the SP know that we've created this player */
   if( This->dp2->spData.lpCB->CreatePlayer )
   {
     DPSP_CREATEPLAYERDATA data;
-    DWORD dwCreateFlags = 0;
-
-    TRACE( "Calling SP CreatePlayer\n" );
-
-    if( ( dwFlags & DPPLAYER_SERVERPLAYER ) &&
-        ( *lpidPlayer == DPID_SERVERPLAYER )
-      )
-      dwCreateFlags |= DPLAYI_PLAYER_APPSERVER;
-
-    if( ( dwFlags & DPPLAYER_SERVERPLAYER ) &&
-        ( *lpidPlayer == DPID_NAME_SERVER ) 
-      )
-      dwCreateFlags |= (DPLAYI_PLAYER_NAMESRVR|DPLAYI_PLAYER_SYSPLAYER);
-
-    if( lpMsgHdr == NULL )
-      dwCreateFlags |= DPLAYI_PLAYER_PLAYERLOCAL;
 
     data.idPlayer          = *lpidPlayer;
     data.dwFlags           = dwCreateFlags;
     data.lpSPMessageHeader = lpMsgHdr;
     data.lpISP             = This->dp2->spData.lpISP;
 
-    (*This->dp2->spData.lpCB->CreatePlayer)( &data );
+    TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
+           *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
+
+    hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
+  }
+
+  if( FAILED(hr) )
+  {
+    ERR( "Failed to create player with sp: %s\n", DPLAYX_HresultToString(hr) );
+    return hr;
+  }
+
+  /* Now let the SP know that this player is a member of the system group */
+  if( This->dp2->spData.lpCB->AddPlayerToGroup )
+  {
+    DPSP_ADDPLAYERTOGROUPDATA data;
+
+    data.idPlayer = *lpidPlayer;
+    data.idGroup  = DPID_SYSTEM_GROUP;
+    data.lpISP    = This->dp2->spData.lpISP;
+
+    TRACE( "Calling SP AddPlayerToGroup (sys group)\n" );
+
+    hr = (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
+  }
+
+  if( FAILED(hr) )
+  {
+    ERR( "Failed to add player to sys group with sp: %s\n",
+         DPLAYX_HresultToString(hr) );
+    return hr;
   }
 
+#if 1
+  if( This->dp2->bHostInterface == FALSE )
+  {
+    /* Let the name server know about the creation of this player */
+    /* FIXME: Is this only to be done for the creation of a server player or
+     *        is this used for regular players? If only for server players, move
+     *        this call to DP_SecureOpen(...);
+     */
+#if 0
+    TRACE( "Sending message to self to get my addr\n" );
+    DP_MSG_ToSelf( This, *lpidPlayer ); /* This is a hack right now */
+#endif
+
+    hr = DP_MSG_ForwardPlayerCreation( This, *lpidPlayer);
+  }
+#else
   /* Inform all other peers of the creation of a new player. If there are
-   * no peers keep this quiet. 
+   * no peers keep this quiet.
    * Also, if this was a remote event, no need to rebroadcast it.
    */
   if( ( lpMsgHdr == NULL ) &&
@@ -1435,15 +1593,16 @@ static HRESULT WINAPI DP_IF_CreatePlayer
     /* FIXME: Correct to just use send effectively? */
     /* FIXME: Should size include data w/ message or just message "header" */
     /* FIXME: Check return code */
-    DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
-               0, 0, NULL, NULL, bAnsi );
+    hr = DP_SendEx( This, DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg,
+                    sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
   }
+#endif
 
-  return DP_OK;
+  return hr;
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
-          ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName, 
+          ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
             HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -1457,12 +1616,12 @@ static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
     *lpidPlayer = DPID_UNKNOWN;
   }
 
-  return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent, 
+  return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
                            lpData, dwDataSize, dwFlags, TRUE );
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
-          ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName, 
+          ( LPDIRECTPLAY2 iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName,
             HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -1476,7 +1635,7 @@ static HRESULT WINAPI DirectPlay2WImpl_CreatePlayer
     *lpidPlayer = DPID_UNKNOWN;
   }
 
-  return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent, 
+  return DP_IF_CreatePlayer( This, NULL, lpidPlayer, lpPlayerName, hEvent,
                            lpData, dwDataSize, dwFlags, FALSE );
 }
 
@@ -1489,15 +1648,15 @@ static DPID DP_GetRemoteNextObjectId(void)
 }
 
 static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
-          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, 
+          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
             DPID idPlayer, BOOL bAnsi )
 {
   HRESULT hr = DP_OK;
 
   lpGroupData  lpGData;
   lpPlayerList lpPList;
-  
-  TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n", 
+
+  TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
          This, lpMsgHdr, idGroup, idPlayer, bAnsi );
 
   /* Find the group */
@@ -1577,24 +1736,24 @@ cbRemoveGroupOrPlayer(
 {
   lpDPRGOPContext lpCtxt = (lpDPRGOPContext)lpContext;
 
-  TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n", 
+  TRACE( "Removing element:0x%08lx (type:0x%08lx) from element:0x%08lx\n",
            dpId, dwPlayerType, lpCtxt->idGroup );
 
   if( dwPlayerType == DPPLAYERTYPE_GROUP )
   {
-    if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup, 
-                                            dpId ) 
-              ) 
+    if( FAILED( DP_IF_DeleteGroupFromGroup( lpCtxt->This, lpCtxt->idGroup,
+                                            dpId )
+              )
       )
     {
-      ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n", 
+      ERR( "Unable to delete group 0x%08lx from group 0x%08lx\n",
              dpId, lpCtxt->idGroup );
     }
   }
   else
   {
-    if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This, 
-                                             NULL, lpCtxt->idGroup, 
+    if( FAILED( DP_IF_DeletePlayerFromGroup( (IDirectPlay2Impl*)lpCtxt->This,
+                                             NULL, lpCtxt->idGroup,
                                              dpId, lpCtxt->bAnsi )
               )
       )
@@ -1603,7 +1762,7 @@ cbRemoveGroupOrPlayer(
              dpId, lpCtxt->idGroup );
     }
   }
-  
+
   return TRUE; /* Continue enumeration */
 }
 
@@ -1613,7 +1772,7 @@ static HRESULT WINAPI DP_IF_DestroyGroup
   lpGroupData lpGData;
   DPRGOPContext context;
 
-  FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n", 
+  FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
          This, lpMsgHdr, idGroup, bAnsi );
 
   /* Find the group */
@@ -1627,11 +1786,11 @@ static HRESULT WINAPI DP_IF_DestroyGroup
   context.idGroup = idGroup;
 
   /* Remove all players that this group has */
-  DP_IF_EnumGroupPlayers( This, idGroup, NULL, 
+  DP_IF_EnumGroupPlayers( This, idGroup, NULL,
                           cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
 
   /* Remove all links to groups that this group has since this is dp3 */
-  DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL, 
+  DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, idGroup, NULL,
                            cbRemoveGroupOrPlayer, (LPVOID)&context, 0, bAnsi );
 
   /* Remove this group from the parent group - if it has one */
@@ -1639,12 +1798,12 @@ static HRESULT WINAPI DP_IF_DestroyGroup
       ( lpGData->parent != DPID_SYSTEM_GROUP )
     )
   {
-    DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent, 
-                                idGroup ); 
+    DP_IF_DeleteGroupFromGroup( (IDirectPlay3Impl*)This, lpGData->parent,
+                                idGroup );
   }
-  
+
   /* Now delete this group data and list from the system group */
-  DP_DeleteGroup( This, idGroup ); 
+  DP_DeleteGroup( This, idGroup );
 
   /* Let the SP know that we've destroyed this group */
   if( This->dp2->spData.lpCB->DeleteGroup )
@@ -1654,7 +1813,7 @@ static HRESULT WINAPI DP_IF_DestroyGroup
     FIXME( "data.dwFlags is incorrect\n" );
 
     data.idGroup = idGroup;
-    data.dwFlags = 0; 
+    data.dwFlags = 0;
     data.lpISP   = This->dp2->spData.lpISP;
 
     (*This->dp2->spData.lpCB->DeleteGroup)( &data );
@@ -1691,7 +1850,7 @@ static HRESULT WINAPI DP_IF_DestroyPlayer
 {
   DPFAGContext cbContext;
 
-  FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n", 
+  FIXME( "(%p)->(%p,0x%08lx,%u): semi stub\n",
          This, lpMsgHdr, idPlayer, bAnsi );
 
   if( DP_FindPlayer( This, idPlayer ) == NULL )
@@ -1721,7 +1880,7 @@ static HRESULT WINAPI DP_IF_DestroyPlayer
     FIXME( "data.dwFlags is incorrect\n" );
 
     data.idPlayer = idPlayer;
-    data.dwFlags = 0; 
+    data.dwFlags = 0;
     data.lpISP   = This->dp2->spData.lpISP;
 
     (*This->dp2->spData.lpCB->DeletePlayer)( &data );
@@ -1753,7 +1912,7 @@ cbDeletePlayerFromAllGroups(
     DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)lpCtxt->This,
                              dpId, NULL,
                              cbDeletePlayerFromAllGroups,
-                             (LPVOID)lpContext, DPENUMGROUPS_ALL, 
+                             (LPVOID)lpContext, DPENUMGROUPS_ALL,
                              lpCtxt->bAnsi );
 
   }
@@ -1780,15 +1939,15 @@ static HRESULT WINAPI DirectPlay2WImpl_DestroyPlayer
 }
 
 static HRESULT WINAPI DP_IF_EnumGroupPlayers
-          ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance, 
+          ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
             LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
 {
   lpGroupData  lpGData;
   lpPlayerList lpPList;
 
-  FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n", 
-          This, idGroup, lpguidInstance, lpEnumPlayersCallback2, 
+  FIXME("(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
+          This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
           lpContext, dwFlags, bAnsi );
 
   /* Find the group */
@@ -1801,7 +1960,7 @@ static HRESULT WINAPI DP_IF_EnumGroupPlayers
   {
     return DP_OK;
   }
+
   lpPList = DPQ_FIRST( lpGData->players );
 
   /* Walk the players in this group */
@@ -1811,7 +1970,7 @@ static HRESULT WINAPI DP_IF_EnumGroupPlayers
      * concequence to the end user.
      */
     if( ( lpPList->lpPData->dpid != DPID_NAME_SERVER ) &&
-        ( lpPList->lpPData->dpid != DPID_SERVERPLAYER ) 
+        ( lpPList->lpPData->dpid != DPID_SERVERPLAYER )
       )
     {
 
@@ -1830,7 +1989,7 @@ static HRESULT WINAPI DP_IF_EnumGroupPlayers
 
     if( DPQ_IS_ENDOFLIST( lpPList->players ) )
     {
-      break; 
+      break;
     }
 
     lpPList = DPQ_NEXT( lpPList->players );
@@ -1840,7 +1999,7 @@ static HRESULT WINAPI DP_IF_EnumGroupPlayers
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
-          ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance, 
+          ( LPDIRECTPLAY2A iface, DPID idGroup, LPGUID lpguidInstance,
             LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags )
 {
@@ -1851,7 +2010,7 @@ static HRESULT WINAPI DirectPlay2AImpl_EnumGroupPlayers
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
-          ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance, 
+          ( LPDIRECTPLAY2 iface, DPID idGroup, LPGUID lpguidInstance,
             LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags )
 {
@@ -1863,19 +2022,19 @@ static HRESULT WINAPI DirectPlay2WImpl_EnumGroupPlayers
 
 /* NOTE: This only enumerates top level groups (created with CreateGroup) */
 static HRESULT WINAPI DP_IF_EnumGroups
-          ( IDirectPlay2Impl* This, LPGUID lpguidInstance, 
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 
+          ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
 {
-  return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This, 
+  return DP_IF_EnumGroupsInGroup( (IDirectPlay3Impl*)This,
                                   DPID_SYSTEM_GROUP, lpguidInstance,
                                   lpEnumPlayersCallback2, lpContext,
                                   dwFlags, bAnsi );
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
-          ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance, 
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 
+          ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -1884,8 +2043,8 @@ static HRESULT WINAPI DirectPlay2AImpl_EnumGroups
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
-          ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance, 
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 
+          ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -1894,8 +2053,8 @@ static HRESULT WINAPI DirectPlay2WImpl_EnumGroups
 }
 
 static HRESULT WINAPI DP_IF_EnumPlayers
-          ( IDirectPlay2Impl* This, LPGUID lpguidInstance, 
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 
+          ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
 {
   return DP_IF_EnumGroupPlayers( This, DPID_SYSTEM_GROUP, lpguidInstance,
@@ -1904,8 +2063,8 @@ static HRESULT WINAPI DP_IF_EnumPlayers
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
-          ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance, 
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 
+          ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance,
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -1914,8 +2073,8 @@ static HRESULT WINAPI DirectPlay2AImpl_EnumPlayers
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
-          ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance, 
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 
+          ( LPDIRECTPLAY2 iface, LPGUID lpguidInstance,
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -1936,6 +2095,9 @@ static void DP_InvokeEnumSessionCallbacks
 
   FIXME( ": not checking for conditions\n" );
 
+  /* Not sure if this should be pruning but it's convenient */
+  NS_PruneSessionCache( lpNSInfo );
+
   NS_ResetSessionEnumeration( lpNSInfo );
 
   /* Enumerate all sessions */
@@ -2006,7 +2168,8 @@ static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
   /* Does a thread exist? If so we were doing an async enum session */
   if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
   {
-    TRACE( "Killing EnumSession thread\n" );
+    TRACE( "Killing EnumSession thread %u\n",
+           This->dp2->hEnumSessionThread );
 
     /* Request that the thread kill itself nicely */
     SetEvent( This->dp2->hKillEnumSessionThreadEvent );
@@ -2020,13 +2183,13 @@ static void DP_KillEnumSessionThread( IDirectPlay2Impl* This )
 }
 
 static HRESULT WINAPI DP_IF_EnumSessions
-          ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, 
+          ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
             LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
             LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
 {
   HRESULT hr = DP_OK;
 
-  TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n", 
+  TRACE( "(%p)->(%p,0x%08lx,%p,%p,0x%08lx,%u)\n",
          This, lpsd, dwTimeout, lpEnumSessionsCallback2, lpContext, dwFlags,
          bAnsi );
 
@@ -2036,6 +2199,47 @@ static HRESULT WINAPI DP_IF_EnumSessions
     return DPERR_GENERIC;
   }
 
+#if 1
+  /* The loading of a lobby provider _seems_ to require a backdoor loading
+   * of the service provider to also associate with this DP object. This is
+   * because the app doesn't seem to have to call EnumConnections and
+   * InitializeConnection for the SP before calling this method. As such
+   * we'll do their dirty work for them with a quick hack so as to always
+   * load the TCP/IP service provider.
+   *
+   * The correct solution would seem to involve creating a dialog box which
+   * contains the possible SPs. These dialog boxes most likely follow SDK
+   * examples.
+   */
+   if( This->dp2->bDPLSPInitialized && !This->dp2->bSPInitialized )
+   {
+     LPVOID lpConnection;
+     DWORD  dwSize;
+
+     WARN( "Hack providing TCP/IP SP for lobby provider activated\n" );
+
+     if( !DP_BuildSPCompoundAddr( (LPGUID)&DPSPGUID_TCPIP, &lpConnection, &dwSize ) )
+     {
+       ERR( "Can't build compound addr\n" );
+       return DPERR_GENERIC;
+     }
+
+     hr = DP_IF_InitializeConnection( (IDirectPlay3Impl*)This, lpConnection,
+                                      0, bAnsi );
+     if( FAILED(hr) )
+     {
+       return hr;
+     }
+
+     /* Free up the address buffer */
+     HeapFree( GetProcessHeap(), 0, lpConnection );
+
+     /* The SP is now initialized */
+     This->dp2->bSPInitialized = TRUE;
+   }
+#endif
+
+
   /* Use the service provider default? */
   if( dwTimeout == 0 )
   {
@@ -2045,7 +2249,12 @@ static HRESULT WINAPI DP_IF_EnumSessions
     DP_IF_GetCaps( This, &spCaps, 0 );
     dwTimeout = spCaps.dwTimeout;
 
-    /* FIXME: If it's still 0, we need to provide the IP default */
+    /* The service provider doesn't provide one either! */
+    if( dwTimeout == 0 )
+    {
+      /* Provide the TCP/IP default */
+      dwTimeout = DPMSG_WAIT_5_SECS;
+    }
   }
 
   if( dwFlags & DPENUMSESSIONS_STOPASYNC )
@@ -2058,8 +2267,8 @@ static HRESULT WINAPI DP_IF_EnumSessions
   if( ( dwFlags & DPENUMSESSIONS_ASYNC ) )
   {
     /* Enumerate everything presently in the local session cache */
-    DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2, 
-                                   This->dp2->lpNameServerData, dwTimeout, 
+    DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
+                                   This->dp2->lpNameServerData, dwTimeout,
                                    lpContext );
 
 
@@ -2076,20 +2285,21 @@ static HRESULT WINAPI DP_IF_EnumSessions
 
       if( !FAILED(hr) )
       {
-        EnumSessionAsyncCallbackData* lpData 
+        EnumSessionAsyncCallbackData* lpData
           = (EnumSessionAsyncCallbackData*)HeapAlloc( GetProcessHeap(),
                                                       HEAP_ZERO_MEMORY,
                                                        sizeof( *lpData ) );
         /* FIXME: need to kill the thread on object deletion */
         lpData->lpSpData  = &This->dp2->spData;
+
         CopyMemory( &lpData->requestGuid, &lpsd->guidApplication, sizeof(GUID) );
         lpData->dwEnumSessionFlags = dwFlags;
         lpData->dwTimeout = dwTimeout;
-  
-        This->dp2->hKillEnumSessionThreadEvent = 
+
+        This->dp2->hKillEnumSessionThreadEvent =
           CreateEventA( NULL, TRUE, FALSE, NULL );
-  
-        if( !DuplicateHandle( GetCurrentProcess(), 
+
+        if( !DuplicateHandle( GetCurrentProcess(),
                               This->dp2->hKillEnumSessionThreadEvent,
                               GetCurrentProcess(),
                               &lpData->hSuicideRequest,
@@ -2098,9 +2308,9 @@ static HRESULT WINAPI DP_IF_EnumSessions
         {
           ERR( "Can't duplicate thread killing handle\n" );
         }
-  
+
         TRACE( ": creating EnumSessionsRequest thread\n" );
-  
+
         This->dp2->hEnumSessionThread = CreateThread( NULL,
                                                       0,
                                                       DP_EnumSessionsSendAsyncRequestThread,
@@ -2108,7 +2318,7 @@ static HRESULT WINAPI DP_IF_EnumSessions
                                                       0,
                                                       &dwThreadId );
       }
-    } 
+    }
   }
   else
   {
@@ -2123,8 +2333,8 @@ static HRESULT WINAPI DP_IF_EnumSessions
 
     SleepEx( dwTimeout, FALSE );
 
-    DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2, 
-                                   This->dp2->lpNameServerData, dwTimeout, 
+    DP_InvokeEnumSessionCallbacks( lpEnumSessionsCallback2,
+                                   This->dp2->lpNameServerData, dwTimeout,
                                    lpContext );
   }
 
@@ -2132,7 +2342,7 @@ static HRESULT WINAPI DP_IF_EnumSessions
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
-          ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, 
+          ( LPDIRECTPLAY2A iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
             LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
             LPVOID lpContext, DWORD dwFlags )
 {
@@ -2142,7 +2352,7 @@ static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
-          ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout, 
+          ( LPDIRECTPLAY2 iface, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
             LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
             LPVOID lpContext, DWORD dwFlags )
 {
@@ -2152,7 +2362,7 @@ static HRESULT WINAPI DirectPlay2WImpl_EnumSessions
 }
 
 static HRESULT WINAPI DP_IF_GetPlayerCaps
-          ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps, 
+          ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
             DWORD dwFlags )
 {
   DPSP_GETCAPSDATA data;
@@ -2189,14 +2399,14 @@ static HRESULT WINAPI DirectPlay2WImpl_GetCaps
 }
 
 static HRESULT WINAPI DP_IF_GetGroupData
-          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 
+          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
             LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
 {
   lpGroupData lpGData;
   DWORD dwRequiredBufferSize;
   LPVOID lpCopyDataFrom;
 
-  TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n", 
+  TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
          This, idGroup, lpData, lpdwDataSize, dwFlags, bAnsi );
 
   if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
@@ -2224,11 +2434,11 @@ static HRESULT WINAPI DP_IF_GetGroupData
 
   /* Is the user requesting to know how big a buffer is required? */
   if( ( lpData == NULL ) ||
-      ( *lpdwDataSize < dwRequiredBufferSize ) 
+      ( *lpdwDataSize < dwRequiredBufferSize )
     )
   {
     *lpdwDataSize = dwRequiredBufferSize;
-    return DPERR_BUFFERTOOSMALL; 
+    return DPERR_BUFFERTOOSMALL;
   }
 
   CopyMemory( lpData, lpCopyDataFrom, dwRequiredBufferSize );
@@ -2237,32 +2447,32 @@ static HRESULT WINAPI DP_IF_GetGroupData
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_GetGroupData
-          ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData, 
+          ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
             LPDWORD lpdwDataSize, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
-  return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize, 
+  return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
                            dwFlags, TRUE );
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_GetGroupData
-          ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData, 
+          ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
             LPDWORD lpdwDataSize, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
-  return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize, 
+  return DP_IF_GetGroupData( This, idGroup, lpData, lpdwDataSize,
                            dwFlags, FALSE );
 }
 
 static HRESULT WINAPI DP_IF_GetGroupName
-          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 
+          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
             LPDWORD lpdwDataSize, BOOL bAnsi )
 {
   lpGroupData lpGData;
   LPDPNAME    lpName = (LPDPNAME)lpData;
   DWORD       dwRequiredDataSize;
 
-  FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n", 
+  FIXME("(%p)->(0x%08lx,%p,%p,%u) ANSI ignored\n",
           This, idGroup, lpData, lpdwDataSize, bAnsi );
 
   if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
@@ -2272,16 +2482,16 @@ static HRESULT WINAPI DP_IF_GetGroupName
 
   dwRequiredDataSize = lpGData->name.dwSize;
 
-  if( lpGData->name.psn.lpszShortNameA )
+  if( lpGData->name.u1.lpszShortNameA )
   {
-    dwRequiredDataSize += strlen( lpGData->name.psn.lpszShortNameA ) + 1;
+    dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
   }
 
-  if( lpGData->name.pln.lpszLongNameA )
+  if( lpGData->name.u2.lpszLongNameA )
   {
-    dwRequiredDataSize += strlen( lpGData->name.pln.lpszLongNameA ) + 1;
+    dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
   }
+
   if( ( lpData == NULL ) ||
       ( *lpdwDataSize < dwRequiredDataSize )
     )
@@ -2293,31 +2503,31 @@ static HRESULT WINAPI DP_IF_GetGroupName
   /* Copy the structure */
   CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
 
-  if( lpGData->name.psn.lpszShortNameA )
+  if( lpGData->name.u1.lpszShortNameA )
   {
-    strcpy( ((BYTE*)lpName)+lpGData->name.dwSize, 
-            lpGData->name.psn.lpszShortNameA );
+    strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
+            lpGData->name.u1.lpszShortNameA );
   }
   else
   {
-    lpName->psn.lpszShortNameA = NULL;
+    lpName->u1.lpszShortNameA = NULL;
   }
 
-  if( lpGData->name.psn.lpszShortNameA )
+  if( lpGData->name.u1.lpszShortNameA )
   {
-    strcpy( ((BYTE*)lpName)+lpGData->name.dwSize, 
-            lpGData->name.pln.lpszLongNameA );
+    strcpy( ((BYTE*)lpName)+lpGData->name.dwSize,
+            lpGData->name.u2.lpszLongNameA );
   }
   else
   {
-    lpName->pln.lpszLongNameA = NULL;
+    lpName->u2.lpszLongNameA = NULL;
   }
 
   return DP_OK;
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
-          ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData, 
+          ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
             LPDWORD lpdwDataSize )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -2325,7 +2535,7 @@ static HRESULT WINAPI DirectPlay2AImpl_GetGroupName
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
-          ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData, 
+          ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
             LPDWORD lpdwDataSize )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -2333,12 +2543,12 @@ static HRESULT WINAPI DirectPlay2WImpl_GetGroupName
 }
 
 static HRESULT WINAPI DP_IF_GetMessageCount
-          ( IDirectPlay2Impl* This, DPID idPlayer, 
+          ( IDirectPlay2Impl* This, DPID idPlayer,
             LPDWORD lpdwCount, BOOL bAnsi )
 {
   FIXME("(%p)->(0x%08lx,%p,%u): stub\n", This, idPlayer, lpdwCount, bAnsi );
-  return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer, 
-                                DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL, 
+  return DP_IF_GetMessageQueue( (IDirectPlay4Impl*)This, 0, idPlayer,
+                                DPMESSAGEQUEUE_RECEIVE, lpdwCount, NULL,
                                 bAnsi );
 }
 
@@ -2373,7 +2583,7 @@ static HRESULT WINAPI DirectPlay2WImpl_GetPlayerAddress
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
-          ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps, 
+          ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -2381,7 +2591,7 @@ static HRESULT WINAPI DirectPlay2AImpl_GetPlayerCaps
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
-          ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps, 
+          ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPCAPS lpPlayerCaps,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -2389,14 +2599,14 @@ static HRESULT WINAPI DirectPlay2WImpl_GetPlayerCaps
 }
 
 static HRESULT WINAPI DP_IF_GetPlayerData
-          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData, 
+          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
             LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi )
 {
   lpPlayerList lpPList;
   DWORD dwRequiredBufferSize;
   LPVOID lpCopyDataFrom;
 
-  TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n", 
+  TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx,%u)\n",
          This, idPlayer, lpData, lpdwDataSize, dwFlags, bAnsi );
 
   if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
@@ -2437,32 +2647,32 @@ static HRESULT WINAPI DP_IF_GetPlayerData
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerData
-          ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, 
+          ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
             LPDWORD lpdwDataSize, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
-  return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize, 
+  return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
                             dwFlags, TRUE );
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerData
-          ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, 
+          ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
             LPDWORD lpdwDataSize, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
-  return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize, 
+  return DP_IF_GetPlayerData( This, idPlayer, lpData, lpdwDataSize,
                             dwFlags, FALSE );
 }
 
 static HRESULT WINAPI DP_IF_GetPlayerName
-          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData, 
+          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
             LPDWORD lpdwDataSize, BOOL bAnsi )
 {
   lpPlayerList lpPList;
   LPDPNAME    lpName = (LPDPNAME)lpData;
   DWORD       dwRequiredDataSize;
 
-  FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n", 
+  FIXME( "(%p)->(0x%08lx,%p,%p,%u): ANSI \n",
          This, idPlayer, lpData, lpdwDataSize, bAnsi );
 
   if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
@@ -2472,14 +2682,14 @@ static HRESULT WINAPI DP_IF_GetPlayerName
 
   dwRequiredDataSize = lpPList->lpPData->name.dwSize;
 
-  if( lpPList->lpPData->name.psn.lpszShortNameA )
+  if( lpPList->lpPData->name.u1.lpszShortNameA )
   {
-    dwRequiredDataSize += strlen( lpPList->lpPData->name.psn.lpszShortNameA ) + 1;
+    dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
   }
 
-  if( lpPList->lpPData->name.pln.lpszLongNameA )
+  if( lpPList->lpPData->name.u2.lpszLongNameA )
   {
-    dwRequiredDataSize += strlen( lpPList->lpPData->name.pln.lpszLongNameA ) + 1;
+    dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
   }
 
   if( ( lpData == NULL ) ||
@@ -2493,31 +2703,31 @@ static HRESULT WINAPI DP_IF_GetPlayerName
   /* Copy the structure */
   CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
 
-  if( lpPList->lpPData->name.psn.lpszShortNameA )
+  if( lpPList->lpPData->name.u1.lpszShortNameA )
   {
     strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
-            lpPList->lpPData->name.psn.lpszShortNameA );
+            lpPList->lpPData->name.u1.lpszShortNameA );
   }
   else
   {
-    lpName->psn.lpszShortNameA = NULL;
+    lpName->u1.lpszShortNameA = NULL;
   }
 
-  if( lpPList->lpPData->name.psn.lpszShortNameA )
+  if( lpPList->lpPData->name.u1.lpszShortNameA )
   {
     strcpy( ((BYTE*)lpName)+lpPList->lpPData->name.dwSize,
-            lpPList->lpPData->name.pln.lpszLongNameA );
+            lpPList->lpPData->name.u2.lpszLongNameA );
   }
   else
   {
-    lpName->pln.lpszLongNameA = NULL;
+    lpName->u2.lpszLongNameA = NULL;
   }
 
   return DP_OK;
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
-          ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, 
+          ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
             LPDWORD lpdwDataSize )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -2525,7 +2735,7 @@ static HRESULT WINAPI DirectPlay2AImpl_GetPlayerName
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
-          ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, 
+          ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
             LPDWORD lpdwDataSize )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -2533,14 +2743,14 @@ static HRESULT WINAPI DirectPlay2WImpl_GetPlayerName
 }
 
 static HRESULT WINAPI DP_GetSessionDesc
-          ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize, 
+          ( IDirectPlay2Impl* This, LPVOID lpData, LPDWORD lpdwDataSize,
             BOOL bAnsi )
 {
   DWORD dwRequiredSize;
 
   TRACE( "(%p)->(%p,%p,%u)\n", This, lpData, lpdwDataSize, bAnsi );
 
-  if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) ) 
+  if( ( lpData == NULL ) && ( lpdwDataSize == NULL ) )
   {
     return DPERR_INVALIDPARAMS;
   }
@@ -2555,10 +2765,10 @@ static HRESULT WINAPI DP_GetSessionDesc
     *lpdwDataSize = dwRequiredSize;
     return DPERR_BUFFERTOOSMALL;
   }
-  
+
   DP_CopySessionDesc( lpData, This->dp2->lpSessionDesc, bAnsi );
 
-  return DP_OK;  
+  return DP_OK;
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_GetSessionDesc
@@ -2601,7 +2811,7 @@ static HRESULT WINAPI DP_SecureOpen
 {
   HRESULT hr = DP_OK;
 
-  FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n", 
+  FIXME( "(%p)->(%p,0x%08lx,%p,%p): partial stub\n",
          This, lpsd, dwFlags, lpSecurity, lpCredentials );
 
   if( This->dp2->bConnectionOpen )
@@ -2617,14 +2827,14 @@ static HRESULT WINAPI DP_SecureOpen
   {
     /* Rightoo - this computer is the host and the local computer needs to be
        the name server so that others can join this session */
-    NS_SetLocalComputerAsNameServer( lpsd );
+    NS_SetLocalComputerAsNameServer( lpsd, This->dp2->lpNameServerData );
 
     This->dp2->bHostInterface = TRUE;
 
     hr = DP_SetSessionDesc( This, lpsd, 0, TRUE, bAnsi );
     if( FAILED( hr ) )
     {
-      ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );  
+      ERR( "Unable to set session desc: %s\n", DPLAYX_HresultToString( hr ) );
       return hr;
     }
   }
@@ -2637,7 +2847,7 @@ static HRESULT WINAPI DP_SecureOpen
     FIXME( "Not all data fields are correct. Need new parameter\n" );
 
     data.bCreate           = (dwFlags & DPOPEN_CREATE ) ? TRUE : FALSE;
-    data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL 
+    data.lpSPMessageHeader = (dwFlags & DPOPEN_CREATE ) ? NULL
                                                         : NS_GetNSAddr( This->dp2->lpNameServerData );
     data.lpISP             = This->dp2->spData.lpISP;
     data.bReturnStatus     = (dwFlags & DPOPEN_RETURNSTATUS) ? TRUE : FALSE;
@@ -2647,7 +2857,7 @@ static HRESULT WINAPI DP_SecureOpen
     hr = (*This->dp2->spData.lpCB->Open)(&data);
     if( FAILED( hr ) )
     {
-      ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );  
+      ERR( "Unable to open session: %s\n", DPLAYX_HresultToString( hr ) );
       return hr;
     }
   }
@@ -2658,24 +2868,25 @@ static HRESULT WINAPI DP_SecureOpen
 
     hr = DP_IF_CreateGroup( This, NULL, &systemGroup, NULL,
                             NULL, 0, 0, TRUE );
-                       
+
   }
 
   if( dwFlags & DPOPEN_JOIN )
   {
-    DPID dpidServerId = DPID_SERVERPLAYER;
+    DPID dpidServerId = DPID_UNKNOWN;
+
     /* Create the server player for this interface. This way we can receive
      * messages for this session.
      */
-    /* FIXME: I suppose that we should be setting an event for a receive 
+    /* FIXME: I suppose that we should be setting an event for a receive
      *        type of thing. That way the messaging thread could know to wake
      *        up. DPlay would then trigger the hEvent for the player the
      *        message is directed to.
      */
-    hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL, 
-                             0, 
+    hr = DP_IF_CreatePlayer( This, NULL, &dpidServerId, NULL, 0, NULL,
+                             0,
                              DPPLAYER_SERVERPLAYER | DPPLAYER_LOCAL , bAnsi );
+
   }
   else if( dwFlags & DPOPEN_CREATE )
   {
@@ -2685,6 +2896,12 @@ static HRESULT WINAPI DP_SecureOpen
                              0, DPPLAYER_SERVERPLAYER, bAnsi );
   }
 
+  if( FAILED(hr) )
+  {
+    ERR( "Couldn't create name server/system player: %s\n",
+         DPLAYX_HresultToString(hr) );
+  }
+
   return hr;
 }
 
@@ -2705,12 +2922,12 @@ static HRESULT WINAPI DirectPlay2WImpl_Open
 }
 
 static HRESULT WINAPI DP_IF_Receive
-          ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo, 
+          ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
             DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi )
 {
   LPDPMSG lpMsg = NULL;
 
-  FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n", 
+  FIXME( "(%p)->(%p,%p,0x%08lx,%p,%p,%u): stub\n",
          This, lpidFrom, lpidTo, dwFlags, lpData, lpdwDataSize, bAnsi );
 
   if( dwFlags == 0 )
@@ -2733,7 +2950,7 @@ static HRESULT WINAPI DP_IF_Receive
     if( !( dwFlags & DPRECEIVE_PEEK ) )
     {
       FIXME( "Remove from queue\n" );
-    } 
+    }
   }
   else if( ( dwFlags & DPRECEIVE_TOPLAYER ) ||
            ( dwFlags & DPRECEIVE_FROMPLAYER )
@@ -2758,20 +2975,20 @@ static HRESULT WINAPI DP_IF_Receive
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_Receive
-          ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo, 
+          ( LPDIRECTPLAY2A iface, LPDPID lpidFrom, LPDPID lpidTo,
             DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
-  return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, 
+  return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
                         lpData, lpdwDataSize, TRUE );
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_Receive
-          ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo, 
+          ( LPDIRECTPLAY2 iface, LPDPID lpidFrom, LPDPID lpidTo,
             DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
-  return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags, 
+  return DP_IF_Receive( This, lpidFrom, lpidTo, dwFlags,
                         lpData, lpdwDataSize, FALSE );
 }
 
@@ -2779,7 +2996,7 @@ static HRESULT WINAPI DirectPlay2AImpl_Send
           ( LPDIRECTPLAY2A iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
-  return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize, 
+  return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
                     0, 0, NULL, NULL, TRUE );
 }
 
@@ -2787,17 +3004,17 @@ static HRESULT WINAPI DirectPlay2WImpl_Send
           ( LPDIRECTPLAY2 iface, DPID idFrom, DPID idTo, DWORD dwFlags, LPVOID lpData, DWORD dwDataSize )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
-  return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize, 
+  return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
                     0, 0, NULL, NULL, FALSE );
 }
 
 static HRESULT WINAPI DP_IF_SetGroupData
-          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData, 
+          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
             DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
 {
   lpGroupData lpGData;
 
-  TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n", 
+  TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
          This, idGroup, lpData, dwDataSize, dwFlags, bAnsi );
 
   /* Parameter check */
@@ -2817,7 +3034,7 @@ static HRESULT WINAPI DP_IF_SetGroupData
   if( dwFlags & DPSET_REMOTE )
   {
     FIXME( "Was this group created by this interface?\n" );
-    /* FIXME: If this is a remote update need to allow it but not 
+    /* FIXME: If this is a remote update need to allow it but not
      *        send a message.
      */
   }
@@ -2836,28 +3053,28 @@ static HRESULT WINAPI DP_IF_SetGroupData
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
-          ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData, 
+          ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData,
             DWORD dwDataSize, DWORD dwFlags )
-{  
+{
   ICOM_THIS(IDirectPlay2Impl,iface);
   return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, TRUE );
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_SetGroupData
-          ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData, 
+          ( LPDIRECTPLAY2 iface, DPID idGroup, LPVOID lpData,
             DWORD dwDataSize, DWORD dwFlags )
-{   
+{
   ICOM_THIS(IDirectPlay2Impl,iface);
   return DP_IF_SetGroupData( This, idGroup, lpData, dwDataSize, dwFlags, FALSE );
 }
 
 static HRESULT WINAPI DP_IF_SetGroupName
-          ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName, 
+          ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
             DWORD dwFlags, BOOL bAnsi )
 {
   lpGroupData lpGData;
 
-  TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup, 
+  TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", This, idGroup,
          lpGroupName, dwFlags, bAnsi );
 
   if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
@@ -2874,7 +3091,7 @@ static HRESULT WINAPI DP_IF_SetGroupName
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
-          ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName, 
+          ( LPDIRECTPLAY2A iface, DPID idGroup, LPDPNAME lpGroupName,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -2882,7 +3099,7 @@ static HRESULT WINAPI DirectPlay2AImpl_SetGroupName
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
-          ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName, 
+          ( LPDIRECTPLAY2 iface, DPID idGroup, LPDPNAME lpGroupName,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -2890,12 +3107,12 @@ static HRESULT WINAPI DirectPlay2WImpl_SetGroupName
 }
 
 static HRESULT WINAPI DP_IF_SetPlayerData
-          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData, 
+          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
             DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
 {
   lpPlayerList lpPList;
 
-  TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n", 
+  TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx,%u)\n",
          This, idPlayer, lpData, dwDataSize, dwFlags, bAnsi );
 
   /* Parameter check */
@@ -2915,7 +3132,7 @@ static HRESULT WINAPI DP_IF_SetPlayerData
   if( dwFlags & DPSET_REMOTE )
   {
     FIXME( "Was this group created by this interface?\n" );
-    /* FIXME: If this is a remote update need to allow it but not 
+    /* FIXME: If this is a remote update need to allow it but not
      *        send a message.
      */
   }
@@ -2931,30 +3148,30 @@ static HRESULT WINAPI DP_IF_SetPlayerData
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
-          ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, 
+          ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData,
             DWORD dwDataSize, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
-  return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize, 
+  return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
                               dwFlags, TRUE );
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerData
-          ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData, 
+          ( LPDIRECTPLAY2 iface, DPID idPlayer, LPVOID lpData,
             DWORD dwDataSize, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
-  return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize, 
+  return DP_IF_SetPlayerData( This, idPlayer, lpData, dwDataSize,
                               dwFlags, FALSE );
 }
 
 static HRESULT WINAPI DP_IF_SetPlayerName
-          ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName, 
+          ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
             DWORD dwFlags, BOOL bAnsi )
 {
   lpPlayerList lpPList;
 
-  TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n", 
+  TRACE( "(%p)->(0x%08lx,%p,0x%08lx,%u)\n",
          This, idPlayer, lpPlayerName, dwFlags, bAnsi );
 
   if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
@@ -2971,7 +3188,7 @@ static HRESULT WINAPI DP_IF_SetPlayerName
 }
 
 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
-          ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName, 
+          ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -2979,7 +3196,7 @@ static HRESULT WINAPI DirectPlay2AImpl_SetPlayerName
 }
 
 static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
-          ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName, 
+          ( LPDIRECTPLAY2 iface, DPID idPlayer, LPDPNAME lpPlayerName,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
@@ -2987,13 +3204,13 @@ static HRESULT WINAPI DirectPlay2WImpl_SetPlayerName
 }
 
 static HRESULT WINAPI DP_SetSessionDesc
-          ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc, 
+          ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
             DWORD dwFlags, BOOL bInitial, BOOL bAnsi  )
 {
   DWORD            dwRequiredSize;
   LPDPSESSIONDESC2 lpTempSessDesc;
 
-  TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n", 
+  TRACE( "(%p)->(%p,0x%08lx,%u,%u)\n",
          This, lpSessDesc, dwFlags, bInitial, bAnsi );
 
   if( dwFlags )
@@ -3009,8 +3226,8 @@ static HRESULT WINAPI DP_SetSessionDesc
 
   /* FIXME: Copy into This->dp2->lpSessionDesc */
   dwRequiredSize = DP_CalcSessionDescSize( lpSessDesc, bAnsi );
-  lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(), 
-                                                HEAP_ZERO_MEMORY, 
+  lpTempSessDesc = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
+                                                HEAP_ZERO_MEMORY,
                                                 dwRequiredSize );
 
   if( lpTempSessDesc == NULL )
@@ -3026,13 +3243,13 @@ static HRESULT WINAPI DP_SetSessionDesc
   /* Set the new */
   DP_CopySessionDesc( This->dp2->lpSessionDesc, lpSessDesc, bAnsi );
 
-  /* If this is an external invocation of the interface, we should be 
+  /* If this is an external invocation of the interface, we should be
    * letting everyone know that things have changed. Otherwise this is
    * just an initialization and it doesn't need to be propagated.
    */
   if( !bInitial )
   {
-    FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" ); 
+    FIXME( "Need to send a DPMSG_SETSESSIONDESC msg to everyone\n" );
   }
 
   return DP_OK;
@@ -3068,28 +3285,28 @@ DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
 
   if( bAnsi )
   {
-    if( lpSessDesc->sess.lpszSessionNameA )
+    if( lpSessDesc->u1.lpszSessionNameA )
     {
-      dwSize += lstrlenA( lpSessDesc->sess.lpszSessionNameA ) + 1;
+      dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
     }
 
-    if( lpSessDesc->pass.lpszPasswordA )
+    if( lpSessDesc->u2.lpszPasswordA )
     {
-      dwSize += lstrlenA( lpSessDesc->pass.lpszPasswordA ) + 1;
+      dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
     }
   }
   else /* UNICODE */
   {
-    if( lpSessDesc->sess.lpszSessionName )
+    if( lpSessDesc->u1.lpszSessionName )
     {
       dwSize += sizeof( WCHAR ) *
-        ( lstrlenW( lpSessDesc->sess.lpszSessionName ) + 1 );
+        ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
     }
 
-    if( lpSessDesc->pass.lpszPassword )
+    if( lpSessDesc->u2.lpszPassword )
     {
       dwSize += sizeof( WCHAR ) *
-        ( lstrlenW( lpSessDesc->pass.lpszPassword ) + 1 );
+        ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
     }
   }
 
@@ -3097,7 +3314,7 @@ DWORD DP_CalcSessionDescSize( LPCDPSESSIONDESC2 lpSessDesc, BOOL bAnsi )
 }
 
 /* Assumes that contugous buffers are already allocated. */
-static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest, 
+static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
                                 LPCDPSESSIONDESC2 lpSessionSrc, BOOL bAnsi )
 {
   BYTE* lpStartOfFreeSpace;
@@ -3114,44 +3331,44 @@ static void DP_CopySessionDesc( LPDPSESSIONDESC2 lpSessionDest,
 
   if( bAnsi )
   {
-    if( lpSessionSrc->sess.lpszSessionNameA )
+    if( lpSessionSrc->u1.lpszSessionNameA )
     {
-      lstrcpyA( (LPSTR)lpStartOfFreeSpace, 
-                lpSessionDest->sess.lpszSessionNameA );
-      lpSessionDest->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
-      lpStartOfFreeSpace += 
-        lstrlenA( (LPSTR)lpSessionDest->sess.lpszSessionNameA ) + 1;
-    } 
-
-    if( lpSessionSrc->pass.lpszPasswordA )
+      lstrcpyA( (LPSTR)lpStartOfFreeSpace,
+                lpSessionDest->u1.lpszSessionNameA );
+      lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
+      lpStartOfFreeSpace +=
+        lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
+    }
+
+    if( lpSessionSrc->u2.lpszPasswordA )
     {
-      lstrcpyA( (LPSTR)lpStartOfFreeSpace, 
-                lpSessionDest->pass.lpszPasswordA );
-      lpSessionDest->pass.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
-      lpStartOfFreeSpace += 
-        lstrlenA( (LPSTR)lpSessionDest->pass.lpszPasswordA ) + 1;
-    }  
+      lstrcpyA( (LPSTR)lpStartOfFreeSpace,
+                lpSessionDest->u2.lpszPasswordA );
+      lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
+      lpStartOfFreeSpace +=
+        lstrlenA( (LPSTR)lpSessionDest->u2.lpszPasswordA ) + 1;
+    }
   }
   else /* UNICODE */
   {
-    if( lpSessionSrc->sess.lpszSessionName )
+    if( lpSessionSrc->u1.lpszSessionName )
     {
       lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
-                lpSessionDest->sess.lpszSessionName );
-      lpSessionDest->sess.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
+                lpSessionDest->u1.lpszSessionName );
+      lpSessionDest->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace += sizeof(WCHAR) *
-        ( lstrlenW( (LPWSTR)lpSessionDest->sess.lpszSessionName ) + 1 );
+        ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
     }
 
-    if( lpSessionSrc->pass.lpszPassword )
-    { 
-      lstrcpyW( (LPWSTR)lpStartOfFreeSpace, 
-                lpSessionDest->pass.lpszPassword );
-      lpSessionDest->pass.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
+    if( lpSessionSrc->u2.lpszPassword )
+    {
+      lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
+                lpSessionDest->u2.lpszPassword );
+      lpSessionDest->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace += sizeof(WCHAR) *
-        ( lstrlenW( (LPWSTR)lpSessionDest->pass.lpszPassword ) + 1 );
+        ( lstrlenW( (LPWSTR)lpSessionDest->u2.lpszPassword ) + 1 );
     }
-  }  
+  }
 }
 
 
@@ -3173,14 +3390,14 @@ static HRESULT WINAPI DP_IF_AddGroupToGroup
   {
     return DPERR_INVALIDGROUP;
   }
+
   /* Create a player list (ie "shortcut" ) */
   lpNewGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                                        sizeof( *lpNewGList ) );
   if( lpNewGList == NULL )
   {
     return DPERR_CANTADDPLAYER;
-  }  
+  }
 
   /* Add the shortcut */
   lpGData->uRef++;
@@ -3191,7 +3408,7 @@ static HRESULT WINAPI DP_IF_AddGroupToGroup
 
   /* Send a ADDGROUPTOGROUP message */
   FIXME( "Not sending message\n" );
-  
+
   return DP_OK;
 }
 
@@ -3210,27 +3427,27 @@ static HRESULT WINAPI DirectPlay3WImpl_AddGroupToGroup
 }
 
 static HRESULT WINAPI DP_IF_CreateGroupInGroup
-          ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup, 
-            LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, 
+          ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
+            LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
             DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi )
 {
   lpGroupData lpGParentData;
   lpGroupList lpGList;
   lpGroupData lpGData;
 
-  TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n", 
-         This, idParentGroup, lpidGroup, lpGroupName, lpData, 
+  TRACE( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,0x%08lx,%u)\n",
+         This, idParentGroup, lpidGroup, lpGroupName, lpData,
          dwDataSize, dwFlags, bAnsi );
 
   /* Verify that the specified parent is valid */
-  if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, 
-                                         idParentGroup ) ) == NULL 
+  if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This,
+                                         idParentGroup ) ) == NULL
     )
   {
     return DPERR_INVALIDGROUP;
-  } 
+  }
 
-  lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName, 
+  lpGData = DP_CreateGroup( (IDirectPlay2AImpl*)This, lpidGroup, lpGroupName,
                             dwFlags, idParentGroup, bAnsi );
 
   if( lpGData == NULL )
@@ -3240,12 +3457,12 @@ static HRESULT WINAPI DP_IF_CreateGroupInGroup
 
   /* Something else is referencing this data */
   lpGData->uRef++;
-  
+
   DP_SetGroupData( lpGData, DPSET_REMOTE, lpData, dwDataSize );
 
   /* The list has now been inserted into the interface group list. We now
      need to put a "shortcut" to this group in the parent group */
-  lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 
+  lpGList = (lpGroupList)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                                     sizeof( *lpGList ) );
   if( lpGList == NULL )
   {
@@ -3253,7 +3470,7 @@ static HRESULT WINAPI DP_IF_CreateGroupInGroup
     return DPERR_CANTADDPLAYER; /* yes player not group */
   }
 
-  lpGList->lpGData = lpGData; 
+  lpGList->lpGData = lpGData;
 
   DPQ_INSERT( lpGParentData->groups, lpGList, groups );
 
@@ -3272,10 +3489,10 @@ static HRESULT WINAPI DP_IF_CreateGroupInGroup
     (*This->dp2->spData.lpCB->CreateGroup)( &data );
   }
 
-  /* Inform all other peers of the creation of a new group. If there are 
-   * no peers keep this quiet. 
+  /* Inform all other peers of the creation of a new group. If there are
+   * no peers keep this quiet.
    */
-  if( This->dp2->lpSessionDesc && 
+  if( This->dp2->lpSessionDesc &&
       ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
   {
     DPMSG_CREATEPLAYERORGROUP msg;
@@ -3291,7 +3508,7 @@ static HRESULT WINAPI DP_IF_CreateGroupInGroup
     /* FIXME: Correct to just use send effectively? */
     /* FIXME: Should size include data w/ message or just message "header" */
     /* FIXME: Check return code */
-    DP_SendEx( (IDirectPlay2Impl*)This, 
+    DP_SendEx( (IDirectPlay2Impl*)This,
                DPID_SERVERPLAYER, DPID_ALLPLAYERS, 0, &msg, sizeof( msg ),
                0, 0, NULL, NULL, bAnsi );
   }
@@ -3300,30 +3517,30 @@ static HRESULT WINAPI DP_IF_CreateGroupInGroup
 }
 
 static HRESULT WINAPI DirectPlay3AImpl_CreateGroupInGroup
-          ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup, 
-            LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, 
+          ( LPDIRECTPLAY3A iface, DPID idParentGroup, LPDPID lpidGroup,
+            LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay3Impl,iface);
 
   *lpidGroup = DPID_UNKNOWN;
 
-  return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, 
-                                   lpGroupName, lpData, dwDataSize, dwFlags, 
+  return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
+                                   lpGroupName, lpData, dwDataSize, dwFlags,
                                    TRUE );
 }
 
 static HRESULT WINAPI DirectPlay3WImpl_CreateGroupInGroup
-          ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup, 
-            LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, 
+          ( LPDIRECTPLAY3 iface, DPID idParentGroup, LPDPID lpidGroup,
+            LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay3Impl,iface);
 
   *lpidGroup = DPID_UNKNOWN;
 
-  return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup, 
-                                   lpGroupName, lpData, dwDataSize, 
+  return DP_IF_CreateGroupInGroup( This, NULL, idParentGroup, lpidGroup,
+                                   lpGroupName, lpData, dwDataSize,
                                    dwFlags, FALSE );
 }
 
@@ -3339,7 +3556,7 @@ static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
   if( ( lpGParentData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idParentGroup ) ) == NULL )
   {
     return DPERR_INVALIDGROUP;
-  } 
+  }
 
   /* Remove the group from the parent group queue */
   DPQ_REMOVE_ENTRY( lpGParentData->groups, groups, lpGData->dpid, ==, idGroup, lpGList );
@@ -3353,7 +3570,7 @@ static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
   lpGList->lpGData->uRef--;
 
   /* Free up the list item */
-  HeapFree( GetProcessHeap(), 0, lpGList ); 
+  HeapFree( GetProcessHeap(), 0, lpGList );
 
   /* Should send a DELETEGROUPFROMGROUP message */
   FIXME( "message not sent\n" );
@@ -3375,6 +3592,45 @@ static HRESULT WINAPI DirectPlay3WImpl_DeleteGroupFromGroup
   return DP_IF_DeleteGroupFromGroup( This, idParentGroup, idGroup );
 }
 
+static
+BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
+                                    LPDWORD lpdwBufSize )
+{
+  DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
+  HRESULT                  hr;
+
+  dpCompoundAddress.dwDataSize = sizeof( GUID );
+  memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider,
+          sizeof( GUID ) ) ;
+  dpCompoundAddress.lpData = lpcSpGuid;
+
+  *lplpAddrBuf = NULL;
+  *lpdwBufSize = 0;
+
+  hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
+                                  lpdwBufSize, TRUE );
+
+  if( hr != DPERR_BUFFERTOOSMALL )
+  {
+    ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
+    return FALSE;
+  }
+
+  /* Now allocate the buffer */
+  *lplpAddrBuf = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                            *lpdwBufSize );
+
+  hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, *lplpAddrBuf,
+                                  lpdwBufSize, TRUE );
+  if( FAILED(hr) )
+  {
+    ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
 static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
           ( LPDIRECTPLAY3A iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
 {
@@ -3389,7 +3645,7 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
 
   if( ! ( ( dwFlags & DPCONNECTION_DIRECTPLAY ) ||
           ( dwFlags & DPCONNECTION_DIRECTPLAYLOBBY ) )
-    ) 
+    )
   {
     return DPERR_INVALIDFLAGS;
   }
@@ -3405,7 +3661,7 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
     HKEY hkResult;
     LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
     LPSTR guidDataSubKey   = "Guid";
-    char subKeyName[51]; 
+    char subKeyName[51];
     DWORD dwIndex, sizeOfSubKeyName=50;
     FILETIME filetime;
 
@@ -3421,7 +3677,7 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
 
     /* Traverse all the service providers we have available */
     for( dwIndex=0;
-         RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 
+         RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
                         NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
          ++dwIndex, sizeOfSubKeyName=51 )
     {
@@ -3430,11 +3686,10 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
       GUID     serviceProviderGUID;
       DWORD    returnTypeGUID, sizeOfReturnBuffer = 50;
       char     returnBuffer[51];
-      LPWSTR   lpWGUIDString;
+      WCHAR    buff[51];
       DPNAME   dpName;
-      HRESULT  hr;
+      BOOL     bBuildPass;
 
-      DPCOMPOUNDADDRESSELEMENT dpCompoundAddress;
       LPVOID                   lpAddressBuffer = NULL;
       DWORD                    dwAddressBufferSize = 0;
 
@@ -3457,47 +3712,36 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
       }
 
       /* FIXME: Check return types to ensure we're interpreting data right */
-      lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
-      CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
-      HeapFree( GetProcessHeap(), 0, lpWGUIDString );
+      MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
+      CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
       /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
 
       /* Fill in the DPNAME struct for the service provider */
       dpName.dwSize             = sizeof( dpName );
       dpName.dwFlags            = 0;
-      dpName.psn.lpszShortNameA = subKeyName;
-      dpName.pln.lpszLongNameA  = NULL;
-
-      /* Create the compound address for the service provider. 
-         NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
-               nast stuff. This may be why the native dll just gets around this little bit by
-               allocating an 80 byte buffer which isn't even a filled with a valid compound 
-               address. Oh well. Creating a proper compound address is the way to go anyways 
-               despite this method taking slightly more heap space and realtime :) */
-      dpCompoundAddress.dwDataSize   = sizeof( GUID );
-      memcpy( &dpCompoundAddress.guidDataType, &DPAID_ServiceProvider, 
-              sizeof( GUID ) ) ;
-      dpCompoundAddress.lpData       = &serviceProviderGUID; 
-
-      if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer, 
-                                     &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
+      dpName.u1.lpszShortNameA = subKeyName;
+      dpName.u2.lpszLongNameA  = NULL;
+
+      /* Create the compound address for the service provider.
+       * NOTE: This is a gruesome architectural scar right now.  DP
+       * uses DPL and DPL uses DP.  Nasty stuff. This may be why the
+       * native dll just gets around this little bit by allocating an
+       * 80 byte buffer which isn't even filled with a valid compound
+       * address. Oh well. Creating a proper compound address is the
+       * way to go anyways despite this method taking slightly more
+       * heap space and realtime :) */
+
+      bBuildPass = DP_BuildSPCompoundAddr( &serviceProviderGUID,
+                                           &lpAddressBuffer,
+                                           &dwAddressBufferSize );
+      if( !bBuildPass )
       {
-        ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
-        return hr;
-      }
-
-      /* Now allocate the buffer */
-      lpAddressBuffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressBufferSize );
-
-      if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
-                                     &dwAddressBufferSize, TRUE ) ) != DP_OK )
-      {
-        ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) );
-        return hr;
+        ERR( "Can't build compound addr\n" );
+        return DPERR_GENERIC;
       }
 
       /* The enumeration will return FALSE if we are not to continue */
-      if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize, 
+      if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize,
                            &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) )
       {
          return DP_OK;
@@ -3511,7 +3755,7 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
     HKEY hkResult;
     LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
     LPSTR guidDataSubKey   = "Guid";
-    char subKeyName[51]; 
+    char subKeyName[51];
     DWORD dwIndex, sizeOfSubKeyName=50;
     FILETIME filetime;
 
@@ -3527,7 +3771,7 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
 
     /* Traverse all the lobby providers we have available */
     for( dwIndex=0;
-         RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 
+         RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
                         NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
          ++dwIndex, sizeOfSubKeyName=51 )
     {
@@ -3536,7 +3780,7 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
       GUID     serviceProviderGUID;
       DWORD    returnTypeGUID, sizeOfReturnBuffer = 50;
       char     returnBuffer[51];
-      LPWSTR   lpWGUIDString;
+      WCHAR    buff[51];
       DPNAME   dpName;
       HRESULT  hr;
 
@@ -3563,28 +3807,28 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
       }
 
       /* FIXME: Check return types to ensure we're interpreting data right */
-      lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
-      CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
-      HeapFree( GetProcessHeap(), 0, lpWGUIDString );
+      MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
+      CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
       /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
 
       /* Fill in the DPNAME struct for the service provider */
       dpName.dwSize             = sizeof( dpName );
       dpName.dwFlags            = 0;
-      dpName.psn.lpszShortNameA = subKeyName;
-      dpName.pln.lpszLongNameA  = NULL;
+      dpName.u1.lpszShortNameA = subKeyName;
+      dpName.u2.lpszLongNameA  = NULL;
 
-      /* Create the compound address for the service provider. 
+      /* Create the compound address for the service provider.
          NOTE: This is a gruesome architectural scar right now. DP uses DPL and DPL uses DP
                nast stuff. This may be why the native dll just gets around this little bit by
-               allocating an 80 byte buffer which isn't even a filled with a valid compound 
-               address. Oh well. Creating a proper compound address is the way to go anyways 
+               allocating an 80 byte buffer which isn't even a filled with a valid compound
+               address. Oh well. Creating a proper compound address is the way to go anyways
                despite this method taking slightly more heap space and realtime :) */
+
       dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
       dpCompoundAddress.dwDataSize   = sizeof( GUID );
-      dpCompoundAddress.lpData       = &serviceProviderGUID; 
+      dpCompoundAddress.lpData       = &serviceProviderGUID;
 
-      if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer, 
+      if( ( hr = DPL_CreateCompoundAddress( &dpCompoundAddress, 1, lpAddressBuffer,
                                      &dwAddressBufferSize, TRUE ) ) != DPERR_BUFFERTOOSMALL )
       {
         ERR( "can't get buffer size: %s\n", DPLAYX_HresultToString( hr ) );
@@ -3615,7 +3859,7 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections
 
 static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
           ( LPDIRECTPLAY3 iface, LPCGUID lpguidApplication, LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, LPVOID lpContext, DWORD dwFlags )
-{ 
+{
   ICOM_THIS(IDirectPlay3Impl,iface);
   FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidApplication, lpEnumCallback, lpContext, dwFlags );
   return DP_OK;
@@ -3623,17 +3867,17 @@ static HRESULT WINAPI DirectPlay3WImpl_EnumConnections
 
 static HRESULT WINAPI DP_IF_EnumGroupsInGroup
           ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, 
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
             LPVOID lpContext, DWORD dwFlags, BOOL bAnsi )
 {
   lpGroupList lpGList;
   lpGroupData lpGData;
 
-  FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n", 
-         This, idGroup, lpguidInstance, lpEnumPlayersCallback2,  
+  FIXME( "(%p)->(0x%08lx,%p,%p,%p,0x%08lx,%u): semi stub\n",
+         This, idGroup, lpguidInstance, lpEnumPlayersCallback2,
          lpContext, dwFlags, bAnsi );
 
-  if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL ) 
+  if( ( lpGData = DP_FindAnyGroup( (IDirectPlay2AImpl*)This, idGroup ) ) == NULL )
   {
     return DPERR_INVALIDGROUP;
   }
@@ -3669,12 +3913,12 @@ static HRESULT WINAPI DP_IF_EnumGroupsInGroup
 }
 
 static HRESULT WINAPI DirectPlay3AImpl_EnumGroupsInGroup
-          ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance, 
-            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, 
+          ( LPDIRECTPLAY3A iface, DPID idGroup, LPGUID lpguidInstance,
+            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay3Impl,iface);
-  return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance, 
+  return DP_IF_EnumGroupsInGroup( This, idGroup, lpguidInstance,
                                   lpEnumPlayersCallback2, lpContext, dwFlags,
                                   TRUE );
 }
@@ -3717,7 +3961,7 @@ BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
       ( IsEqualGUID( guidDataType, &DPAID_LobbyProvider ) )
     )
   {
-    TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n", 
+    TRACE( "Found SP/LP (%s) %s (data size = 0x%08lx)\n",
            debugstr_guid( guidDataType ), debugstr_guid( lpData ), dwDataSize );
 
     if( dwDataSize != sizeof( GUID ) )
@@ -3730,18 +3974,18 @@ BOOL CALLBACK DP_GetSpLpGuidFromCompoundAddress(
     /* There shouldn't be more than 1 GUID/compound address */
     return FALSE;
   }
-  
+
   /* Still waiting for what we want */
   return TRUE;
 }
 
 
 /* Find and perform a LoadLibrary on the requested SP or LP GUID */
-static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
+static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp )
 {
-  UINT i; 
+  UINT i;
   LPCSTR spSubKey         = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
-  LPCSTR lpSubKey         = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers"; 
+  LPCSTR lpSubKey         = "SOFTWARE\\Microsoft\\DirectPlay\\Lobby Providers";
   LPCSTR guidDataSubKey   = "Guid";
   LPCSTR majVerDataSubKey = "dwReserved1";
   LPCSTR minVerDataSubKey = "dwReserved2";
@@ -3759,7 +4003,8 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
     FILETIME filetime;
 
     (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
-    
+    *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
+
 
     /* Need to loop over the service providers in the registry */
     if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
@@ -3781,8 +4026,8 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
       GUID     serviceProviderGUID;
       DWORD    returnType, sizeOfReturnBuffer = 255;
       char     returnBuffer[256];
-      LPWSTR   lpWGUIDString;
-      DWORD    dwTemp;
+      WCHAR    buff[51];
+      DWORD    dwTemp, len;
 
       TRACE(" this time through: %s\n", subKeyName );
 
@@ -3803,9 +4048,8 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
       }
 
       /* FIXME: Check return types to ensure we're interpreting data right */
-      lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
-      CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
-      HeapFree( GetProcessHeap(), 0, lpWGUIDString );
+      MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
+      CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
       /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
 
       /* Determine if this is the Service Provider that the user asked for */
@@ -3814,8 +4058,12 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
         continue;
       }
 
-      /* Save the name of the SP or LP */
-      lpSpData->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0, subKeyName );
+      if( i == 0 ) /* DP SP */
+      {
+        len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
+        lpSpData->lpszName = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+        MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
+      }
 
       sizeOfReturnBuffer = 255;
 
@@ -3828,8 +4076,9 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
          continue;
       }
 
-      lpSpData->dwReserved1 = GET_DWORD( returnBuffer );
+      if( i == 0 )
+          memcpy( &lpSpData->dwReserved1, returnBuffer, sizeof(lpSpData->dwReserved1) );
+
       sizeOfReturnBuffer = 255;
 
       /* Get dwReserved2 */
@@ -3841,11 +4090,11 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
          continue;
       }
 
-      lpSpData->dwReserved2 = GET_DWORD( returnBuffer );
-
+      if( i == 0 )
+          memcpy( &lpSpData->dwReserved2, returnBuffer, sizeof(lpSpData->dwReserved2) );
 
       sizeOfReturnBuffer = 255;
-   
+
       /* Get the path for this service provider */
       if( ( dwTemp = RegQueryValueExA( hkServiceProvider, pathSubKey,
                             NULL, NULL, returnBuffer,
@@ -3855,6 +4104,7 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
         continue;
       }
 
+      TRACE( "Loading %s\n", returnBuffer );
       return LoadLibraryA( returnBuffer );
     }
   }
@@ -3862,31 +4112,105 @@ static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData )
   return 0;
 }
 
-static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
-          ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
+static
+HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider )
 {
-  HMODULE hServiceProvider;
   HRESULT hr;
   LPDPSP_SPINIT SPInit;
-  GUID guidSP;
-  DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
 
-  ICOM_THIS(IDirectPlay3Impl,iface);
+  /* Initialize the service provider by calling SPInit */
+  SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
+
+  if( SPInit == NULL )
+  {
+    ERR( "Service provider doesn't provide SPInit interface?\n" );
+    FreeLibrary( hServiceProvider );
+    return DPERR_UNAVAILABLE;
+  }
 
-  TRACE("(%p)->(%p,0x%08lx)\n", This, lpConnection, dwFlags );
+  TRACE( "Calling SPInit (DP SP entry point)\n" );
 
-  if( dwFlags != 0 )
+  hr = (*SPInit)( &This->dp2->spData );
+
+  if( FAILED(hr) )
   {
-    return DPERR_INVALIDFLAGS;
+    ERR( "DP SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
+    FreeLibrary( hServiceProvider );
+    return hr;
   }
 
-  if( This->dp2->bConnectionInitialized == TRUE )
+  /* FIXME: Need to verify the sanity of the returned callback table
+   *        using IsBadCodePtr */
+  This->dp2->bSPInitialized = TRUE;
+
+  /* This interface is now initialized as a DP object */
+  This->dp2->connectionInitialized = DP_SERVICE_PROVIDER;
+
+  /* Store the handle of the module so that we can unload it later */
+  This->dp2->hServiceProvider = hServiceProvider;
+
+  return hr;
+}
+
+static
+HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hLobbyProvider )
+{
+  HRESULT hr;
+  LPSP_INIT DPLSPInit;
+
+  /* Initialize the service provider by calling SPInit */
+  DPLSPInit = (LPSP_INIT)GetProcAddress( hLobbyProvider, "DPLSPInit" );
+
+  if( DPLSPInit == NULL )
   {
-    return DPERR_ALREADYINITIALIZED;
+    ERR( "Service provider doesn't provide DPLSPInit interface?\n" );
+    FreeLibrary( hLobbyProvider );
+    return DPERR_UNAVAILABLE;
+  }
+
+  TRACE( "Calling DPLSPInit (DPL SP entry point)\n" );
+
+  hr = (*DPLSPInit)( &This->dp2->dplspData );
+
+  if( FAILED(hr) )
+  {
+    ERR( "DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
+    FreeLibrary( hLobbyProvider );
+    return hr;
+  }
+
+  /* FIXME: Need to verify the sanity of the returned callback table
+   *        using IsBadCodePtr */
+
+  This->dp2->bDPLSPInitialized = TRUE;
+
+  /* This interface is now initialized as a lobby object */
+  This->dp2->connectionInitialized = DP_LOBBY_PROVIDER;
+
+  /* Store the handle of the module so that we can unload it later */
+  This->dp2->hDPLobbyProvider = hLobbyProvider;
+
+  return hr;
+}
+
+static HRESULT WINAPI DP_IF_InitializeConnection
+          ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
+{
+  HMODULE hServiceProvider;
+  HRESULT hr;
+  GUID guidSP;
+  const DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
+  BOOL bIsDpSp; /* TRUE if Direct Play SP, FALSE if Direct Play Lobby SP */
+
+  TRACE("(%p)->(%p,0x%08lx,%u)\n", This, lpConnection, dwFlags, bAnsi );
+
+  if( dwFlags != 0 )
+  {
+    return DPERR_INVALIDFLAGS;
   }
 
   /* Find out what the requested SP is and how large this buffer is */
-  hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection, 
+  hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection,
                         dwAddrSize, &guidSP );
 
   if( FAILED(hr) )
@@ -3895,61 +4219,71 @@ static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
     return DPERR_UNAVAILABLE;
   }
 
-  /* Initialize what we can of the Service Provider required information.
-   * The rest will be done in DP_LoadSP
-   */
-  This->dp2->spData.lpAddress = lpConnection;
-  This->dp2->spData.dwAddressSize = dwAddrSize;
-  This->dp2->spData.lpGuid = &guidSP;
-
   /* Load the service provider */
-  hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData );
+  hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
 
   if( hServiceProvider == 0 )
   {
     ERR( "Unable to load service provider\n" );
-    return DPERR_UNAVAILABLE; 
+    return DPERR_UNAVAILABLE;
   }
-  
-  /* Initialize the service provider by calling SPInit */
-  SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
 
-  if( SPInit == NULL )
+  if( bIsDpSp )
   {
-    ERR( "Service provider doesn't provide SPInit interface?\n" );
-    FreeLibrary( hServiceProvider );
-    return DPERR_UNAVAILABLE;
-  }  
+     /* Fill in what we can of the Service Provider required information.
+      * The rest was be done in DP_LoadSP
+      */
+     This->dp2->spData.lpAddress = lpConnection;
+     This->dp2->spData.dwAddressSize = dwAddrSize;
+     This->dp2->spData.lpGuid = &guidSP;
 
-  TRACE( "Calling SPInit\n" );
-  hr = (*SPInit)( &This->dp2->spData );
+     hr = DP_InitializeDPSP( This, hServiceProvider );
+  }
+  else
+  {
+     This->dp2->dplspData.lpAddress = lpConnection;
+
+     hr = DP_InitializeDPLSP( This, hServiceProvider );
+  }
 
   if( FAILED(hr) )
   {
-    ERR( "SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
-    FreeLibrary( hServiceProvider );
     return hr;
   }
 
-  /* This interface is now initialized */
-  This->dp2->bConnectionInitialized = TRUE;
+  return DP_OK;
+}
 
-  /* Store the handle of the module so that we can unload it later */
-  This->dp2->hServiceProvider = hServiceProvider;
+static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
+          ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
+{
+  ICOM_THIS(IDirectPlay3Impl,iface);
 
-  return DP_OK;
+  /* This may not be externally invoked once either an SP or LP is initialized */
+  if( This->dp2->connectionInitialized != NO_PROVIDER )
+  {
+    return DPERR_ALREADYINITIALIZED;
+  }
+
+  return DP_IF_InitializeConnection( This, lpConnection, dwFlags, TRUE );
 }
 
 static HRESULT WINAPI DirectPlay3WImpl_InitializeConnection
           ( LPDIRECTPLAY3 iface, LPVOID lpConnection, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay3Impl,iface);
-  FIXME("(%p)->(%p,0x%08lx): stub\n", This, lpConnection, dwFlags );
-  return DP_OK;
+
+  /* This may not be externally invoked once either an SP or LP is initialized */
+  if( This->dp2->connectionInitialized != NO_PROVIDER )
+  {
+    return DPERR_ALREADYINITIALIZED;
+  }
+
+  return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
 }
 
 static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
-          ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags, 
+          ( LPDIRECTPLAY3A iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
             LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
 {
   ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
@@ -3957,9 +4291,9 @@ static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
 }
 
 static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
-          ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags, 
+          ( LPDIRECTPLAY3 iface, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
             LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials )
-{   
+{
   ICOM_THIS(IDirectPlay2Impl,iface); /* Yes a dp 2 interface */
   return DP_SecureOpen( This, lpsd, dwFlags, lpSecurity, lpCredentials, FALSE );
 }
@@ -4011,7 +4345,7 @@ static HRESULT WINAPI DirectPlay3WImpl_StartSession
   FIXME("(%p)->(0x%08lx,0x%08lx): stub\n", This, dwFlags, idGroup );
   return DP_OK;
 }
+
 static HRESULT WINAPI DirectPlay3AImpl_GetGroupFlags
           ( LPDIRECTPLAY3A iface, DPID idGroup, LPDWORD lpdwFlags )
 {
@@ -4029,7 +4363,7 @@ static HRESULT WINAPI DirectPlay3WImpl_GetGroupFlags
 }
 
 static HRESULT WINAPI DP_IF_GetGroupParent
-          ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup, 
+          ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
             BOOL bAnsi )
 {
   lpGroupData lpGData;
@@ -4050,13 +4384,13 @@ static HRESULT WINAPI DirectPlay3AImpl_GetGroupParent
           ( LPDIRECTPLAY3A iface, DPID idGroup, LPDPID lpidGroup )
 {
   ICOM_THIS(IDirectPlay3Impl,iface);
-  return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE ); 
+  return DP_IF_GetGroupParent( This, idGroup, lpidGroup, TRUE );
 }
 static HRESULT WINAPI DirectPlay3WImpl_GetGroupParent
           ( LPDIRECTPLAY3 iface, DPID idGroup, LPDPID lpidGroup )
 {
   ICOM_THIS(IDirectPlay3Impl,iface);
-  return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE ); 
+  return DP_IF_GetGroupParent( This, idGroup, lpidGroup, FALSE );
 }
 
 static HRESULT WINAPI DirectPlay3AImpl_GetPlayerAccount
@@ -4124,7 +4458,7 @@ static HRESULT WINAPI DirectPlay4WImpl_SetGroupOwner
 }
 
 static HRESULT WINAPI DP_SendEx
-          ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags, 
+          ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
             LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
             LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi )
 {
@@ -4161,7 +4495,7 @@ static HRESULT WINAPI DP_SendEx
    */
   if( idTo == DPID_ALLPLAYERS )
   {
-    bValidDestination = TRUE;  
+    bValidDestination = TRUE;
 
     /* See if SP has the ability to multicast. If so, use it */
     if( This->dp2->spData.lpCB->SendToGroupEx )
@@ -4179,7 +4513,7 @@ static HRESULT WINAPI DP_SendEx
     }
   }
 
-  if( ( !bValidDestination ) && 
+  if( ( !bValidDestination ) &&
       ( DP_FindPlayer( This, idTo ) != NULL )
     )
   {
@@ -4240,22 +4574,22 @@ static HRESULT WINAPI DP_SendEx
 
 
 static HRESULT WINAPI DirectPlay4AImpl_SendEx
-          ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags, 
+          ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
             LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
             LPVOID lpContext, LPDWORD lpdwMsgID )
 {
   ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
-  return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize, 
+  return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
                     dwPriority, dwTimeout, lpContext, lpdwMsgID, TRUE );
 }
 
 static HRESULT WINAPI DirectPlay4WImpl_SendEx
-          ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags, 
+          ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
             LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
             LPVOID lpContext, LPDWORD lpdwMsgID )
 {
   ICOM_THIS(IDirectPlay2Impl,iface); /* yes downcast to 2 */
-  return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize, 
+  return DP_SendEx( This, idFrom, idTo, dwFlags, lpData, dwDataSize,
                     dwPriority, dwTimeout, lpContext, lpdwMsgID, FALSE );
 }
 
@@ -4272,24 +4606,24 @@ static HRESULT WINAPI DP_SP_SendEx
 
   lpMElem = (LPDPMSG)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                                sizeof( *lpMElem ) );
-  lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 
+  lpMElem->msg = (DPMSG_GENERIC*)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                                             dwDataSize );
 
   CopyMemory( lpMElem->msg, lpData, dwDataSize );
 
   /* FIXME: Need to queue based on priority */
-  DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs ); 
-   
+  DPQ_INSERT( This->dp2->sendMsgs, lpMElem, msgs );
+
   return DP_OK;
 }
 
 static HRESULT WINAPI DP_IF_GetMessageQueue
-          ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags, 
+          ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
             LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi )
 {
   HRESULT hr = DP_OK;
 
-  FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n", 
+  FIXME( "(%p)->(0x%08lx,0x%08lx,0x%08lx,%p,%p,%u): semi stub\n",
          This, idFrom, idTo, dwFlags, lpdwNumMsgs, lpdwNumBytes, bAnsi );
 
   /* FIXME: Do we need to do idFrom and idTo sanity checking here? */
@@ -4304,12 +4638,12 @@ static HRESULT WINAPI DP_IF_GetMessageQueue
     /* FIXME: None of this is documented :( */
 
     data.lpISP        = This->dp2->spData.lpISP;
-    data.dwFlags      = dwFlags; 
+    data.dwFlags      = dwFlags;
     data.idFrom       = idFrom;
     data.idTo         = idTo;
     data.lpdwNumMsgs  = lpdwNumMsgs;
     data.lpdwNumBytes = lpdwNumBytes;
-  
+
     hr = (*This->dp2->spData.lpCB->GetMessageQueue)( &data );
   }
   else
@@ -4321,7 +4655,7 @@ static HRESULT WINAPI DP_IF_GetMessageQueue
 }
 
 static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
-          ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags, 
+          ( LPDIRECTPLAY4A iface, DPID idFrom, DPID idTo, DWORD dwFlags,
             LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
 {
   ICOM_THIS(IDirectPlay4Impl,iface);
@@ -4330,7 +4664,7 @@ static HRESULT WINAPI DirectPlay4AImpl_GetMessageQueue
 }
 
 static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
-          ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags, 
+          ( LPDIRECTPLAY4 iface, DPID idFrom, DPID idTo, DWORD dwFlags,
             LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes )
 {
   ICOM_THIS(IDirectPlay4Impl,iface);
@@ -4339,12 +4673,12 @@ static HRESULT WINAPI DirectPlay4WImpl_GetMessageQueue
 }
 
 static HRESULT WINAPI DP_IF_CancelMessage
-          ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags, 
+          ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
             DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi )
 {
   HRESULT hr = DP_OK;
 
-  FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n", 
+  FIXME( "(%p)->(0x%08lx,0x%08lx,%u): semi stub\n",
          This, dwMsgID, dwFlags, bAnsi );
 
   if( This->dp2->spData.lpCB->Cancel )
@@ -4386,7 +4720,7 @@ static HRESULT WINAPI DirectPlay4AImpl_CancelMessage
   {
     dwFlags |= DPCANCELSEND_ALL;
   }
+
   return DP_IF_CancelMessage( This, dwMsgID, dwFlags, 0, 0, TRUE );
 }
 
@@ -4409,7 +4743,7 @@ static HRESULT WINAPI DirectPlay4WImpl_CancelMessage
 }
 
 static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
-          ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority, 
+          ( LPDIRECTPLAY4A iface, DWORD dwMinPriority, DWORD dwMaxPriority,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay4Impl,iface);
@@ -4419,12 +4753,12 @@ static HRESULT WINAPI DirectPlay4AImpl_CancelPriority
     return DPERR_INVALIDFLAGS;
   }
 
-  return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority, 
+  return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
                               dwMaxPriority, TRUE );
 }
 
 static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
-          ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority, 
+          ( LPDIRECTPLAY4 iface, DWORD dwMinPriority, DWORD dwMaxPriority,
             DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay4Impl,iface);
@@ -4434,18 +4768,18 @@ static HRESULT WINAPI DirectPlay4WImpl_CancelPriority
     return DPERR_INVALIDFLAGS;
   }
 
-  return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority, 
+  return DP_IF_CancelMessage( This, 0, DPCANCELSEND_PRIORITY, dwMinPriority,
                               dwMaxPriority, FALSE );
 }
 
 /* Note: Hack so we can reuse the old functions without compiler warnings */
 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)     (typeof(directPlay2WVT.fn##fun))
+# define XCAST(fun)     (typeof(directPlay2WVT.fun))
 #else
 # define XCAST(fun)     (void*)
 #endif
 
-static ICOM_VTABLE(IDirectPlay2) directPlay2WVT = 
+static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
 {
   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
   XCAST(QueryInterface)DP_QueryInterface,
@@ -4486,12 +4820,12 @@ static ICOM_VTABLE(IDirectPlay2) directPlay2WVT =
 
 /* Note: Hack so we can reuse the old functions without compiler warnings */
 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)     (typeof(directPlay2AVT.fn##fun))
+# define XCAST(fun)     (typeof(directPlay2AVT.fun))
 #else
 # define XCAST(fun)     (void*)
 #endif
 
-static ICOM_VTABLE(IDirectPlay2) directPlay2AVT = 
+static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
 {
   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
   XCAST(QueryInterface)DP_QueryInterface,
@@ -4533,12 +4867,12 @@ static ICOM_VTABLE(IDirectPlay2) directPlay2AVT =
 
 /* Note: Hack so we can reuse the old functions without compiler warnings */
 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)     (typeof(directPlay3AVT.fn##fun))
+# define XCAST(fun)     (typeof(directPlay3AVT.fun))
 #else
 # define XCAST(fun)     (void*)
 #endif
 
-static ICOM_VTABLE(IDirectPlay3) directPlay3AVT = 
+static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
 {
   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
   XCAST(QueryInterface)DP_QueryInterface,
@@ -4595,11 +4929,11 @@ static ICOM_VTABLE(IDirectPlay3) directPlay3AVT =
 
 /* Note: Hack so we can reuse the old functions without compiler warnings */
 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)     (typeof(directPlay3WVT.fn##fun))
+# define XCAST(fun)     (typeof(directPlay3WVT.fun))
 #else
 # define XCAST(fun)     (void*)
 #endif
-static ICOM_VTABLE(IDirectPlay3) directPlay3WVT = 
+static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
 {
   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
   XCAST(QueryInterface)DP_QueryInterface,
@@ -4656,7 +4990,7 @@ static ICOM_VTABLE(IDirectPlay3) directPlay3WVT =
 
 /* Note: Hack so we can reuse the old functions without compiler warnings */
 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)     (typeof(directPlay4WVT.fn##fun))
+# define XCAST(fun)     (typeof(directPlay4WVT.fun))
 #else
 # define XCAST(fun)     (void*)
 #endif
@@ -4725,7 +5059,7 @@ static ICOM_VTABLE(IDirectPlay4) directPlay4WVT =
 
 /* Note: Hack so we can reuse the old functions without compiler warnings */
 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
-# define XCAST(fun)     (typeof(directPlay4AVT.fn##fun))
+# define XCAST(fun)     (typeof(directPlay4AVT.fun))
 #else
 # define XCAST(fun)     (void*)
 #endif
@@ -4791,27 +5125,61 @@ static ICOM_VTABLE(IDirectPlay4) directPlay4AVT =
 };
 #undef XCAST
 
+extern
+HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP,
+                            DPID idPlayer,
+                            LPVOID* lplpData )
+{
+  lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
+
+  if( lpPlayer == NULL )
+  {
+    return DPERR_INVALIDPLAYER;
+  }
+
+  *lplpData = lpPlayer->lpPData->lpSPPlayerData;
+
+  return DP_OK;
+}
+
+extern
+HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP,
+                            DPID idPlayer,
+                            LPVOID lpData )
+{
+  lpPlayerList lpPlayer = DP_FindPlayer( lpDP, idPlayer );
+
+  if( lpPlayer == NULL )
+  {
+    return DPERR_INVALIDPLAYER;
+  }
+
+  lpPlayer->lpPData->lpSPPlayerData = lpData;
+
+  return DP_OK;
+}
 
 /***************************************************************************
- *  DirectPlayEnumerateA (DPLAYX.2) 
+ *  DirectPlayEnumerate  [DPLAYX.9]
+ *  DirectPlayEnumerateA [DPLAYX.2]
  *
- *  The pointer to the structure lpContext will be filled with the 
+ *  The pointer to the structure lpContext will be filled with the
  *  appropriate data for each service offered by the OS. These services are
  *  not necessarily available on this particular machine but are defined
  *  as simple service providers under the "Service Providers" registry key.
- *  This structure is then passed to lpEnumCallback for each of the different 
- *  services. 
+ *  This structure is then passed to lpEnumCallback for each of the different
+ *  services.
  *
  *  This API is useful only for applications written using DirectX3 or
  *  worse. It is superceeded by IDirectPlay3::EnumConnections which also
  *  gives information on the actual connections.
  *
  * defn of a service provider:
- * A dynamic-link library used by DirectPlay to communicate over a network. 
+ * A dynamic-link library used by DirectPlay to communicate over a network.
  * The service provider contains all the network-specific code required
  * to send and receive messages. Online services and network operators can
  * supply service providers to use specialized hardware, protocols, communications
- * media, and network resources. 
+ * media, and network resources.
  *
  * TODO: Allocate string buffer space from the heap (length from reg)
  *       Pass real device driver numbers...
@@ -4821,11 +5189,11 @@ HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
                                      LPVOID lpContext )
 {
 
-  HKEY   hkResult; 
+  HKEY   hkResult;
   LPCSTR searchSubKey    = "SOFTWARE\\Microsoft\\DirectPlay\\Service Providers";
   DWORD  dwIndex;
   DWORD  sizeOfSubKeyName=50;
-  char   subKeyName[51]; 
+  char   subKeyName[51];
   FILETIME filetime;
 
   TRACE(": lpEnumCallback=%p lpContext=%p\n", lpEnumCallback, lpContext );
@@ -4839,26 +5207,26 @@ HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
   if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, searchSubKey,
                        0, KEY_READ, &hkResult ) != ERROR_SUCCESS )
   {
-    /* Hmmm. Does this mean that there are no service providers? */ 
+    /* Hmmm. Does this mean that there are no service providers? */
     ERR(": no service providers?\n");
-    return DP_OK; 
+    return DP_OK;
   }
 
   /* Traverse all the service providers we have available */
   for( dwIndex=0;
-       RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName, 
+       RegEnumKeyExA( hkResult, dwIndex, subKeyName, &sizeOfSubKeyName,
                       NULL, NULL, NULL, &filetime ) != ERROR_NO_MORE_ITEMS;
        ++dwIndex, sizeOfSubKeyName=50 )
   {
-    LPSTR    majVerDataSubKey = "dwReserved1";  
-    LPSTR    minVerDataSubKey = "dwReserved2";  
+    LPSTR    majVerDataSubKey = "dwReserved1";
+    LPSTR    minVerDataSubKey = "dwReserved2";
     LPSTR    guidDataSubKey   = "Guid";
     HKEY     hkServiceProvider;
     GUID     serviceProviderGUID;
     DWORD    returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
     char     returnBuffer[51];
+    WCHAR    buff[51];
     DWORD    majVersionNum , minVersionNum = 0;
-    LPWSTR   lpWGUIDString; 
 
     TRACE(" this time through: %s\n", subKeyName );
 
@@ -4870,21 +5238,20 @@ HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
       continue;
     }
 
-    /* Get the GUID, Device major number and device minor number 
-     * from the registry. 
+    /* Get the GUID, Device major number and device minor number
+     * from the registry.
      */
     if( RegQueryValueExA( hkServiceProvider, guidDataSubKey,
                             NULL, &returnTypeGUID, returnBuffer,
                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
     {
       ERR(": missing GUID registry data members\n" );
-      continue; 
+      continue;
     }
 
     /* FIXME: Check return types to ensure we're interpreting data right */
-    lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, returnBuffer );
-    CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID ); 
-    HeapFree( GetProcessHeap(), 0, lpWGUIDString );
+    MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) );
+    CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
 
     /* FIXME: Need to know which of dwReserved1 and dwReserved2 are maj and min */
 
@@ -4894,10 +5261,9 @@ HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
                             &sizeOfReturnBuffer ) != ERROR_SUCCESS )
     {
       ERR(": missing dwReserved1 registry data members\n") ;
-      continue; 
+      continue;
     }
-
-    majVersionNum = GET_DWORD( returnBuffer );
+    memcpy( &majVersionNum, returnBuffer, sizeof(majVersionNum) );
 
     sizeOfReturnBuffer = 50;
     if( RegQueryValueExA( hkServiceProvider, minVerDataSubKey,
@@ -4907,8 +5273,7 @@ HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
       ERR(": missing dwReserved2 registry data members\n") ;
       continue;
     }
-
-    minVersionNum = GET_DWORD( returnBuffer );
+    memcpy( &minVersionNum, returnBuffer, sizeof(minVersionNum) );
 
 
     /* The enumeration will return FALSE if we are not to continue */
@@ -4925,7 +5290,7 @@ HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA lpEnumCallback,
 }
 
 /***************************************************************************
- *  DirectPlayEnumerateW (DPLAYX.3)
+ *  DirectPlayEnumerateW [DPLAYX.3]
  *
  */
 HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID lpContext )
@@ -4933,18 +5298,18 @@ HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW lpEnumCallback, LPVOID
 
   FIXME(":stub\n");
 
-  return DPERR_OUTOFMEMORY; 
+  return DPERR_OUTOFMEMORY;
 
 }
 
 typedef struct tagCreateEnum
 {
   LPVOID  lpConn;
-  LPCGUID lpGuid; 
+  LPCGUID lpGuid;
 } CreateEnumData, *lpCreateEnumData;
 
 /* Find and copy the matching connection for the SP guid */
-static BOOL CALLBACK cbDPCreateEnumConnections( 
+static BOOL CALLBACK cbDPCreateEnumConnections(
     LPCGUID     lpguidSP,
     LPVOID      lpConnection,
     DWORD       dwConnectionSize,
@@ -4952,7 +5317,7 @@ static BOOL CALLBACK cbDPCreateEnumConnections(
     DWORD       dwFlags,
     LPVOID      lpContext)
 {
-  lpCreateEnumData lpData = (lpCreateEnumData)lpContext; 
+  lpCreateEnumData lpData = (lpCreateEnumData)lpContext;
 
   if( IsEqualGUID( lpguidSP, lpData->lpGuid ) )
   {
@@ -4972,7 +5337,7 @@ static BOOL CALLBACK cbDPCreateEnumConnections(
 
 
 /***************************************************************************
- *  DirectPlayCreate (DPLAYX.1) (DPLAY.1)
+ *  DirectPlayCreate [DPLAYX.1]
  *
  */
 HRESULT WINAPI DirectPlayCreate
@@ -4981,7 +5346,7 @@ HRESULT WINAPI DirectPlayCreate
   HRESULT hr;
   LPDIRECTPLAY3A lpDP3A;
   CreateEnumData cbData;
-  
+
   TRACE( "lpGUID=%s lplpDP=%p pUnk=%p\n", debugstr_guid(lpGUID), lplpDP, pUnk );
 
   if( pUnk != NULL )
@@ -4989,18 +5354,17 @@ HRESULT WINAPI DirectPlayCreate
     return CLASS_E_NOAGGREGATION;
   }
 
-
   /* Create an IDirectPlay object. We don't support that so we'll cheat and
      give them an IDirectPlay2A object and hope that doesn't cause problems */
   if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK )
   {
     return DPERR_UNAVAILABLE;
-  } 
+  }
 
   if( IsEqualGUID( &GUID_NULL, lpGUID ) )
   {
     /* The GUID_NULL means don't bind a service provider. Just return the
-       interface as is */ 
+       interface as is */
     return DP_OK;
   }
 
@@ -5008,11 +5372,11 @@ HRESULT WINAPI DirectPlayCreate
   TRACE( "Service Provider binding for %s\n", debugstr_guid(lpGUID) );
 
   /* We're going to use a DP3 interface */
-  hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A, 
+  hr = IDirectPlayX_QueryInterface( *lplpDP, &IID_IDirectPlay3A,
                                     (LPVOID*)&lpDP3A );
   if( FAILED(hr) )
   {
-    ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) ); 
+    ERR( "Failed to get DP3 interface: %s\n", DPLAYX_HresultToString(hr) );
     return hr;
   }
 
@@ -5020,20 +5384,20 @@ HRESULT WINAPI DirectPlayCreate
   cbData.lpGuid = lpGUID;
 
   /* We were given a service provider, find info about it... */
-  hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections, 
+  hr = IDirectPlayX_EnumConnections( lpDP3A, NULL, cbDPCreateEnumConnections,
                                      &cbData, DPCONNECTION_DIRECTPLAY );
   if( ( FAILED(hr) ) ||
-      ( cbData.lpConn == NULL )    
+      ( cbData.lpConn == NULL )
     )
   {
-    ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );  
+    ERR( "Failed to get Enum for SP: %s\n", DPLAYX_HresultToString(hr) );
     IDirectPlayX_Release( lpDP3A );
     return DPERR_UNAVAILABLE;
   }
 
   /* Initialize the service provider */
   hr = IDirectPlayX_InitializeConnection( lpDP3A, cbData.lpConn, 0 );
-  if( FAILED(hr) ) 
+  if( FAILED(hr) )
   {
     ERR( "Failed to Initialize SP: %s\n", DPLAYX_HresultToString(hr) );
     HeapFree( GetProcessHeap(), 0, cbData.lpConn );