Index: trunk/src/DPlayX/dplay.cpp
===================================================================
--- trunk/src/DPlayX/dplay.cpp	(revision 5309)
+++ trunk/src/DPlayX/dplay.cpp	(revision 5311)
@@ -1,3 +1,3 @@
-// $Id: dplay.cpp,v 1.3 2000-10-06 19:49:03 hugh Exp $
+// $Id: dplay.cpp,v 1.4 2001-03-13 23:13:27 hugh Exp $
 /* Direct Play 2,3,4 Implementation
  *
@@ -18,4 +18,6 @@
 #include "winnt.h"
 #include "winreg.h"
+#include "winnls.h"
+#include "wine/unicode.h"
 #include "dplay.h"
 #include "heap.h"
@@ -173,4 +175,6 @@
             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,
@@ -187,5 +191,5 @@
 
 
-static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData );
+static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
 
 
@@ -254,4 +258,5 @@
   DPQ_INIT(This->dp2->receiveMsgs);
   DPQ_INIT(This->dp2->sendMsgs);
+  DPQ_INIT(This->dp2->replysExpected);
 
   if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
@@ -518,5 +523,5 @@
 
   *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                       sizeof( IDirectPlay2Impl ) );
+                       sizeof( *This ) );
 
   if( *ppvObj == NULL )
@@ -525,5 +530,6 @@
   }
 
-  CopyMemory( *ppvObj, iface, sizeof( IDirectPlay2Impl )  );
+  //CopyMemory( *ppvObj, iface, sizeof( IDirectPlay2Impl )  );
+  CopyMemory( *ppvObj, This, sizeof( *This )  );
   (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;
 
@@ -627,14 +633,13 @@
 
 /* *lplpReply will be non NULL iff there is something to reply */
-HRESULT DP_HandleMessage( IDirectPlay2Impl* This, LPCVOID lpMessageBody,
-                          DWORD  dwMessageBodySize, LPCVOID lpMessageHeader,
+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 );
 
-  DebugBreak();
 
   switch( wCommandId )
@@ -642,8 +647,6 @@
     case DPMSGCMD_REQUESTNEWPLAYERID:
     {
-#if 0
       LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
-        (LPCDPMSG_REQUESTNEWPLAYERID)lpMessageBody;
-#endif
+        (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;
       LPDPMSG_NEWPLAYERIDREPLY lpReply;
 
@@ -654,23 +657,7 @@
                                                         *lpdwMsgSize );
 
-      FIXME( "Ignoring dwFlags in request msg\n" );
-
-#if 0
-      /* This is just a test. See how large the SPData is and send it */
-      {
-        LPVOID lpData;
-        DWORD  dwDataSize;
-        HRESULT hr;
-
-        hr = IDirectPlaySP_GetSPData( This->dp2->spData.lpISP, &lpData,
-                                      &dwDataSize, DPSET_REMOTE );
-
-        if( FAILED(hr) )
-        {
-          ERR( "Unable to get remote SPData %s\n", DPLAYX_HresultToString(hr) );
-        }
-
-      }
-#endif
+      FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
+             lpcMsg->dwFlags );
+
 
       /* Setup the reply */
@@ -690,27 +677,22 @@
     }
 
+    case DPMSGCMD_GETNAMETABLEREPLY:
     case DPMSGCMD_NEWPLAYERIDREPLY:
     {
-
-      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 - only expecting in reply mode\n" );
-      }
+      DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
 
       break;
     }
 
+    case DPMSGCMD_FORWARDADDPLAYERNACK:
+    {
+      DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
+      break;
+    }
+
     default:
     {
       FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
+      DebugBreak();
       break;
     }
@@ -887,4 +869,6 @@
   lpGData->dwFlags = dwFlags;
 
+  TRACE( "Created group id 0x%08lx\n", *lpid );
+
   return lpGData;
 }
@@ -982,4 +966,5 @@
   {
     This->dp2->lpSysGroup = lpGData;
+    TRACE( "Inserting system group\n" );
   }
   else
@@ -1163,4 +1148,9 @@
   }
 
+  /* Initialize the SP data section */
+  lpPData->lpSPPlayerData = DPSP_CreateSPPlayerData();
+
+  TRACE( "Created player id 0x%08lx\n", *lpid );
+
   return lpPData;
 }
@@ -1170,6 +1160,6 @@
 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 );
 }
 
@@ -1234,12 +1224,12 @@
 
   /* Delete any existing pointers */
-  if( lpDst->psn.lpszShortNameA )
-  {
-    HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
-  }
-
-  if( lpDst->pln.lpszLongNameA )
-  {
-    HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
+  if( lpDst->u1.lpszShortNameA )
+  {
+    HeapFree( GetProcessHeap(), 0, lpDst->u1.lpszShortNameA );
+  }
+
+  if( lpDst->u2.lpszLongNameA )
+  {
+    HeapFree( GetProcessHeap(), 0, lpDst->u2.lpszLongNameA );
   }
 
@@ -1249,30 +1239,30 @@
   if( bAnsi )
   {
-    if( lpSrc->psn.lpszShortNameA )
-    {
-      lpDst->psn.lpszShortNameA =
-        HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                        lpSrc->psn.lpszShortNameA );
-    }
-    if( lpSrc->pln.lpszLongNameA )
-    {
-      lpDst->pln.lpszLongNameA =
-        HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                        lpSrc->pln.lpszLongNameA );
+    if( lpSrc->u1.lpszShortNameA )
+    {
+        lpDst->u1.lpszShortNameA = (LPSTR)HeapAlloc( GetProcessHeap(), 0,
+                                                     strlen(lpSrc->u1.lpszShortNameA)+1 );
+        strcpy( lpDst->u1.lpszShortNameA, lpSrc->u1.lpszShortNameA );
+    }
+    if( lpSrc->u2.lpszLongNameA )
+    {
+        lpDst->u2.lpszLongNameA = (LPSTR)HeapAlloc( GetProcessHeap(), 0,
+                                                    strlen(lpSrc->u2.lpszLongNameA)+1 );
+        strcpy( lpDst->u2.lpszLongNameA, lpSrc->u2.lpszLongNameA );
     }
   }
   else
   {
-    if( lpSrc->psn.lpszShortNameA )
-    {
-      lpDst->psn.lpszShortName =
-        HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                        lpSrc->psn.lpszShortName );
-    }
-    if( lpSrc->pln.lpszLongNameA )
-    {
-      lpDst->pln.lpszLongName =
-        HEAP_strdupW( GetProcessHeap(), HEAP_ZERO_MEMORY,
-                        lpSrc->pln.lpszLongName );
+    if( lpSrc->u1.lpszShortNameA )
+    {
+        lpDst->u1.lpszShortName = (LPWSTR) HeapAlloc( GetProcessHeap(), 0,
+                                                      (strlenW(lpSrc->u1.lpszShortName)+1)*sizeof(WCHAR) );
+        strcpyW( lpDst->u1.lpszShortName, lpSrc->u1.lpszShortName );
+    }
+    if( lpSrc->u2.lpszLongNameA )
+    {
+        lpDst->u2.lpszLongName = (LPWSTR)HeapAlloc( GetProcessHeap(), 0,
+                                                    (strlenW(lpSrc->u2.lpszLongName)+1)*sizeof(WCHAR) );
+        strcpyW( lpDst->u2.lpszLongName, lpSrc->u2.lpszLongName );
     }
   }
@@ -1339,4 +1329,5 @@
   lpPlayerData lpPData;
   lpPlayerList lpPList;
+  DWORD dwCreateFlags = 0;
 
   TRACE( "(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx,%u)\n",
@@ -1352,4 +1343,32 @@
   {
     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;
   }
 
@@ -1374,5 +1393,5 @@
     else
     {
-      hr = DP_MSG_SendRequestPlayerId( This, dwFlags, lpidPlayer );
+      hr = DP_MSG_SendRequestPlayerId( This, dwCreateFlags, lpidPlayer );
 
       if( FAILED(hr) )
@@ -1390,4 +1409,5 @@
   }
 
+  /* FIXME: Should we be storing these dwFlags or the creation ones? */
   lpPData = DP_CreatePlayer( This, lpidPlayer, lpPlayerName, dwFlags,
                              hEvent, bAnsi );
@@ -1420,20 +1440,4 @@
   {
     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;
@@ -1442,4 +1446,7 @@
     data.lpISP             = This->dp2->spData.lpISP;
 
+    TRACE( "Calling SP CreatePlayer 0x%08lx: dwFlags: 0x%08lx lpMsgHdr: %p\n",
+           *lpidPlayer, data.dwFlags, data.lpSPMessageHeader );
+
     hr = (*This->dp2->spData.lpCB->CreatePlayer)( &data );
   }
@@ -1467,9 +1474,20 @@
   if( FAILED(hr) )
   {
-    ERR( "Failed to add player to sys groupwith sp: %s\n",
+    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(...);
+     */
+    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.
@@ -1498,4 +1516,5 @@
                     sizeof( msg ), 0, 0, NULL, NULL, bAnsi );
   }
+#endif
 
   return hr;
@@ -2069,5 +2088,6 @@
   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 */
@@ -2108,5 +2128,10 @@
     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;
+    }
   }
 
@@ -2335,12 +2360,12 @@
   dwRequiredDataSize = lpGData->name.dwSize;
 
-  if( lpGData->name.psn.lpszShortNameA )
-  {
-    dwRequiredDataSize += strlen( lpGData->name.psn.lpszShortNameA ) + 1;
-  }
-
-  if( lpGData->name.pln.lpszLongNameA )
-  {
-    dwRequiredDataSize += strlen( lpGData->name.pln.lpszLongNameA ) + 1;
+  if( lpGData->name.u1.lpszShortNameA )
+  {
+    dwRequiredDataSize += strlen( lpGData->name.u1.lpszShortNameA ) + 1;
+  }
+
+  if( lpGData->name.u2.lpszLongNameA )
+  {
+    dwRequiredDataSize += strlen( lpGData->name.u2.lpszLongNameA ) + 1;
   }
 
@@ -2356,22 +2381,22 @@
   CopyMemory( lpName, &lpGData->name, lpGData->name.dwSize );
 
-  if( lpGData->name.psn.lpszShortNameA )
+  if( lpGData->name.u1.lpszShortNameA )
   {
     strcpy( ((char*)lpName)+lpGData->name.dwSize,
-            lpGData->name.psn.lpszShortNameA );
+            lpGData->name.u1.lpszShortNameA );
   }
   else
   {
-    lpName->psn.lpszShortNameA = NULL;
-  }
-
-  if( lpGData->name.psn.lpszShortNameA )
+    lpName->u1.lpszShortNameA = NULL;
+  }
+
+  if( lpGData->name.u2.lpszLongNameA )
   {
     strcpy( ((char*)lpName)+lpGData->name.dwSize,
-            lpGData->name.pln.lpszLongNameA );
+            lpGData->name.u2.lpszLongNameA );
   }
   else
   {
-    lpName->pln.lpszLongNameA = NULL;
+    lpName->u2.lpszLongNameA = NULL;
   }
 
@@ -2535,12 +2560,12 @@
   dwRequiredDataSize = lpPList->lpPData->name.dwSize;
 
