- Added a little more dll level debugging and small changes
- Start on group and player interfaces

diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c
index a3d7c33..d5a2448 100644
--- a/dlls/dplayx/dplay.c
+++ b/dlls/dplayx/dplay.c
@@ -18,6 +18,7 @@
 #include "dpinit.h"
 #include "dplayx_global.h"
 #include "name_server.h"
+#include "dplayx_queue.h"
 
 /* FIXME: This stuff shouldn't really be here. It indicates a poor architectural coupling */
 #include "dplobby.h"
@@ -56,13 +57,55 @@
   CRITICAL_SECTION  DP_lock;
 } DirectPlayIUnknownData;
 
-typedef struct _enumSessionAsyncCallbackData
+typedef struct tagEnumSessionAsyncCallbackData
 {
   LPDPENUMSESSIONSCALLBACK2 cb;
   LPVOID lpContext;
   DWORD dwTimeout;
 } EnumSessionAsyncCallbackData;
 
+
+struct PlayerData
+{
+  /* Individual player information */
+  DPID dpid;
+  
+  DPNAME name;
+  HANDLE hEvent;
+  LPVOID lpData;
+  DWORD  dwDataSize;
+};
+typedef struct PlayerData* lpPlayerData;
+
+struct PlayerList
+{
+  TAILQ_ENTRY(PlayerList) players;
+
+  struct PlayerData playerData;
+};
+typedef struct PlayerList* lpPlayerList;
+
+struct GroupData
+{
+  TAILQ_ENTRY(GroupList)  groups;  /* A group has [0..n] groups */
+  TAILQ_ENTRY(PlayerList) players; /* A group has [0..n] players */
+
+  /* Individual group information */
+  DPID   dpid;
+  DPNAME name;
+  LPVOID lpData;
+  DWORD  dwDataSize;
+};
+typedef struct GroupData* lpGroupData;
+
+struct GroupList
+{
+  TAILQ_ENTRY(GroupList) groups;
+
+  struct GroupData groupData;
+};
+typedef struct GroupList* lpGroupList;
+
 /* Contains all dp1 and dp2 data members */
 typedef struct tagDirectPlay2Data
 {
@@ -72,7 +115,12 @@
 
   EnumSessionAsyncCallbackData enumSessionAsyncCallbackData;
 
-  LPVOID lpNameServerData; /* DPlay interface doesn't know type */
+  LPVOID lpNameServerData; /* DPlay interface doesn't know contents */
+
+  BOOL bHostInterface; /* Did this interface create the session */
+
+  TAILQ_HEAD( ,PlayerList) players;
+  TAILQ_HEAD( ,GroupList)  groups;
 } DirectPlay2Data;
 
 typedef struct tagDirectPlay3Data
@@ -118,6 +166,30 @@
 static ICOM_VTABLE(IDirectPlay3) directPlay3WVT;
 static ICOM_VTABLE(IDirectPlay4) directPlay4WVT;
 
