⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dplay.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Direct Play 2,3,4 Implementation
 *
 * Copyright 1998,1999,2000,2001 - Peter Hunnisett
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "config.h"
#include "wine/port.h"

#include <stdarg.h>
#include <string.h>

#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winerror.h"
#include "winbase.h"
#include "winnt.h"
#include "winreg.h"
#include "winnls.h"
#include "wine/unicode.h"
#include "wine/debug.h"

#include "dpinit.h"
#include "dplayx_global.h"
#include "name_server.h"
#include "dplayx_queue.h"
#include "dplaysp.h"
#include "dplay_global.h"

WINE_DEFAULT_DEBUG_CHANNEL(dplay);

/* FIXME: Should this be externed? */
extern HRESULT DPL_CreateCompoundAddress
( LPCDPCOMPOUNDADDRESSELEMENT lpElements, DWORD dwElementCount,
  LPVOID lpAddress, LPDWORD lpdwAddressSize, BOOL bAnsiInterface );


/* Local function prototypes */
static lpPlayerList DP_FindPlayer( IDirectPlay2AImpl* This, DPID dpid );
static lpPlayerData DP_CreatePlayer( IDirectPlay2Impl* iface, LPDPID lpid,
                                     LPDPNAME lpName, DWORD dwFlags,
                                     HANDLE hEvent, BOOL bAnsi );
static BOOL DP_CopyDPNAMEStruct( LPDPNAME lpDst, LPDPNAME lpSrc, BOOL bAnsi );
static void DP_SetPlayerData( lpPlayerData lpPData, DWORD dwFlags,
                              LPVOID lpData, DWORD dwDataSize );

static lpGroupData DP_CreateGroup( IDirectPlay2AImpl* iface, LPDPID lpid,
                                   LPDPNAME lpName, DWORD dwFlags,
                                   DPID idParent, BOOL bAnsi );
static void DP_SetGroupData( lpGroupData lpGData, DWORD dwFlags,
                             LPVOID lpData, DWORD dwDataSize );
static void DP_DeleteDPNameStruct( LPDPNAME lpDPName );
static void DP_DeletePlayer( IDirectPlay2Impl* This, DPID dpid );
static BOOL CALLBACK cbDeletePlayerFromAllGroups( DPID dpId,
                                                  DWORD dwPlayerType,
                                                  LPCDPNAME lpName,
                                                  DWORD dwFlags,
                                                  LPVOID lpContext );
static lpGroupData DP_FindAnyGroup( IDirectPlay2AImpl* This, DPID dpid );
static BOOL CALLBACK cbRemoveGroupOrPlayer( DPID dpId, DWORD dwPlayerType,
                                            LPCDPNAME lpName, DWORD dwFlags,
                                            LPVOID lpContext );
static void DP_DeleteGroup( IDirectPlay2Impl* This, DPID dpid );

/* Forward declarations of virtual tables */
static const IDirectPlay2Vtbl directPlay2AVT;
static const IDirectPlay3Vtbl directPlay3AVT;
static const IDirectPlay4Vtbl directPlay4AVT;

static const IDirectPlay2Vtbl directPlay2WVT;
static const IDirectPlay3Vtbl directPlay3WVT;
static const IDirectPlay4Vtbl directPlay4WVT;

/* Helper methods for player/group interfaces */
static HRESULT WINAPI DP_IF_DeletePlayerFromGroup
          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
            DPID idPlayer, BOOL bAnsi );
static HRESULT WINAPI DP_IF_CreatePlayer
          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, LPDPID lpidPlayer,
            LPDPNAME lpPlayerName, HANDLE hEvent, LPVOID lpData,
            DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_DestroyGroup
          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup, BOOL bAnsi );
static HRESULT WINAPI DP_IF_DestroyPlayer
          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idPlayer, BOOL bAnsi );