-  if( lpPList->lpPData->name.psn.lpszShortNameA )
-  {
-    dwRequiredDataSize += strlen( lpPList->lpPData->name.psn.lpszShortNameA ) + 1;
-  }
-
-  if( lpPList->lpPData->name.pln.lpszLongNameA )
-  {
-    dwRequiredDataSize += strlen( lpPList->lpPData->name.pln.lpszLongNameA ) + 1;
+  if( lpPList->lpPData->name.u1.lpszShortNameA )
+  {
+    dwRequiredDataSize += strlen( lpPList->lpPData->name.u1.lpszShortNameA ) + 1;
+  }
+
+  if( lpPList->lpPData->name.u2.lpszLongNameA )
+  {
+    dwRequiredDataSize += strlen( lpPList->lpPData->name.u2.lpszLongNameA ) + 1;
   }
 
@@ -2556,22 +2581,22 @@
   CopyMemory( lpName, &lpPList->lpPData->name, lpPList->lpPData->name.dwSize );
 
-  if( lpPList->lpPData->name.psn.lpszShortNameA )
+  if( lpPList->lpPData->name.u1.lpszShortNameA )
   {
     strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
-            lpPList->lpPData->name.psn.lpszShortNameA );
+            lpPList->lpPData->name.u1.lpszShortNameA );
   }
   else
   {
-    lpName->psn.lpszShortNameA = NULL;
-  }
-
-  if( lpPList->lpPData->name.psn.lpszShortNameA )
+    lpName->u1.lpszShortNameA = NULL;
+  }
+
+  if( lpPList->lpPData->name.u2.lpszLongNameA )
   {
     strcpy( ((char*)lpName)+lpPList->lpPData->name.dwSize,
-            lpPList->lpPData->name.pln.lpszLongNameA );
+            lpPList->lpPData->name.u2.lpszLongNameA );
   }
   else
   {
-    lpName->pln.lpszLongNameA = NULL;
+    lpName->u2.lpszLongNameA = NULL;
   }
 
@@ -3137,26 +3162,26 @@
   if( bAnsi )
   {
-    if( lpSessDesc->sess.lpszSessionNameA )
-    {
-      dwSize += lstrlenA( lpSessDesc->sess.lpszSessionNameA ) + 1;
-    }
-
-    if( lpSessDesc->pass.lpszPasswordA )
-    {
-      dwSize += lstrlenA( lpSessDesc->pass.lpszPasswordA ) + 1;
+    if( lpSessDesc->u1.lpszSessionNameA )
+    {
+      dwSize += lstrlenA( lpSessDesc->u1.lpszSessionNameA ) + 1;
+    }
+
+    if( lpSessDesc->u2.lpszPasswordA )
+    {
+      dwSize += lstrlenA( lpSessDesc->u2.lpszPasswordA ) + 1;
     }
   }
   else /* UNICODE */
   {
-    if( lpSessDesc->sess.lpszSessionName )
+    if( lpSessDesc->u1.lpszSessionName )
     {
       dwSize += sizeof( WCHAR ) *
-        ( lstrlenW( lpSessDesc->sess.lpszSessionName ) + 1 );
-    }
-
-    if( lpSessDesc->pass.lpszPassword )
+        ( lstrlenW( lpSessDesc->u1.lpszSessionName ) + 1 );
+    }
+
+    if( lpSessDesc->u2.lpszPassword )
     {
       dwSize += sizeof( WCHAR ) *
-        ( lstrlenW( lpSessDesc->pass.lpszPassword ) + 1 );
+        ( lstrlenW( lpSessDesc->u2.lpszPassword ) + 1 );
     }
   }
@@ -3183,40 +3208,40 @@
   if( bAnsi )
   {
-    if( lpSessionSrc->sess.lpszSessionNameA )
+    if( lpSessionSrc->u1.lpszSessionNameA )
     {
       lstrcpyA( (LPSTR)lpStartOfFreeSpace,
-                lpSessionDest->sess.lpszSessionNameA );
-      lpSessionDest->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
+                lpSessionDest->u1.lpszSessionNameA );
+      lpSessionDest->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace +=
-        lstrlenA( (LPSTR)lpSessionDest->sess.lpszSessionNameA ) + 1;
-    }
-
-    if( lpSessionSrc->pass.lpszPasswordA )
+        lstrlenA( (LPSTR)lpSessionDest->u1.lpszSessionNameA ) + 1;
+    }
+
+    if( lpSessionSrc->u2.lpszPasswordA )
     {
       lstrcpyA( (LPSTR)lpStartOfFreeSpace,
-                lpSessionDest->pass.lpszPasswordA );
-      lpSessionDest->pass.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
+                lpSessionDest->u2.lpszPasswordA );
+      lpSessionDest->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace +=
-        lstrlenA( (LPSTR)lpSessionDest->pass.lpszPasswordA ) + 1;
+        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 );
-    }
-
-    if( lpSessionSrc->pass.lpszPassword )
+        ( lstrlenW( (LPWSTR)lpSessionDest->u1.lpszSessionName ) + 1 );
+    }
+
+    if( lpSessionSrc->u2.lpszPassword )
     {
       lstrcpyW( (LPWSTR)lpStartOfFreeSpace,
-                lpSessionDest->pass.lpszPassword );
-      lpSessionDest->pass.lpszPassword = (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 );
     }
   }
@@ -3499,5 +3524,5 @@
       DWORD    returnTypeGUID, sizeOfReturnBuffer = 50;
       char     returnBuffer[51];
-      LPWSTR   lpWGUIDString;
+      WCHAR    buff[51];
       DPNAME   dpName;
       HRESULT  hr;
@@ -3526,7 +3551,6 @@
 
       /* 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? */
 
@@ -3534,12 +3558,12 @@
       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.
-         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
+         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 anyway ...
                despite this method taking slightly more heap space and realtime :) */
       dpCompoundAddress.dwDataSize   = sizeof( GUID );
@@ -3605,5 +3629,5 @@
       DWORD    returnTypeGUID, sizeOfReturnBuffer = 50;
       char     returnBuffer[51];
-      LPWSTR   lpWGUIDString;
+      WCHAR    buff[51];
       DPNAME   dpName;
       HRESULT  hr;
@@ -3632,7 +3656,6 @@
 
       /* 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? */
 
@@ -3640,12 +3663,12 @@
       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.
-         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
+         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 anyway ...
                despite this method taking slightly more heap space and realtime :) */
       dpCompoundAddress.guidDataType = DPAID_LobbyProvider;
@@ -3806,5 +3829,5 @@
 
 /* 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;
@@ -3828,4 +3851,5 @@
 
     (i == 0) ? (searchSubKey = spSubKey ) : (searchSubKey = lpSubKey );
+    *lpbIsDpSp = (i == 0) ? TRUE : FALSE;
 
 
@@ -3850,6 +3874,6 @@
       DWORD    returnType, sizeOfReturnBuffer = 255;
       char     returnBuffer[256];
-      LPWSTR   lpWGUIDString;
-      DWORD    dwTemp;
+      WCHAR    buff[51];
+      DWORD    dwTemp, len;
 
       TRACE(" this time through: %s\n", subKeyName );
@@ -3872,7 +3896,6 @@
 
       /* 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? */
 
@@ -3884,5 +3907,7 @@
 
       /* Save the name of the SP or LP */
-      lpSpData->lpszName = HEAP_strdupAtoW( GetProcessHeap(), 0, subKeyName );
+      len = MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, NULL, 0 );
+      lpSpData->lpszName = (WCHAR*)HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+      MultiByteToWideChar( CP_ACP, 0, subKeyName, -1, lpSpData->lpszName, len );
 
       sizeOfReturnBuffer = 255;
@@ -3924,4 +3949,5 @@
       }
 
+      TRACE( "Loading %s\n", returnBuffer );
       return LoadLibraryA( returnBuffer );
     }
@@ -3931,6 +3957,6 @@
 }
 
-static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
-          ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
+static HRESULT WINAPI DP_IF_InitializeConnection
+          ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi )
 {
   HMODULE hServiceProvider;
@@ -3938,9 +3964,8 @@
   LPDPSP_SPINIT SPInit;
   GUID guidSP;
-  DWORD dwAddrSize = 80; /* FIXME: Need to calculate it correctly */
-
-  ICOM_THIS(IDirectPlay3Impl,iface);
-
-  TRACE("(%p)->(%p,0x%08lx)\n", This, lpConnection, dwFlags );
+  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 )
@@ -3972,5 +3997,5 @@
 
   /* Load the service provider */
-  hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData );
+  hServiceProvider = DP_LoadSP( &guidSP, &This->dp2->spData, &bIsDpSp );
 
   if( hServiceProvider == 0 )
@@ -3980,20 +4005,33 @@
   }
 
-  /* Initialize the service provider by calling SPInit */
-  SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
+  if( bIsDpSp )
+  {
+    /* Initialize the service provider by calling SPInit */
+    SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "SPInit" );
+  }
+  else
+  {
+    /* Initialize the service provider by calling SPInit */
+    SPInit = (LPDPSP_SPINIT)GetProcAddress( hServiceProvider, "DPLSPInit" );
+  }
 
   if( SPInit == NULL )
   {
-    ERR( "Service provider doesn't provide SPInit interface?\n" );
+    ERR( "Service provider doesn't provide %s interface?\n",
+         bIsDpSp ? "SPInit" : "DPLSPInit" );
     FreeLibrary( hServiceProvider );
     return DPERR_UNAVAILABLE;
   }
 
-  TRACE( "Calling SPInit\n" );
+  TRACE( "Calling %s (SP entry point)\n", bIsDpSp ? "SPInit" : "DPLSPInit" );
+
+  /* FIXME: Need to break this out into a separate routine for DP SP and
+   *        DPL SP as they actually use different stuff...
+   */
   hr = (*SPInit)( &This->dp2->spData );
 
   if( FAILED(hr) )
   {
-    ERR( "SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
+    ERR( "DP/DPL SP Initialization failed: %s\n", DPLAYX_HresultToString(hr) );
     FreeLibrary( hServiceProvider );
     return hr;
@@ -4009,10 +4047,16 @@
 }
 
+static HRESULT WINAPI DirectPlay3AImpl_InitializeConnection
+          ( LPDIRECTPLAY3A iface, LPVOID lpConnection, DWORD dwFlags )
+{
+  ICOM_THIS(IDirectPlay3Impl,iface);
+  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;
+  return DP_IF_InitializeConnection( This, lpConnection, dwFlags, FALSE );
 }
 
@@ -4816,7 +4860,40 @@
 };
 
+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)
+ *  DirectPlayEnumerateA [DPLAYX.2][DPLAYX.9][DPLAY.2]
  *
  *  The pointer to the structure lpContext will be filled with the
@@ -4882,6 +4959,6 @@
     DWORD    returnTypeGUID, returnTypeReserved, sizeOfReturnBuffer = 50;
     char     returnBuffer[51];
+    WCHAR    buff[51];
     DWORD    majVersionNum , minVersionNum = 0;
-    LPWSTR   lpWGUIDString;
 
     TRACE(" this time through: %s\n", subKeyName );
@@ -4907,7 +4984,6 @@
 
     /* 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 */
@@ -4950,5 +5026,5 @@
 
 /***************************************************************************
- *  DirectPlayEnumerateW (DPLAYX.3)
+ *  DirectPlayEnumerateW ([DPLAYX.3]
  *
  */