+/* Local function prototypes */
+static lpPlayerData DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
+static lpPlayerData DP_CreatePlayer( IDirectPlay2* iface, LPDPID lpid, 
+                                     LPDPNAME lpName, HANDLE hEvent, 
+                                     BOOL bAnsi );
+static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
+static void DP_SetPlayerData( lpPlayerData lpPData, LPVOID lpData, 
+                              DWORD dwDataSize );
+
+static lpGroupData DP_FindGroup( IDirectPlay2AImpl* This, DPID dpid );
+static lpGroupData DP_CreateGroup( IDirectPlay2* iface, LPDPID lpid,
+                                   LPDPNAME lpName, BOOL bAnsi );
+static void DP_SetGroupData( lpGroupData lpGData, LPVOID lpData,
+                             DWORD dwDataSize );
+
+
+
+
+static DWORD kludgePlayerGroupId = 100;
+
+
+/* ------------------------------------------------------------------ */
+
+
 BOOL DP_CreateIUnknown( LPVOID lpDP )
 {
   ICOM_THIS(IDirectPlay2AImpl,lpDP);
@@ -165,6 +237,11 @@
   This->dp2->enumSessionAsyncCallbackData.lpContext = NULL;
   This->dp2->enumSessionAsyncCallbackData.dwTimeout = INFINITE;
 
+  This->dp2->bHostInterface = FALSE;
+
+  TAILQ_INIT(&This->dp2->players);
+  TAILQ_INIT(&This->dp2->groups);
+
   if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
   {
     return FALSE;
@@ -177,12 +254,16 @@
 {
   ICOM_THIS(IDirectPlay2AImpl,lpDP);
 
+  FIXME( ": memory leak\n" );
+
   if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
   {
     TerminateThread( This->dp2->hEnumSessionThread, 0 );
     CloseHandle( This->dp2->hEnumSessionThread );
   }
 
+  /* Delete the player and group lists */
+
   NS_DeleteSessionCache( This->dp2->lpNameServerData );
   
   /* Delete the contents */
@@ -624,14 +705,110 @@
   return DP_OK;
 }
 
+static
+lpGroupData DP_CreateGroup( IDirectPlay2* iface, LPDPID lpid,
+                            LPDPNAME lpName, BOOL bAnsi )
+{
+  ICOM_THIS(IDirectPlay2Impl,iface);
+  lpGroupList lpGroup;
+
+  TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
+
+  /* Allocate the new space and add to end of interface player list */
+  lpGroup = (lpGroupList) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                     sizeof( *lpGroup ) );
+
+  if( lpGroup == NULL )
+  {
+    return NULL;
+  }
+
+  TAILQ_INSERT_TAIL(&This->dp2->groups,lpGroup,groups);
+
+  if( *lpid == DPID_UNKNOWN )
+  {
+    /* Assign the next available player ID - FIXME crap solution */
+    lpGroup->groupData.dpid = kludgePlayerGroupId++;
+  }
+  else
+  {
+    /* Set the desired player ID - no sanity checking to see if it exists */
+    lpGroup->groupData.dpid = *lpid;
+  }
+
+  DP_CopyDPNAMEStruct( &lpGroup->groupData.name, lpName, bAnsi );
+
+  return &lpGroup->groupData;
+}
+
+static lpGroupData DP_FindGroup( IDirectPlay2AImpl* This, DPID dpid )
+{
+  lpGroupList lpGroups;
+
+  TRACE( "(%p)->(0x%08lx)\n", This, dpid );
+
+  TAILQ_FIND_ENTRY( &This->dp2->groups, groups, groupData.dpid, dpid, lpGroups );
+
+  if( lpGroups )
+  {
+    return &lpGroups->groupData;
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+
 static HRESULT WINAPI DirectPlay2AImpl_CreateGroup
           ( LPDIRECTPLAY2A iface, LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
 {
+  lpGroupData lpGData;
+
   ICOM_THIS(IDirectPlay2Impl,iface);
+
   FIXME("(%p)->(%p,%p,%p,0x%08lx,0x%08lx): stub\n", This, lpidGroup, lpGroupName, lpData, dwDataSize, dwFlags );
+
+  lpGData = DP_CreateGroup( iface, lpidGroup, lpGroupName, TRUE /* Ansi */ );
+
+  if( lpGData == NULL )
+  {
+    return DPERR_CANTADDPLAYER; /* yes player not group */
+  }
+ 
+  DP_SetGroupData( lpGData, lpData, dwDataSize );
+
+  /* FIXME: Should send DPMSG_CREATEPLAYERORGROUP message to everyone,
+            local and remote, that belongs to this session. This will not
+            be done by calling SetPlayerData */
+  FIXME( "Should broadcast group creation to everything in session\n" );
+
   return DP_OK;
 }
 
+static void
+DP_SetGroupData( lpGroupData lpGData, LPVOID lpData, DWORD dwDataSize )
+{
+  /* Clear out the data with this player */
+  if( lpGData->dwDataSize != 0 )
+  {
+        HeapFree( GetProcessHeap(), 0, lpGData->lpData );
+        lpGData->lpData = NULL;
+        lpGData->dwDataSize = 0;
+  }
+
+  /* Reallocate for new data */
+  if( lpData )
+  {
+    lpGData->lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                 sizeof( dwDataSize ) );
+    memcpy( lpGData->lpData, lpData, dwDataSize );
+    lpGData->dwDataSize = dwDataSize;
+  }
+
+}
+
+
 static HRESULT WINAPI DirectPlay2WImpl_CreateGroup
           ( LPDIRECTPLAY2 iface, LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
 {
@@ -640,15 +817,218 @@
   return DP_OK;
 }
 
-static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer
-          ( LPDIRECTPLAY2A iface, LPDPID lpidPlayer, LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
+/* This function will just create the storage for the new player.
+ * In the future it may want to intialize, but for the time being
+ * that will be done seperately. 
+ * 
+ * If *lpid == DPID_UNKNOWN then assign the next available player
+ */
+static 
+lpPlayerData DP_CreatePlayer( IDirectPlay2* iface, LPDPID lpid, 
+                              LPDPNAME lpName, HANDLE hEvent, BOOL bAnsi )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
+  lpPlayerList lpPlayer;
 
-  FIXME("(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx): stub\n", This, lpidPlayer, lpPlayerName, hEvent, lpData, dwDataSize, dwFlags );
+  TRACE( "(%p)->(%p,%p,%u)\n", This, lpid, lpName, bAnsi );
 
-  /* FIXME: Should send DPMSG_CREATEPLAYERORGROUP message to everyone, local and remote, that
-            belongs to this session */
+  /* Allocate the new space and add to end of interface player list */
+  lpPlayer = (lpPlayerList) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                       sizeof( *lpPlayer ) );
+
+  if( lpPlayer == NULL )
+  {
+    return NULL;
+  }
+
+  TAILQ_INSERT_TAIL(&This->dp2->players,lpPlayer,players);
+
+  if( *lpid == DPID_UNKNOWN )
+  {
+    /* Assign the next available player ID - FIXME crap solution */
+    lpPlayer->playerData.dpid = kludgePlayerGroupId++; 
+  }
+  else 
+  {
+    /* Set the desired player ID - no sanity checking to see if it exists */
+    lpPlayer->playerData.dpid = *lpid;
+  }
+
+  DP_CopyDPNAMEStruct( &lpPlayer->playerData.name, lpName, bAnsi );
+
+  lpPlayer->playerData.hEvent = hEvent;
+
+  return &lpPlayer->playerData;
+}
+
+static lpPlayerData DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid )
+{
+  lpPlayerList lpPlayers;
+
+  TRACE( "(%p)->(0x%08lx)\n", This, dpid );
+
+  TAILQ_FIND_ENTRY( &This->dp2->players, players, playerData.dpid, dpid, lpPlayers );
+
+  if( lpPlayers )
+  {
+    return &lpPlayers->playerData;
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+/* Basic area for Dst must already be allocated */
+static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi )
+{
+  if( lpSrc == NULL )
+  {
+    ZeroMemory( lpDst, sizeof( *lpDst ) );
+    lpDst->dwSize = sizeof( *lpDst );
+    return TRUE;
+  }
+
+  if( lpSrc->dwSize != sizeof( *lpSrc) )   
+  {
+    return FALSE;
+  }
+
+  /* Delete any existing pointers */
+  if( lpDst->psn.lpszShortNameA )
+  {
+    HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
+  }
+
+  if( lpDst->pln.lpszLongNameA )
+  {
+    HeapFree( GetProcessHeap(), 0, lpDst->psn.lpszShortNameA );
+  }
+
+  /* Copy as required */
+  memcpy( lpDst, lpSrc, lpSrc->dwSize ); 
+
+  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 );
+    }
+  }
+  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 );
+    }
+  }
+
+  return TRUE;
+}
+
+static void 
+DP_SetPlayerData( lpPlayerData lpPData, LPVOID lpData, DWORD dwDataSize )
+{
+  /* Clear out the data with this player */
+  if( lpPData->dwDataSize != 0 )
+  {
+        HeapFree( GetProcessHeap(), 0, lpPData->lpData );
+        lpPData->lpData = NULL;
+        lpPData->dwDataSize = 0;
+  }
+
+  /* Reallocate for new data */
+  if( lpData )
+  {
+    lpPData->lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                   sizeof( dwDataSize ) );
+    memcpy( lpPData->lpData, lpData, dwDataSize );
+    lpPData->dwDataSize = dwDataSize;
+  }
+  
+}
+
+static HRESULT WINAPI DirectPlay2AImpl_CreatePlayer 
+( LPDIRECTPLAY2A iface, 
+  LPDPID lpidPlayer, 
+  LPDPNAME lpPlayerName, 
+  HANDLE hEvent, 
+  LPVOID lpData, 
+  DWORD dwDataSize, 
+  DWORD dwFlags )
+{
+  lpPlayerData lpPData;
+  ICOM_THIS(IDirectPlay2Impl,iface);
+
+  TRACE("(%p)->(%p,%p,%d,%p,0x%08lx,0x%08lx)\n", This, lpidPlayer, lpPlayerName, hEvent, lpData, dwDataSize, dwFlags );
+
+  if( dwFlags == 0 ) 
+  {
+    dwFlags = DPPLAYER_SPECTATOR;
+  }
+
+  /* Verify we know how to handle all the flags */
+  if( !( ( dwFlags & DPPLAYER_SERVERPLAYER ) ||
+         ( dwFlags & DPPLAYER_SPECTATOR )
+       )
+    )
+  {
+    /* Assume non fatal failure */
+    ERR( "unknown dwFlags = 0x%08lx\n", dwFlags );
+  }
+
+  if ( dwFlags & DPPLAYER_SERVERPLAYER )
+  {
+    /* We have a request to create the "master" of the session.
+     * This computer needs to be the session host and the server
+     * player can't have been created yet. 
+     */
+    if( ( !This->dp2->bHostInterface ) ||
+        ( DP_FindPlayer( This, DPID_SERVERPLAYER ) )
+      )
+    {
+      return DPERR_CANTCREATEPLAYER;
+    }
+
+    *lpidPlayer = DPID_SERVERPLAYER;
+  }
+  else
+  {
+    *lpidPlayer = DPID_UNKNOWN;
+  }
+
+  lpPData = DP_CreatePlayer( iface, lpidPlayer, 
+                             lpPlayerName, hEvent, TRUE /*Ansi*/ );
+
+  if( lpPData == NULL )
+  {
+    return DPERR_CANTADDPLAYER;
+  }
+
+  /* Update the information and send it to all players in the session */
+  DP_SetPlayerData( lpPData, lpData, dwDataSize );  
+
+
+  /* FIXME: Should send DPMSG_CREATEPLAYERORGROUP message to everyone, 
+            local and remote, that belongs to this session. This will not 
+            be done by calling SetPlayerData */
+  FIXME( "Should broadcast player creation to everything in session\n" );
 
   return DP_OK;
 }
@@ -747,7 +1127,9 @@
           ( LPDIRECTPLAY2A iface, LPGUID lpguidInstance, LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, LPVOID lpContext, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
+
   FIXME("(%p)->(%p,%p,%p,0x%08lx): stub\n", This, lpguidInstance, lpEnumPlayersCallback2, lpContext, dwFlags );
+
   return DP_OK;
 }
 
@@ -1098,6 +1480,7 @@
        the name server so that others can join this session */
     NS_SetLocalComputerAsNameServer( lpsd );
 
+    This->dp2->bHostInterface = TRUE;
   }
 
   if( dwFlags )
@@ -1151,8 +1534,28 @@
 static HRESULT WINAPI DirectPlay2AImpl_SetGroupData
           ( LPDIRECTPLAY2A iface, DPID idGroup, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
 {
+  lpGroupData lpGData;
   ICOM_THIS(IDirectPlay2Impl,iface);
-  FIXME("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n", This, idGroup, lpData, dwDataSize, dwFlags );
+
+  FIXME("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): dwFlags ignored\n", This, idGroup, lpData, dwDataSize, dwFlags );
+
+  /* Parameter check */
+  if( lpData == NULL )
+  {
+    if( dwDataSize != 0 )
+    {
+      return DPERR_INVALIDPARAMS;
+    }
+  }
+
+  /* Find the pointer to the data for this player */
+  if( ( lpGData = DP_FindGroup( This, idGroup ) ) == NULL )
+  {
+    return DPERR_INVALIDOBJECT;
+  }
+
+  DP_SetGroupData( lpGData, lpData, dwDataSize );
+
   return DP_OK;
 }
 
@@ -1183,8 +1586,33 @@
 static HRESULT WINAPI DirectPlay2AImpl_SetPlayerData
           ( LPDIRECTPLAY2A iface, DPID idPlayer, LPVOID lpData, DWORD dwDataSize, DWORD dwFlags )
 {
+  lpPlayerData lpPData;
   ICOM_THIS(IDirectPlay2Impl,iface);
-  FIXME("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx): stub\n", This, idPlayer, lpData, dwDataSize, dwFlags );
+
+  TRACE("(%p)->(0x%08lx,%p,0x%08lx,0x%08lx)\n", This, idPlayer, lpData, dwDataSize, dwFlags );
+
+  /* Parameter check */
+  if( lpData == NULL )
+  {
+    if( dwDataSize != 0 )
+    {
+      return DPERR_INVALIDPARAMS;
+    }
+  }
+
+  /* Find the pointer to the data for this player */
+  if( ( lpPData = DP_FindPlayer( This, idPlayer ) ) == NULL )
+  {
+    return DPERR_INVALIDOBJECT;
+  }
+
+  DP_SetPlayerData( lpPData, lpData, dwDataSize );
+
+  if( !(dwFlags & DPSET_LOCAL ) ) /* Is DPSET_REMOTE? */
+  {
+    FIXME( "Change not propagated to all players in the session\n" );
+  }
+
   return DP_OK;
 }
 
@@ -1200,7 +1628,9 @@
           ( LPDIRECTPLAY2A iface, DPID idPlayer, LPDPNAME lpPlayerName, DWORD dwFlags )
 {
   ICOM_THIS(IDirectPlay2Impl,iface);
+
   FIXME("(%p)->(0x%08lx,%p,0x%08lx): stub\n", This, idPlayer, lpPlayerName, dwFlags );
+
   return DP_OK;
 }
 
@@ -1645,7 +2075,9 @@
        the name server so that others can join this session */
     NS_SetLocalComputerAsNameServer( lpsd );
 
+    This->dp2->bHostInterface = TRUE;
   }
+
   if( dwFlags )
   {
     ERR( ": ignored dwFlags 0x%08lx\n", dwFlags );
diff --git a/dlls/dplayx/dplayx_main.c b/dlls/dplayx/dplayx_main.c
index c09b8dd..9b2d4ff 100644
--- a/dlls/dplayx/dplayx_main.c
+++ b/dlls/dplayx/dplayx_main.c
@@ -16,6 +16,9 @@
 
 BOOL WINAPI DPLAYX_LibMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
 {
+
+  FIXME( "(%p,0x%08lx,%p) & 0x%08lx\n", hinstDLL, fdwReason, lpvReserved, DPLAYX_dwProcessesAttached );
+
   switch ( fdwReason ) 
   {
     case DLL_PROCESS_ATTACH:
@@ -24,6 +27,7 @@
       if ( DPLAYX_dwProcessesAttached == 0 )
       {
         /* First instance perform construction of global processor data */ 
+        FIXME( "DPLAYX_dwProcessesAttached = 0x%08lx\n", DPLAYX_dwProcessesAttached );
         DPLAYX_ConstructData();
       } 
 
diff --git a/dlls/dplayx/dplayx_queue.h b/dlls/dplayx/dplayx_queue.h
new file mode 100644
index 0000000..b4656c3
--- /dev/null
+++ b/dlls/dplayx/dplayx_queue.h
@@ -0,0 +1,39 @@
+
+/* Helper functions for TAILQ functions defined in <sys/queue.h> 
+ * 
+ * Blame any implementation mistakes on Peter Hunnisett
+ * <hunnise@nortelnetworks.com>
+ */
+
+#ifndef __WINE_DPLAYX_QUEUE_H
+#define __WINE_DPLAYX_QUEUE_H
+
+#include <sys/queue.h>
+
+/* head - pointer to TAILQ_HEAD struct
+ * elm  - how to find the next element
+ * field - to be concatenated to rc to compare with fieldToEqual
+ * fieldToEqual - The value that we're looking for
+ * rc - Variable to put the return code. Same type as (head)->tqh_first
+ */
+#define TAILQ_FIND_ENTRY( head, elm, field, fieldToEqual, rc ) { \
+  (rc) = (head)->tqh_first; /* NULL head? */                    \
+                                                                 \
+  while( rc )                                                    \
+  {                                                              \
+      /* What we're searching for? */                            \
+      if( (rc)->field == (fieldToEqual) )                        \
+      {                                                          \
+        break; /* rc == correct element */                       \
+      }                                                          \
+                                                                 \
+      /* End of list check */                                    \
+      if( ( (rc) = (rc)->elm.tqe_next ) == (head)->tqh_first )   \
+      {                                                          \
+        rc = NULL;                                               \
+        break;                                                   \
+      }                                                          \
+  }                                                              \
+}
+
+#endif /* __WINE_DPLAYX_QUEUE_H */
diff --git a/dlls/dplayx/dplobby.c b/dlls/dplayx/dplobby.c
index 805bb00..b2337de 100644
--- a/dlls/dplayx/dplobby.c
+++ b/dlls/dplayx/dplobby.c
@@ -1986,13 +1986,20 @@
   /* Parameter Check: lpGUIDSP, lpUnk & lpData must be NULL. dwDataSize must 
    * equal 0. These fields are mostly for future expansion.
    */
-  if ( lpGUIDDSP || lpUnk || lpData || dwDataSize )
+  if ( lpGUIDDSP || lpData || dwDataSize )
   {
      *lplpDPL = NULL;
      ERR("Bad parameters!\n" );
      return DPERR_INVALIDPARAMS;
   }
 
+  if( lpUnk )
+  {
+     *lplpDPL = NULL;
+     ERR("Bad parameters!\n" );
+     return CLASS_E_NOAGGREGATION;
+  }
+
   return directPlayLobby_QueryInterface( &IID_IDirectPlayLobby, (void**)lplpDPL );  
 
 }