static HRESULT WINAPI DP_IF_EnumGroupPlayers
          ( IDirectPlay2Impl* This, DPID idGroup, LPGUID lpguidInstance,
            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
            LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_EnumGroups
          ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
            LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_EnumPlayers
          ( IDirectPlay2Impl* This, LPGUID lpguidInstance,
            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
            LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetGroupData
          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
            LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetGroupName
          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
            LPDWORD lpdwDataSize, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetPlayerData
          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
            LPDWORD lpdwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetPlayerName
          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
            LPDWORD lpdwDataSize, BOOL bAnsi );
static HRESULT WINAPI DP_IF_SetGroupName
          ( IDirectPlay2Impl* This, DPID idGroup, LPDPNAME lpGroupName,
            DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_SetPlayerData
          ( IDirectPlay2Impl* This, DPID idPlayer, LPVOID lpData,
            DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_SetPlayerName
          ( IDirectPlay2Impl* This, DPID idPlayer, LPDPNAME lpPlayerName,
            DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_AddGroupToGroup
          ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
static HRESULT WINAPI DP_IF_CreateGroup
          ( IDirectPlay2AImpl* This, LPVOID lpMsgHdr, LPDPID lpidGroup,
            LPDPNAME lpGroupName, LPVOID lpData, DWORD dwDataSize,
            DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_CreateGroupInGroup
          ( IDirectPlay3Impl* This, LPVOID lpMsgHdr, DPID idParentGroup,
            LPDPID lpidGroup, LPDPNAME lpGroupName, LPVOID lpData,
            DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_AddPlayerToGroup
          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
            DPID idPlayer, BOOL bAnsi );
static HRESULT WINAPI DP_IF_DeleteGroupFromGroup
          ( IDirectPlay3Impl* This, DPID idParentGroup, DPID idGroup );
static HRESULT WINAPI DP_SetSessionDesc
          ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpSessDesc,
            DWORD dwFlags, BOOL bInitial, BOOL bAnsi  );
static HRESULT WINAPI DP_SecureOpen
          ( IDirectPlay2Impl* This, LPCDPSESSIONDESC2 lpsd, DWORD dwFlags,
            LPCDPSECURITYDESC lpSecurity, LPCDPCREDENTIALS lpCredentials,
            BOOL bAnsi );
static HRESULT WINAPI DP_SendEx
          ( IDirectPlay2Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
            LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
            LPVOID lpContext, LPDWORD lpdwMsgID, BOOL bAnsi );
static HRESULT WINAPI DP_IF_Receive
          ( IDirectPlay2Impl* This, LPDPID lpidFrom, LPDPID lpidTo,
            DWORD dwFlags, LPVOID lpData, LPDWORD lpdwDataSize, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetMessageQueue
          ( IDirectPlay4Impl* This, DPID idFrom, DPID idTo, DWORD dwFlags,
            LPDWORD lpdwNumMsgs, LPDWORD lpdwNumBytes, BOOL bAnsi );
static HRESULT WINAPI DP_SP_SendEx
          ( IDirectPlay2Impl* This, DWORD dwFlags,
            LPVOID lpData, DWORD dwDataSize, DWORD dwPriority, DWORD dwTimeout,
            LPVOID lpContext, LPDWORD lpdwMsgID );
static HRESULT WINAPI DP_IF_SetGroupData
          ( IDirectPlay2Impl* This, DPID idGroup, LPVOID lpData,
            DWORD dwDataSize, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetPlayerCaps
          ( IDirectPlay2Impl* This, DPID idPlayer, LPDPCAPS lpDPCaps,
            DWORD dwFlags );
static HRESULT WINAPI DP_IF_Close( IDirectPlay2Impl* This, BOOL bAnsi );
static HRESULT WINAPI DP_IF_CancelMessage
          ( IDirectPlay4Impl* This, DWORD dwMsgID, DWORD dwFlags,
            DWORD dwMinPriority, DWORD dwMaxPriority, BOOL bAnsi );
static HRESULT WINAPI DP_IF_EnumGroupsInGroup
          ( IDirectPlay3AImpl* This, DPID idGroup, LPGUID lpguidInstance,
            LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2,
            LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetGroupParent
          ( IDirectPlay3AImpl* This, DPID idGroup, LPDPID lpidGroup,
            BOOL bAnsi );
static HRESULT WINAPI DP_IF_GetCaps
          ( IDirectPlay2Impl* This, LPDPCAPS lpDPCaps, DWORD dwFlags );
static HRESULT WINAPI DP_IF_EnumSessions
          ( IDirectPlay2Impl* This, LPDPSESSIONDESC2 lpsd, DWORD dwTimeout,
            LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
            LPVOID lpContext, DWORD dwFlags, BOOL bAnsi );
static HRESULT WINAPI DP_IF_InitializeConnection
          ( IDirectPlay3Impl* This, LPVOID lpConnection, DWORD dwFlags, BOOL bAnsi );
static BOOL CALLBACK cbDPCreateEnumConnections( LPCGUID lpguidSP,
    LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName,
    DWORD dwFlags, LPVOID lpContext );
static BOOL WINAPI DP_BuildSPCompoundAddr( LPGUID lpcSpGuid, LPVOID* lplpAddrBuf,
                                           LPDWORD lpdwBufSize );



static inline DPID DP_NextObjectId(void);
static DPID DP_GetRemoteNextObjectId(void);


static void DP_CopySessionDesc( LPDPSESSIONDESC2 destSessionDesc,
                                LPCDPSESSIONDESC2 srcSessDesc, BOOL bAnsi );


static HMODULE DP_LoadSP( LPCGUID lpcGuid, LPSPINITDATA lpSpData, LPBOOL lpbIsDpSp );
static HRESULT DP_InitializeDPSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );
static HRESULT DP_InitializeDPLSP( IDirectPlay3Impl* This, HMODULE hServiceProvider );






#define DPID_NOPARENT_GROUP 0 /* Magic number to indicate no parent of group */
#define DPID_SYSTEM_GROUP DPID_NOPARENT_GROUP /* If system group is supported
                                                 we don't have to change much */
#define DPID_NAME_SERVER 0x19a9d65b  /* Don't ask me why */

/* Strip out dwFlag values which cannot be sent in the CREATEGROUP msg */
#define DPMSG_CREATEGROUP_DWFLAGS(x) ( (x) & DPGROUP_HIDDEN )

/* Strip out all dwFlags values for CREATEPLAYER msg */
#define DPMSG_CREATEPLAYER_DWFLAGS(x) 0

static LONG kludgePlayerGroupId = 1000;

/* ------------------------------------------------------------------ */


static BOOL DP_CreateIUnknown( LPVOID lpDP )
{
  IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;

  This->unk = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->unk) ) );
  if ( This->unk == NULL )
  {
    return FALSE;
  }

  InitializeCriticalSection( &This->unk->DP_lock );

  return TRUE;
}

static BOOL DP_DestroyIUnknown( LPVOID lpDP )
{
  IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;

  DeleteCriticalSection( &This->unk->DP_lock );
  HeapFree( GetProcessHeap(), 0, This->unk );

  return TRUE;
}

static BOOL DP_CreateDirectPlay2( LPVOID lpDP )
{
  IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;

  This->dp2 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(This->dp2) ) );
  if ( This->dp2 == NULL )
  {
    return FALSE;
  }

  This->dp2->bConnectionOpen = FALSE;

  This->dp2->hEnumSessionThread = INVALID_HANDLE_VALUE;

  This->dp2->bHostInterface = FALSE;

  DPQ_INIT(This->dp2->receiveMsgs);
  DPQ_INIT(This->dp2->sendMsgs);
  DPQ_INIT(This->dp2->replysExpected);

  if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
  {
    /* FIXME: Memory leak */
    return FALSE;
  }

  /* Provide an initial session desc with nothing in it */
  This->dp2->lpSessionDesc = HeapAlloc( GetProcessHeap(),
                                        HEAP_ZERO_MEMORY,
                                        sizeof( *This->dp2->lpSessionDesc ) );
  if( This->dp2->lpSessionDesc == NULL )
  {
    /* FIXME: Memory leak */
    return FALSE;
  }
  This->dp2->lpSessionDesc->dwSize = sizeof( *This->dp2->lpSessionDesc );

  /* We are emulating a dp 6 implementation */
  This->dp2->spData.dwSPVersion = DPSP_MAJORVERSION;

  This->dp2->spData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                                      sizeof( *This->dp2->spData.lpCB ) );
  This->dp2->spData.lpCB->dwSize = sizeof( *This->dp2->spData.lpCB );
  This->dp2->spData.lpCB->dwVersion = DPSP_MAJORVERSION;

  /* This is the pointer to the service provider */
  if( FAILED( DPSP_CreateInterface( &IID_IDirectPlaySP,
                                    (LPVOID*)&This->dp2->spData.lpISP, This ) )
    )
  {
    /* FIXME: Memory leak */
    return FALSE;
  }

  /* Setup lobby provider information */
  This->dp2->dplspData.dwSPVersion = DPSP_MAJORVERSION;
  This->dp2->dplspData.lpCB = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                                         sizeof( *This->dp2->dplspData.lpCB ) );
  This->dp2->dplspData.lpCB->dwSize = sizeof(  *This->dp2->dplspData.lpCB );

  if( FAILED( DPLSP_CreateInterface( &IID_IDPLobbySP,
                                     (LPVOID*)&This->dp2->dplspData.lpISP, This ) )
    )
  {
    /* FIXME: Memory leak */
    return FALSE;
  }

  return TRUE;
}

