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

📄 dplay.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
static BOOL DP_CreateDirectPlay3( LPVOID lpDP )
{
  IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;

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

  return TRUE;
}

static BOOL DP_DestroyDirectPlay3( LPVOID lpDP )
{
  IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;

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

  return TRUE;
}

static BOOL DP_CreateDirectPlay4( LPVOID lpDP )
{
  IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)lpDP;

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

  return TRUE;
}

static BOOL DP_DestroyDirectPlay4( LPVOID lpDP )
{
  IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)lpDP;

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

  return TRUE;
}


/* Create a new interface */
extern
HRESULT DP_CreateInterface
         ( REFIID riid, LPVOID* ppvObj )
{
  TRACE( " for %s\n", debugstr_guid( riid ) );

  *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                       sizeof( IDirectPlay2Impl ) );

  if( *ppvObj == NULL )
  {
    return DPERR_OUTOFMEMORY;
  }

  if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
  {
    IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
    This->lpVtbl = &directPlay2WVT;
  }
  else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
  {
    IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
    This->lpVtbl = &directPlay2AVT;
  }
  else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
  {
    IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
    This->lpVtbl = &directPlay3WVT;
  }
  else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
  {
    IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
    This->lpVtbl = &directPlay3AVT;
  }
  else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
  {
    IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
    This->lpVtbl = &directPlay4WVT;
  }
  else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
  {
    IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
    This->lpVtbl = &directPlay4AVT;
  }
  else
  {
    /* Unsupported interface */
    HeapFree( GetProcessHeap(), 0, *ppvObj );
    *ppvObj = NULL;

    return E_NOINTERFACE;
  }

  /* Initialize it */
  if ( DP_CreateIUnknown( *ppvObj ) &&
       DP_CreateDirectPlay2( *ppvObj ) &&
       DP_CreateDirectPlay3( *ppvObj ) &&
       DP_CreateDirectPlay4( *ppvObj )
     )
  {
    IDirectPlayX_AddRef( (LPDIRECTPLAY2A)*ppvObj );

    return S_OK;
  }

  /* Initialize failed, destroy it */
  DP_DestroyDirectPlay4( *ppvObj );
  DP_DestroyDirectPlay3( *ppvObj );
  DP_DestroyDirectPlay2( *ppvObj );
  DP_DestroyIUnknown( *ppvObj );

  HeapFree( GetProcessHeap(), 0, *ppvObj );

  *ppvObj = NULL;
  return DPERR_NOMEMORY;
}


/* Direct Play methods */

/* Shared between all dplay types */
static HRESULT WINAPI DP_QueryInterface
         ( LPDIRECTPLAY2 iface, REFIID riid, LPVOID* ppvObj )
{
  IDirectPlay2Impl *This = (IDirectPlay2Impl *)iface;
  TRACE("(%p)->(%s,%p)\n", This, debugstr_guid( riid ), ppvObj );

  *ppvObj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                       sizeof( *This ) );

  if( *ppvObj == NULL )
  {
    return DPERR_OUTOFMEMORY;
  }

  CopyMemory( *ppvObj, This, sizeof( *This )  );
  (*(IDirectPlay2Impl**)ppvObj)->ulInterfaceRef = 0;

  if( IsEqualGUID( &IID_IDirectPlay2, riid ) )
  {
    IDirectPlay2Impl *This = (IDirectPlay2Impl *)*ppvObj;
    This->lpVtbl = &directPlay2WVT;
  }
  else if( IsEqualGUID( &IID_IDirectPlay2A, riid ) )
  {
    IDirectPlay2AImpl *This = (IDirectPlay2AImpl *)*ppvObj;
    This->lpVtbl = &directPlay2AVT;
  }
  else if( IsEqualGUID( &IID_IDirectPlay3, riid ) )
  {
    IDirectPlay3Impl *This = (IDirectPlay3Impl *)*ppvObj;
    This->lpVtbl = &directPlay3WVT;
  }
  else if( IsEqualGUID( &IID_IDirectPlay3A, riid ) )
  {
    IDirectPlay3AImpl *This = (IDirectPlay3AImpl *)*ppvObj;
    This->lpVtbl = &directPlay3AVT;
  }
  else if( IsEqualGUID( &IID_IDirectPlay4, riid ) )
  {
    IDirectPlay4Impl *This = (IDirectPlay4Impl *)*ppvObj;
    This->lpVtbl = &directPlay4WVT;
  }
  else if( IsEqualGUID( &IID_IDirectPlay4A, riid ) )
  {
    IDirectPlay4AImpl *This = (IDirectPlay4AImpl *)*ppvObj;
    This->lpVtbl = &directPlay4AVT;
  }
  else
  {
    /* Unsupported interface */
    HeapFree( GetProcessHeap(), 0, *ppvObj );
    *ppvObj = NULL;

    return E_NOINTERFACE;
  }

  IDirectPlayX_AddRef( (LPDIRECTPLAY2)*ppvObj );

  return S_OK;
}

/* Shared between all dplay types */
static ULONG WINAPI DP_AddRef
         ( LPDIRECTPLAY3 iface )
{
  ULONG ulInterfaceRefCount, ulObjRefCount;
  IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;

  ulObjRefCount       = InterlockedIncrement( &This->unk->ulObjRef );
  ulInterfaceRefCount = InterlockedIncrement( &This->ulInterfaceRef );

  TRACE( "ref count incremented to %lu:%lu for %p\n",
         ulInterfaceRefCount, ulObjRefCount, This );

  return ulObjRefCount;
}

static ULONG WINAPI DP_Release
( LPDIRECTPLAY3 iface )
{
  ULONG ulInterfaceRefCount, ulObjRefCount;

  IDirectPlay3Impl *This = (IDirectPlay3Impl *)iface;

  ulObjRefCount       = InterlockedDecrement( &This->unk->ulObjRef );
  ulInterfaceRefCount = InterlockedDecrement( &This->ulInterfaceRef );

  TRACE( "ref count decremented to %lu:%lu for %p\n",
         ulInterfaceRefCount, ulObjRefCount, This );

  /* Deallocate if this is the last reference to the object */
  if( ulObjRefCount == 0 )
  {
     /* If we're destroying the object, this must be the last ref
        of the last interface */
     DP_DestroyDirectPlay4( This );
     DP_DestroyDirectPlay3( This );
     DP_DestroyDirectPlay2( This );
     DP_DestroyIUnknown( This );
  }

  /* Deallocate the interface */
  if( ulInterfaceRefCount == 0 )
  {
    HeapFree( GetProcessHeap(), 0, This );
  }

  return ulObjRefCount;
}

static inline DPID DP_NextObjectId(void)
{
  return (DPID)InterlockedIncrement( &kludgePlayerGroupId );
}

/* *lplpReply will be non NULL iff there is something to reply */
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, lpcMessageBody, dwMessageBodySize, lpcMessageHeader, wCommandId,
         wVersion );

  switch( wCommandId )
  {
    /* Name server needs to handle this request */
    case DPMSGCMD_ENUMSESSIONSREQUEST:
    {
      /* Reply expected */
      NS_ReplyToEnumSessionsRequest( lpcMessageBody, lplpReply, lpdwMsgSize, This );

      break;
    }

    /* Name server needs to handle this request */
    case DPMSGCMD_ENUMSESSIONSREPLY:
    {
      /* No reply expected */
      NS_AddRemoteComputerAsNameServer( lpcMessageHeader,
                                        This->dp2->spData.dwSPHeaderSize,
                                        (LPDPMSG_ENUMSESSIONSREPLY)lpcMessageBody,
                                        This->dp2->lpNameServerData );
      break;
    }

    case DPMSGCMD_REQUESTNEWPLAYERID:
    {
      LPCDPMSG_REQUESTNEWPLAYERID lpcMsg =
        (LPCDPMSG_REQUESTNEWPLAYERID)lpcMessageBody;

      LPDPMSG_NEWPLAYERIDREPLY lpReply;

      *lpdwMsgSize = This->dp2->spData.dwSPHeaderSize + sizeof( *lpReply );

      *lplpReply = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *lpdwMsgSize );

      FIXME( "Ignoring dwFlags 0x%08lx in request msg\n",
             lpcMsg->dwFlags );

      /* Setup the reply */
      lpReply = (LPDPMSG_NEWPLAYERIDREPLY)( (BYTE*)(*lplpReply) +
                                            This->dp2->spData.dwSPHeaderSize );

      lpReply->envelope.dwMagic    = DPMSGMAGIC_DPLAYMSG;
      lpReply->envelope.wCommandId = DPMSGCMD_NEWPLAYERIDREPLY;
      lpReply->envelope.wVersion   = DPMSGVER_DP6;

      lpReply->dpidNewPlayerId = DP_NextObjectId();

      TRACE( "Allocating new playerid 0x%08lx from remote request\n",
             lpReply->dpidNewPlayerId );

      break;
    }

    case DPMSGCMD_GETNAMETABLEREPLY:
    case DPMSGCMD_NEWPLAYERIDREPLY:
    {

#if 0
      if( wCommandId == DPMSGCMD_NEWPLAYERIDREPLY )
        DebugBreak();
#endif
      DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );

      break;
    }

#if 1
    case DPMSGCMD_JUSTENVELOPE:
    {
      TRACE( "GOT THE SELF MESSAGE: %p -> 0x%08lx\n", lpcMessageHeader, ((LPDWORD)lpcMessageHeader)[1] );
      NS_SetLocalAddr( This->dp2->lpNameServerData, lpcMessageHeader, 20 );
      DP_MSG_ReplyReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
    }
#endif

    case DPMSGCMD_FORWARDADDPLAYER:
    {
#if 0
      DebugBreak();
#endif
#if 1
    TRACE( "Sending message to self to get my addr\n" );
    DP_MSG_ToSelf( This, 1 ); /* This is a hack right now */
#endif
      break;
    }

    case DPMSGCMD_FORWARDADDPLAYERNACK:
    {
      DP_MSG_ErrorReceived( This, wCommandId, lpcMessageBody, dwMessageBodySize );
      break;
    }

    default:
    {
      FIXME( "Unknown wCommandId %u. Ignoring message\n", wCommandId );
      DebugBreak();
      break;
    }
  }

  /* FIXME: There is code in dplaysp.c to handle dplay commands. Move to here. */

  return DP_OK;
}


static HRESULT WINAPI DP_IF_AddPlayerToGroup
          ( IDirectPlay2Impl* This, LPVOID lpMsgHdr, DPID idGroup,
            DPID idPlayer, BOOL bAnsi )
{
  lpGroupData  lpGData;
  lpPlayerList lpPList;
  lpPlayerList lpNewPList;

  TRACE( "(%p)->(%p,0x%08lx,0x%08lx,%u)\n",
         This, lpMsgHdr, idGroup, idPlayer, bAnsi );

  /* Find the group */
  if( ( lpGData = DP_FindAnyGroup( This, idGroup ) ) == NULL )
  {
    return DPERR_INVALIDGROUP;
  }

  /* Find the player */
  if( ( lpPList = DP_FindPlayer( This, idPlayer ) ) == NULL )
  {
    return DPERR_INVALIDPLAYER;
  }

  /* Create a player list (ie "shortcut" ) */
  lpNewPList = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpNewPList ) );
  if( lpNewPList == NULL )
  {
    return DPERR_CANTADDPLAYER;
  }

  /* Add the shortcut */
  lpPList->lpPData->uRef++;
  lpNewPList->lpPData = lpPList->lpPData;

  /* Add the player to the list of players for this group */
  DPQ_INSERT(lpGData->players,lpNewPList,players);

  /* Let the SP know that we've added a player to the group */
  if( This->dp2->spData.lpCB->AddPlayerToGroup )
  {
    DPSP_ADDPLAYERTOGROUPDATA data;

    TRACE( "Calling SP AddPlayerToGroup\n" );

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

    (*This->dp2->spData.lpCB->AddPlayerToGroup)( &data );
  }

  /* Inform all other peers of the addition of player to the group. If there are
   * no peers keep this event quiet.
   * Also, if this event was the result of another machine sending it to us,
   * don't bother rebroadcasting it.
   */
  if( ( lpMsgHdr == NULL ) &&
      This->dp2->lpSessionDesc &&
      ( This->dp2->lpSessionDesc->dwFlags & DPSESSION_MULTICASTSERVER ) )
  {
    DPMSG_ADDPLAYERTOGROUP msg;
    msg.dwType = DPSYS_ADDPLAYERTOGROUP;

⌨️ 快捷键说明

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