@@ -4997,5 +5073,5 @@
 
 /***************************************************************************
- *  DirectPlayCreate (DPLAYX.1) (DPLAY.1)
+ *  DirectPlayCreate [DPLAYX.1][DPLAY.1]
  *
  */
@@ -5014,6 +5090,5 @@
   }
 
-
-  /* Create an IDirectPlay object. We don't support that so we'll cheat and
+ /* 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 )
Index: trunk/src/DPlayX/dplay_global.h
===================================================================
--- trunk/src/DPlayX/dplay_global.h	(revision 5309)
+++ trunk/src/DPlayX/dplay_global.h	(revision 5311)
@@ -1,3 +1,3 @@
-// $Id: dplay_global.h,v 1.2 2000-09-24 22:47:40 hugh Exp $
+// $Id: dplay_global.h,v 1.3 2001-03-13 23:13:28 hugh Exp $
 #ifndef __WINE_DPLAY_GLOBAL_INCLUDED
 #define __WINE_DPLAY_GLOBAL_INCLUDED
@@ -37,4 +37,19 @@
 } EnumSessionAsyncCallbackData;
 
+typedef struct tagDP_MSG_REPLY_STRUCT
+{
+  HANDLE hReceipt;
+  WORD   wExpectedReply;
+  LPVOID lpReplyMsg;
+  DWORD  dwMsgBodySize;
+  /* FIXME: Is the message header required as well? */
+} DP_MSG_REPLY_STRUCT, *LPDP_MSG_REPLY_STRUCT;
+
+typedef struct tagDP_MSG_REPLY_STRUCT_LIST
+{
+  DPQ_ENTRY(tagDP_MSG_REPLY_STRUCT_LIST) replysExpected;
+  DP_MSG_REPLY_STRUCT replyExpected;
+} DP_MSG_REPLY_STRUCT_LIST, *LPDP_MSG_REPLY_STRUCT_LIST;
+
 struct PlayerData
 {
@@ -55,4 +70,7 @@
   DWORD  dwRemoteDataSize;
 
+  /* SP data on a per player basis */
+  LPVOID lpSPPlayerData;
+
   DWORD  dwFlags; /* Special remarks about the type of player */
 };
@@ -139,8 +157,6 @@
   BOOL bConnectionInitialized;
 
-
-  /* proof of concept for message reception */
-  HANDLE hMsgReceipt;
-  LPVOID lpMsgReceived;
+  /* Expected messages queue */
+  DPQ_HEAD( tagDP_MSG_REPLY_STRUCT_LIST ) replysExpected;
 } DirectPlay2Data;
 
@@ -194,4 +210,10 @@
                           LPVOID* lplpReply, LPDWORD lpdwMsgSize );
 
+/* DP SP external interfaces into DirectPlay */
+extern HRESULT DP_GetSPPlayerData( IDirectPlay2Impl* lpDP, DPID idPlayer, LPVOID* lplpData );
+extern HRESULT DP_SetSPPlayerData( IDirectPlay2Impl* lpDP, DPID idPlayer, LPVOID lpData );
+
+/* DP external interfaces to call into DPSP interface */
+extern LPVOID DPSP_CreateSPPlayerData(void);
 
 #endif /* __WINE_DPLAY_GLOBAL_INCLUDED */
Index: trunk/src/DPlayX/dplaysp.cpp
===================================================================
--- trunk/src/DPlayX/dplaysp.cpp	(revision 5309)
+++ trunk/src/DPlayX/dplaysp.cpp	(revision 5311)
@@ -1,3 +1,3 @@
-// $Id: dplaysp.cpp,v 1.3 2000-10-06 19:49:04 hugh Exp $
+// $Id: dplaysp.cpp,v 1.4 2001-03-13 23:13:27 hugh Exp $
 /* This contains the implementation of the interface Service
  * Providers require to communicate with Direct Play
@@ -58,6 +58,4 @@
   IDirectPlay2Impl* dplay; /* FIXME: This should perhaps be iface not impl */
 
-  LPVOID lpPlayerData; /* FIXME: Need to figure out how this actually behaves */
-  DWORD dwPlayerDataSize;
 } DirectPlaySPData;
 
@@ -75,4 +73,14 @@
 /* Forward declaration of virtual tables */
 extern ICOM_VTABLE(IDirectPlaySP) directPlaySPVT;
+
+/* This structure is passed to the DP object for safe keeping */
+typedef struct tagDP_SPPLAYERDATA
+{
+  LPVOID lpPlayerLocalData;
+  DWORD  dwPlayerLocalDataSize;
+
+  LPVOID lpPlayerRemoteData;
+  DWORD  dwPlayerRemoteDataSize;
+} DP_SPPLAYERDATA, *LPDP_SPPLAYERDATA;
 
 
@@ -177,4 +185,13 @@
   /* IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp ); */
 
+  /* FIXME: This is a kludge to get around a problem where a queryinterface
+   *        is used to get a new interface and then is closed. We will then
+   *        reference garbage. However, with this we will never deallocate
+   *        the interface we store. The correct fix is to require all
+   *        DP internal interfaces to use the This->dp2 interface which
+   *        should be changed to This->dp
+   */
+  IDirectPlayX_AddRef( (LPDIRECTPLAY2)dp );
+
   return TRUE;
 }
@@ -375,16 +392,48 @@
 )
 {
-  ICOM_THIS(IDirectPlaySPImpl,iface);
-
-  TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
-  FIXME( "(%p)->(0x%08lx,%p,%p,0x%08lx): stub\n",
+  HRESULT hr;
+  LPDP_SPPLAYERDATA lpPlayerData;
+  ICOM_THIS(IDirectPlaySPImpl,iface);
+
+/*  TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
+  TRACE( "(%p)->(0x%08lx,%p,%p,0x%08lx)\n",
          This, idPlayer, lplpData, lpdwDataSize, dwFlags );
 
+  hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerData );
+
+  if( FAILED(hr) )
+  {
+    TRACE( "Couldn't get player data: %s\n", DPLAYX_HresultToString(hr) );
+    return DPERR_INVALIDPLAYER;
+  }
+
   /* What to do in the case where there is nothing set yet? */
-
-  *lplpData     = This->sp->lpPlayerData;
-  *lpdwDataSize = This->sp->dwPlayerDataSize;
-
-  return DP_OK;
+  if( dwFlags == DPSET_LOCAL )
+  {
+    if( lpPlayerData->lpPlayerLocalData )
+    {
+      HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerLocalData );
+    }
+
+    *lplpData     = lpPlayerData->lpPlayerLocalData;
+    *lpdwDataSize = lpPlayerData->dwPlayerLocalDataSize;
+  }
+  else if( dwFlags == DPSET_REMOTE )
+  {
+    if( lpPlayerData->lpPlayerRemoteData )
+    {
+      HeapFree( GetProcessHeap(), 0, lpPlayerData->lpPlayerRemoteData );
+    }
+
+    *lplpData     = lpPlayerData->lpPlayerRemoteData;
+    *lpdwDataSize = lpPlayerData->dwPlayerRemoteDataSize;
+  }
+
+  if( *lplpData == NULL )
+  {
+    hr = DPERR_GENERIC;
+  }
+
+  return hr;
 }
 
@@ -403,5 +452,5 @@
   ICOM_THIS(IDirectPlaySPImpl,iface);
 
-  TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
+/*  TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
   FIXME( "(%p)->(%p,0x%08lx,%p): mostly stub\n",
          This, lpMessageBody, dwMessageBodySize, lpMessageHeader );
@@ -421,4 +470,5 @@
   {
     /* Name server needs to handle this request */
+    /* FIXME: This should be done in direct play handler */
     case DPMSGCMD_ENUMSESSIONSREQUEST:
     {
@@ -442,4 +492,5 @@
 
     /* Name server needs to handle this request */
+    /* FIXME: This should be done in direct play handler */
     case DPMSGCMD_ENUMSESSIONSREPLY:
     {
@@ -450,12 +501,11 @@
 
       /* No reply expected */
-
-      break;
-    }
-
-    case DPMSGCMD_GETNAMETABLE:
-    case DPMSGCMD_GETNAMETABLEREPLY:
-    case DPMSGCMD_NEWPLAYERIDREPLY:
-    case DPMSGCMD_REQUESTNEWPLAYERID:
+      hr = DP_OK;
+
+      break;
+    }
+
+    /* Pass everything else to Direct Play */
+    default:
     {
       DPSP_REPLYDATA data;
@@ -465,5 +515,5 @@
 
       /* Pass this message to the dplay interface to handle */
-      DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
+      hr = DP_HandleMessage( This->sp->dplay, lpMessageBody, dwMessageBodySize,
                         lpMessageHeader, wCommandId, wVersion,
                         &data.lpMessage, &data.dwMessageSize );
@@ -488,8 +538,4 @@
       break;
     }
-
-    default:
-      FIXME( "Unknown Command of %u and size 0x%08lx\n",
-             lpMsg->wCommandId, dwMessageBodySize );
   }
 
@@ -748,20 +794,38 @@
 )
 {
-  ICOM_THIS(IDirectPlaySPImpl,iface);
-
-  /* FIXME: I'm not sure if this stuff should be associated with the DPlay
-   *        player lists. How else would this stuff get deleted?
-   */
-
-  TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
-  FIXME( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n",
+  HRESULT           hr;
+  LPDP_SPPLAYERDATA lpPlayerEntry;
+  LPVOID            lpPlayerData;
+
+  ICOM_THIS(IDirectPlaySPImpl,iface);
+
+/*  TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
+  TRACE( "(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n",
          This, idPlayer, lpData, dwDataSize, dwFlags );
 
-  This->sp->lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
-
-  This->sp->dwPlayerDataSize = dwDataSize;
-  CopyMemory( This->sp->lpPlayerData, lpData, dwDataSize );
-
-  return DP_OK;
+  hr = DP_GetSPPlayerData( This->sp->dplay, idPlayer, (LPVOID*)&lpPlayerEntry );
+  if( FAILED(hr) )
+  {
+    /* Player must not exist */
+    return DPERR_INVALIDPLAYER;
+  }
+
+  lpPlayerData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
+  CopyMemory( lpPlayerData, lpData, dwDataSize );
+
+  if( dwFlags == DPSET_LOCAL )
+  {
+    lpPlayerEntry->lpPlayerLocalData = lpPlayerData;
+    lpPlayerEntry->dwPlayerLocalDataSize = dwDataSize;
+  }
+  else if( dwFlags == DPSET_REMOTE )
+  {
+    lpPlayerEntry->lpPlayerRemoteData = lpPlayerData;
+    lpPlayerEntry->dwPlayerRemoteDataSize = dwDataSize;
+  }
+
+  hr = DP_SetSPPlayerData( This->sp->dplay, idPlayer, lpPlayerEntry );
+
+  return hr;
 }
 
@@ -789,7 +853,8 @@
 )
 {
-  ICOM_THIS(IDirectPlaySPImpl,iface);
-
-  TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
+  HRESULT hr = DP_OK;
+  ICOM_THIS(IDirectPlaySPImpl,iface);
+
+/*  TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
   TRACE( "(%p)->(%p,%p,0x%08lx)\n",
          This, lplpData, lpdwDataSize, dwFlags );
@@ -797,5 +862,5 @@
 #if 0
   /* This is what the documentation says... */
-  if( dwFlags != 0 )
+  if( dwFlags != DPSET_REMOTE )
   {
     return DPERR_INVALIDPARAMS;
@@ -806,9 +871,11 @@
    * thing?
    */
-  if( dwFlags != 0 )
+  if( dwFlags != DPSET_REMOTE )
   {
     FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
   }
 #endif
+
+  /* FIXME: What to do in the case where this isn't initialized yet? */
 
   /* Yes, we're supposed to return a pointer to the memory we have stored! */
@@ -817,4 +884,9 @@
     *lpdwDataSize = This->sp->dwSpRemoteDataSize;
     *lplpData     = This->sp->lpSpRemoteData;
+
+    if( This->sp->lpSpRemoteData == NULL )
+    {
+      hr = DPERR_GENERIC;
+    }
   }
   else if( dwFlags == DPSET_LOCAL )
@@ -822,7 +894,12 @@
     *lpdwDataSize = This->sp->dwSpLocalDataSize;
     *lplpData     = This->sp->lpSpLocalData;
-  }
-
-  return DP_OK;
+
+    if( This->sp->lpSpLocalData == NULL )
+    {
+      hr = DPERR_GENERIC;
+    }
+  }
+
+  return hr;
 }
 
@@ -838,5 +915,5 @@
   ICOM_THIS(IDirectPlaySPImpl,iface);
 
-  TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() );
+/*  TRACE( "Called on process 0x%08lx\n", GetCurrentProcessId() ); */
   TRACE( "(%p)->(%p,0x%08lx,0x%08lx)\n",
          This, lpData, dwDataSize, dwFlags );
@@ -844,5 +921,5 @@
 #if 0
   /* This is what the documentation says... */
-  if( dwFlags != 0 )
+  if( dwFlags != DPSET_REMOTE )
   {
     return DPERR_INVALIDPARAMS;
@@ -853,5 +930,5 @@
    * thing?
    */
-  if( dwFlags != 0 )
+  if( dwFlags != DPSET_REMOTE )
   {
     FIXME( "Undocumented dwFlags 0x%08lx used\n", dwFlags );
@@ -859,13 +936,5 @@
 #endif
 
-  if( dwFlags == DPSET_REMOTE )
-  {
-    lpSpData = DPLAYX_PrivHeapAlloc( HEAP_ZERO_MEMORY, dwDataSize );
-  }
-  else
-  {
-    lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
-  }
-
+  lpSpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwDataSize );
   CopyMemory( lpSpData, lpData, dwDataSize );
 
@@ -873,13 +942,9 @@
   if( dwFlags == DPSET_REMOTE )
   {
-    /* FIXME: This doesn't strictly make sense as there is no means to share
-     *        this shared data. Must be misinterpreting something...
-     */
     if( This->sp->lpSpRemoteData )
     {
-      DPLAYX_PrivHeapFree( This->sp->lpSpRemoteData );
-    }
-
-    /* NOTE: dwDataSize is also stored in the heap structure */
+      HeapFree( GetProcessHeap(), 0, This->sp->lpSpRemoteData );
+    }
+
     This->sp->dwSpRemoteDataSize = dwDataSize;
     This->sp->lpSpRemoteData = lpSpData;
@@ -933,2 +998,14 @@
   IDirectPlaySPImpl_SendComplete
 };
+
+
+/* DP external interfaces to call into DPSP interface */
+
+/* Allocate the structure */
+extern LPVOID DPSP_CreateSPPlayerData(void)
+{
+  TRACE( "Creating SPPlayer data struct\n" );
+  return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                    sizeof( DP_SPPLAYERDATA ) );
+}
+
Index: trunk/src/DPlayX/dplaysp.h
===================================================================
--- trunk/src/DPlayX/dplaysp.h	(revision 5309)
+++ trunk/src/DPlayX/dplaysp.h	(revision 5311)
@@ -1,3 +1,3 @@
-// $Id: dplaysp.h,v 1.2 2000-09-24 22:47:39 hugh Exp $
+// $Id: dplaysp.h,v 1.3 2001-03-13 23:13:28 hugh Exp $
 #ifndef __WINE_DIRECT_PLAY_SP_H
 #define __WINE_DIRECT_PLAY_SP_H
@@ -57,21 +57,24 @@
 #undef ICOM_INTERFACE
 
+/* NOTE: The microsoft provided header file doesn't have these access
+ * functions
+ */
 /*** IUnknown methods ***/
-#define IDirectPlaySP_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
-#define IDirectPlaySP_AddRef(p)             ICOM_CALL (AddRef,p)
-#define IDirectPlaySP_Release(p)            ICOM_CALL (Release,p)
+#define IDirectPlaySP_QueryInterface(p,a,b)        ICOM_CALL2(QueryInterface,p,a,b)
+#define IDirectPlaySP_AddRef(p)                    ICOM_CALL (AddRef,p)
+#define IDirectPlaySP_Release(p)                   ICOM_CALL (Release,p)
 /*** IDirectPlaySP methods ***/
-#define IDirectPlaySP_AddMRUEntry           ICOM_CALL5(AddMRUEntry,p,a,b,c,d,e)
-#define IDirectPlaySP_CreateAddress         ICOM_CALL6(CreateAddress,p,a,b,c,d,e,f)
-#define IDirectPlaySP_EnumAddress           ICOM_CALL4(EnumAddress,p,a,b,c,d)
-#define IDirectPlaySP_EnumMRUEntries        ICOM_CALL4(EnumMRUEntries,p,a,b,c,d)
-#define IDirectPlaySP_GetPlayerFlags        ICOM_CALL2(GetPlayerFlags,p,a,b)
-#define IDirectPlaySP_GetSPPlayerData       ICOM_CALL4(GetSPPlayerData,p,a,b,c,d)
-#define IDirectPlaySP_HandleMessage         ICOM_CALL3(HandleMessage,p,a,b,c)
-#define IDirectPlaySP_SetSPPlayerData       ICOM_CALL4(SetSPPlayerData,p,a,b,c,d)
-#define IDirectPlaySP_CreateCompoundAddress ICOM_CALL4(CreateCompoundAddress,p,a,b,c,d)
-#define IDirectPlaySP_GetSPData             ICOM_CALL3(GetSPData,p,a,b,c)
-#define IDirectPlaySP_SetSPData             ICOM_CALL3(SetSPData,p,a,b,c)
-#define IDirectPlaySP_SendComplete          ICOM_CALL2(SendComplete,p,a,b)
+#define IDirectPlaySP_AddMRUEntry(p,a,b,c,d,e)     ICOM_CALL5(AddMRUEntry,p,a,b,c,d,e)
+#define IDirectPlaySP_CreateAddress(p,a,b,c,d,e,f) ICOM_CALL6(CreateAddress,p,a,b,c,d,e,f)
+#define IDirectPlaySP_EnumAddress(p,a,b,c,d)       ICOM_CALL4(EnumAddress,p,a,b,c,d)
+#define IDirectPlaySP_EnumMRUEntries(p,a,b,c,d)    ICOM_CALL4(EnumMRUEntries,p,a,b,c,d)
+#define IDirectPlaySP_GetPlayerFlags(p,a,b)        ICOM_CALL2(GetPlayerFlags,p,a,b)
+#define IDirectPlaySP_GetSPPlayerData(p,a,b,c,d)   ICOM_CALL4(GetSPPlayerData,p,a,b,c,d)
+#define IDirectPlaySP_HandleMessage(p,a,b,c)       ICOM_CALL3(HandleMessage,p,a,b,c)
+#define IDirectPlaySP_SetSPPlayerData(p,a,b,c,d)   ICOM_CALL4(SetSPPlayerData,p,a,b,c,d)
+#define IDirectPlaySP_CreateCompoundAddress(p,a,b,c,d)  ICOM_CALL4(CreateCompoundAddress,p,a,b,c,d)
+#define IDirectPlaySP_GetSPData(p,a,b,c)           ICOM_CALL3(GetSPData,p,a,b,c)
+#define IDirectPlaySP_SetSPData(p,a,b,c)           ICOM_CALL3(SetSPData,p,a,b,c)
+#define IDirectPlaySP_SendComplete(p,a,b)          ICOM_CALL2(SendComplete,p,a,b)
 
 /* SP Callback stuff */
@@ -333,5 +336,6 @@
  * SP directly
  */
-extern __declspec(dllimport) DWORD gdwDPlaySPRefCount;
+//extern __declspec(dllimport) DWORD gdwDPlaySPRefCount;
+extern DWORD gdwDPlaySPRefCount;
 
 #endif
Index: trunk/src/DPlayX/dplayx_global.cpp
===================================================================
--- trunk/src/DPlayX/dplayx_global.cpp	(revision 5309)
+++ trunk/src/DPlayX/dplayx_global.cpp	(revision 5311)
@@ -1,3 +1,3 @@
-// $Id: dplayx_global.cpp,v 1.3 2000-10-06 19:49:05 hugh Exp $
+// $Id: dplayx_global.cpp,v 1.4 2001-03-13 23:13:27 hugh Exp $
 /* dplayx.dll global data implementation.
  *
@@ -659,18 +659,18 @@
 
     /* Session names may or may not exist */
-    if( src->lpSessionDesc->sess.lpszSessionNameA )
-    {
-      strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->sess.lpszSessionNameA );
-      dest->lpSessionDesc->sess.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
+    if( src->lpSessionDesc->u1.lpszSessionNameA )
+    {
+      strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u1.lpszSessionNameA );
+      dest->lpSessionDesc->u1.lpszSessionNameA = (LPSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace +=
-        strlen( (LPSTR)dest->lpSessionDesc->sess.lpszSessionNameA ) + 1;
-    }
-
-    if( src->lpSessionDesc->pass.lpszPasswordA )
-    {
-      strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->pass.lpszPasswordA );
-      dest->lpSessionDesc->pass.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
+        strlen( (LPSTR)dest->lpSessionDesc->u1.lpszSessionNameA ) + 1;
+    }
+
+    if( src->lpSessionDesc->u2.lpszPasswordA )
+    {
+      strcpy( (LPSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPasswordA );
+      dest->lpSessionDesc->u2.lpszPasswordA = (LPSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace +=
-        strlen( (LPSTR)dest->lpSessionDesc->pass.lpszPasswordA ) + 1;
+        strlen( (LPSTR)dest->lpSessionDesc->u2.lpszPasswordA ) + 1;
     }
   }
@@ -683,18 +683,18 @@
     CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
 
-    if( src->lpPlayerName->psn.lpszShortNameA )
-    {
-      strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->psn.lpszShortNameA );
-      dest->lpPlayerName->psn.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
+    if( src->lpPlayerName->u1.lpszShortNameA )
+    {
+      strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortNameA );
+      dest->lpPlayerName->u1.lpszShortNameA = (LPSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace +=
-        strlen( (LPSTR)dest->lpPlayerName->psn.lpszShortNameA ) + 1;
-    }
-
-    if( src->lpPlayerName->pln.lpszLongNameA )
-    {
-      strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->pln.lpszLongNameA );
-      dest->lpPlayerName->pln.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
+        strlen( (LPSTR)dest->lpPlayerName->u1.lpszShortNameA ) + 1;
+    }
+
+    if( src->lpPlayerName->u2.lpszLongNameA )
+    {
+      strcpy( (LPSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongNameA );
+      dest->lpPlayerName->u2.lpszLongNameA = (LPSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace +=
-        strlen( (LPSTR)dest->lpPlayerName->pln.lpszLongName ) + 1 ;
+        strlen( (LPSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 ;
     }
 
@@ -781,18 +781,18 @@
 
     /* Session names may or may not exist */
-    if( src->lpSessionDesc->sess.lpszSessionName )
-    {
-      strcpyW( (LPWSTR)lpStartOfFreeSpace, dest->lpSessionDesc->sess.lpszSessionName );
-      src->lpSessionDesc->sess.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
+    if( src->lpSessionDesc->u1.lpszSessionName )
+    {
+      strcpyW( (LPWSTR)lpStartOfFreeSpace, dest->lpSessionDesc->u1.lpszSessionName );
+      src->lpSessionDesc->u1.lpszSessionName = (LPWSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace +=  sizeof(WCHAR) *
-        ( strlenW( (LPWSTR)dest->lpSessionDesc->sess.lpszSessionName ) + 1 );
-    }
-
-    if( src->lpSessionDesc->pass.lpszPassword )
-    {
-      strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->pass.lpszPassword );
-      dest->lpSessionDesc->pass.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
+        ( strlenW( (LPWSTR)dest->lpSessionDesc->u1.lpszSessionName ) + 1 );
+    }
+
+    if( src->lpSessionDesc->u2.lpszPassword )
+    {
+      strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpSessionDesc->u2.lpszPassword );
+      dest->lpSessionDesc->u2.lpszPassword = (LPWSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace +=  sizeof(WCHAR) *
-        ( strlenW( (LPWSTR)dest->lpSessionDesc->pass.lpszPassword ) + 1 );
+        ( strlenW( (LPWSTR)dest->lpSessionDesc->u2.lpszPassword ) + 1 );
     }
   }
@@ -805,18 +805,18 @@
     CopyMemory( dest->lpPlayerName, src->lpPlayerName, sizeof( DPNAME ) );
 
-    if( src->lpPlayerName->psn.lpszShortName )
-    {
-      strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->psn.lpszShortName );
-      dest->lpPlayerName->psn.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
+    if( src->lpPlayerName->u1.lpszShortName )
+    {
+      strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u1.lpszShortName );
+      dest->lpPlayerName->u1.lpszShortName = (LPWSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace +=  sizeof(WCHAR) *
-        ( strlenW( (LPWSTR)dest->lpPlayerName->psn.lpszShortName ) + 1 );
-    }
-
-    if( src->lpPlayerName->pln.lpszLongName )
-    {
-      strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->pln.lpszLongName );
-      dest->lpPlayerName->pln.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
+        ( strlenW( (LPWSTR)dest->lpPlayerName->u1.lpszShortName ) + 1 );
+    }
+
+    if( src->lpPlayerName->u2.lpszLongName )
+    {
+      strcpyW( (LPWSTR)lpStartOfFreeSpace, src->lpPlayerName->u2.lpszLongName );
+      dest->lpPlayerName->u2.lpszLongName = (LPWSTR)lpStartOfFreeSpace;
       lpStartOfFreeSpace +=  sizeof(WCHAR) *
-        ( strlenW( (LPWSTR)dest->lpPlayerName->pln.lpszLongName ) + 1 );
+        ( strlenW( (LPWSTR)dest->lpPlayerName->u2.lpszLongName ) + 1 );
     }
 
@@ -964,12 +964,12 @@
     dwTotalSize += sizeof( DPSESSIONDESC2 );
 
-    if( lpConn->lpSessionDesc->sess.lpszSessionNameA )
-    {
-      dwTotalSize += strlen( lpConn->lpSessionDesc->sess.lpszSessionNameA ) + 1;
-    }
-
-    if( lpConn->lpSessionDesc->pass.lpszPasswordA )
-    {
-      dwTotalSize += strlen( lpConn->lpSessionDesc->pass.lpszPasswordA ) + 1;
+    if( lpConn->lpSessionDesc->u1.lpszSessionNameA )
+    {
+      dwTotalSize += strlen( lpConn->lpSessionDesc->u1.lpszSessionNameA ) + 1;
+    }
+
+    if( lpConn->lpSessionDesc->u2.lpszPasswordA )
+    {
+      dwTotalSize += strlen( lpConn->lpSessionDesc->u2.lpszPasswordA ) + 1;
     }
   }
@@ -979,12 +979,12 @@
     dwTotalSize += sizeof( DPNAME );
 
-    if( lpConn->lpPlayerName->psn.lpszShortNameA )
-    {
-      dwTotalSize += strlen( lpConn->lpPlayerName->psn.lpszShortNameA ) + 1;
-    }
-
-    if( lpConn->lpPlayerName->pln.lpszLongNameA )
-    {
-      dwTotalSize += strlen( lpConn->lpPlayerName->pln.lpszLongNameA ) + 1;
+    if( lpConn->lpPlayerName->u1.lpszShortNameA )
+    {
+      dwTotalSize += strlen( lpConn->lpPlayerName->u1.lpszShortNameA ) + 1;
+    }
+
+    if( lpConn->lpPlayerName->u2.lpszLongNameA )
+    {
+      dwTotalSize += strlen( lpConn->lpPlayerName->u2.lpszLongNameA ) + 1;
     }
 
@@ -1011,14 +1011,14 @@
     dwTotalSize += sizeof( DPSESSIONDESC2 );
 
-    if( lpConn->lpSessionDesc->sess.lpszSessionName )
+    if( lpConn->lpSessionDesc->u1.lpszSessionName )
     {
       dwTotalSize += sizeof( WCHAR ) *
-        ( strlenW( lpConn->lpSessionDesc->sess.lpszSessionName ) + 1 );
-    }
-
-    if( lpConn->lpSessionDesc->pass.lpszPassword )
+        ( strlenW( lpConn->lpSessionDesc->u1.lpszSessionName ) + 1 );
+    }
+
+    if( lpConn->lpSessionDesc->u2.lpszPassword )
     {
       dwTotalSize += sizeof( WCHAR ) *
-        ( strlenW( lpConn->lpSessionDesc->pass.lpszPassword ) + 1 );
+        ( strlenW( lpConn->lpSessionDesc->u2.lpszPassword ) + 1 );
     }
   }
@@ -1028,14 +1028,14 @@
     dwTotalSize += sizeof( DPNAME );
 
-    if( lpConn->lpPlayerName->psn.lpszShortName )
+    if( lpConn->lpPlayerName->u1.lpszShortName )
     {
       dwTotalSize += sizeof( WCHAR ) *
-        ( strlenW( lpConn->lpPlayerName->psn.lpszShortName ) + 1 );
-    }
-
-    if( lpConn->lpPlayerName->pln.lpszLongName )
+        ( strlenW( lpConn->lpPlayerName->u1.lpszShortName ) + 1 );
+    }
+
+    if( lpConn->lpPlayerName->u2.lpszLongName )
     {
       dwTotalSize += sizeof( WCHAR ) *
-        ( strlenW( lpConn->lpPlayerName->pln.lpszLongName ) + 1 );
+        ( strlenW( lpConn->lpPlayerName->u2.lpszLongName ) + 1 );
     }
 
@@ -1065,15 +1065,15 @@
   CopyMemory( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
 
-  if( lpSessionSrc->sess.lpszSessionNameA )
-  {
-    lpSessionDest->sess.lpszSessionNameA =
-      HEAP_strdupA( GetProcessHeap(),
-                    HEAP_ZERO_MEMORY, lpSessionSrc->sess.lpszSessionNameA );
-  }
-  if( lpSessionSrc->pass.lpszPasswordA )
-  {
-    lpSessionDest->pass.lpszPasswordA =
-      HEAP_strdupA( GetProcessHeap(),
-                    HEAP_ZERO_MEMORY, lpSessionSrc->pass.lpszPasswordA );
+  if( lpSessionSrc->u1.lpszSessionNameA )
+  {
+      if ((lpSessionDest->u1.lpszSessionNameA = (LPSTR)HeapAlloc( GetProcessHeap(), 0,
+                                                             strlen(lpSessionSrc->u1.lpszSessionNameA)+1 )))
+          strcpy( lpSessionDest->u1.lpszSessionNameA, lpSessionSrc->u1.lpszSessionNameA );
+  }
+  if( lpSessionSrc->u2.lpszPasswordA )
+  {
+      if ((lpSessionDest->u2.lpszPasswordA = (LPSTR)HeapAlloc( GetProcessHeap(), 0,
+                                                          strlen(lpSessionSrc->u2.lpszPasswordA)+1 )))
+          strcpy( lpSessionDest->u2.lpszPasswordA, lpSessionSrc->u2.lpszPasswordA );
   }
 
Index: trunk/src/DPlayX/dplayx_main.cpp
===================================================================
--- trunk/src/DPlayX/dplayx_main.cpp	(revision 5309)
+++ trunk/src/DPlayX/dplayx_main.cpp	(revision 5311)
@@ -1,3 +1,3 @@
-// $Id: dplayx_main.cpp,v 1.3 2001-02-14 15:14:41 sandervl Exp $
+// $Id: dplayx_main.cpp,v 1.4 2001-03-13 23:13:27 hugh Exp $
 /*
  * DPLAYX.DLL LibMain
@@ -23,8 +23,5 @@
 
 DEFAULT_DEBUG_CHANNEL(dplay);
-
-DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
-
-static DWORD DPLAYX_dwProcessesAttached = 0;
+DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
 /* This is a globally exported variable at ordinal 6 of DPLAYX.DLL */
@@ -34,33 +31,22 @@
 {
 
-  TRACE( "(%u,0x%08lx,%p) & 0x%08lx\n", hinstDLL, fdwReason, lpvReserved, DPLAYX_dwProcessesAttached );
+  TRACE( "(%u,0x%08lx,%p) & 0x%08lx\n", hinstDLL, fdwReason, lpvReserved, gdwDPlaySPRefCount );
 
   switch ( fdwReason )
   {
     case DLL_PROCESS_ATTACH:
-    {
-
-      if ( DPLAYX_dwProcessesAttached++ == 0 )
-      {
         /* First instance perform construction of global processor data */
         return DPLAYX_ConstructData();
-      }
-
-      break;
-    }
 
     case DLL_PROCESS_DETACH:
     {
-
-      if ( --DPLAYX_dwProcessesAttached == 0 )
-      {
-        BOOL rc;
-        /* Last instance performs destruction of global processor data */
-        rc = DPLAYX_DestructData();
+      BOOL rc;
+      /* Last instance performs destruction of global processor data */
+      rc = DPLAYX_DestructData();
 #ifdef __WIN32OS2__
+      if(gdwDPlaySPRefCount==0) // only do this the last time ?
         ctordtorTerm();
 #endif
         return rc;
-      }
 
       break;
Index: trunk/src/DPlayX/dplayx_messages.cpp
===================================================================
--- trunk/src/DPlayX/dplayx_messages.cpp	(revision 5309)
+++ trunk/src/DPlayX/dplayx_messages.cpp	(revision 5311)
@@ -1,3 +1,3 @@
-// $Id: dplayx_messages.cpp,v 1.3 2000-10-06 19:49:05 hugh Exp $
+// $Id: dplayx_messages.cpp,v 1.4 2001-03-13 23:13:27 hugh Exp $
 /* DirectPlay & DirectPlayLobby messaging implementation
  *
@@ -24,5 +24,5 @@
 #include "dplayx_global.h"
 
-DEFAULT_DEBUG_CHANNEL(dplay)
+DEFAULT_DEBUG_CHANNEL(dplay);
 
 #undef  debugstr_guid
@@ -39,4 +39,7 @@
 
 static DWORD CALLBACK DPL_MSG_ThreadMain( LPVOID lpContext );
+static LPVOID DP_MSG_ExpectReply( IDirectPlay2AImpl* This, LPDPSP_SENDDATA data, 
+                                  DWORD dwWaitTime, WORD wReplyCommandId,
+                                  LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize );
 
 /* Create the message reception thread to allow the application to receive
@@ -133,11 +136,5 @@
   {
     MSG lobbyMsg;
-#ifdef STRICT
-    HANDLE hNullHandle = NULL;
-#else
-    HANDLE hNullHandle = 0;
-#endif
-
-    GetMessageW( &lobbyMsg, hNullHandle, 0, 0 );
+    GetMessageW( &lobbyMsg, 0, 0, 0 );
   }
 
@@ -149,4 +146,40 @@
 }
 
+/* DP messageing stuff */
+static HANDLE DP_MSG_BuildAndLinkReplyStruct( IDirectPlay2Impl* This,
+                                              LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList, 
+                                              WORD wReplyCommandId );
+static LPVOID DP_MSG_CleanReplyStruct( LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
+                                       LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize );
+
+
+static
+HANDLE DP_MSG_BuildAndLinkReplyStruct( IDirectPlay2Impl* This,
+                                       LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList, WORD wReplyCommandId )
+{
+  lpReplyStructList->replyExpected.hReceipt       = CreateEventA( NULL, FALSE, FALSE, NULL );
+  lpReplyStructList->replyExpected.wExpectedReply = wReplyCommandId;
+  lpReplyStructList->replyExpected.lpReplyMsg     = NULL;
+  lpReplyStructList->replyExpected.dwMsgBodySize  = 0;
+
+  /* Insert into the message queue while locked */
+  EnterCriticalSection( &This->unk->DP_lock );
+    DPQ_INSERT( This->dp2->replysExpected, lpReplyStructList, replysExpected );
+  LeaveCriticalSection( &This->unk->DP_lock );
+
+  return lpReplyStructList->replyExpected.hReceipt;
+}
+
+static
+LPVOID DP_MSG_CleanReplyStruct( LPDP_MSG_REPLY_STRUCT_LIST lpReplyStructList,
+                                LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize  )
+{
+  CloseHandle( lpReplyStructList->replyExpected.hReceipt );
+
+  *lplpReplyMsg    = lpReplyStructList->replyExpected.lpReplyMsg;
+  *lpdwMsgBodySize = lpReplyStructList->replyExpected.dwMsgBodySize;
+
+  return lpReplyStructList->replyExpected.lpReplyMsg;
+}
 
 HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
@@ -156,5 +189,4 @@
   LPDPMSG_REQUESTNEWPLAYERID lpMsgBody;
   DWORD                      dwMsgSize;
-  DWORD                      dwWaitReturn;
   HRESULT                    hr = DP_OK;
 
@@ -166,16 +198,13 @@
                                              This->dp2->spData.dwSPHeaderSize );
 
+  /* Compose dplay message envelope */
   lpMsgBody->envelope.dwMagic    = DPMSGMAGIC_DPLAYMSG;
   lpMsgBody->envelope.wCommandId = DPMSGCMD_REQUESTNEWPLAYERID;
   lpMsgBody->envelope.wVersion   = DPMSGVER_DP6;
 
+  /* Compose the body of the message */
   lpMsgBody->dwFlags = dwFlags;
 
-  /* FIXME: Need to have a more advanced queuing system as this needs to
-   *        block on send until we get response. Otherwise we need to be
-   *        able to ensure we can pick out the exact response. Of course,
-   *        with something as non critical as this, would it matter? The
-   *        id has been effectively reserved for this session...
-   */
+  /* Send the message */
   {
     DPSP_SENDDATA data;
@@ -189,28 +218,13 @@
     data.lpISP          = This->dp2->spData.lpISP;
 
-    /* Setup for receipt */
-    This->dp2->hMsgReceipt = CreateEventA( NULL, FALSE, FALSE, NULL );
-
-    TRACE( "Sending request for player id\n" );
-
-    hr = (*This->dp2->spData.lpCB->Send)( &data );
-
-    if( FAILED(hr) )
-    {
-      ERR( "Request for new playerID send failed: %s\n",
-           DPLAYX_HresultToString( hr ) );
-      return DPERR_NOCONNECTION;
-    }
-  }
-
-  dwWaitReturn = WaitForSingleObject( This->dp2->hMsgReceipt, 30000 );
-  if( dwWaitReturn != WAIT_OBJECT_0 )
-  {
-    ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
-    hr = DPERR_TIMEOUT;
-  }
-
-  CloseHandle( This->dp2->hMsgReceipt );
-  This->dp2->hMsgReceipt = 0;
+    TRACE( "Asking for player id w/ dwFlags 0x%08lx\n", 
+           lpMsgBody->dwFlags );
+
+
+    DP_MSG_ExpectReply( This, &data, DPMSG_DEFAULT_WAIT_TIME, DPMSGCMD_NEWPLAYERIDREPLY, 
+                        &lpMsg, &dwMsgSize );
+
+  }
+
 
   /* Need to examine the data and extract the new player id */
@@ -219,5 +233,5 @@
     LPCDPMSG_NEWPLAYERIDREPLY lpcReply;
 
-    lpcReply = (LPCDPMSG_NEWPLAYERIDREPLY)This->dp2->lpMsgReceived;
+    lpcReply = (LPCDPMSG_NEWPLAYERIDREPLY)lpMsg;
 
     *lpdpidAllocatedId = lpcReply->dpidNewPlayerId;
@@ -227,14 +241,115 @@
     /* FIXME: I think that the rest of the message has something to do
      *        with remote data for the player that perhaps I need to setup.
+     *        However, with the information that is passed, all that it could
+     *        be used for is a standardized intialization value, which I'm 
+     *        guessing we can do without. Unless the message content is the same
+     *        for several different messages?
      */
+
+    HeapFree( GetProcessHeap(), 0, lpMsg ); 
+  }
+
+  return hr;
+}
+
+HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer )
+{
+  LPVOID                   lpMsg;
+  LPDPMSG_FORWARDADDPLAYER lpMsgBody;
+  DWORD                    dwMsgSize;
+  HRESULT                  hr = DP_OK;
+
+  dwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpMsgBody );
+
+  lpMsg = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMsgSize );
+
+  lpMsgBody = (LPDPMSG_FORWARDADDPLAYER)( (BYTE*)lpMsg +
+                                          This->dp2->spData.dwSPHeaderSize );
+
+  /* Compose dplay message envelope */
+  lpMsgBody->envelope.dwMagic    = DPMSGMAGIC_DPLAYMSG;
+  lpMsgBody->envelope.wCommandId = DPMSGCMD_FORWARDADDPLAYER;
+  lpMsgBody->envelope.wVersion   = DPMSGVER_DP6;
+
 #if 0
-   /* Set the passed service provider data */
-   IDirectPlaySP_SetSPData( This->dp2->spData.lpISP, data,
-                            msgsize, DPSET_REMOTE );
-
+  {
+    LPBYTE lpPData;
+    DWORD  dwDataSize;
+    
+    /* SP Player remote data needs to be propagated at some point - is this the point? */
+    IDirectPlaySP_GetSPPlayerData( This->dp2->spData.lpISP, dpidServer, (LPVOID*)&lpPData, &dwDataSize, DPSET_REMOTE );
+    
+    ERR( "Player Data size is 0x%08lx\n"
+         "[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n"
+         "[%02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x]\n", 
+ 
+	 dwDataSize,
+         lpPData[0], lpPData[1], lpPData[2], lpPData[3], lpPData[4],
+	 lpPData[5], lpPData[6], lpPData[7], lpPData[8], lpPData[9],
+         lpPData[10], lpPData[11], lpPData[12], lpPData[13], lpPData[14],
+	 lpPData[15], lpPData[16], lpPData[17], lpPData[18], lpPData[19],
+         lpPData[20], lpPData[21], lpPData[22], lpPData[23], lpPData[24],
+	 lpPData[25], lpPData[26], lpPData[27], lpPData[28], lpPData[29],
+         lpPData[30], lpPData[31]	 	 
+        );
+    DebugBreak();
+  }
 #endif
 
-    HeapFree( GetProcessHeap(), 0, This->dp2->lpMsgReceived );
-    This->dp2->lpMsgReceived = NULL;
+  /* Compose body of message */
+  lpMsgBody->dpidAppServer = dpidServer;
+  lpMsgBody->unknown2[0] = 0x0;
+  lpMsgBody->unknown2[1] = 0x1c;
+  lpMsgBody->unknown2[2] = 0x6c;
+  lpMsgBody->unknown2[3] = 0x50;
+  lpMsgBody->unknown2[4] = 0x9;
+
+  lpMsgBody->dpidAppServer2 = dpidServer;
+  lpMsgBody->unknown3[0] = 0x0;
+  lpMsgBody->unknown3[0] = 0x0;
+  lpMsgBody->unknown3[0] = 0x20;
+  lpMsgBody->unknown3[0] = 0x0;
+  lpMsgBody->unknown3[0] = 0x0;
+  
+  lpMsgBody->dpidAppServer3 = dpidServer;
+  lpMsgBody->unknown4[0] =  0x30; 
+  lpMsgBody->unknown4[1] =  0xb;
+  lpMsgBody->unknown4[2] =  0x0;
+  lpMsgBody->unknown4[3] =  0x1e090002;
+  lpMsgBody->unknown4[4] =  0x0;
+  lpMsgBody->unknown4[5] =  0x0;
+  lpMsgBody->unknown4[6] =  0x0;
+  lpMsgBody->unknown4[7] =  0x32090002;
+  lpMsgBody->unknown4[8] =  0x0;
+  lpMsgBody->unknown4[9] =  0x0;
+  lpMsgBody->unknown4[10] = 0x0;
+  lpMsgBody->unknown4[11] = 0x0;
+  lpMsgBody->unknown4[12] = 0x0;
+
+  lpMsgBody->unknown5[0] = 0x0;
+  lpMsgBody->unknown5[1] = 0x0;
+
+  /* Send the message */
+  {
+    DPSP_SENDDATA data;
+
+    data.dwFlags        = DPSEND_GUARANTEED;
+    data.idPlayerTo     = 0; /* Name server */
+    data.idPlayerFrom   = dpidServer; /* Sending from session server */
+    data.lpMessage      = lpMsg;
+    data.dwMessageSize  = dwMsgSize;
+    data.bSystemMessage = TRUE; /* Allow reply to be sent */
+    data.lpISP          = This->dp2->spData.lpISP;
+
+    lpMsg = DP_MSG_ExpectReply( This, &data, 
+                                DPMSG_WAIT_60_SECS, 
+                                DPMSGCMD_GETNAMETABLEREPLY,
+                                &lpMsg, &dwMsgSize );
+  }
+
+  /* Need to examine the data and extract the new player id */
+  if( lpMsg != NULL )
+  {
+    FIXME( "Name Table reply received: stub\n" );
   }
 
@@ -242,31 +357,100 @@
 }
 
-
-/* This function seems to cause a trap in the SP. It would seem unnecessary */
-/* FIXME: Remove this method if not required */
-HRESULT DP_MSG_OpenStream( IDirectPlay2AImpl* This )
-{
-  HRESULT       hr;
-  DPSP_SENDDATA data;
-
-  data.dwFlags        = DPSEND_OPENSTREAM;
-  data.idPlayerTo     = 0; /* Name server */
-  data.idPlayerFrom   = 0; /* From DP itself */
-  data.lpMessage      = NULL;
-  data.dwMessageSize  = This->dp2->spData.dwSPHeaderSize;
-  data.bSystemMessage = FALSE; /* FIXME? */
-  data.lpISP          = This->dp2->spData.lpISP;
-
-  hr = (*This->dp2->spData.lpCB->Send)( &data );
+/* Queue up a structure indicating that we want a reply of type wReplyCommandId. DPlay does
+ * not seem to offer any way of uniquely differentiating between replies of the same type
+ * relative to the request sent. There is an implicit assumption that there will be no
+ * ordering issues on sends and receives from the opposite machine. No wonder MS is not
+ * a networking company.
+ */
+static
+LPVOID DP_MSG_ExpectReply( IDirectPlay2AImpl* This, LPDPSP_SENDDATA lpData, 
+                           DWORD dwWaitTime, WORD wReplyCommandId,
+                           LPVOID* lplpReplyMsg, LPDWORD lpdwMsgBodySize )
+{
+  HRESULT                  hr;
+  HANDLE                   hMsgReceipt;
+  DP_MSG_REPLY_STRUCT_LIST replyStructList;
+  DWORD                    dwWaitReturn;
+ 
+  /* Setup for receipt */
+  hMsgReceipt = DP_MSG_BuildAndLinkReplyStruct( This, &replyStructList, 
+                                                wReplyCommandId );
+
+  TRACE( "Sending msg and expecting cmd %u in reply within %lu ticks\n", 
+         wReplyCommandId, dwWaitTime );
+  hr = (*This->dp2->spData.lpCB->Send)( lpData );
 
   if( FAILED(hr) )
   {
-      ERR( "Request for open stream send failed: %s\n",
-           DPLAYX_HresultToString( hr ) );
-  }
-
-  /* FIXME: hack to give some time for channel to open */
-  SleepEx( 1000 /* 1 sec */, FALSE );
-
-  return hr;
-}
+    ERR( "Request for new playerID send failed: %s\n",
+         DPLAYX_HresultToString( hr ) );
+    return NULL;
+  }
+
+  dwWaitReturn = WaitForSingleObject( hMsgReceipt, dwWaitTime );
+  if( dwWaitReturn != WAIT_OBJECT_0 )
+  {
+    ERR( "Wait failed 0x%08lx\n", dwWaitReturn );
+    return NULL;
+  }
+
+  /* Clean Up */
+  return DP_MSG_CleanReplyStruct( &replyStructList, lplpReplyMsg, lpdwMsgBodySize );
+}
+
+/* Determine if there is a matching request for this incomming message and then copy
+ * all important data. It is quite silly to have to copy the message, but the documents
+ * indicate that a copy is taken. Silly really.
+ */
+void DP_MSG_ReplyReceived( IDirectPlay2AImpl* This, WORD wCommandId, 
+                           LPCVOID lpcMsgBody, DWORD dwMsgBodySize )
+{
+  LPDP_MSG_REPLY_STRUCT_LIST lpReplyList;
+
+#if 0
+  if( wCommandId == DPMSGCMD_FORWARDADDPLAYER )
+  {
+    DebugBreak();
+  }
+#endif
+
+  /* Find, and immediately remove (to avoid double triggering), the appropriate entry. Call locked to 
+   * avoid problems.
+   */
+  EnterCriticalSection( &This->unk->DP_lock );
+    DPQ_REMOVE_ENTRY( This->dp2->replysExpected, replysExpected, replyExpected.wExpectedReply,\
+                     ==, wCommandId, lpReplyList );
+  LeaveCriticalSection( &This->unk->DP_lock );  
+
+  if( lpReplyList != NULL )
+  {
+    lpReplyList->replyExpected.dwMsgBodySize = dwMsgBodySize; 
+    lpReplyList->replyExpected.lpReplyMsg = HeapAlloc( GetProcessHeap(),
+                                                       HEAP_ZERO_MEMORY,
+                                                       dwMsgBodySize );
+    CopyMemory( lpReplyList->replyExpected.lpReplyMsg, 
+                lpcMsgBody, dwMsgBodySize );
+
+    /* Signal the thread which sent the message that it has a reply */
+    SetEvent( lpReplyList->replyExpected.hReceipt );
+  }
+  else
+  {
+    ERR( "No receipt event set - only expecting in reply mode\n" );
+    DebugBreak();
+  }
+ 
+}
+
+void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId,
+                           LPCVOID lpMsgBody, DWORD dwMsgBodySize )
+{
+  LPCDPMSG_FORWARDADDPLAYERNACK lpcErrorMsg;
+
+  lpcErrorMsg = (LPCDPMSG_FORWARDADDPLAYERNACK)lpMsgBody;
+
+  ERR( "Received error message %u. Error is %s\n", 
+       wCommandId, DPLAYX_HresultToString( lpcErrorMsg->errorCode) );
+  DebugBreak();
+}
+
Index: trunk/src/DPlayX/dplayx_messages.h
===================================================================
--- trunk/src/DPlayX/dplayx_messages.h	(revision 5309)
+++ trunk/src/DPlayX/dplayx_messages.h	(revision 5311)
@@ -1,3 +1,3 @@
-// $Id: dplayx_messages.h,v 1.3 2000-10-06 19:49:06 hugh Exp $
+// $Id: dplayx_messages.h,v 1.4 2001-03-13 23:13:28 hugh Exp $
 
 #ifndef __WINE_DPLAYX_MESSAGES__
@@ -13,4 +13,18 @@
                                          HANDLE hDeath, HANDLE hConnRead );
 
+HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
+                                    LPDPID lpdipidAllocatedId );
+HRESULT DP_MSG_ForwardPlayerCreation( IDirectPlay2AImpl* This, DPID dpidServer );
+
+void DP_MSG_ReplyReceived( IDirectPlay2AImpl* This, WORD wCommandId, 
+                           LPCVOID lpMsgBody, DWORD dwMsgBodySize );
+void DP_MSG_ErrorReceived( IDirectPlay2AImpl* This, WORD wCommandId,
+                           LPCVOID lpMsgBody, DWORD dwMsgBodySize );
+
+/* Timings -> 1000 ticks/sec */
+#define DPMSG_WAIT_5_SECS   5000
+#define DPMSG_WAIT_30_SECS 30000
+#define DPMSG_WAIT_60_SECS 60000
+#define DPMSG_DEFAULT_WAIT_TIME DPMSG_WAIT_30_SECS
 
 /* Message types etc. */
@@ -20,10 +34,10 @@
 #define DPMSGCMD_ENUMSESSIONSREPLY    1
 #define DPMSGCMD_ENUMSESSIONSREQUEST  2
-
+#define DPMSGCMD_GETNAMETABLEREPLY    3  /* Contains all existing players in session */
 
 #define DPMSGCMD_REQUESTNEWPLAYERID   5
 
 #define DPMSGCMD_NEWPLAYERIDREPLY     7
-#define DPMSGCMD_CREATESESSION        8
+#define DPMSGCMD_CREATESESSION        8 /* Might be a create nameserver or new player msg */ 
 #define DPMSGCMD_CREATENEWPLAYER      9
 #define DPMSGCMD_SYSTEMMESSAGE        10
@@ -33,7 +47,7 @@
 #define DPMSGCMD_ENUMGROUPS           17
 
-#define DPMSGCMD_GETNAMETABLE         19
+#define DPMSGCMD_FORWARDADDPLAYER     19
 
-#define DPMSGCMD_GETNAMETABLEREPLY    29
+#define DPMSGCMD_FORWARDADDPLAYERNACK 36
 
 /* This is what DP 6 defines it as. Don't know what it means. All messages
@@ -47,7 +61,6 @@
 /* All messages sent from the system are sent with this at the beginning of
  * the message.
+ * Size is 8 bytes
  */
-
-/* Size is 8 bytes */
 typedef struct tagDPMSG_SENDENVELOPE
 {
@@ -58,4 +71,7 @@
 typedef const DPMSG_SENDENVELOPE* LPCDPMSG_SENDENVELOPE;
 
+/* System messages exchanged between players seems to have this
+ * payload envelope on top of the basic envelope 
+ */
 typedef struct tagDPMSG_SYSMSGENVELOPE
 {
@@ -65,5 +81,5 @@
 typedef const DPMSG_SYSMSGENVELOPE* LPCDPMSG_SYSMSGENVELOPE;
 
-
+/* Reply sent in response to an enumsession request */
 typedef struct tagDPMSG_ENUMSESSIONSREPLY
 {
@@ -95,4 +111,5 @@
 typedef const DPMSG_ENUMSESSIONSREPLY* LPCDPMSG_ENUMSESSIONSREPLY;
 
+/* Msg sent to find out what sessions are available */
 typedef struct tagDPMSG_ENUMSESSIONSREQUEST
 {
@@ -101,5 +118,5 @@
   GUID  guidApplication;
 
-  DWORD dwPasswordSize; /* A Guess. This is normally 0x00000000. */
+  DWORD dwPasswordSize; /* A Guess. This is 0x00000000. */
                         /* This might be the name server DPID which
                            is needed for the reply */
@@ -133,23 +150,49 @@
 
   DPID dpidNewPlayerId;
-#if 1
+
   /* Assume that this is data that is tacked on to the end of the message
    * that comes from the SP remote data stored that needs to be propagated.
    */
   BYTE unknown[36];     /* This appears to always be 0 - not sure though */
-#endif
-
 } DPMSG_NEWPLAYERIDREPLY, *LPDPMSG_NEWPLAYERIDREPLY;
 typedef const DPMSG_NEWPLAYERIDREPLY* LPCDPMSG_NEWPLAYERIDREPLY;
 
+typedef struct tagDPMSG_FORWARDADDPLAYER
+{
+  DPMSG_SENDENVELOPE envelope;
+
+  DWORD unknown; /* 0 */
+
+  DPID  dpidAppServer; /* Remote application server id */
+  DWORD unknown2[5]; /* ??? */
+#define FORWARDADDPLAYER_UNKNOWN2_INIT { 0x0, 0x1c, 0x6c, 0x50, 0x9 }
+
+  DPID  dpidAppServer2; /* Remote application server id again !? */
+  DWORD unknown3[5]; /* ??? */
+#define FORWARDADDPLAYER_UNKNOWN3_INIT { 0x0, 0x0, 0x20, 0x0, 0x0 }
+
+  DPID  dpidAppServer3; /* Remote application server id again !? */
+
+  DWORD unknown4[12]; /* ??? - Is this a clump of 5 and then 8? */
+                      /* NOTE: 1 byte infront of the two 0x??090002 entries changes! */
+#define FORWARDADDPLAYER_UNKNOWN4_INIT { 0x30, 0xb, 0x0, 0x1e090002, 0x0, 0x0, 0x0, 0x32090002, 0x0, 0x0, 0x0, 0x0 }
+
+  BYTE unknown5[2]; /* 2 bytes at the end. This may be a part of something! */
+#define FORWARDADDPLAYER_UNKNOWN5_INIT { 0x0 }
+
+} DPMSG_FORWARDADDPLAYER, *LPDPMSG_FORWARDADDPLAYER;
+typedef const DPMSG_FORWARDADDPLAYER* LPCDPMSG_FORWARDADDPLAYER;
+
+/* This is an error message that can be received. Not sure if this is 
+ * specifically for a forward add player or for all errors
+ */
+typedef struct tagDPMSG_FORWARDADDPLAYERNACK
+{
+  DPMSG_SENDENVELOPE envelope;
+  HRESULT errorCode;
+} DPMSG_FORWARDADDPLAYERNACK, *LPDPMSG_FORWARDADDPLAYERNACK;
+typedef const DPMSG_FORWARDADDPLAYERNACK* LPCDPMSG_FORWARDADDPLAYERNACK;
+
 #include "poppack.h"
 
-
-HRESULT DP_MSG_SendRequestPlayerId( IDirectPlay2AImpl* This, DWORD dwFlags,
-                                    LPDPID lpdipidAllocatedId );
-
-/* FIXME: I don't think that this is a needed method */
-HRESULT DP_MSG_OpenStream( IDirectPlay2AImpl* This );
-
-
 #endif
Index: trunk/src/DPlayX/dplobby.cpp
===================================================================
--- trunk/src/DPlayX/dplobby.cpp	(revision 5309)
+++ trunk/src/DPlayX/dplobby.cpp	(revision 5311)
@@ -1,3 +1,3 @@
-// $Id: dplobby.cpp,v 1.3 2000-10-06 19:49:05 hugh Exp $
+// $Id: dplobby.cpp,v 1.4 2001-03-13 23:13:27 hugh Exp $
 /* Direct Play Lobby 2 & 3 Implementation
  *
@@ -16,4 +16,5 @@
 #include "winnt.h"
 #include "winreg.h"
+#include "winnls.h"
 #include "heap.h"
 #include "heapstring.h"
@@ -26,5 +27,5 @@
 #include "dplayx_queue.h"
 
-DEFAULT_DEBUG_CHANNEL(dplay)
+DEFAULT_DEBUG_CHANNEL(dplay);
 
 #undef  debugstr_guid
@@ -363,5 +364,5 @@
 
   CopyMemory( *ppvObj, iface, sizeof( IDirectPlayLobbyWImpl )  );
-  (*(IDirectPlayLobbyWImpl**)ppvObj)->ulInterfaceRef = 0;
+  (*(IDirectPlayLobbyAImpl**)ppvObj)->ulInterfaceRef = 0;
 
   if( IsEqualGUID( &IID_IDirectPlayLobby, riid ) )
@@ -767,5 +768,5 @@
       char     atSubKey[51];
       char     returnBuffer[51];
-      LPWSTR   lpWGUIDString;
+      WCHAR    buff[51];
       DWORD    dwAtIndex;
       LPSTR    atKey = "Address Types";
@@ -793,7 +794,6 @@
 
       /* 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? */
 
@@ -821,7 +821,6 @@
 
         /* FIXME: Check return types to ensure we're interpreting data right */
-        lpWGUIDString = HEAP_strdupAtoW( GetProcessHeap(), 0, atSubKey );
-        CLSIDFromString( (LPCOLESTR)lpWGUIDString, &serviceProviderGUID );
-        HeapFree( GetProcessHeap(), 0, lpWGUIDString );
+        MultiByteToWideChar( CP_ACP, 0, atSubKey, -1, buff, sizeof(buff)/sizeof(WCHAR) );
+        CLSIDFromString( (LPCOLESTR)buff, &serviceProviderGUID );
         /* FIXME: Have I got a memory leak on the serviceProviderGUID? */
 
@@ -918,5 +917,5 @@
     DWORD      returnTypeGUID, sizeOfReturnBuffer = 50;
     char       returnBuffer[51];
-    LPWSTR     lpWGUIDString;
+    WCHAR      buff[51];
     DPLAPPINFO dplAppInfo;
 
@@ -940,12 +939,11 @@
 
     /* 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? */
 
     dplAppInfo.dwSize               = sizeof( dplAppInfo );
     dplAppInfo.guidApplication      = serviceProviderGUID;
-    dplAppInfo.appName.lpszAppNameA = subKeyName;
+    dplAppInfo.u.lpszAppNameA = subKeyName;
 
     EnterCriticalSection( &This->unk->DPL_lock );
@@ -1096,5 +1094,6 @@
     else
     {
-      lpData->lpszCommandLine = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, returnBuffer );
+        if ((lpData->lpszCommandLine = (LPSTR)HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
+            strcpy( lpData->lpszCommandLine, returnBuffer );
     }
 
@@ -1109,5 +1108,6 @@
     else
     {
-      lpData->lpszCurrentDirectory = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, returnBuffer );
+        if ((lpData->lpszCurrentDirectory = (LPSTR)HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
+            strcpy( lpData->lpszCurrentDirectory, returnBuffer );
     }
 
@@ -1122,5 +1122,6 @@
     else
     {
-      lpData->lpszFileName = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, returnBuffer );
+        if ((lpData->lpszFileName = (LPSTR)HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
+            strcpy( lpData->lpszFileName, returnBuffer );
     }
 
@@ -1135,5 +1136,6 @@
     else
     {
-      lpData->lpszPath = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, returnBuffer );
+        if ((lpData->lpszPath = (LPSTR)HeapAlloc( GetProcessHeap(), 0, strlen(returnBuffer)+1 )))
+            strcpy( lpData->lpszPath, returnBuffer );
     }
 
@@ -1149,5 +1151,5 @@
 {
   /* These are the handles for the created process */
-  HANDLE hAppStart, hAppDeath, hAppRead, hTemp;;
+  HANDLE hAppStart, hAppDeath, hAppRead, hTemp;
   SECURITY_ATTRIBUTES s_attrib;
 
@@ -1245,5 +1247,5 @@
   HeapFree( GetProcessHeap(), 0, enumData.lpszPath );
   HeapFree( GetProcessHeap(), 0, enumData.lpszFileName );
-  appName = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, temp );
+  if ((appName = (LPSTR)HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 ))) strcpy( appName, temp );
 
   /* Now the command line */
@@ -1251,5 +1253,6 @@
   strcat( temp, enumData.lpszCommandLine );
   HeapFree( GetProcessHeap(), 0, enumData.lpszCommandLine );
-  enumData.lpszCommandLine = HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, temp );
+  if ((enumData.lpszCommandLine = (LPSTR)HeapAlloc( GetProcessHeap(), 0, strlen(temp)+1 )))
+      strcpy( enumData.lpszCommandLine, temp );
 
   ZeroMemory( &startupInfo, sizeof( startupInfo ) );
Index: trunk/src/DPlayX/name_server.cpp
===================================================================
--- trunk/src/DPlayX/name_server.cpp	(revision 5309)
+++ trunk/src/DPlayX/name_server.cpp	(revision 5311)
@@ -1,3 +1,3 @@
-// $Id: name_server.cpp,v 1.3 2000-10-06 19:49:06 hugh Exp $
+// $Id: name_server.cpp,v 1.4 2001-03-13 23:13:27 hugh Exp $
 /* DPLAYX.DLL name server implementation
  *
@@ -18,4 +18,6 @@
 #include "winbase.h"
 #include "winuser.h"
+#include "winnls.h"
+#include "wine/unicode.h"
 #include "debugtools.h"
 #include "heap.h"
@@ -82,4 +84,5 @@
                                        LPVOID                    lpNSInfo )
 {
+  DWORD len;
   lpNSCache     lpCache = (lpNSCache)lpNSInfo;
   lpNSCacheData lpCacheNode;
@@ -128,9 +131,10 @@
 
   CopyMemory( lpCacheNode->data, &lpMsg->sd, sizeof( *lpCacheNode->data ) );
-  lpCacheNode->data->sess.lpszSessionNameA = HEAP_strdupWtoA( GetProcessHeap(),
-                                                              HEAP_ZERO_MEMORY,
-                                                              (LPWSTR)(lpMsg+1) );
-
-  lpCacheNode->dwTime = GetTickCount();
+  len = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1, NULL, 0, NULL, NULL );
+  if ((lpCacheNode->data->u1.lpszSessionNameA = (LPSTR)HeapAlloc( GetProcessHeap(), 0, len )))
+      WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1,
+                           lpCacheNode->data->u1.lpszSessionNameA, len, NULL, NULL );
+
+  lpCacheNode->dwTime = timeGetTime();
 
   DPQ_INSERT(lpCache->first, lpCacheNode, next );
@@ -199,4 +203,5 @@
 }
 
+/* Delete a name server node which has been allocated on the heap */
 DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData )
 {
@@ -209,6 +214,4 @@
 }
 
-
-
 /* Render all data in a session cache invalid */
 void NS_InvalidateSessionCache( LPVOID lpNSInfo )
@@ -257,5 +260,4 @@
 void NS_ResetSessionEnumeration( LPVOID lpNSInfo )
 {
-
   ((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first.lpQHFirst;
 }
@@ -285,4 +287,5 @@
  * older than the criteria. If so, just delete that information.
  */
+/* FIXME: This needs to be called by some periodic timer */
 void NS_PruneSessionCache( LPVOID lpNSInfo )
 {
@@ -337,7 +340,5 @@
 }
 
-
-
-/* Message stuff */
+/* NAME SERVER Message stuff */
 void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg,
                                     LPDPSP_REPLYDATA lpReplyData,
@@ -347,5 +348,4 @@
   DWORD dwVariableSize;
   DWORD dwVariableLen;
-  LPWSTR string;
   /* LPDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpMsg; */
   BOOL bAnsi = TRUE; /* FIXME: This needs to be in the DPLAY interface */
@@ -353,6 +353,10 @@
   FIXME( ": few fixed + need to check request for response\n" );
 
-  dwVariableLen = bAnsi ? lstrlenA( lpDP->dp2->lpSessionDesc->sess.lpszSessionNameA ) + 1
-                         : lstrlenW( lpDP->dp2->lpSessionDesc->sess.lpszSessionName ) + 1;
+  if (bAnsi)
+      dwVariableLen = MultiByteToWideChar( CP_ACP, 0,
+                                           lpDP->dp2->lpSessionDesc->u1.lpszSessionNameA,
+                                           -1, NULL, 0 );
+  else
+      dwVariableLen = strlenW( lpDP->dp2->lpSessionDesc->u1.lpszSessionName ) + 1;
 
   dwVariableSize = dwVariableLen * sizeof( WCHAR );
@@ -374,16 +378,7 @@
   rmsg->dwUnknown = 0x0000005c;
   if( bAnsi )
-  {
-    string = HEAP_strdupAtoW( GetProcessHeap(), 0,
-                              lpDP->dp2->lpSessionDesc->sess.lpszSessionNameA );
-    /* FIXME: Memory leak */
-  }
+      MultiByteToWideChar( CP_ACP, 0, lpDP->dp2->lpSessionDesc->u1.lpszSessionNameA, -1,
+                           (LPWSTR)(rmsg+1), dwVariableLen );
   else
-  {
-    string = lpDP->dp2->lpSessionDesc->sess.lpszSessionName;
-  }
-
-  lstrcpyW( (LPWSTR)(rmsg+1), string );
-
-}
-
+      strcpyW( (LPWSTR)(rmsg+1), lpDP->dp2->lpSessionDesc->u1.lpszSessionName );
+}