/* Definition of the global function in dplayx_queue.h. #
 * FIXME: Would it be better to have a dplayx_queue.c for this function? */
DPQ_DECL_DELETECB( cbDeleteElemFromHeap, LPVOID )
{
  HeapFree( GetProcessHeap(), 0, elem );
}

/* Function to delete the list of groups with this interface. Needs to
 * delete the group and player lists associated with this group as well
 * as the group data associated with this group. It should not delete
 * player data as that is shared with the top player list and will be
 * deleted with that.
 */
DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList );
DPQ_DECL_DELETECB( cbDeleteGroupsElem, lpGroupList )
{
  DPQ_DELETEQ( elem->lpGData->groups, groups,
               lpGroupList, cbDeleteElemFromHeap );
  DPQ_DELETEQ( elem->lpGData->players, players,
               lpPlayerList, cbDeleteElemFromHeap );
  HeapFree( GetProcessHeap(), 0, elem->lpGData );
  HeapFree( GetProcessHeap(), 0, elem );
}

/* Function to delete the list of players with this interface. Needs to
 * delete the player data for all players as well.
 */
DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList );
DPQ_DECL_DELETECB( cbDeletePlayerElem, lpPlayerList )
{
  HeapFree( GetProcessHeap(), 0, elem->lpPData );
  HeapFree( GetProcessHeap(), 0, elem );
}

static BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
{
  IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)lpDP;

  if( This->dp2->hEnumSessionThread != INVALID_HANDLE_VALUE )
  {
    TerminateThread( This->dp2->hEnumSessionThread, 0 );
    CloseHandle( This->dp2->hEnumSessionThread );
  }

  /* Finish with the SP - have it shutdown */
  if( This->dp2->spData.lpCB->ShutdownEx )
  {
    DPSP_SHUTDOWNDATA data;

    TRACE( "Calling SP ShutdownEx\n" );

    data.lpISP = This->dp2->spData.lpISP;

    (*This->dp2->spData.lpCB->ShutdownEx)( &data );
  }
  else if (This->dp2->spData.lpCB->Shutdown ) /* obsolete interface */
  {
    TRACE( "Calling obsolete SP Shutdown\n" );
    (*This->dp2->spData.lpCB->Shutdown)();
  }

  /* Unload the SP (if it exists) */
  if( This->dp2->hServiceProvider != 0 )
  {
    FreeLibrary( This->dp2->hServiceProvider );
  }

  /* Unload the Lobby Provider (if it exists) */
  if( This->dp2->hDPLobbyProvider != 0 )
  {
    FreeLibrary( This->dp2->hDPLobbyProvider );
  }

#if 0
  DPQ_DELETEQ( This->dp2->players, players, lpPlayerList, cbDeletePlayerElem );
  DPQ_DELETEQ( This->dp2->groups, groups, lpGroupList, cbDeleteGroupsElem );
#endif

  /* FIXME: Need to delete receive and send msgs queue contents */

  NS_DeleteSessionCache( This->dp2->lpNameServerData );

  HeapFree( GetProcessHeap(), 0, This->dp2->lpSessionDesc );

  IDirectPlaySP_Release( This->dp2->spData.lpISP );

  /* Delete the contents */
  HeapFree( GetProcessHeap(), 0, This->dp2 );

  return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -