// -------------------------------------------------------------------------- // ========================================================================== // File: TDx_Play.CPP // Authors: BCB_Code_Generator v1.70, // Darren Dwyer (source code, documentation, demos, website), // Hugh Edwards (documentation, icons), // Brian Austin (some source code, documentation) // Description: This file contains the code for the TDx_Play Component // // "TDx_Play_Library v1.70" // (c) 2003 BCB-Tools.com Pty. Ltd., Sydney, Australia. // All Rights Reserved. // // Refer to the 'Licence.Txt' file for licencing & copyright information. // ========================================================================== // -------------------------------------------------------------------------- // #includes ... // -------------------------------------------------------------------------- #include #pragma hdrstop // -------------------------------------------------------------------------- #include "TDx_Play.H" // -------------------------------------------------------------------------- // external classes used by the TDx_Play component. #include "TDPName.H" #include "TDPChat.H" #include "TDPLConnection.H" // -------------------------------------------------------------------------- // external classes used by TDx_Play methods. #include "TDPSessionDesc.H" #include "TDPCaps.H" #include "TDPSecurityDesc.H" #include "TDPCredentials.H" // -------------------------------------------------------------------------- #pragma link "TDx_Library_Defns" #pragma link "TDx_Library_Functions" #pragma link "TDx_Play_Library_Defns" #pragma link "TDx_Play_Library_Functions" // -------------------------------------------------------------------------- // Object Registration... // -------------------------------------------------------------------------- #if (__BORLANDC__ >= 0x0530) // BCB Version 3+ #pragma package(smart_init) #endif // -------------------------------------------------------------------------- static inline void ValidCtrCheck(TDx_Play*) { new TDx_Play(NULL); } // -------------------------------------------------------------------------- namespace Tdx_play { #if (__BORLANDC__ >= 0x0530) // BCB Version 3+ void __fastcall PACKAGE Register() #else void __fastcall Register() #endif { TComponentClass classes[1] = {__classid(TDx_Play)}; RegisterComponents("TDx_Play", classes, 0); } } // -------------------------------------------------------------------------- // Global Variables used internally by the TDx_Play component. // -------------------------------------------------------------------------- static TComponent* TDx_Play_ThreadParent = NULL; // -------------------------------------------------------------------------- // Global Functions used internally by the TDx_Play component. // -------------------------------------------------------------------------- class TDx_Play_ThreadClass : public TThread { public: __property bool HandlesModified = {write=fHandlesModified, default=true}; void __fastcall DoNothing() {}; void __fastcall Pause() { while (fRebuildingHandles) DoNothing(); SetEvent( fPauseEvent ); } void __fastcall Restart() { while (fRebuildingHandles) DoNothing(); SetEvent( fRestartEvent ); } void __fastcall TerminateImmediately() { while (fRebuildingHandles) DoNothing(); SetEvent( fTerminateEvent ); } void __fastcall RebuildHandles(); __fastcall TDx_Play_ThreadClass(); virtual __fastcall ~TDx_Play_ThreadClass(); protected: void __fastcall Execute(); void __fastcall Translate(); private: HANDLE* fHandles; TDx_Play** fHandleOwners; int fNumHandles; HANDLE fPauseEvent; HANDLE fRestartEvent; HANDLE fTerminateEvent; int fPauseIndex; int fRestartIndex; int fTerminateIndex; int fEventNum; bool fHandlesModified; bool fRebuildingHandles; }; //--------------------------------------------------------------------------- static TList* TDx_Play_ComponentList = NULL; static TDx_Play_ThreadClass* TDx_Play_Thread = NULL; //--------------------------------------------------------------------------- __fastcall TDx_Play_ThreadClass::TDx_Play_ThreadClass() : TThread(true) { fHandles = NULL; fNumHandles = 0; fEventNum = 0; fPauseEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); fPauseIndex = -1; fRestartEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); fRestartIndex = -1; fTerminateEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); fTerminateIndex = -1; fHandlesModified = true; fRebuildingHandles = false; } //--------------------------------------------------------------------------- __fastcall TDx_Play_ThreadClass::~TDx_Play_ThreadClass() { if (fHandles) { delete[] fHandles; fHandles = NULL; fNumHandles = 0; } if (fTerminateEvent) { CloseHandle( fTerminateEvent ); fTerminateEvent = NULL; } if (fRestartEvent) { CloseHandle( fRestartEvent ); fRestartEvent = NULL; } if (fPauseEvent) { CloseHandle( fPauseEvent ); fPauseEvent = NULL; } } //--------------------------------------------------------------------------- void __fastcall TDx_Play_ThreadClass::Execute() { FreeOnTerminate = true; // wait for events while (true) { // rebuild handles iff required if (fHandlesModified) { fRebuildingHandles = true; RebuildHandles(); fHandlesModified = false; // do not change the order of these 2 bools fRebuildingHandles = false; // because other threads might be waiting for -this- result before changing ^one } // wait for notifications + pause, restart, terminate events fEventNum = WaitForMultipleObjects( fNumHandles+3, fHandles, FALSE, INFINITE ); // if for some reason the handles were invalid, re-try if (fEventNum==WAIT_FAILED) { fHandlesModified = true; // force a rebuild of the handles continue; } // modify the result fEventNum -= WAIT_OBJECT_0; // if it's a pause, wait for a resume or a terminate if (fEventNum == fPauseIndex) { // wait for restart / terminate event fEventNum = WaitForMultipleObjects( 2, &fHandles[fRestartIndex], FALSE, INFINITE ); } // if it's a restart, simply restart if (fEventNum == fRestartIndex) { continue; } // if it's a terminate event, exit immediately if (fEventNum == fTerminateIndex) { break; } // otherwise, the event is a notification event, send it to the user if (fEventNum < fNumHandles) { Synchronize(Translate); } } // finished } //--------------------------------------------------------------------------- void __fastcall TDx_Play_ThreadClass::RebuildHandles() { if (fHandles) { delete[] fHandles; fHandles = NULL; fNumHandles = 0; } if (fHandleOwners) { delete[] fHandleOwners; fHandleOwners = NULL; } // determine the number of handles that need to be added int num_handles = 0; for (int i=0;iCount;i++) { TDx_Play* play = (TDx_Play*) TDx_Play_ComponentList->Items[i]; if (play) if (play->Created) if (play->NumPlayers>0) num_handles += play->NumPlayers; } // allocate storage for handles and something to tell us who the handle refers to fHandles = new HANDLE [num_handles+3]; if (!fHandles) return; fHandleOwners = new TDx_Play* [num_handles+3]; if (!fHandleOwners) { delete[] fHandles; fHandles = NULL; return; } fNumHandles = num_handles; // add notification events to internal storage int pos = 0; for (int i=0;iCount;i++) { TDx_Play* play = (TDx_Play*) TDx_Play_ComponentList->Items[i]; if (play) if (play->Created) if (play->NumPlayers>0) for (int j=0;jNumPlayers;j++) { fHandles[pos] = play->PlayerEvents->Items[j]; fHandleOwners[pos] = play; pos++; } } // add pause, restart, terminate events fPauseIndex = fNumHandles; fHandles[fPauseIndex] = fPauseEvent; fRestartIndex = fNumHandles+1; fHandles[fRestartIndex] = fRestartEvent; fTerminateIndex = fNumHandles+2; fHandles[fTerminateIndex] = fTerminateEvent; } //--------------------------------------------------------------------------- void __fastcall TDx_Play_ThreadClass::Translate() { // if the handles were modified during the synchronize, abort immediately if (fHandlesModified) { return; } // send it to the relevant BCB event handler try { TDx_Play* play = (TDx_Play*) fHandleOwners[fEventNum]; if (play) // send to the TDx_Play::OnReceive() event (if one has been setup) if (play->OnReceive) play->OnReceive( play ); } // absorb anything extraordinary catch (...) {} } // -------------------------------------------------------------------------- // Extra code for Callback Handling // -------------------------------------------------------------------------- TDx_Play* TDx_Play_OnEnumConnectionsOwner = NULL; TDx_Play* TDx_Play_OnEnumGroupPlayersOwner = NULL; TDx_Play* TDx_Play_OnEnumGroupsOwner = NULL; TDx_Play* TDx_Play_OnEnumGroupsInGroupOwner = NULL; TDx_Play* TDx_Play_OnEnumPlayersOwner = NULL; TDx_Play* TDx_Play_OnEnumSessionsOwner = NULL; // -------------------------------------------------------------------------- // Constructor: TDx_Play::TDx_Play() // Description: The default constructor for the TDx_Play object. // -------------------------------------------------------------------------- __fastcall TDx_Play::TDx_Play(TComponent* Owner) : TComponent(Owner) { // Set up the IDs, Events and EventList internal variables fCreated = false; fErrorValue = DP_OK; fNumPlayers = 0; fPlayerIDs = new TList(); if (fPlayerIDs == NULL) { fErrorValue = DPERR_OUTOFMEMORY; } fPlayerEvents = new TList(); if (fPlayerEvents == NULL) { delete fPlayerIDs; fErrorValue = DPERR_OUTOFMEMORY; } // create the thread iff required bool inside_ide = false; if (Screen) if (Screen->ActiveForm) if (Screen->ActiveForm->Designer) inside_ide = true; if (!inside_ide) if (TDx_Play_ThreadParent==NULL) { TDx_Play_ComponentList = new TList(); if (TDx_Play_ComponentList) { TDx_Play_Thread = new TDx_Play_ThreadClass(); if (TDx_Play_Thread) { TDx_Play_ThreadParent=this; TDx_Play_Thread->Resume(); } else { delete TDx_Play_ComponentList; TDx_Play_ComponentList = NULL; TDx_Play_ThreadParent = NULL; } } } } // -------------------------------------------------------------------------- // Destructor: TDx_Play::~TDx_Play() // Description: The destructor for the TDx_Play object. // -------------------------------------------------------------------------- __fastcall TDx_Play::~TDx_Play() { // make sure to destroy internals if (Created) Destroy(); // destroy the thread iff required if (TDx_Play_Thread != NULL) if (TDx_Play_ThreadParent==this) { TDx_Play_Thread->Pause(); // remove from list if (TDx_Play_ComponentList) if (TDx_Play_ComponentList->IndexOf(this)!=-1) TDx_Play_ComponentList->Delete( TDx_Play_ComponentList->IndexOf(this) ); // if there are any other components still alive, migrate the parent bool migrated = false; for (int i=0;iCount;i++) if (TDx_Play_ComponentList->Items[i]!=NULL) { TDx_Play_ThreadParent = (TDx_Play*) TDx_Play_ComponentList->Items[i]; migrated = true; break; } // otherwise, destroy the thread and the component list if (!migrated) { TDx_Play_Thread->TerminateImmediately(); TDx_Play_Thread = NULL; // :: DO NOT :: delete TDx_Play_Thread; delete TDx_Play_ComponentList; TDx_Play_ComponentList = NULL; TDx_Play_ThreadParent = NULL; } else // restart the thread with the new parent. { TDx_Play_Thread->HandlesModified = true; TDx_Play_Thread->Restart(); } } //clean up internal TLists for (int i=0;iCount;i++) { if (fPlayerEvents->Items[i]!=NULL) { // remove player event HANDLE handle = (HANDLE) fPlayerEvents->Items[i]; CloseHandle( handle ); } } if (fPlayerEvents) delete fPlayerEvents; if (fPlayerIDs) delete fPlayerIDs; } // -------------------------------------------------------------------------- // Property: Created // Description: The Created property is true if the internal LPDIRECTPLAY4 // used in this component has been successfully created, // otherwise Created is false. // // To create the internal LPDIRECTPLAY4, call the // TDx_Play::Create() method. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::FGetCreated() { return fCreated; } // -------------------------------------------------------------------------- void __fastcall TDx_Play::FSetCreated( bool pCreated ) { fCreated = (pCreated && (fLPDIRECTPLAY4==NULL)); } // -------------------------------------------------------------------------- // Property: ErrorValue // Description: The ErrorValue property contains the last error value // returned from a call to a TDx_Play method or fget/fset. eg. // DP_OK or DDERR_SURFACELOST or TDX_ERROR // -------------------------------------------------------------------------- HRESULT __fastcall TDx_Play::FGetErrorValue() { return fErrorValue; } // -------------------------------------------------------------------------- void __fastcall TDx_Play::FSetErrorValue( HRESULT pErrorValue ) { fErrorValue = pErrorValue; } // -------------------------------------------------------------------------- // Property: NumPlayers // Description: The NumPlayers property defines how many players are // currently active for this component. // -------------------------------------------------------------------------- int __fastcall TDx_Play::FGetNumPlayers() { return fNumPlayers; } // -------------------------------------------------------------------------- void __fastcall TDx_Play::FSetNumPlayers( int pNumPlayers ) { fNumPlayers = pNumPlayers; } // -------------------------------------------------------------------------- // Property: PlayerEvents // Description: The PlayerEvents property references a windows event list // that is used internally by the TDx_Play and // TDx_Play_ThreadClass. // -------------------------------------------------------------------------- TList* __fastcall TDx_Play::FGetPlayerEvents() { return fPlayerEvents; } // -------------------------------------------------------------------------- // Property: PlayerIDs // Description: The PlayerIDs property references the player ID's belonging // to this component. // -------------------------------------------------------------------------- TList* __fastcall TDx_Play::FGetPlayerIDs() { return fPlayerIDs; } // -------------------------------------------------------------------------- // Property: UseAnsiString // Description: The UseAnsiString property is used to toggle a DirectPlay // interface between AnsiString or UniCode. // Set this property to true to enable an AnsiString interface. // Set this property to false to enable a Unicode interface. // You should set this property before calling the // TDx_Play::Create() method. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::FGetUseAnsiString() { return fUseAnsiString; } // -------------------------------------------------------------------------- void __fastcall TDx_Play::FSetUseAnsiString( bool pUseAnsiString ) { fUseAnsiString = pUseAnsiString; } // -------------------------------------------------------------------------- // Method: AddGroupToGroup() // Description: The AddGroupToGroup method will add a shortcut to another // group within an existing group. // // TDx_Play::EnumGroupsInGroup() can be used to enumerate linked // groups, and a group may be linked to multiple other groups. // TDx_Play::DeleteGroupFromGroup() can be used to remove an // existing group link. // // A DPMSG_ADDGROUPTOGROUP system message will inform players of // the change. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDGROUP // Params: pParentGroup - // The ParentGroup parameter identifies the group to which the // link is to be added. // pGroup - // The Group parameter identifies the group whose link is to be // added to the ParentGroup. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::AddGroupToGroup( DPID pParentGroup, DPID pGroup ) { // Original Function Definition // HRESULT AddGroupToGroup( // DPID idParentGroup, // DPID idGroup // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::AddGroupToGroup()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pParentGroup==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::AddGroupToGroup()", "TDX_BADPARAMS", "'pParentGroup' cannot be 'NULL'"); return false; } if (pGroup==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::AddGroupToGroup()", "TDX_BADPARAMS", "'pGroup' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->AddGroupToGroup( pParentGroup, pGroup ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::AddGroupToGroup()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: AddPlayerToGroup() // Description: The AddPlayerToGroup method will add a player to an existing // group. // // Players may be present within multiple groups and any player // may be added to any group. // // A DPMSG_ADDPLAYERTOGROUP system message will inform other // players of the change. // // Error values that can be generated are: // // DPERR_CANTADDPLAYER // DPERR_CONNECTIONLOST // DPERR_INVALIDGROUP // DPERR_INVALIDPLAYER // DPERR_NOSESSIONS // Params: pGroup - // The Group parameter identifies the group to which the player // is to be added. // pPlayer - // The Player parameter identifies the player to be added to the // Group. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::AddPlayerToGroup( DPID pGroup, DPID pPlayer ) { // Original Function Definition // HRESULT AddPlayerToGroup( // DPID idGroup, // DPID idPlayer // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::AddPlayerToGroup()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pGroup==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::AddPlayerToGroup()", "TDX_BADPARAMS", "'pGroup' cannot be 'NULL'"); return false; } if (pPlayer==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::AddPlayerToGroup()", "TDX_BADPARAMS", "'pPlayer' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->AddPlayerToGroup( pGroup, pPlayer ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::AddPlayerToGroup()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: CancelMessage() // Description: The CancelMessage method is used to cancel asynchronous // messages from the send queue. // // Specific messages can be cancelled by specifying the ID // assigned to them by TDx_Play::SendEx(). // Partially sent messages cannot be cancelled, a group message // that has already been sent to at least one group member is // regarded to be partially sent. // // A DPMSG_SENDCOMPLETE system message is generated to indicate // successful cancellation. // // Error values that can be generated are: // // DPERR_CANCELFAILED // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_UNKNOWNMESSAGE // DPERR_UNSUPPORTED // Params: pMsgID - // The MsgID identifies the message to be cancelled. // // Set zero to cancel all pending messages. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::CancelMessage( dword pMsgID ) { // Original Function Definition // HRESULT CancelMessage( // DWORD dwMsgID, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::CancelMessage()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->CancelMessage( (DWORD) pMsgID, 0 ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::CancelMessage()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: CancelPriority() // Description: The CancelPriority method is used to cancel asynchronous // messages within a specified priority range from the send // queue. // // Partially sent messages cannot be cancelled, a group message // that has already been sent to at least one group member is // regarded to be partially sent. // // A DPMSG_SENDCOMPLETE system message will be generated for // cancelled messages, indicating successful cancellation. // // Error values that can be generated are: // // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_UNSUPPORTED // Params: pMinPriority - // The MinPriority defines the lowest message priority that is // to be cancelled. // pMaxPriority - // The MaxPriority defines the highest message priority that is // to be cancelled. // // Must be higher than MinPriority. // Set MAXPRIORITY to specify the maximum possible value. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::CancelPriority( dword pMinPriority, dword pMaxPriority ) { // Original Function Definition // HRESULT CancelPriority( // DWORD dwMinPriority, // DWORD dwMaxPriority, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::CancelPriority()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->CancelPriority( (DWORD) pMinPriority, (DWORD) pMaxPriority, 0 ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::CancelPriority()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Close() // Description: The Close method will close a previosly created session. // // Ownership of locally created groups is migrated to the // session host and locally created players will be destroyed. // // DPMSG_DELETEPLAYERFROMGROUP and DPMSG_DESTROYPLAYERORGROUP // system messages will be sent as appropriate to inform other // session participants of the changes. // // Error values that can be generated are: // // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_NOSESSIONS // -------------------------------------------------------------------------- bool __fastcall TDx_Play::Close() { // Original Function Definition // HRESULT Close(); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Close()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->Close( ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::Close()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Create() // Description: The Create() method is used to automatically create the // internal LPDIRECTPLAY4 interface used in the TDx_Play // component and must be called before any methods of the // TDx_Play component will function. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::Create() { // if the component internals have already been created, exit if (fCreated) { fErrorValue = TDX_ALREADYCREATED; if (FOnError) FOnError( this, Name+"::Create()", "TDX_ALREADYCREATED", "The "+Name+"::Create() method was called when the component has already been created successfully." ); return false; } // initialize DirectPlay fLPDIRECTPLAY4=NULL; CoInitialize(NULL); if (UseAnsiString) fErrorValue = CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_ALL, IID_IDirectPlay4A, (LPVOID*)&fLPDIRECTPLAY4); else fErrorValue = CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_ALL, IID_IDirectPlay4, (LPVOID*)&fLPDIRECTPLAY4); if (fErrorValue != DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::Create()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } if (fLPDIRECTPLAY4 != NULL) { fErrorValue = DP_OK; fCreated = true; if (FOnCreate) FOnCreate(this); } else if (FOnError) FOnError( this, Name+"::Create()", "TDX_ERROR", "The "+Name+"::Create() method failed because CoCreateInstance(...) failed." ); return fCreated; } // -------------------------------------------------------------------------- // Method: CreateGroup() // Description: The CreateGroup method will create a group within the // session. // // For a client server session, no group notification messages // are sent and groups are only visible on the machine that // created them. // For a peer to peer session, CreateGroup generates a // DPMSG_CREATEPLAYERORGROUP message notifying players of the // change. TDx_Play::Send() can then send messages to all group // members by sending a message to the group ID. // // Groups created with this method are the top level groups // within the session and can be enumerated by // TDx_Play::EnumGroups(). To create subgroups // TDx_Play::CreateGroupInGroup() must be used. // // The creating player is the owner and only they may change the // group properties, but any player may add or remove members or // delete the group. // // If the creating player leaves the session, ownership is // migrated to the host, and a group will persist within the // session until it is explicitly destroyed. // // Error values that can be generated are: // // DPERR_CANTADDPLAYER // DPERR_CONNECTIONLOST // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // Params: pGroup - // The Group parameter will reference the new groups ID if this // method returns successfully. // pGroupName - // The GroupName parameter references a TDPName component // holding the name for the new group. // // The name is assigned and used by the application, it need not // be unique and NULL can be set if no group name is required. // pData - // The Data parameter references data to be propagated once the // group is created as if TDx_Play::SetGroupData() had been // called. // // The data is application defined and this parameter may be set // to NULL if no initial data is needed. // pDataSize - // The DataSize parameter defines the size, in bytes, of the // data referenced by the Data parameter. // pFlags - // The Flags parameter defines flags indicating the group type // to be created. // The described effect applies when the flag is set. // // Setting zero (the default) will result in a group that // migrates to the session host if its owner leaves the session // and the group must be explicitly destroyed. // Flags: // DPGROUP_HIDDEN - // The group being created will only be enumerated when // DPENUMGROUPS_HIDDEN is set in the // TDx_Play::EnumGroups() Flags parameter. // // For lobby sessions, the group will only be available // via TDx_Play::AddGroupToGroup() links. // Basically this flag is very similar to the // DPPLAYER_SPECTATOR flag for players. // DPGROUP_STAGINGAREA - // The group being created is a staging area. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::CreateGroup( DPID* pGroup, TDPName* pGroupName, void* pData, dword pDataSize, dword pFlags ) { // Original Function Definition // HRESULT CreateGroup( // LPDPID lpidGroup, // LPDPNAME lpGroupName, // LPVOID lpData, // DWORD dwDataSize, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::CreateGroup()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pGroup==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::CreateGroup()", "TDX_BADPARAMS", "'pGroup' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->CreateGroup( (LPDPID) pGroup, (pGroupName==NULL) ? NULL : pGroupName->Internal_DPNAME_Ptr, (LPVOID) pData, (DWORD) pDataSize, (DWORD) pFlags ); // Translate Data returned from Function if (pGroupName!=NULL) pGroupName->Internal_DPNAME_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::CreateGroup()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: CreateGroupInGroup() // Description: The CreateGroupInGroup method will create a group within an // existing group. // // For a client server session, no group notification messages // are sent and groups are only visible on the machine that // created them. // For a peer to peer session, CreateGroupInGroup generates a // DPMSG_CREATEPLAYERORGROUP message notifying players of the // change. TDx_Play::Send() can then send messages to all group // members by sending a message to the group ID. // // Groups created with this method can only be enumerated by // TDx_Play::EnumGroupsInGroup() and destroyed using // TDx_Play::DestroyGroup(). // // When a parent group is destroyed, all member groups are also // destroyed and appropriate destruction messages generated. // // Error values that can be generated are: // // DPERR_CANTADDPLAYER // DPERR_CONNECTIONLOST // DPERR_INVALIDFLAGS // DPERR_INVALIDGROUP // DPERR_INVALIDPARAMS // Params: pParentGroup - // The ParentGroup parameter identifies the parent group for the // new group. // pGroup - // The Group parameter will reference the new groups ID if this // method returns successfully. // pGroupName - // The GroupName parameter references a TDPName component // holding the name for the new group. // // The name is assigned and used by the application, it need not // be unique and NULL can be set if no group name is required. // pData - // The Data parameter references data to be propagated once the // group is created as if TDx_Play::SetGroupData() had been // called. // // The data is application defined and this parameter may be set // to NULL if no initial data is needed. // pDataSize - // The DataSize parameter defines the size, in bytes, of the // data referenced by the Data parameter. // pFlags - // The Flags parameter defines flags indicating the group type // to be created. // The described effect applies when the flag is set. // // Setting zero will result in a normal, default, group. // Flags: // DPGROUP_HIDDEN - // The group being created will only be enumerated when // DPENUMGROUPS_HIDDEN is set in the // TDx_Play::EnumGroupInGroup() Flags parameter. // // For lobby sessions, the group will only be available // via TDx_Play::AddGroupToGroup() links. // Basically this flag is very similar to the // DPPLAYER_SPECTATOR flag for players. // DPGROUP_STAGINGAREA - // The group being created is a staging area. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::CreateGroupInGroup( DPID pParentGroup, DPID* pGroup, TDPName* pGroupName, void* pData, dword pDataSize, dword pFlags ) { // Original Function Definition // HRESULT CreateGroupInGroup( // DPID idParentGroup, // LPDPID lpidGroup, // LPDPNAME lpGroupName, // LPVOID lpData, // DWORD dwDataSize, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::CreateGroupInGroup()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pParentGroup==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::CreateGroupInGroup()", "TDX_BADPARAMS", "'pParentGroup' cannot be 'NULL'"); return false; } if (pGroup==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::CreateGroupInGroup()", "TDX_BADPARAMS", "'pGroup' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->CreateGroupInGroup( pParentGroup, (LPDPID) pGroup, (pGroupName==NULL) ? NULL : pGroupName->Internal_DPNAME_Ptr, (LPVOID) pData, (DWORD) pDataSize, (DWORD) pFlags ); // Translate Data returned from Function if (pGroupName!=NULL) pGroupName->Internal_DPNAME_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::CreateGroupInGroup()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: CreatePlayer() // Description: The CreatePlayer method will create a local player within the // session. // // CreatePlayer will generate a DPMSG_CREATEPLAYERORGROUP // message informing other players in the session about the new // player. // // Only the creating application may send messages for the // player or change the players name and data. // // TDx_Play::DestroyPlayer() may be used by the creating // application or session host to destroy a player. All local // players will be automatically destroyed if the session is // closed. // // Error values that can be generated are: // // DPERR_CANTADDPLAYER // DPERR_CANTCREATEPLAYER // DPERR_CONNECTIONLOST // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_NOCONNECTION // Params: pPlayer - // The Player parameter will reference the new players ID if // this method returns successfully. // pPlayerName - // The PlayerName parameter references a TDPName component // holding the new players name. // // The name is assigned and used by the application, it need not // be unique and NULL can be set if no player name is required. // pData - // The Data parameter references data to be propagated once the // player is created as if TDx_Play::SetPlayerData() had been // called. // // The data is application defined and this parameter may be set // to NULL if no initial data is needed. // pDataSize - // The DataSize parameter defines the size, in bytes, of the // data referenced by the Data parameter. // pFlags - // The Flags parameter defines flags indicating the player type // to be created. // The described effect applies when the flag is set. // // Setting zero will result in a nonspectator, nonserver player. // Flags: // DPPLAYER_SERVERPLAYER - // The player is to be the server player in a client // server session. // // Only one server player may exist per session and it // must be created by the host. // // The player ID will always be DPID_SERVERPLAYER when // this flag is set. // DPPLAYER_SPECTATOR - // The player is designated a spectator player. // // The application must define spectator behaviour, the // player behaves normally other than having this flag // set. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::CreatePlayer( DPID* pPlayer, TDPName* pPlayerName, void* pData, dword pDataSize, dword pFlags ) { // Original Function Definition // HRESULT Create( // LPDPID lpid, // LPDPNAME lpName, // HANDLE hEvent, // LPVOID lpData, // DWORD dwDataSize, // DWORD dwFlags // ); //create players event HANDLE fEvent = CreateEvent(NULL,FALSE,FALSE,NULL); if (fEvent == NULL) { fErrorValue = DPERR_NOMEMORY; if (FOnError) FOnError( this, Name+"::CreatePlayer()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue)); return false; } // Call Original Function DPID player_number; if (fLPDIRECTPLAY4!=NULL) fErrorValue = fLPDIRECTPLAY4->CreatePlayer( (LPDPID) &player_number, (pPlayerName==NULL) ? NULL : pPlayerName->Internal_DPNAME_Ptr, fEvent, (LPVOID) pData, (DWORD) pDataSize, (DWORD) pFlags ); // Translate Data returned from Function if (pPlayerName!=NULL) pPlayerName->Internal_DPNAME_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::CreatePlayer()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); CloseHandle(fEvent); return false; } else { // pause existing thread if (TDx_Play_Thread) TDx_Play_Thread->Pause(); // add player event to array for message receive fPlayerIDs->Add( (void*) player_number ); // dword fPlayerEvents->Add( (void*) fEvent ); // HANDLE *pPlayer = player_number; // return the player number fNumPlayers = fNumPlayers + 1; // restart the thread if (TDx_Play_Thread) { TDx_Play_Thread->HandlesModified = true; TDx_Play_Thread->Restart(); } } // Finished! return true; } // -------------------------------------------------------------------------- // Method: DeleteGroupFromGroup() // Description: The DeleteGroupFromGroup method will remove a specified group // link from its parent group // // These links are added using TDx_Play::AddGroupToGroup() // Only the link is deleted, the group itself is not destroyed. // // A DPMSG_DELETEGROUPFROMGROUP system message informing players // of the change will be generated. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDGROUP // Params: pParentGroup - // The ParentGroup parameter identifies the group from which the // link is to be removed. // pGroup - // The Group parameter identifies the group whose link is to be // removed. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::DeleteGroupFromGroup( DPID pParentGroup, DPID pGroup ) { // Original Function Definition // HRESULT DeleteGroupFromGroup( // DPID idParentGroup, // DPID idGroup // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::DeleteGroupFromGroup()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->DeleteGroupFromGroup( pParentGroup, pGroup ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::DeleteGroupFromGroup()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: DeletePlayerFromGroup() // Description: The DeletePlayerFromGroup method will remove a player from a // group. // // A player may delete any another from a group. // // A DPMSG_DELETEPLAYERFROMGROUP system message informing // players of the change will be generated. // // Error values that can be generated are: // // DPERR_CONNECTIONLOST // DPERR_INVALIDGROUP // DPERR_INVALIDOBJECT // DPERR_INVALIDPLAYER // Params: pGroup - // The Group parameter identifies the group from which the // player is to be removed. // pPlayer - // The Player parameter identifies the player that is to be // removed. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::DeletePlayerFromGroup( DPID pGroup, DPID pPlayer ) { // Original Function Definition // HRESULT DeletePlayerFromGroup( // DPID idGroup, // DPID idPlayer // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::DeletePlayerFromGroup()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->DeletePlayerFromGroup( pGroup, pPlayer ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::DeletePlayerFromGroup()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Destroy() // Description: The Destroy() method is used to automatically destroy the // internal LPDIRECTPLAY4 interface used in the TDx_Play // component and should be called when the internal interface is // no longer required. // // Note: This method is called by the component's destructor. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::Destroy() { // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Destroy()", "TDX_NOTCREATED", "The "+Name+"::Destroy() method was called before being created successfully." ); return false; } // exit if there is no lobby to destroy if (fLPDIRECTPLAY4==NULL) { if (FOnError) FOnError( this, Name+"::Destroy()", "TDX_ERROR", "The "+Name+" component's internal IDirectPlay interface is NULL but the TDx_Play component is expecting it to be not NULL. Aborting the Destroy()." ); return false; } // call the OnDestroy() event try { if (FOnDestroy) FOnDestroy(this); } catch (...) { fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::Destroy()", "TDX_ERROR", "An exception has occurred within "+Name+"::OnDestroy()" ); } // destroy the internal interface try { if (fLPDIRECTPLAY4!=NULL) fLPDIRECTPLAY4->Release(); } catch (...) { fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::Destroy()", "TDX_ERROR", "An exception has occurred within LPDIRECTPLAY->Release(). Check that you are destroying all components in reverse order of creation." ); } // successful destruction fCreated = false; fLPDIRECTPLAY4 = NULL; fLPDIRECTPLAY = NULL; CoUninitialize(); return true; } // -------------------------------------------------------------------------- // Method: DestroyGroup() // Description: The DestroyGroup method will destroy a specified group within // the session. // // The group ID will not be reused during the session. // // Any application can destroy any group. // Players belonging to the group are removed but not destroyed. // // Each player in the group will be sent a // DPMSG_DELETEPLAYERFROMGROUP and a DPMSG_DESTROYPLAYERORGROUP // system message indicating the change. // // Error values that can be generated are: // // DPERR_CONNECTIONLOST // DPERR_INVALIDGROUP // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pGroup - // The Group parameter identifies the group to be destroyed. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::DestroyGroup( DPID pGroup ) { // Original Function Definition // HRESULT DestroyGroup( // DPID idGroup // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::DestroyGroup()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->DestroyGroup( pGroup ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::DestroyGroup()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: DestroyPlayer() // Description: The DestroyPlayer method will destroy a specified player // within the session. // // The player is removed from any groups, and all messages for // the player are removed from the queue. // Any messages in the players asynchronous queue must be // cancelled or sent prior to this method call. // The player ID will not be reused during the session. // // The player is usually only destroyed by the creating // application, but the the session host may destroy any player // in the session. // // A DPMSG_DELETEPLAYERFROMGROUP message is generated for each // group the player was in, followed by a // DPMSG_DESTROYPLAYERORGROUP message. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDOBJECT // DPERR_INVALIDPLAYER // DPERR_UNAVAILABLE // Params: pPlayer - // The Player parameter identifies the player to be destroyed. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::DestroyPlayer( DPID pPlayer ) { // Original Function Definition // HRESULT DestroyPlayer( // DPID idPlayer // ); // Call Original Function if (fLPDIRECTPLAY4!=NULL) fErrorValue = fLPDIRECTPLAY4->DestroyPlayer( (DPID) pPlayer ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::DestroyPlayer()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // get rid of the Event & ID from the lists bool deleted = false; for (int i=0;iCount;i++) { if (fPlayerIDs->Items[i]!=NULL) { DPID fPlayer = (DPID) fPlayerIDs->Items[i]; if (pPlayer==fPlayer) { // pause existing thread if (TDx_Play_Thread) TDx_Play_Thread->Pause(); //remove player event HANDLE handle = (HANDLE) fPlayerEvents->Items[i]; CloseHandle( handle ); fPlayerEvents->Delete(i); fPlayerIDs->Delete(i); fNumPlayers = fNumPlayers - 1; // restart the thread if (TDx_Play_Thread) { TDx_Play_Thread->HandlesModified = true; TDx_Play_Thread->Restart(); } deleted = true; break; } } } if (!deleted) { // Failure. if (FOnError) FOnError( this, Name+"::DestroyPlayer()", "ID Not Found", "The Specified ID was not found to be deleted." ); return false; } // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::DestroyPlayer()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Finished! return true; } // -------------------------------------------------------------------------- // Method: EnumConnections() // Description: The EnumConnections method will enumerate available // registered service and lobby providers. // // The order of enumeration is indeterminate and the // TDx_Play::OnEnumConnections() event will be called for each // connection enumerated. // // Some enumerated providers may not be available for use, check // the TDx_Play::InitializeConnection() return values to be // sure, an error will be returned if the connection is // unavailable. // For example, a modem service provider would still be // enumerated even if the modem is not attached to the system. // // Error values that can be generated are: // // DPERR_CONNECTIONLOST // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // Params: pApplication - // The Application parameter references the application // identifier. // // Setting NULL results in all connections being enumerated, // otherwise only connections usable by the specified // application will be enumerated. // pContext - // The Context parameter references application defined data to // be passed to the callback function for each enumeration. // pFlags - // The Flags parameter defines flags indicating the connection // types that are to be enumerated. // The described effect applies when the flag is set. // // The default setting of zero gives the same results as // DPCONNECTION_DIRECTPLAY. // Flags: // DPCONNECTION_DIRECTPLAY - // DirectPlay service providers for communicating within // application sessions are to be enumerated. // DPCONNECTION_DIRECTPLAYLOBBY - // DirectPlayLobby providers for communicating with lobby // servers are to be enumerated. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::EnumConnections( const GUID* pApplication, void* pContext, dword pFlags ) { // Original Function Definition // HRESULT EnumConnections( // LPCGUID lpguidApplication, // LPDPENUMCONNECTIONSCALLBACK lpEnumCallback, // LPVOID lpContext, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::EnumConnections()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function TDx_Play_OnEnumConnectionsOwner = this; fErrorValue = fLPDIRECTPLAY4->EnumConnections( (LPCGUID) pApplication, Internal_EnumConnectionsCallback, (LPVOID) pContext, (DWORD) pFlags ); TDx_Play_OnEnumConnectionsOwner = NULL; // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::EnumConnections()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: EnumGroupPlayers() // Description: The EnumGroupPlayers method will enumerate players belonging // to the specified group of an open session. // // Remote sessions that are not password protected can have // their players enumerated by using the DPENUMPLAYERS_SESSION // flag and specifying the GUID of the remote session when there // is no session open, but the enumeration call must occur after // TDx_Play::EnumSessions() and before calling TDx_Play::Open() // or TDx_Play::Close(). // // The TDx_Play::OnEnumGroupPlayers() event will be called for // each player enumerated. // // To enumerate players in a lobby session, you must be // connected to it. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDPARAMS // DPERR_INVALIDGROUP // DPERR_NOSESSIONS // DPERR_UNAVAILABLE // Params: pGroup - // The Group parameter identifies the group for which the // players are to be enumerated. // pInstance - // The Instance parameter references the identifier of the // session to be enumerated. // // Ignored unless DPENUMPLAYERS_SESSION flag is set. // These GUIDs are obtained using TDx_Play::EnumSessions(). // pContext - // The Context parameter references application defined data to // be passed to the callback function for each player // enumerated. // pFlags - // The Flags parameter defines flags indicating how to perform // the enumeration. // The described effect applies when the flag is set. // // The default setting of zero results in the enumeration of the // players within a group in the current session. // Only players meeting all of the specified criteria will be // enumerated. // Flags: // DPENUMPLAYERS_LOCAL - // Only enumerate locally created players. // DPENUMPLAYERS_OWNER - // Only enumerate the group owner. // DPENUMPLAYERS_REMOTE - // Only enumerate remotely created players. // DPENUMPLAYERS_SERVERPLAYER - // Only enumerate the server player. // DPENUMPLAYERS_SESSION - // Enumerate the players of the session identified by the // Instance parameter. // Only usable when there is no session open and the // target session is not a lobby session. // DPENUMPLAYERS_SPECTATOR - // Only enumerate spectator players. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::EnumGroupPlayers( DPID pGroup, GUID* pInstance, void* pContext, dword pFlags ) { // Original Function Definition // HRESULT EnumGroupPlayers( // DPID idGroup, // LPGUID lpguidInstance, // LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, // LPVOID lpContext, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::EnumGroupPlayers()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function TDx_Play_OnEnumGroupPlayersOwner = this; fErrorValue = fLPDIRECTPLAY4->EnumGroupPlayers( pGroup, (LPGUID) pInstance, Internal_EnumGroupPlayersCallback, (LPVOID) pContext, (DWORD) pFlags ); TDx_Play_OnEnumGroupPlayersOwner = NULL; // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::EnumGroupPlayers()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: EnumGroups() // Description: The EnumGroups method will enumerate the top level groups of // the session. // // Remote sessions that are not password protected can have // their groups enumerated by using the DPENUMGROUPS_SESSION // flag and specifying the GUID of the remote session when there // is no session open. // // To enumerate groups in a lobby session, you must be connected // to it. // // The TDx_Play::OnEnumGroups() event will be called for each // group enumerated. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDPARAMS // DPERR_INVALIDGROUP // DPERR_NOSESSIONS // DPERR_UNAVAILABLE // Params: pInstance - // The Instance parameter references the identifier of the // session whose groups are to be enumerated. // // Setting NULL will result in the current sessions groups being // enumerated. // // There must not be an open session and the // DPENUMGROUPS_SESSION flag must be set to use this parameter. // // Session GUIDs are obtained by TDx_Play::EnumSessions(). // pContext - // The Context parameter references application defined data to // be passed to the callback function for each group enumerated. // pFlags - // The Flags parameter defines flags indicating how to perform // the enumeration. // The described effect applies when the flag is set. // // The default setting of zero results in the enumeration of all // groups in the current active session. // Only groups meeting all of the specified criteria will be // enumerated. // Flags: // DPENUMGROUPS_ALL - // Enumerate all the groups in the session. // DPENUMGROUPS_HIDDEN - // Only enumerate available hidden groups. // DPENUMGROUPS_LOCAL - // Only enumerate locally created groups. // DPENUMGROUPS_REMOTE - // Only enumerate remotely created groups. // DPENUMGROUPS_SESSION - // Enumerate the groups of the session identified by the // Instance parameter. // Only usable when there is no session open and the // target session is not a lobby session. // DPENUMGROUPS_STAGINGAREA - // Only enumerate staging area groups. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::EnumGroups( GUID* pInstance, void* pContext, dword pFlags ) { // Original Function Definition // HRESULT EnumGroups( // LPGUID lpguidInstance, // LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, // LPVOID lpContext, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::EnumGroups()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function TDx_Play_OnEnumGroupsOwner = this; fErrorValue = fLPDIRECTPLAY4->EnumGroups( (LPGUID) pInstance, Internal_EnumGroupsCallback, (LPVOID) pContext, (DWORD) pFlags ); TDx_Play_OnEnumGroupsOwner = NULL; // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::EnumGroups()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: EnumGroupsInGroup() // Description: The EnumGroupsInGroup method will enumerate groups and group // links contained within the specified group. // // Only the contents of the specified group will be enumerated, // not the groups it contains. // // Remote sessions that are not password protected can have // their groups enumerated by using the DPENUMGROUPS_SESSION // flag and specifying the GUID of the remote session when there // is no session open. // // To enumerate groups in a lobby session, you must be connected // to it. // // The TDx_Play::OnEnumGroupsInGroup() event will be called for // each group enumerated. // // Error values that can be generated are: // // DPERR_CONNECTIONLOST // DPERR_INVALIDFLAGS // DPERR_INVALIDGROUP // DPERR_INVALIDPARAMS // DPERR_NOSESSIONS // DPERR_UNSUPPORTED // Params: pGroup - // The Group parameter identifies the group whose subgroups are // to be enumerated. // pInstance - // The Instance parameter references the identifier of the // session whose group is to be enumerated. // // The DPENUMGROUPS_SESSION flag must be set to use this // parameter. // // Session GUIDs are obtained by TDx_Play::EnumSessions(). // pContext - // The Context parameter references application defined data to // be passed to the callback function for each group enumerated. // pFlags - // The Flags parameter defines flags indicating how to perform // the enumeration. // The described effect applies when the flag is set. // // The default setting of zero results in the enumeration of all // groups in the specified group. // Only groups meeting all of the specified criteria will be // enumerated. // Flags: // DPENUMGROUPS_ALL - // Enumerate all groups within the specified group. // DPENUMGROUPS_HIDDEN - // Only enumerate hidden groups within the specified // group. // DPENUMGROUPS_LOCAL - // Only enumerate locally created groups within the // specified group. // DPENUMGROUPS_REMOTE - // Only enumerate remotely created groups within the // specified group. // DPENUMGROUPS_SESSION - // Enumerate the specified group in the session identified // by the Instance parameter. // Only usable when there is no session open and the // target session is not a lobby session. // DPENUMGROUPS_SHORTCUT - // Only enumerate only the linked groups within the // specified group. // DPENUMGROUPS_STAGINGAREA - // Only enumerate staging area groups within the specified // group. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::EnumGroupsInGroup( DPID pGroup, GUID* pInstance, void* pContext, dword pFlags ) { // Original Function Definition // HRESULT EnumGroupsInGroup( // DPID idGroup, // LPGUID lpguidInstance, // LPDPENUMPLAYERSCALLBACK2 lpEnumCallback, // LPVOID lpContext, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::EnumGroupsInGroup()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function TDx_Play_OnEnumGroupsInGroupOwner = this; fErrorValue = fLPDIRECTPLAY4->EnumGroupsInGroup( pGroup, (LPGUID) pInstance, Internal_EnumGroupsInGroupCallback, (LPVOID) pContext, (DWORD) pFlags ); TDx_Play_OnEnumGroupsInGroupOwner = NULL; // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::EnumGroupsInGroup()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: EnumPlayers() // Description: The EnumPlayers method will enumerate players in the session. // // Remote sessions that are not password protected can have // their players enumerated by using the DPENUMPLAYERS_SESSION // flag and specifying the GUID of the remote session when there // is no session open, but the enumeration call must occur after // TDx_Play::EnumSessions() and before calling TDx_Play::Open() // or TDx_Play::Close(). // // The TDx_Play::OnEnumPlayers() event will be called for each // player enumerated. // // You cannot use this method in a lobby session or from within // TDx_Play::OnEnumSessions(). // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDPARAMS // DPERR_INVALIDGROUP // DPERR_NOSESSIONS // DPERR_UNAVAILABLE // Params: pInstance - // The Instance parameter references the identifier of the // session whose players are to be enumerated. // // The DPENUMPLAYERS_SESSION flag must be set to use this // parameter. // // Session GUIDs are obtained by TDx_Play::EnumSessions(). // pContext - // The Context parameter references application defined data to // be passed to the callback function for each player // enumerated. // pFlags - // The Flags parameter defines flags indicating how to perform // the enumeration. // The described effect applies when the flag is set. // // The default setting of zero results in the enumeration of all // players within the current session. // Only players meeting all of the specified criteria will be // enumerated. // Flags: // DPENUMPLAYERS_ALL - // Enumerate all players within the session. // DPENUMPLAYERS_GROUP - // Include groups in the enumeration. // DPENUMPLAYERS_LOCAL - // Only enumerate locally created players. // DPENUMPLAYERS_REMOTE - // Only enumerate remotely created players. // DPENUMPLAYERS_SERVERPLAYER - // Only enumerate the server player. // DPENUMPLAYERS_SESSION - // Enumerate the players of the session identified by the // Instance parameter. // Only usable when there is no session open and the // target session is not a lobby session. // DPENUMPLAYERS_SPECTATOR - // Only enumerate spectator players. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::EnumPlayers( GUID* pInstance, void* pContext, dword pFlags ) { // Original Function Definition // HRESULT EnumPlayers( // LPGUID lpguidInstance, // LPDPENUMPLAYERSCALLBACK2 lpEnumPlayersCallback2, // LPVOID lpContext, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::EnumPlayers()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function TDx_Play_OnEnumPlayersOwner = this; fErrorValue = fLPDIRECTPLAY4->EnumPlayers( (LPGUID) pInstance, Internal_EnumPlayersCallback, (LPVOID) pContext, (DWORD) pFlags ); TDx_Play_OnEnumPlayersOwner = NULL; // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::EnumPlayers()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: EnumSessions() // Description: The EnumSessions method will enumerate all active and/or // lobby sessions for a specified application. // // This method should not be called while a session is open. // The TDx_Play::OnEnumSessions() event will be called for each // session enumerated. // // When enumerating synchronously, the internal session cache is // cleared, the enumeration requests sent and the application // blocked until all replies have timed out or been enumerated. // // When enumerating asychronously, all sessions in the internal // session cache are enumerated through the callback and the // method returns. Enumeration requests are then sent // automatically, the replies to which are used to update, // remove or add to the internal session cache. // Call EnumSessions asynchronously once more to obtain the most // recent session list. // Enumeration will be performed periodically without further // calls until TDx_Play::Open() or this method with // DPENUMSESSIONS_STOPASYNC set is called. // Asychronous enumeration must be halted before changing a // sessions description. // // Error values that can be generated are: // // DPERR_CONNECTING // DPERR_CONNECTIONLOST // DPERR_EXCEPTION // DPERR_GENERIC // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_NOCONNECTION // DPERR_UNINITIALIZED // DPERR_USERCANCEL // Params: pSD - // The SD parameter references a TDPSessionDesc component // defining which sessions are to be enumerated. // // TDPSessionDesc::Application identifies which application // sessions should be retrieved. (GUID_NULL for all sessions) // and TDPSessionDesc::Password is used to enumerated private // sessions. // All other TDPSessionDesc properties are ignored. // pTimeout - // The Timeout parameter defines the time, in milliseconds, to // wait for enumeration request responses (for synchronous) or // how long to broadcast enumeration requests (for // asynchronous). // // Set zero to use the default time out defined by // TDPCaps::Timeout. // pContext - // The Context parameter references application defined data to // be passed to the callback function for each session // enumerated. // pFlags - // The Flags parameter defines flags indicating which sessions // are to be enumerated. // The described effect applies when the flag is set. // // The default value of zero is equivilent to // DPENUMSESSIONS_AVAILABLE. // Flags: // DPENUMSESSIONS_ALL - // Enumerate all currently active sessions. // // DPENUMSESSIONS_PASSWORDREQUIRED is still required to // enumerate password protected sessions. // DPENUMSESSIONS_AVAILABLE is assumed if this flag is not // set. // DPENUMSESSIONS_ASYNC - // Enumerate all sessions asychronously into a session // cache. // // The session cache will be updated until // DPENUMSESSIONS_STOPASYNC is set or TDx_Play::Open() or // IUnknown::Release() is called. // Enumeration is synchronous when this flag is not set. // DPENUMSESSIONS_AVAILABLE - // Only enumerate those sessions currently accepting new // players. // // DPENUMSESSIONS_PASSWORDREQUIRED is still required to // enumerate password protected sessions. // DPENUMSESSIONS_PASSWORDREQUIRED - // Also enumerate password protected sessions. // DPENUMSESSIONS_RETURNSTATUS - // Do not display any connection status dialog boxes. // // DDERR_CONNECTING will be returned if the connection // cannot be made immediately. // The application should call this method until DP_OK or // a different error code is returned. // DPENUMSESSIONS_STOPASYNC - // Enumerate all the sessions currently in the session // cache and halt the asynchronous enumeration process. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::EnumSessions( TDPSessionDesc* pSD, dword pTimeout, void* pContext, dword pFlags ) { // Original Function Definition // HRESULT EnumSessions( // LPDPSESSIONDESC2 lpsd, // DWORD dwTimeout, // LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2, // LPVOID lpContext, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::EnumSessions()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function TDx_Play_OnEnumSessionsOwner = this; fErrorValue = fLPDIRECTPLAY4->EnumSessions( (pSD==NULL) ? NULL : pSD->Internal_DPSESSIONDESC2_Ptr, (DWORD) pTimeout, Internal_EnumSessionsCallback, (LPVOID) pContext, (DWORD) pFlags ); TDx_Play_OnEnumSessionsOwner = NULL; // Translate Data returned from Function if (pSD!=NULL) pSD->Internal_DPSESSIONDESC2_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::EnumSessions()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetCaps() // Description: The GetCaps method will retrieve the capabilities of the // current session. // // The session must be open before the supported aspects of // TDx_Play::SendEx() can be determined. // If the host has specified DPSESSION_DIRECTPLAYPROTOCOL in // TDPSessionDesc::Flags, then all TDx_Play::SendEx() // capabilities are available. // // Error values that can be generated are: // // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // Params: pDPCaps - // The DPCaps parameter references a TDPCaps component for // holding the session capabilities if this method returns // successfully. // pFlags - // The Flags parameter defines flags indicating the type of // message capabilities that are to be retrieved. // // The default setting of zero results in nonguaranteed // messaging capabilities being retrieved. // Flags: // DPGETCAPS_GUARANTEED - // Retrieve the guaranteed messaging capabilities for the // session. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetCaps( TDPCaps* pDPCaps, dword pFlags ) { // Original Function Definition // HRESULT GetCaps( // LPDPCAPS lpDPCaps, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetCaps()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetCaps( (pDPCaps==NULL) ? NULL : pDPCaps->Internal_DPCAPS_Ptr, (DWORD) pFlags ); // Translate Data returned from Function if (pDPCaps!=NULL) pDPCaps->Internal_DPCAPS_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetCaps()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetGroupConnectionSettings() // Description: The GetGroupConnectionSettings method will retrieve // connection settings from the TDPLConnection component // associated with the group. // // These settings are used in any session launched from the // group. // This method is only relevent to lobby session staging area // groups. // // If a session has been launched from this group, the // TDPSessionDesc::Instance property will not be GUID_NULL. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_BUFFERTOOSMALL // DPERR_INVALIDGROUP // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_UNSUPPORTED // Params: pGroup - // The Group parameter identifies the group for which connection // settings are to be retrieved. // pData - // The Data parameter references a buffer for holding the // TDPLConnection information if this method returns // successfully. // // Set NULL to allocate appropriate memory to hold the data, the // DataSize parameter will be set to the size of the // TDPLConnection data. // // If previously allocated memory is used and the amount of data // to be returned is greater than the amount specified by the // DataSize initial value, the memory will be released and // replaced with the required memory block. // pDataSize - // The DataSize parameter references the size, in bytes, of the // Data buffer. // // This parameter will be set to the size of the data when the // method returns. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetGroupConnectionSettings( DPID pGroup, void* pData, dword* pDataSize ) { // Original Function Definition // HRESULT GetGroupConnectionSettings( // DWORD dwFlags, // DPID idGroup, // LPVOID lpData, // LPDWORD lpdwDataSize // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetGroupConnectionSettings()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetGroupConnectionSettings( 0, pGroup, (LPVOID) pData, (LPDWORD) pDataSize ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetGroupConnectionSettings()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetGroupData() // Description: The GetGroupData method will retrieve application specific // data previously associated with the group by // TDx_Play::SetGroupData(). // // Local data is set by this TDx_Play component using // DPSET_LOCAL, while remote data may have been set by any // application in the session using DPSET_REMOTE. // // Error values that can be generated are: // // DPERR_BUFFERTOOSMALL // DPERR_INVALIDGROUP // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pGroup - // The Group parameter identifies the group for which data is // being requested. // pData - // The Data parameter references a buffer for holding the // retrieved data if this method returns successfully. // // Set NULL to allocate appropriate memory to hold the data, the // DataSize parameter will be set to the size of the data. // // If previously allocated memory is used and the amount of data // to be returned is greater than the amount specified by the // DataSize initial value, the memory will be released and // replaced with the required memory block. // pDataSize - // The DataSize parameter references the size, in bytes, of the // Data buffer. // // This parameter will be set to the size of the data when the // method returns. // pFlags - // The Flags parameter defines flags indicating which data type // is to be retrieved. // The described effect applies when the flag is set. // // The default setting of zero is equivilent to DPGET_REMOTE. // Flags: // DPGET_LOCAL - // The local data that was set by this application will be // retrieved. // DPGET_REMOTE - // The current data of the remote shared data space will // be retrieved. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetGroupData( DPID pGroup, void* pData, dword* pDataSize, dword pFlags ) { // Original Function Definition // HRESULT GetGroupData( // DPID idGroup, // LPVOID lpData, // LPDWORD lpdwDataSize, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetGroupData()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetGroupData( pGroup, (LPVOID) pData, (LPDWORD) pDataSize, (DWORD) pFlags ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetGroupData()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetGroupFlags() // Description: The GetGroupFlags method will retrieve a specified group's // descriptive flags. // // Error values that can be generated are: // // DPERR_INVALIDGROUP // DPERR_INVALIDPARAMS // Params: pGroup - // The Group parameter identifies the group for which the flags // are being retrieved. // pFlags - // The Flags parameter references the group flag settings if // this method returns successfully. // The described effect applies when the flag is set. // Flags: // DPGROUP_LOCAL - // The group was created by this application. // // The absence of this flag denotes a remote group. // DPGROUP_STAGINGAREA - // The group is a staging area. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetGroupFlags( DPID pGroup, dword* pFlags ) { // Original Function Definition // HRESULT GetGroupFlags( // DPID idGroup, // LPDWORD lpdwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetGroupFlags()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetGroupFlags( pGroup, (LPDWORD) pFlags ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetGroupFlags()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetGroupName() // Description: The GetGroupName method will retrieve a groups name. // // Use TDPName to retrieve the group name from the Data // parameter. // // Error values that can be generated are: // // DPERR_BUFFERTOOSMALL // DPERR_INVALIDGROUP // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pGroup - // The Group parameter identifies the group for which the name // is being retrieved. // pData - // The Data parameter references a buffer for holding the // TDPName information if this method returns successfully. // // Set NULL to allocate appropriate memory to hold the name, the // DataSize parameter will be set to the size of the data. // // If previously allocated memory is used and the name requires // more memory than the amount specified by the DataSize initial // value, the memory will be released and replaced with the // required memory block. // pDataSize - // The DataSize parameter references the size, in bytes, of the // Data buffer. // // This parameter will be set to the size of the name when the // method returns. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetGroupName( DPID pGroup, void* pData, dword* pDataSize ) { // Original Function Definition // HRESULT GetGroupName( // DPID idGroup, // LPVOID lpData, // LPDWORD lpdwDataSize // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetGroupName()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetGroupName( pGroup, (LPVOID) pData, (LPDWORD) pDataSize ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetGroupName()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetGroupOwner() // Description: The GetGroupOwner method will identify the groups owner // within a lobby session. // // Error values that can be generated are: // // DPERR_GENERIC // DPERR_INVALIDGROUP // DPERR_INVALIDPARAMS // DPERR_UNAVAILABLE // Params: pGroup - // The Group parameter identifies the group whose owner is being // requested. // pOwner - // The Owner parameter references the group owners ID if the // method returns successfully. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetGroupOwner( DPID pGroup, DPID* pOwner ) { // Original Function Definition // HRESULT GetGroupOwner( // DPID idGroup, // LPDPID lpidOwner // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetGroupOwner()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetGroupOwner( pGroup, (LPDPID) pOwner ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetGroupOwner()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetGroupParent() // Description: The GetGroupParent method will retrieve the ID of the parent // of the specified group. // // Error values that can be generated are: // // DPERR_INVALIDGROUP // DPERR_INVALIDPARAMS // Params: pGroup - // The Group parameter identifies the group whose parent ID is // being retrieved. // pParent - // The Parent parameter will reference the parent groups ID if // the method returns successfully. // // A result of zero denotes a root group. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetGroupParent( DPID pGroup, DPID* pParent ) { // Original Function Definition // HRESULT GetGroupOwner( // DPID idGroup, // LPDPID lpidOwner // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetGroupParent()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetGroupOwner( pGroup, (LPDPID) pParent ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetGroupParent()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetMessageCount() // Description: The GetMessageCount method will retrieve the number of // messages in the specified local players receive queue. // // Error values that can be generated are: // // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pPlayer - // The Player parameter identifies the local player whose // message count is being retrieved. // pCount - // The Count parameter will reference the message count if this // method returns successfully. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetMessageCount( DPID pPlayer, dword* pCount ) { // Original Function Definition // HRESULT GetMessageCount( // DPID idPlayer, // LPDWORD lpdwCount // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetMessageCount()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetMessageCount( pPlayer, (LPDWORD) pCount ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetMessageCount()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetMessageQueue() // Description: The GetMessageQueue method retrieves how many messages are on // the local send or receive queues for the session. // // On slower networks, this information can be used to regulate // network usage. // These message queues are for all local players in the // session, not neccessarily individual players. // // Error values that can be generated are: // // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // DPERR_UNSUPPORTED // Params: pFrom - // The From parameter identifies the player who has sent the // messages. // // Setting zero obtains the number of messages recieved from all // players. // pTo - // The To parameter identifies the player who is to receive the // messages. // // Setting zero obtains the number of messages sent to all // players. // pFlags - // The Flags parameter defines flags indicating which queue's // information is the be retrieved. // // The default value of zero is equivilent to // DPMESSAGEQUEUE_SEND. // Flags: // DPMESSAGEQUEUE_RECEIVE - // Retrieve receive queue information. // // DPMESSAGEQUEUE_SEND should not also be set. // DPMESSAGEQUEUE_SEND - // Retrieve send queue information. // // DPMESSAGEQUEUE_RECEIVE should not also be set. // pNumMsgs - // The NumMsgs parameter will reference the number of messages // in the requested queue. // // Set NULL if the number of messages is not required. // pNumBytes - // The NumMsgs parameter will reference the number of bytes in // the requested queue. // // Set NULL if the queue size is not required. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetMessageQueue( DPID pFrom, DPID pTo, dword pFlags, dword* pNumMsgs, dword* pNumBytes ) { // Original Function Definition // HRESULT GetMessageQueue( // DPID idFrom, // DPID idTo, // DWORD dwFlags, // LPDWORD lpdwNumMsgs, // LPDWORD lpdwNumBytes // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetMessageQueue()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetMessageQueue( pFrom, pTo, (DWORD) pFlags, (LPDWORD) pNumMsgs, (LPDWORD) pNumBytes ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetMessageQueue()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetPlayerAccount() // Description: The GetPlayerAccount method will retrieve account information // about the specified player. // // This method can only be used by the session host during a // secure session. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_BUFFERTOOSMALL // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pPlayer - // The Player parameter identifies the player for which account // information is being retrieved. // pData - // The Data parameter references a buffer for holding the // TDPAccountDesc information if this method returns // successfully. // // Set NULL to allocate appropriate memory to hold the name, the // DataSize parameter will be set to the size of the data. // // If previously allocated memory is used and the TDPAccountDesc // requires more memory than the amount specified by the // DataSize initial value, the memory will be released and // replaced with the required memory block. // pDataSize - // The DataSize parameter references the size, in bytes, of the // Data buffer. // // This parameter will be set to the size of the Data when the // method returns. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetPlayerAccount( DPID pPlayer, void* pData, dword* pDataSize ) { // Original Function Definition // HRESULT GetPlayerAccount( // DPID idPlayer, // DWORD dwFlags, // LPVOID lpData, // LPDWORD lpdwDataSize // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetPlayerAccount()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetPlayerAccount( pPlayer, 0, (LPVOID) pData, (LPDWORD) pDataSize ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetPlayerAccount()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetPlayerAddress() // Description: The GetPlayerAddress method will retrieve the network address // of a specified player. // // TDx_PlayLobby::EnumAddress() can be used to parse the // retrieved buffer. // // If a local players address is requested, the address of the // local computer will be returned if available. // Multiple addresses may be returned if a computer has more // than one network interface. // // Error values that can be generated are: // // DPERR_BUFFERTOOSMALL // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // DPERR_UNAVAILABLE // Params: pPlayer - // The Player parameter identifies the player for which address // information to be retrieved. // // Setting this parameter to zero obtains a valid address option // list for the service provider. // pData - // The Data parameter references a buffer for holding the // retrieved addresses if this method returns successfully. // // Set NULL to allocate appropriate memory to hold the name, the // DataSize parameter will be set to the size of the data. // // If previously allocated memory is used and the retrieved data // requires more memory than the amount specified by the // DataSize initial value, the memory will be released and // replaced with the required memory block. // pDataSize - // The DataSize parameter references the size, in bytes, of the // Data buffer. // // This parameter will be set to the size of the Data when the // method returns. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetPlayerAddress( DPID pPlayer, void* pData, dword* pDataSize ) { // Original Function Definition // HRESULT GetPlayerAddress( // DPID idPlayer, // LPVOID lpData, // LPDWORD lpdwDataSize // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetPlayerAddress()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetPlayerAddress( pPlayer, (LPVOID) pData, (LPDWORD) pDataSize ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetPlayerAddress()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetPlayerCaps() // Description: The GetPlayerCaps method will retrieve a specific player's // current capabilities. // // Error values that can be generated are: // // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pPlayer - // The Player parameter identifies the player whose capabilities // are to be retrieved. // pPlayerCaps - // The PlayerCaps reference a TDPCaps component for holding the // players capabilities if this method returns successfully. // pFlags - // The Flags parameter defines a flag indicating the messaging // type for which the players capabilities are to be retrieved. // // The described effect applies when the flag is set. // // The default setting of zero results in capabilities being // retrieved for nonguaranteed messaging. // Flags: // DPGETCAPS_GUARANTEED - // The guaranteed message delivery capabilties of the // player are to be retrieved. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetPlayerCaps( DPID pPlayer, TDPCaps* pPlayerCaps, dword pFlags ) { // Original Function Definition // HRESULT GetPlayerCaps( // DPID idPlayer, // LPDPCAPS lpPlayerCaps, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetPlayerCaps()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pPlayerCaps==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetPlayerCaps()", "TDX_BADPARAMS", "'pPlayerCaps' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetPlayerCaps( pPlayer, pPlayerCaps->Internal_DPCAPS_Ptr, (DWORD) pFlags ); // Translate Data returned from Function pPlayerCaps->Internal_DPCAPS_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetPlayerCaps()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetPlayerData() // Description: The GetPlayerData method will retrieve application specific // data previously associated with the player by // TDx_Play::SetPlayerData(). // // Local data is set by this TDx_Play component using // DPSET_LOCAL, while remote data may have been set by any // application in the session using DPSET_REMOTE. // // Error values that can be generated are: // // DPERR_BUFFERTOOSMALL // DPERR_INVALIDFLAGS // DPERR_INVALIDOBJECT // DPERR_INVALIDPLAYER // Params: pPlayer - // The Player parameter identifies the player for which the data // is to be retrieved. // pData - // The Data parameter references a buffer for holding the // retrieved data if this method returns successfully. // // Set NULL to allocate appropriate memory to hold the data, the // DataSize parameter will be set to the size of the data. // // If previously allocated memory is used and the retrieved data // requires more memory than the amount specified by the // DataSize initial value, the memory will be released and // replaced with the required memory block. // pDataSize - // The DataSize parameter references the size, in bytes, of the // Data buffer. // // This parameter will be set to the size of the Data when the // method returns. // pFlags - // The Flags parameter defines flags indicating which data type // is to be retrieved. // The described effect applies when the flag is set. // // The default setting of zero is equivilent to DPGET_REMOTE. // Flags: // DPGET_LOCAL - // The local data that was set by this application will be // retrieved. // DPGET_REMOTE - // The current data of the remote shared data space will // be retrieved. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetPlayerData( DPID pPlayer, void* pData, dword* pDataSize, dword pFlags ) { // Original Function Definition // HRESULT GetPlayerData( // DPID idPlayer, // LPVOID lpData, // LPDWORD lpdwDataSize, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetPlayerData()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetPlayerData( pPlayer, (LPVOID) pData, (LPDWORD) pDataSize, (DWORD) pFlags ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetPlayerData()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetPlayerFlags() // Description: The GetPlayerFlags method will retrieve a specified players // descriptive flags. // // Error values that can be generated are: // // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pPlayer - // The Player parameter identifies the player for which the flag // settings are to be retrieved. // pFlags - // The Flags parameter will reference the players flag settings // if this method returns successfully. // The described effect applies when the flag is set. // Flags: // DPPLAYER_LOCAL - // The player was created by this application. // The absence of this flag denotes a remote player. // DPPLAYER_SERVERPLAYER - // In a client/server session, the player is a server // player. // DPPLAYER_SPECTATOR - // The player is a spectator. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetPlayerFlags( DPID pPlayer, dword* pFlags ) { // Original Function Definition // HRESULT GetPlayerFlags( // DPID idPlayer, // LPDWORD lpdwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetPlayerFlags()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetPlayerFlags( pPlayer, (LPDWORD) pFlags ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetPlayerFlags()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetPlayerName() // Description: The GetPlayerName method will retrieve a groups name. // // Use TDPName to retrieve the player name from the Data // parameter. // // Error values that can be generated are: // // DPERR_BUFFERTOOSMALL // DPERR_INVALIDOBJECT // DPERR_INVALIDPLAYER // Params: pPlayer - // The Player parameter identifies the player for which the name // is being retrieved. // pData - // The Data parameter references a buffer for holding the // TDPName information if this method returns successfully. // // Set NULL to allocate appropriate memory to hold the name, the // DataSize parameter will be set to the size of the data. // // If previously allocated memory is used and the name requires // more memory than the amount specified by the DataSize initial // value, the memory will be released and replaced with the // required memory block. // pDataSize - // The DataSize parameter references the size, in bytes, of the // Data buffer. // // This parameter will be set to the size of the name when the // method returns. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetPlayerName( DPID pPlayer, void* pData, dword* pDataSize ) { // Original Function Definition // HRESULT GetPlayerName( // DPID idPlayer, // LPVOID lpData, // LPDWORD lpdwDataSize // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetPlayerName()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetPlayerName( pPlayer, (LPVOID) pData, (LPDWORD) pDataSize ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetPlayerName()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetSessionDesc() // Description: The GetSessionDesc method will retrieve the currently open // session's properties. // // Use TDPSessionDesc to retrieve the session information from // the Data parameter. // // Error values that can be generated are: // // DPERR_BUFFERTOOSMALL // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_NOCONNECTION // Params: pData - // The Data parameter references a buffer for holding the // TDPSessionDesc information if this method returns // successfully. // // Set NULL to allocate appropriate memory to hold the data, the // DataSize parameter will be set to the size of the data. // // If previously allocated memory is used and the data requires // more memory than the amount specified by the DataSize initial // value, the memory will be released and replaced with the // required memory block. // pDataSize - // The DataSize parameter references the size, in bytes, of the // Data buffer. // // This parameter will be set to the size of the data when the // method returns. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::GetSessionDesc( void* pData, dword* pDataSize ) { // Original Function Definition // HRESULT GetSessionDesc( // LPVOID lpData, // LPDWORD lpdwDataSize // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetSessionDesc()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->GetSessionDesc( (LPVOID) pData, (LPDWORD) pDataSize ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetSessionDesc()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: InitializeConnection() // Description: The InitializeConnection method will initialize a TDx_Play // connection. // // Error values that can be generated are: // // DPERR_ALREADYINITIALIZED // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_UNAVAILABLE // Params: pConnection - // The Connection parameter references a buffer detailing the // service provider, server network address and session guid. // // The buffer contains a TDx_Play address retrieved using // TDx_Play::EnumConnections() or created using // TDx_PlayLobby::CreateCompoundAddress. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::InitializeConnection( void* pConnection ) { // Original Function Definition // HRESULT InitializeConnection( // LPVOID lpConnection, // DWORD dwFlags, // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::InitializeConnection()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->InitializeConnection( (LPVOID) pConnection, 0 ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::InitializeConnection()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Internal_EnumConnectionsCallback() // Description: The Internal_EnumConnectionsCallback method is used to // process enumeration for TDx_Play::EnumConnections(). // Params: pSP - // The SP parameter identifies the service provider being used // for the connection. // pConnection - // The Connection that is currently being enumerated. // pConnectionSize - // The ConnectionSize parameter indicates the size of the // enumerated connection. // pName - // The Name of the currently enumerated connection. // pFlags - // The Flags parameter is not used at this time. // pContext - // The Context parameter is user defined data passed to the // calling function. // -------------------------------------------------------------------------- BOOL __stdcall TDx_Play::Internal_EnumConnectionsCallback( LPCGUID pSP, LPVOID pConnection, DWORD pConnectionSize, LPCDPNAME pName, DWORD pFlags, LPVOID pContext ) { // Original Function Definition // BOOL FAR PASCAL EnumConnectionsCallback( // LPCGUID lpguidSP, // LPVOID lpConnection, // DWORD dwConnectionSize, // LPCDPNAME lpName, // DWORD dwFlags, // LPVOID lpContext // ); bool fContinue = true; // translate parameters const GUID* SP = pSP; void* Connection = pConnection; dword ConnectionSize = pConnectionSize; dword Flags = pFlags; void* Context = pContext; TDPName* Name = new TDPName( NULL ); if (Name) { if (TDx_Play_OnEnumConnectionsOwner->UseAnsiString) { AnsiString temp1 = (char*) pName->lpszShortNameA; AnsiString temp2 = (char*) pName->lpszLongNameA; Name->ShortNameA = temp1; Name->LongNameA = temp2; } else { AnsiString temp1 = (char*) pName->lpszShortName; AnsiString temp2 = (char*) pName->lpszLongName; Name->ShortName = temp1; Name->LongName = temp2; } } // Call Original Function if (TDx_Play_OnEnumConnectionsOwner->OnEnumConnections) TDx_Play_OnEnumConnectionsOwner->OnEnumConnections(TDx_Play_OnEnumConnectionsOwner, SP, Connection, ConnectionSize, Name, Flags, Context, fContinue ); // cleanup if (Name) delete Name; // Finished! return fContinue; } // -------------------------------------------------------------------------- // Method: Internal_EnumGroupPlayersCallback() // Description: The Internal_EnumGroupPlayersCallback method is used to // process enumeration for TDx_Play::EnumGroupPlayers(). // Params: pId - // The Id of the player being enumerated. // pPlayerType - // The type of player being enumerated. // pName - // The Name of the currently enumerated player. // pFlags - // The Flags parameter describe the currently enumerated player. // pContext - // The Context parameter is user defined data pased to the // calling function. // -------------------------------------------------------------------------- BOOL __stdcall TDx_Play::Internal_EnumGroupPlayersCallback( DPID pId, DWORD pPlayerType, LPCDPNAME pName, DWORD pFlags, LPVOID pContext ) { // Original Function Definition //BOOL FAR PASCAL EnumPlayersCallback2( // DPID dpId, // DWORD dwPlayerType, // LPCDPNAME lpName, // DWORD dwFlags, // LPVOID lpContext //); bool fContinue = true; // translate parameters dword Id = pId; dword PlayerType = pPlayerType; dword Flags = pFlags; void* Context = pContext; TDPName* Name = new TDPName( NULL ); if (Name) { if (TDx_Play_OnEnumGroupPlayersOwner->UseAnsiString) { AnsiString temp1 = (char*) pName->lpszShortNameA; AnsiString temp2 = (char*) pName->lpszLongNameA; Name->ShortNameA = temp1; Name->LongNameA = temp2; } else { AnsiString temp1 = (char*) pName->lpszShortName; AnsiString temp2 = (char*) pName->lpszLongName; Name->ShortName = temp1; Name->LongName = temp2; } } // Call Original Function if (TDx_Play_OnEnumGroupPlayersOwner->OnEnumGroupPlayers) TDx_Play_OnEnumGroupPlayersOwner->OnEnumGroupPlayers(TDx_Play_OnEnumGroupPlayersOwner, Id, PlayerType, Name, Flags, Context, fContinue ); // cleanup delete Name; // Finished! return fContinue; } // -------------------------------------------------------------------------- // Method: Internal_EnumGroupsCallback() // Description: The Internal_EnumGroupsCallback method is used to process // enumeration for TDx_Play::EnumGroups(). // Params: pId - // The Id of the currently enumerated group. // pPlayerType - // The PlayerType parameter describes the type of group being // enumerated. // pName - // The Name of the group being enumerated. // pFlags - // The Flags parameter describe the group being enumerated. // DPENUMGROUPS_HIDDEN // DPENUMGROUPS_SHORTCUT // DPENUMGROUPS_STAGINGAREA // DPENUMPLAYERS_GROUP // pContext - // The Context parameter is user defined data passed to the // calling function. // -------------------------------------------------------------------------- BOOL __stdcall TDx_Play::Internal_EnumGroupsCallback( DPID pId, DWORD pPlayerType, LPCDPNAME pName, DWORD pFlags, LPVOID pContext ) { // Original Function Definition // unknown bool fContinue = true; // translate parameters dword Id = pId; dword PlayerType = pPlayerType; dword Flags = pFlags; void* Context = pContext; TDPName* Name = new TDPName( NULL ); if (Name) { if (TDx_Play_OnEnumGroupsOwner->UseAnsiString) { AnsiString temp1 = (char*) pName->lpszShortNameA; AnsiString temp2 = (char*) pName->lpszLongNameA; Name->ShortNameA = temp1; Name->LongNameA = temp2; } else { AnsiString temp1 = (char*) pName->lpszShortName; AnsiString temp2 = (char*) pName->lpszLongName; Name->ShortName = temp1; Name->LongName = temp2; } } // Call Original Function if (TDx_Play_OnEnumGroupsOwner->OnEnumGroups) TDx_Play_OnEnumGroupsOwner->OnEnumGroups(TDx_Play_OnEnumGroupsOwner, Id, PlayerType, Name, Flags, Context, fContinue ); // cleanup delete Name; // Finished! return fContinue; } // -------------------------------------------------------------------------- // Method: Internal_EnumGroupsInGroupCallback() // Description: The Internal_EnumGroupsInGroupCallback method is used to // process enumeration for TDx_Play::EnumGroupsInGroup(). // Params: pId - // The Id of the group being enumerated. // pPlayerType - // The PlayerType parameter indicates the type of group being // enumerated. // pName - // The Name of the group being enumerated. // pFlags - // The Flags parameter describe the group being enumerated. // pContext - // The Context parameter is user defined data passed to the // calling function. // -------------------------------------------------------------------------- BOOL __stdcall TDx_Play::Internal_EnumGroupsInGroupCallback( DPID pId, DWORD pPlayerType, LPCDPNAME pName, DWORD pFlags, LPVOID pContext ) { // Original Function Definition // unknown bool fContinue = true; // translate parameters dword Id = pId; dword PlayerType = pPlayerType; dword Flags = pFlags; void* Context = pContext; TDPName* Name = new TDPName( NULL ); if (Name) { if (TDx_Play_OnEnumGroupsInGroupOwner->UseAnsiString) { AnsiString temp1 = (char*) pName->lpszShortNameA; AnsiString temp2 = (char*) pName->lpszLongNameA; Name->ShortNameA = temp1; Name->LongNameA = temp2; } else { AnsiString temp1 = (char*) pName->lpszShortName; AnsiString temp2 = (char*) pName->lpszLongName; Name->ShortName = temp1; Name->LongName = temp2; } } // Call Original Function if (TDx_Play_OnEnumGroupsInGroupOwner->OnEnumGroupsInGroup) TDx_Play_OnEnumGroupsInGroupOwner->OnEnumGroupsInGroup(TDx_Play_OnEnumGroupsInGroupOwner, Id, PlayerType, Name, Flags, Context, fContinue ); // cleanup delete Name; // Finished! return fContinue; } // -------------------------------------------------------------------------- // Method: Internal_EnumPlayersCallback() // Description: The Internal_EnumPlayersCallback method is used to process // enumeration from TDx_Play::EnumPlayers(). // Params: pId - // The Id parameter identifies the player being enumerated // pPlayerType - // The PlayerType parameter describes the player being // enumerated. // pName - // The Name parameter references a TDPName component holding the // name of the player being enumerated. // pFlags - // The Flags parameter describes the player being enumerated. // pContext - // The Context parameter references application defined data // passed to the callback function. // -------------------------------------------------------------------------- BOOL __stdcall TDx_Play::Internal_EnumPlayersCallback( DPID pId, DWORD pPlayerType, LPCDPNAME pName, DWORD pFlags, LPVOID pContext ) { // Original Function Definition // unknown bool fContinue = true; // translate parameters dword Id = pId; dword PlayerType = pPlayerType; dword Flags = pFlags; void* Context = pContext; TDPName* Name = new TDPName( NULL ); if (Name) { if (TDx_Play_OnEnumPlayersOwner->UseAnsiString) { AnsiString temp1 = (char*) pName->lpszShortNameA; AnsiString temp2 = (char*) pName->lpszLongNameA; Name->ShortNameA = temp1; Name->LongNameA = temp2; } else { AnsiString temp1 = (char*) pName->lpszShortName; AnsiString temp2 = (char*) pName->lpszLongName; Name->ShortName = temp1; Name->LongName = temp2; } } // Call Original Function if (TDx_Play_OnEnumPlayersOwner->OnEnumPlayers) TDx_Play_OnEnumPlayersOwner->OnEnumPlayers(TDx_Play_OnEnumPlayersOwner, Id, PlayerType, Name, Flags, Context, fContinue ); // cleanup delete Name; // Finished! return fContinue; } // -------------------------------------------------------------------------- // Method: Internal_EnumSessionsCallback() // Description: The Internal_EnumSessionsCallback method is used to process // enumeration for TDx_Play::EnumSessions(). // Params: pThisSD - // The ThisSD parameter references a TDPSessionDesc component // describing the session currently being enumerated. // pTimeOut - // The TimeOut parameter contains the curent timeout value. // // This value can be increased if the DPESC_TIMEDOUT flag is // returned. // pFlags - // The Flags parameter defines a flag indicating enumeration // status. // The described effect applies when the flag is set. // // This parameter is typically set to zero. // Flags: // DPESC_TIMEDOUT - // A timeout condition occured while waiting for session // information. // pContext - // The Context parameter references application defined data // passed to the callback fuinction. // -------------------------------------------------------------------------- BOOL __stdcall TDx_Play::Internal_EnumSessionsCallback( LPCDPSESSIONDESC2 pThisSD, LPDWORD pTimeOut, DWORD pFlags, LPVOID pContext ) { // Original Function Definition // unknown bool fContinue = true; // translate parameters dword* TimeOut = pTimeOut; dword Flags = pFlags; void* Context = pContext; TDPSessionDesc* ThisSD; // lpThisSD may be null if the enumeration timed out. if (pThisSD == NULL) return false; ThisSD = new TDPSessionDesc( NULL ); if (ThisSD) { ThisSD->Flags = pThisSD->dwFlags ; ThisSD->Instance = pThisSD->guidInstance ; ThisSD->Application = pThisSD->guidApplication ; ThisSD->MaxPlayers = pThisSD->dwMaxPlayers ; ThisSD->CurrentPlayers = pThisSD->dwCurrentPlayers ; if (TDx_Play_OnEnumSessionsOwner->UseAnsiString) { AnsiString temp1 = (char*) pThisSD->lpszSessionNameA; AnsiString temp2 = (char*) pThisSD->lpszPasswordA; ThisSD->SessionNameA = temp1; ThisSD->PasswordA = temp2; } else { AnsiString temp1 = (char*) pThisSD->lpszSessionName; AnsiString temp2 = (char*) pThisSD->lpszPassword; ThisSD->SessionName = temp1; ThisSD->Password = temp2; } ThisSD->User1 = pThisSD->dwUser1; ThisSD->User2 = pThisSD->dwUser2; ThisSD->User3 = pThisSD->dwUser3; ThisSD->User4 = pThisSD->dwUser4; } // Call Original Function if (TDx_Play_OnEnumSessionsOwner->OnEnumSessions) TDx_Play_OnEnumSessionsOwner->OnEnumSessions( TDx_Play_OnEnumSessionsOwner, ThisSD, TimeOut, Flags, Context, fContinue ); // cleanup delete ThisSD; // Finished! return fContinue; } // -------------------------------------------------------------------------- // Method: Open() // Description: The Open method will join or create a session. // // Secure sessions must be joined using TDx_Play::SecureOpen(). // Existing sessions to join can be found using // TDx_Play::EnumSessions(). // To open more than one session, the application must employ // multiple TDx_Play components. // Once joined, messages cannot be exchanged until a local // player is created using TDx_Play::CreatePlayer(). // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_ALREADYINITIALIZED // DPERR_AUTHENTICATIONFAILED // DPERR_CANNOTCREATESERVER // DPERR_CANTCREATEPLAYER // DPERR_CANTLOADCAPI // DPERR_CANTLOADSECURITYPACKAGE // DPERR_CANTLOADSSPI // DPERR_CONNECTING // DPERR_CONNECTIONLOST // DPERR_ENCRYPTIONFAILED // DPERR_ENCRYPTIONNOTSUPPORTED // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_INVALIDPASSWORD // DPERR_LOGONDENIED // DPERR_NOCONNECTION // DPERR_NONEWPLAYERS // DPERR_NOSESSIONS // DPERR_SIGNFAILED // DPERR_TIMEOUT // DPERR_UNINITIALIZED // DPERR_USERCANCEL // Params: pSD - // The SD parameter references a TDPSessionDesc component // holding the relevent information about the session to be // created or joined. // // To join a session only requires the TDPSessionDesc::Instance, // and if a password is needed, TDPSessionDesc::Password. // // To create a session all the relevent TDPSessionDesc // properties must be provided. // The session GUID will be generated by DirectPlay. // pFlags - // The Flags parameter defines flags indicating the type of open // action to be performed. // The described effect applies when the flag is set. // Flags: // DPOPEN_CREATE - // A new session instance is to be created. // The local computer will act as the name server and // session host for the new session. // DPOPEN_JOIN - // An existing session is to be joined. // DPOPEN_RETURNSTATUS - // Do not display any connection status dialog boxes. // // DDERR_CONNECTING will be returned if the connection // cannot be made immediately. // The application should call this method until DP_OK or // a different error code is returned. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::Open( TDPSessionDesc* pSD, dword pFlags ) { // Original Function Definition // HRESULT Open( // LPDPSESSIONDESC2 lpsd, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Open()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->Open( (pSD==NULL) ? NULL : pSD->Internal_DPSESSIONDESC2_Ptr, (DWORD) pFlags ); // Translate Data returned from Function if (pSD!=NULL) pSD->Internal_DPSESSIONDESC2_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::Open()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Receive() // Description: The ReceiveEx method will retrieve one message from the // incoming message queue. // // Error values that can be generated are: // // DPERR_BUFFERTOOSMALL // DPERR_GENERIC // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // DPERR_NOMESSAGES // Params: pFrom - // The From parameter will identify the player that sent the // message if this method returns successfully. // // When DPRECEIVE_FROMPLAYER is set, you must identify the // sending player in this parameter. // pTo - // The To parameter will identify the player receiving the // message if this method return successfully. // // When DPRECEIVE_TOPLAYER is set, you must identify the // receiving player in this parameter. // pFlags - // The Flags parameter defines flags indicating how a message is // to be retrieved and treated. // The described effect applies when the flag is set. // // The default setting of zero is equivalent to DPRECEIVE_ALL. // Flags: // DPRECEIVE_ALL - // The first relevent message in the queue will be // retrieved. // DPRECEIVE_FROMPLAYER - // Retrieve only the messages sent from the player // identified by the From parameter. // DPRECEIVE_PEEK - // Retrieves a message defined by the other flag settings // without removing the message from the queue. // // This flag should be set when the Data parameter is // NULL. // DPRECEIVE_TOPLAYER - // Retrieve only the messages sent to the player // identified by the To parameter. // pData - // The Data parameter references a buffer for holding the // message data if this method returns successfully. // // Set NULL to allocate appropriate memory to hold the message // data, the DataSize parameter will be set to the size of the // data. // // If previously allocated memory is used and the message data // requires more memory than the amount specified by the // DataSize initial value, the memory will be released and // replaced with the required memory block. // pDataSize - // The DataSize parameter references the size, in bytes, of the // Data buffer. // // This parameter will be set to the size of the message data // when the method returns. // -------------------------------------------------------------------------- HRESULT __fastcall TDx_Play::Receive( DPID* pFrom, DPID* pTo, dword pFlags, void* pData, dword* pDataSize ) { // Original Function Definition // HRESULT Receive( // LPDPID lpidFrom, // LPDPID lpidTo, // DWORD dwFlags, // LPVOID lpData, // LPDWORD lpdwDataSize // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Receive()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->Receive( (LPDPID) pFrom, (LPDPID) pTo, (DWORD) pFlags, (LPVOID) pData, (LPDWORD) pDataSize ); // Success! return fErrorValue; } // -------------------------------------------------------------------------- // Method: ReceiveEx() // Description: The ReceiveEx method retrieves one message from the incoming // message queue, determines what type of message it is, // converts data as necessary and triggers a corresponding // TDx_Play event, one of :- // // TDx_Play::OnCreatePlayerOrGroup() // TDx_Play::OnDestroyPlayerOrGroup() // TDx_Play::OnAddPlayerToGroup() // TDx_Play::OnDeletePlayerFromGroup() // TDx_Play::OnSessionLost() // TDx_Play::OnHost() // TDx_Play::OnSetPlayerOrGroupData() // TDx_Play::OnSetPlayerOrGroupName() // TDx_Play::OnAddGroupToGroup() // TDx_Play::OnDeleteGroupFromGroup() // TDx_Play::OnChat() // TDx_Play::OnSecureMessage() // TDx_Play::OnSendComplete() // TDx_Play::OnSetGroupOwner() // TDx_Play::OnSetSessionDesc() // TDx_Play::OnStartSession() // TDx_Play::OnGeneric() // // Error values that can be generated are: // // DPERR_BUFFERTOOSMALL // DPERR_GENERIC // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // DPERR_NOMESSAGES // Params: pFrom - // The From parameter will identify the player that sent the // message if this method returns successfully. // // When DPRECEIVE_FROMPLAYER is set, you must identify the // sending player in this parameter. // pTo - // The To parameter will identify the player receiving the // message if this method return successfully. // // When DPRECEIVE_TOPLAYER is set, you must identify the // receiving player in this parameter. // pFlags - // The Flags parameter defines flags indicating how a message is // to be retrieved and treated. // The described effect applies when the flag is set. // // The default setting of zero is equivalent to DPRECEIVE_ALL. // Flags: // DPRECEIVE_ALL - // The first relevent message in the queue will be // retrieved. // DPRECEIVE_FROMPLAYER - // Retrieve only the messages sent from the player // identified by the From parameter. // DPRECEIVE_PEEK - // Retrieves a message defined by the other flag settings // without removing the message from the queue. // This flag should be set when the Data parameter is // NULL. // DPRECEIVE_TOPLAYER - // Retrieve only the messages sent to the player // identified by the To parameter. // -------------------------------------------------------------------------- HRESULT __fastcall TDx_Play::ReceiveEx( LPDPID pFrom, LPDPID pTo, DWORD pFlags ) { // Original Function Definition // HRESULT Receive( // LPDPID lpidFrom, // LPDPID lpidTo, // DWORD dwFlags, // LPVOID lpData, // LPDWORD lpdwDataSize // ); byte* fData = NULL; dword fDataSize = 0; // loop until a single message is successfully read do { // read message from specified player if (fLPDIRECTPLAY4!=NULL) fErrorValue = fLPDIRECTPLAY4->Receive( (LPDPID) pFrom, (LPDPID) pTo, (DWORD) pFlags, (LPVOID) fData, (LPDWORD) &fDataSize ); //if not enough room then resize buffer if (fErrorValue == DPERR_BUFFERTOOSMALL) { if (fData) delete fData ; fData = new byte[fDataSize]; if (fData == NULL) fErrorValue = DPERR_OUTOFMEMORY; } } while (fErrorValue == DPERR_BUFFERTOOSMALL); if ((fErrorValue==DP_OK) && // successfully read a message (fDataSize >= sizeof(DPMSG_GENERIC))) // and it is big enough { // check for system message if (*pFrom == DPID_SYSMSG) { // determine type of message LPDPMSG_GENERIC generic = (LPDPMSG_GENERIC) fData; dword msg_type = generic->dwType; switch (msg_type) { case DPSYS_CREATEPLAYERORGROUP: { if (OnCreatePlayerOrGroup) { TDPName* fName = new TDPName(this); if (fName == NULL) { if (FOnError) FOnError( this, Name+"::ReceiveEx()", TDx_Play_Library_ErrorString(DPERR_OUTOFMEMORY ), TDx_Play_Library_ErrorMessage(DPERR_OUTOFMEMORY ) ); break; } LPDPMSG_CREATEPLAYERORGROUP fTemp = (LPDPMSG_CREATEPLAYERORGROUP) fData; DPNAME* pName = (DPNAME*) &fTemp->dpnName; if (UseAnsiString) { AnsiString temp1 = (char*) pName->lpszShortNameA; AnsiString temp2 = (char*) pName->lpszLongNameA; fName->ShortNameA = temp1; fName->LongNameA = temp2; } else { AnsiString temp1 = (char*) pName->lpszShortName; AnsiString temp2 = (char*) pName->lpszLongName; fName->ShortName = temp1; fName->LongName = temp2; } OnCreatePlayerOrGroup(this, fTemp->dwPlayerType, fTemp->dpId, fTemp->dwCurrentPlayers, fTemp->lpData, fTemp->dwDataSize, fName, fTemp->dpIdParent, fTemp->dwFlags); delete fName; } break; } case DPSYS_DESTROYPLAYERORGROUP: { if (OnDestroyPlayerOrGroup) { TDPName* fName = new TDPName(this); if (fName == NULL) { if (FOnError) FOnError( this, Name+"::ReceiveEx()", TDx_Play_Library_ErrorString(DPERR_OUTOFMEMORY ), TDx_Play_Library_ErrorMessage(DPERR_OUTOFMEMORY ) ); break; } LPDPMSG_DESTROYPLAYERORGROUP fTemp = (LPDPMSG_DESTROYPLAYERORGROUP) fData; DPNAME* pName = (DPNAME*) &fTemp->dpnName; if (UseAnsiString) { AnsiString temp1 = (char*) pName->lpszShortNameA; AnsiString temp2 = (char*) pName->lpszLongNameA; fName->ShortNameA = temp1; fName->LongNameA = temp2; } else { AnsiString temp1 = (char*) pName->lpszShortName; AnsiString temp2 = (char*) pName->lpszLongName; fName->ShortName = temp1; fName->LongName = temp2; } OnDestroyPlayerOrGroup(this, fTemp->dwPlayerType, fTemp->dpId, fTemp->lpLocalData, fTemp->dwLocalDataSize, fTemp->lpRemoteData, fTemp->dwRemoteDataSize, fName, fTemp->dpIdParent, fTemp->dwFlags); delete fName; } break; } case DPSYS_ADDPLAYERTOGROUP: { if (OnAddPlayerToGroup) { LPDPMSG_ADDPLAYERTOGROUP fTemp = (LPDPMSG_ADDPLAYERTOGROUP) fData; OnAddPlayerToGroup(this, fTemp->dpIdGroup, fTemp->dpIdPlayer); } break; } case DPSYS_DELETEPLAYERFROMGROUP: { if (OnDeletePlayerFromGroup) { LPDPMSG_DELETEPLAYERFROMGROUP fTemp = (LPDPMSG_DELETEPLAYERFROMGROUP) fData; OnDeletePlayerFromGroup(this, fTemp->dpIdGroup, fTemp->dpIdPlayer); } break; } case DPSYS_SESSIONLOST: { if (OnSessionLost) OnSessionLost(this); break; } case DPSYS_HOST: { if (OnHost) OnHost(this); break; } case DPSYS_SETPLAYERORGROUPDATA: { if (OnSetPlayerOrGroupData) { LPDPMSG_SETPLAYERORGROUPDATA fTemp = (LPDPMSG_SETPLAYERORGROUPDATA) fData; OnSetPlayerOrGroupData(this, fTemp->dwPlayerType, fTemp->dpId, fTemp->lpData, fTemp->dwDataSize); } break; } case DPSYS_SETPLAYERORGROUPNAME: { if (OnSetPlayerOrGroupName) { TDPName* fName = new TDPName(this); if (fName == NULL) if (FOnError) FOnError( this, Name+"::ReceiveEx()", TDx_Play_Library_ErrorString(DPERR_OUTOFMEMORY ), TDx_Play_Library_ErrorMessage(DPERR_OUTOFMEMORY ) ); LPDPMSG_SETPLAYERORGROUPNAME fTemp = (LPDPMSG_SETPLAYERORGROUPNAME) fData; DPNAME* pName = (DPNAME*) &fTemp->dpnName; if (UseAnsiString) { AnsiString temp1 = (char*) pName->lpszShortNameA; AnsiString temp2 = (char*) pName->lpszLongNameA; fName->ShortNameA = temp1; fName->LongNameA = temp2; } else { AnsiString temp1 = (char*) pName->lpszShortName; AnsiString temp2 = (char*) pName->lpszLongName; fName->ShortName = temp1; fName->LongName = temp2; } OnSetPlayerOrGroupName(this, fTemp->dwPlayerType, fTemp->dpId, fName); delete fName; } break; } case DPSYS_ADDGROUPTOGROUP: { if (OnAddGroupToGroup) { LPDPMSG_ADDGROUPTOGROUP fTemp = (LPDPMSG_ADDGROUPTOGROUP) fData; OnAddGroupToGroup(this, fTemp->dpIdParentGroup, fTemp->dpIdGroup); } break; } case DPSYS_CHAT: { if (OnChat) { TDPChat* fChat = new TDPChat(this); if (fChat == NULL) { if (FOnError) FOnError( this, Name+"::ReceiveEx()", TDx_Play_Library_ErrorString(DPERR_OUTOFMEMORY ), TDx_Play_Library_ErrorMessage(DPERR_OUTOFMEMORY ) ); break; } LPDPMSG_CHAT fTemp = (LPDPMSG_CHAT) fData; DPCHAT* pChat = (DPCHAT*) &fTemp->lpChat; if (UseAnsiString) { AnsiString temp1 = (char*) pChat->lpszMessageA; fChat->MessageA = temp1; } else { AnsiString temp1 = (char*) pChat->lpszMessage; fChat->Message = temp1; } OnChat(this, fTemp->dwFlags, fTemp->idFromPlayer, fTemp->idToPlayer, fTemp->idToGroup, fChat); delete fChat; } break; } case DPSYS_DELETEGROUPFROMGROUP: { if (OnDeleteGroupFromGroup) { LPDPMSG_DELETEGROUPFROMGROUP fTemp = (LPDPMSG_DELETEGROUPFROMGROUP) fData; OnDeleteGroupFromGroup(this, fTemp->dpIdParentGroup, fTemp->dpIdGroup); } break; } //case DPMSG_GENERIC:break; case DPSYS_SECUREMESSAGE: { if (OnSecureMessage) { LPDPMSG_SECUREMESSAGE fTemp = (LPDPMSG_SECUREMESSAGE) fData; OnSecureMessage(this, fTemp->dwFlags, fTemp->dpIdFrom, fTemp->lpData, fTemp->dwDataSize); } break; } case DPSYS_SENDCOMPLETE: { if (OnSendComplete) { LPDPMSG_SENDCOMPLETE fTemp = (LPDPMSG_SENDCOMPLETE) fData; OnSendComplete(this, fTemp->idFrom, fTemp->idTo, fTemp->dwFlags, fTemp->dwPriority, fTemp->dwTimeout, fTemp->lpvContext, fTemp->dwMsgID, fTemp->hr, fTemp->dwSendTime); } break; } case DPSYS_SETGROUPOWNER: { if (OnSetGroupOwner) { LPDPMSG_SETGROUPOWNER fTemp = (LPDPMSG_SETGROUPOWNER) fData; OnSetGroupOwner(this, fTemp->idGroup, fTemp->idNewOwner, fTemp->idOldOwner); } break; } case DPSYS_SETSESSIONDESC: { if (OnSetSessionDesc) { TDPSessionDesc* fDesc = new TDPSessionDesc(this); if (fDesc == NULL) { if (FOnError) FOnError( this, Name+"::ReceiveEx()", TDx_Play_Library_ErrorString(DPERR_OUTOFMEMORY), TDx_Play_Library_ErrorMessage(DPERR_OUTOFMEMORY) ); break; } LPDPMSG_SETSESSIONDESC fTemp = (LPDPMSG_SETSESSIONDESC) fData; DPSESSIONDESC2* pDesc = (DPSESSIONDESC2*) &fTemp->dpDesc; // CopyMemory( fDesc->Internal_DPSESSIONDESC2_Ptr, pDesc, sizeof(DPSESSIONDESC2) ); fDesc->Flags = pDesc->dwFlags; fDesc->Instance = pDesc->guidInstance; fDesc->Application = pDesc->guidApplication; fDesc->MaxPlayers = pDesc->dwMaxPlayers; fDesc->CurrentPlayers = pDesc->dwCurrentPlayers; fDesc->MaxPlayers = pDesc->dwMaxPlayers; fDesc->User1 = pDesc->dwUser1; fDesc->User2 = pDesc->dwUser2; fDesc->User3 = pDesc->dwUser3; fDesc->User4 = pDesc->dwUser4; if (UseAnsiString) { AnsiString temp1 = (char*) pDesc->lpszSessionNameA; AnsiString temp2 = (char*) pDesc->lpszPasswordA; fDesc->SessionNameA = temp1; fDesc->PasswordA = temp2; } else { AnsiString temp1 = (char*) pDesc->lpszSessionName; AnsiString temp2 = (char*) pDesc->lpszPassword; fDesc->SessionName = temp1; fDesc->Password = temp2; } OnSetSessionDesc(this, fDesc); delete fDesc; } break; } case DPSYS_STARTSESSION: { if (OnStartSession) { TDPLConnection* fConn = new TDPLConnection(this); if (fConn == NULL) { if (FOnError) FOnError( this, Name+"::ReceiveEx()", TDx_Play_Library_ErrorString(DPERR_OUTOFMEMORY), TDx_Play_Library_ErrorMessage(DPERR_OUTOFMEMORY) ); break; } TDPName* fName = new TDPName(this); if (fName == NULL) { delete fConn; if (FOnError) FOnError( this, Name+"::ReceiveEx()", TDx_Play_Library_ErrorString(DPERR_OUTOFMEMORY), TDx_Play_Library_ErrorMessage(DPERR_OUTOFMEMORY) ); break; } TDPSessionDesc* fDesc = new TDPSessionDesc(this); if (fDesc == NULL) { delete fName; delete fConn; if (FOnError) FOnError( this, Name+"::ReceiveEx()", TDx_Play_Library_ErrorString(DPERR_OUTOFMEMORY), TDx_Play_Library_ErrorMessage(DPERR_OUTOFMEMORY) ); break; } LPDPMSG_STARTSESSION fTemp = (LPDPMSG_STARTSESSION) fData; DPLCONNECTION* pConn = (DPLCONNECTION*) fTemp->lpConn; DPNAME* pName = (DPNAME*) pConn->lpPlayerName; DPSESSIONDESC2* pDesc = (DPSESSIONDESC2*) pConn->lpSessionDesc; fConn->Size = pConn->dwSize; fConn->Flags = pConn->dwFlags; fConn->SP = pConn->guidSP; fConn->Address = pConn->lpAddress; fConn->AddressSize = pConn->dwAddressSize; fConn->PlayerName = fName; fConn->SessionDesc = fDesc; if (UseAnsiString) { AnsiString temp1 = (char*) pName->lpszShortNameA; AnsiString temp2 = (char*) pName->lpszLongNameA; fName->ShortNameA = temp1; fName->LongNameA = temp2; } else { AnsiString temp1 = (char*) pName->lpszShortName; AnsiString temp2 = (char*) pName->lpszLongName; fName->ShortName = temp1; fName->LongName = temp2; } fDesc->Flags = pDesc->dwFlags; fDesc->Instance = pDesc->guidInstance; fDesc->Application = pDesc->guidApplication; fDesc->MaxPlayers = pDesc->dwMaxPlayers; fDesc->CurrentPlayers = pDesc->dwCurrentPlayers; fDesc->MaxPlayers = pDesc->dwMaxPlayers; fDesc->User1 = pDesc->dwUser1; fDesc->User2 = pDesc->dwUser2; fDesc->User3 = pDesc->dwUser3; fDesc->User4 = pDesc->dwUser4; if (UseAnsiString) { AnsiString temp1 = (char*) pDesc->lpszSessionNameA; AnsiString temp2 = (char*) pDesc->lpszPasswordA; fDesc->SessionNameA = temp1; fDesc->PasswordA = temp2; } else { AnsiString temp1 = (char*) pDesc->lpszSessionName; AnsiString temp2 = (char*) pDesc->lpszPassword; fDesc->SessionName = temp1; fDesc->Password = temp2; } OnStartSession( this, fConn ); delete fConn; delete fName; delete fDesc; } break; } default: { if (FOnError) FOnError ( this, Name+"::ReceiveEx()", "TDX_INVALID", "Message not in list of valid message types." ); } } } // not a system message else { if (OnGeneric) OnGeneric(this, *pFrom, *pTo, pFlags, fData, fDataSize, ((LPDPMSG_GENERIC)fData)->dwType); } } else { if (fData) delete[] fData; if (FOnError) FOnError( this, Name+"::ReceiveEx()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); } // free any memory we created if (fData) delete[] fData; // Finished! return fErrorValue; } // -------------------------------------------------------------------------- // Method: SecureOpen() // Description: The SecureOpen method will create or join a secure session. // // Existing sessions to join can be found using // TDx_Play::EnumSessions(). // To open more than one session, the application must employ // multiple TDx_Play components. // Once joined, messages cannot be exchanged until a local // player is created using TDx_Play::CreatePlayer(). // // Credentials supplied on system login may suffice, so when // first joining a session, supply no credentials. // If DPERR_LOGONDENIED is returned, then collect credentials // from the user and try again. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_ALREADYINITIALIZED // DPERR_AUTHENTICATIONFAILED // DPERR_CANNOTCREATESERVER // DPERR_CANTLOADCAPI // DPERR_CANTLOADSECURITYPACKAGE // DPERR_CANTLOADSSPI // DPERR_CONNECTING // DPERR_CONNECTIONLOST // DPERR_ENCRYPTIONFAILED // DPERR_ENCRYPTIONNOTSUPPORTED // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_INVALIDPASSWORD // DPERR_LOGONDENIED // DPERR_NOCONNECTION // DPERR_NONEWPLAYERS // DPERR_SIGNFAILED // DPERR_TIMEOUT // DPERR_UNINITIALIZED // DPERR_USERCANCEL // Params: pSD - // The SD parameter references a TDPSessionDesc component // holding the relevent information about the secure session to // be created or joined. // // To join a secure session only requires the // TDPSessionDesc::Instance, and if a password is needed, // TDPSessionDesc::Password. // // To create a secure session all the relevent TDPSessionDesc // properties must be provided and the TDPSessionDesc::Flags // DPSESSION_SECURESERVER flag set. // The session GUID will be generated by DirectPlay. // pFlags - // The Flags parameter defines flags indicating the type of open // action to be performed. // The described effect applies when the flag is set. // Flags: // DPOPEN_CREATE - // A new secure session instance is to be created. // The local computer will act as the name server and // session host for the new session. // DPOPEN_JOIN - // An existing secure session instance is to be joined. // DPOPEN_RETURNSTATUS - // Do not display any connection status dialog boxes. // // DDERR_CONNECTING will be returned if the connection // cannot be made immediately. // The application should call this method until DP_OK or // a different error code is returned. // pSecurity - // The Security parameter references a TDPSecurityDesc component // holding the security package that the new session will use. // // Set NULL when joining a session or to create a secure session // using the default security (NT lan manager) and cryptoAPI // (Microsoft RSA base cryptographic provider) packages being // used. // pCredentials - // The Credentials parameter references a TDPCredentials // component holding the logon name, password and domain to be // authenticated by the sessions hosting server. // // Set NULL if there are no credentials or the session is being // created rather than joined. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::SecureOpen( TDPSessionDesc* pSD, dword pFlags, TDPSecurityDesc* pSecurity, TDPCredentials* pCredentials ) { // Original Function Definition // HRESULT SecureOpen( // LPCDPSESSIONDESC2 lpsd, // DWORD dwFlags, // LPCDPSECURITYDESC lpSecurity, // LPCDPCREDENTIALS lpCredentials // ) // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SecureOpen()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->SecureOpen( (pSD==NULL) ? NULL : pSD->Internal_DPSESSIONDESC2_Ptr, (DWORD) pFlags, (pSecurity==NULL) ? NULL : pSecurity->Internal_DPSECURITYDESC_Ptr, (pCredentials==NULL) ? NULL : pCredentials->Internal_DPCREDENTIALS_Ptr ); // Translate Data returned from Function if (pSD!=NULL) pSD->Internal_DPSESSIONDESC2_Update(); if (pSecurity!=NULL) pSecurity->Internal_DPSECURITYDESC_Update(); if (pCredentials!=NULL) pCredentials->Internal_DPCREDENTIALS_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SecureOpen()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Send() // Description: The Send method will send guaranteed or unguaranteed messages // to individual or multiple players. // // TDx_Play::SendEx() can be used to send messages // asynchronously. // // System messages will always be sent guaranteed. An encypted // or signed message is sent as a system message // (DPMSG_SECUREMESSAGE). // // There is no message size limit, large messages will be broken // into packets. It is reccomended large messages be sent // guaranteed, as one lost packet on an unguaranteed message // will result in the entire message being discarded. // The largest message sendable using a single packet can be // determined by checking the TDCaps::MaxBufferSize value // returned by TDx_Play::GetCaps(). // // Error values that can be generated are: // // DPERR_BUSY // DPERR_CONNECTIONLOST // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // DPERR_NOTLOGGEDIN // DPERR_SENDTOOBIG // Params: pFrom - // The From parameter identifies the local player sending the // message. // pTo - // The To parameter identifies the player or group receiving the // message if this method return successfully. // // DPID_ALLPLAYERS can be specified to send the message to all // players in the session, or DPID_SERVERPLAYER to send a // message to the server player of a client server session. // pFlags - // The Flags parameter defines flags indicating how the message // is to be sent. // The described effect applies when the flag is set. // // The default value of zero will result in a nonguaranteed // message being sent. // Flags: // DPSEND_ENCRYPTED - // The message is to be sent encrypted. // // Requires both a secure session and DPSEND_GUARANTEED. // DPSEND_GUARANTEED - // The message is to be sent using guaranteed delivery if // available. // DPSEND_SIGNED - // The message is to be sent with a digital signature. // // Requires both a secure session and DPSEND_GUARANTEED. // pData - // The Data parameter references the message data that is to be // sent. // pDataSize - // The DataSize parameter defines the size, in bytes, of the // message data to be sent. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::Send( DPID pFrom, DPID pTo, dword pFlags, void* pData, dword pDataSize ) { // Original Function Definition // HRESULT Send( // DPID idFrom, // DPID idTo, // DWORD dwFlags, // LPVOID lpData, // DWORD dwDataSize // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Send()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->Send( pFrom, pTo, (DWORD) pFlags, (LPVOID) pData, (DWORD) pDataSize ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::Send()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SendChatMessage() // Description: The SendChatMessage method will send text messages to // individual or multiple players within a lobby session. // // The from ID will be DPID_SYSMSG, the TDPChat component will // identify the actual sending player. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pFrom - // The From parameter identifies the local player sending the // message. // pTo - // The To parameter identifies the player or group receiving the // message if this method return successfully. // // DPID_ALLPLAYERS can also be specified to send the message to // all players in the session. // pFlags - // The Flags parameter defines a flag indicating how the message // is to be sent. // The described effect applies when the flag is set. // // The default setting of zero results in a nonguaranteed // messaging being used. // Flags: // DPSEND_GUARANTEED - // The message is to be sent using guaranteed delivery if // available. // pChatMessage - // The ChatMessage parameter references a TDPChat component // holding the message being sent. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::SendChatMessage( DPID pFrom, DPID pTo, dword pFlags, TDPChat* pChatMessage ) { // Original Function Definition // HRESULT SendChatMessage( // DPID idFrom, // DPID idTo, // DWORD dwFlags, // LPDPCHAT lpChatMessage // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SendChatMessage()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pChatMessage==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::SendChatMessage()", "TDX_BADPARAMS", "'pChatMessage' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->SendChatMessage( pFrom, pTo, (DWORD) pFlags, pChatMessage->Internal_DPCHAT_Ptr ); // Translate Data returned from Function pChatMessage->Internal_DPCHAT_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SendChatMessage()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SendEx() // Description: The SendEx method will send guaranteed or unguaranteed // messages to individual or multiple players. // // It functions like TDx_Play::Send() except asyncronous // messages, message priorities and message timeouts are all // supported. // // When using asynchronous messaging, DPERR_PENDING will be // returned once the message is queued and a DPMSG_SENDCOMPLETE // message received once the send process is completed. // // System messages will always be sent guaranteed. An encypted // or signed message is sent as a system message // (DPMSG_SECUREMESSAGE). // // There is no message size limit, large messages will be broken // into packets. It is reccomended large messages be sent // guaranteed, as one lost packet on an unguaranteed message // will result in the entire message being discarded. // The largest message sendable using a single packet can be // determined by checking the TDCaps::MaxBufferSize value // returned by TDx_Play::GetCaps(). // // It is reccomended that all secure or signed messages be sent // with the same priority level. Secure message validation // depends on receive order, and different priorities may change // that order. // // Error values that can be generated are: // // DPERR_BUSY // DPERR_CONNECTIONLOST // DPERR_INVALIDFLAGS // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // DPERR_INVALIDPRIORITY // DPERR_NOTLOGGEDIN // DPERR_SENDTOOBIG // DPERR_UNSUPPORTED // Params: pFrom - // The From parameter identifies the local player sending the // message. // pTo - // The To parameter identifies the player or group receiving the // message if this method return successfully. // // DPID_ALLPLAYERS can be specified to send the message to all // players in the session, or DPID_SERVERPLAYER to send a // message to the server player of a client server session. // pFlags - // The Flags parameter defines flags indicating how the message // is to be sent. // The described effect applies when the flag is set. // // The default value of zero will result in a nonguaranteed // message being sent. // Flags: // DPSEND_ASYNC - // Send the message asynchronously. // // The method returns immediately, DPERR_PENDING being // returned if the message was added to send queue (rather // than being sent straight away). // A DPMSG_SENDCOMPLETE message will be posted to the // senders receive queue once the message has been sent. // DPSEND_ENCRYPTED - // Send the message as a DPMSG_SECUREMESSAGE system // message with encryption. // // Only usable in a secure session with DPSEND_GUARANTEED // also set. // DPSEND_GUARANTEED - // The message is to be sent using guaranteed delivery if // available. // DPSEND_NOSENDCOMPLETEMSG - // No DPMSG_SENDCOMPLETE message will be posted when // sending an asynchronous message. // // DPSEND_ASYNC must also be set. // DPSEND_SIGNED - // Send the message as a DPMSG_SECUREMESSAGE system // message with a digital signature. // // Only usable in a secure session with DPSEND_GUARANTEED // also set. // pData - // The Data parameter references the message data that is to be // sent. // pDataSize - // The DataSize parameter defines the size, in bytes, of the // message data to be sent. // pPriority - // The Priority parameter defines a message priority, from // lowest priority at zero to highest priority at 65535. // // Messages are sent from the queue in priority order. // // Setting a priority (non zero) when the service provider does // not support them results in a DPERR_UNSUPPORTED error. // Use TDx_Play::GetCaps() to determine if priority messaging is // supported. // pTimeout - // The Timeout parameter defines how long, in milliseconds, to // wait before cancelling the message if it still has not been // delivered. // // A DPMSG_SENDCOMPLETE message will still be posted when a // message times out. // // Setting a timeout (non zero) when the service provider does // not support them results in a DPERR_UNSUPPORTED error. // Use TDx_Play::GetCaps() to determine if timouts are // supported. // pContext - // The Context parameter references application defined data to // be returned in the completion message when the send is // complete. // // Set NULL if no data needs to be returned. // pID - // The ID parameter will reference the identity assigned to an // asynchronous message if the method returns successfully. // // The message ID can be used to check the message status or // cancel it. // Set NULL if no message ID is required. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::SendEx( DPID pFrom, DPID pTo, dword pFlags, void* pData, dword pDataSize, dword pPriority, dword pTimeout, void* pContext, dword* pID ) { // Original Function Definition // HRESULT SendEx( // DPID idFrom, // DPID idTo, // DWORD dwFlags, // LPVOID lpData, // DWORD dwDataSize, // DWORD dwPriority, // DWORD dwTimeout, // LPVOID lpContext, // LPDWORD lpdwMsgID // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SendEx()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->SendEx( pFrom, pTo, (DWORD) pFlags, (LPVOID) pData, (DWORD) pDataSize, (DWORD) pPriority, (DWORD) pTimeout, (LPVOID) pContext, (LPDWORD) pID ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SendEx()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetGroupConnectionSettings() // Description: The SetGroupConnectionSettings method will define a sessions // connection settings when launched from within a lobby session // group. // // The TDPLConnection component should be checked for predefined // defaults by calling TDx_Play::GetGroupConnectionSettings(). // Trying to modify these values may cause errors. // // TDPLConnection::Address, TDPLConnection::AddressSize and // TDPSessionDesc::Instance need not be specified for this // method to work. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDGROUP // DPERR_INVALIDPARAMS // DPERR_UNSUPPORTED // Params: pGroup - // The Group parameter identifies the group whose connection // settings are being defined. // pConnection - // The Connection parameter references a TDPLConnection // component defining the service provider, session description // and application to be launched when starting a session from // the Group. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::SetGroupConnectionSettings( DPID pGroup, TDPLConnection* pConnection ) { // Original Function Definition // HRESULT SetGroupConnectionSettings( // DWORD dwFlags, // DPID idGroup, // LPDPLCONNECTION lpConnection // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetGroupConnectionSettings()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->SetGroupConnectionSettings( 0, pGroup, (pConnection==NULL) ? NULL : pConnection->Internal_DPLCONNECTION_Ptr ); // Translate Data returned from Function if (pConnection!=NULL) pConnection->Internal_DPLCONNECTION_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetGroupConnectionSettings()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetGroupData() // Description: The SetGroupData method will associate application specific // data with the specified group. // // There are two types of group data, local and remote. Local // data is only available to the local computer, while remote // data is propogated to all applications in the session via a // DPMSG_SETPLAYERORGROUPDATA message. // // Only the computer that created the group may modify its data. // // To update real time information, TDx_Play::Send() or // TDx_Play::SendEx() should be used, this method is more // appropriate for sharing information that does not change // rapidly. // // Error values that can be generated are: // // DPERR_BUFFERTOOSMALL // DPERR_INVALIDGROUP // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pGroup - // The Group parameter identifies the group with which the data // is to be associated. // pData - // The Data parameter references the data to be associated with // the specified Group. // // Set NULL to clear any data already associated with the // specified group. // pDataSize - // The DataSize parameter defines the size of the Data buffer. // // When Data is NULL, this parameter must be zero. // pFlags - // The Flags parameter defines flags indicating how to propagate // the data. // The described effect applies when the flag is set. // // The default value of zero will result in remote data being // propagated with non-guaranteed messaging. // Flags: // DPSET_GUARANTEED - // The remote data is to be propagated with guaranteed // messaging. // // DPSET_REMOTE must also be set. // DPSET_LOCAL - // The data is to be used locally and will not be // propagated. // DPSET_REMOTE - // The data will be propagated to all the applications in // the session. // // The group must be owned by the local session for this // flag to be set. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::SetGroupData( DPID pGroup, void* pData, dword pDataSize, dword pFlags ) { // Original Function Definition // HRESULT SetGroupData( // DPID idGroup, // LPVOID lpData, // DWORD dwDataSize, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetGroupData()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->SetGroupData( pGroup, (LPVOID) pData, (DWORD) pDataSize, (DWORD) pFlags ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetGroupData()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetGroupName() // Description: The SetGroupName method is used to change or set the name of // an existing group. // // Only the computer that created the group may modify its name. // // All other players will receive a DPMSG_SETPLAYERORGROUPNAME, // provided DPSESSION_NODATAMESSAGES has not been set in the // session description. // // Error values that can be generated are: // // DPERR_CONNECTIONLOST // DPERR_INVALIDGROUP // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pGroup - // The Group parameter identifies the group whose name is to be // set. // pGroupName - // The GroupName parameter references a TDPName component // holding the new name for the specified Group. // // Set NULL if the group has no name information. // pFlags - // The Flags parameter defines flags indicating how to propagate // the name. // The described effect applies when the flag is set. // // The default setting of zero will result in the name being // propagated to all the remote systems in the local session // using nonguaranteed messaging. // The default can only be used for groups owned by the local // session. // Flags: // DPSET_GUARANTEED - // The name is to be propagated to remote applications // using guaranteed messaging. // // DPSET_REMOTE must also be set. // DPSET_LOCAL - // The name is to be used locally and will not be // propagated. // DPSET_REMOTE - // The name will be propagated to all the applications in // the session. // // The group must be owned by the local session for this // flag to be set. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::SetGroupName( DPID pGroup, TDPName* pGroupName, dword pFlags ) { // Original Function Definition // HRESULT SetGroupName( // DPID idGroup, // LPDPNAME lpGroupName, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetGroupName()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->SetGroupName( pGroup, (pGroupName==NULL) ? NULL : pGroupName->Internal_DPNAME_Ptr, (DWORD) pFlags ); // Translate Data returned from Function if (pGroupName!=NULL) pGroupName->Internal_DPNAME_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetGroupName()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetGroupOwner() // Description: The SetGroupOwner method can be used to change a groups // owner. // // This method can only be used in a lobby session and will // generate a DPMSG_SETGROUPOWNER system message. // // Error values that can be generated are: // // DPERR_CONNECTIONLOST // DPERR_GENERIC // DPERR_INVALIDGROUP // DPERR_INVALIDPLAYER // DPERR_UNAVAILABLE // Params: pGroup - // The Group parameter identifies the group whose ownership is // being modified. // pOwner - // The Owner parameter identifies the player who will be the // groups new owner. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::SetGroupOwner( DPID pGroup, DPID pOwner ) { // Original Function Definition // HRESULT SetGroupOwner( // DPID idGroup, // DPID idOwner // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetGroupOwner()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->SetGroupOwner( pGroup, pOwner ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetGroupOwner()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetPlayerData() // Description: The SetPlayerData method will associate application specific // data with the specified player. // // There are two types of player data, local and remote. Local // data is only available to the local computer, while remote // data is propogated to all applications in the session via a // DPMSG_SETPLAYERORGROUPDATA message. // // Only the computer that created the player may modify its // data. // // To update real time information, TDx_Play::Send() or // TDx_Play::SendEx() should be used, this method is more // appropriate for sharing information that does not change // rapidly. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDFLAGS // DPERR_INVALIDOBJECT // DPERR_INVALIDPARAMS // DPERR_INVALIDPLAYER // Params: pPlayer - // The Group parameter identifies the player with which the data // is to be associated. // pData - // The Data parameter references the data to be associated with // the specified Player. // // Set NULL to clear any data already associated with the // specified Player. // pDataSize - // The DataSize parameter defines the size of the Data buffer. // // When Data is NULL, this parameter must be zero. // pFlags - // The Flags parameter defines flags indicating how to propagate // the data. // The described effect applies when the flag is set. // // The default value of zero will result in remote data being // propagated with non-guaranteed messaging. // Flags: // DPSET_GUARANTEED - // The remote data is to be propagated with guaranteed // messaging. // // DPSET_REMOTE must also be set. // DPSET_LOCAL - // The data is to be used locally and will not be // propagated. // DPSET_REMOTE - // The data will be propagated to all the applications in // the session. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::SetPlayerData( DPID pPlayer, void* pData, dword pDataSize, dword pFlags ) { // Original Function Definition // HRESULT SetPlayerData( // DPID idPlayer, // LPVOID lpData, // DWORD dwDataSize, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetPlayerData()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->SetPlayerData( pPlayer, (LPVOID) pData, (DWORD) pDataSize, (DWORD) pFlags ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetPlayerData()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetPlayerName() // Description: The SetPlayerName method is used to change or set the name of // an existing player. // // Only the computer that created the player may modify its // name. // // All other players will receive a DPMSG_SETPLAYERORGROUPNAME, // provided DPSESSION_NODATAMESSAGES has not been set in the // session description. // // Error values that can be generated are: // // DPERR_CONNECTIONLOST // DPERR_INVALIDOBJECT // DPERR_INVALIDPLAYER // Params: pPlayer - // The Player parameter identifies the player whose name is to // be set. // pPlayerName - // The PlayerName parameter references a TDPName component // holding the new name for the specified player. // // Set NULL if the player has no name information. // pFlags - // The Flags parameter defines flags indicating how to propagate // the name. // The described effect applies when the flag is set. // Flags: // DPSET_GUARANTEED - // The name is to be propagated with guaranteed messaging. // // // DPSET_REMOTE must also be set. // DPSET_LOCAL - // The name is to be used locally and will not be // propagated. // DPSET_REMOTE - // The name will be propagated to all the applications in // the session. // // This is the default value. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::SetPlayerName( DPID pPlayer, TDPName* pPlayerName, dword pFlags ) { // Original Function Definition // HRESULT SetPlayerName( // DPID idPlayer, // LPDPNAME lpPlayerName, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetPlayerName()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->SetPlayerName( pPlayer, (pPlayerName==NULL) ? NULL : pPlayerName->Internal_DPNAME_Ptr, (DWORD) pFlags ); // Translate Data returned from Function if (pPlayerName!=NULL) pPlayerName->Internal_DPNAME_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetPlayerName()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetSessionDesc() // Description: The SetSessionDesc method is used to change the current // sessions properties. // // This method cannot be used in a lobby session and only the // session host can change the session properties. // // A DPMSG_SETSESSIONDESC message will inform all the other // computers in the session of the change. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDPARAMS // DPERR_NOSESSIONS // Params: pSessDesc - // The SessDesc parameter references a TDPSessionDesc component // defining the new session settings. // // The DPSESSION_JOINDISABLED, DPSESSION_NEWPLAYERSDISABLED, // DPSESSION_NODATAMESSAGES and DPSESSION_PRIVATE flags can be // changed, along with the name and password of the session and // any application defined data. // // The maximum number of players can also be modified, although // you cannot specify a lower maximum than the current number of // players. // // Attempts to change any of the other session properties will // either generate an error or be ignored. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::SetSessionDesc( TDPSessionDesc* pSessDesc ) { // Original Function Definition // HRESULT SetSessionDesc( // LPDPSESSIONDESC2 lpSessDesc, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetSessionDesc()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->SetSessionDesc( (pSessDesc==NULL) ? NULL : pSessDesc->Internal_DPSESSIONDESC2_Ptr, 0 ); // Translate Data returned from Function if (pSessDesc!=NULL) pSessDesc->Internal_DPSESSIONDESC2_Update(); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetSessionDesc()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: StartSession() // Description: The StartSession method will launch a TDx_Play session from a // staging area group. // // New players arriving in the staging area can use this method // to join the already running session. // // Session information such as which application to launch, // service provider to use, etc is set using // TDx_Play::SetGroupConnectionSettings(). // // Players in the group will receive a DPMSG_STARTSESSION system // message. // // Error values that can be generated are: // // DPERR_ACCESSDENIED // DPERR_CONNECTIONLOST // DPERR_INVALIDFLAGS // DPERR_INVALIDGROUP // DPERR_INVALIDPARAMS // Params: pGroup - // The Group parameter identifies the staging area group whose // session is to be started. // -------------------------------------------------------------------------- bool __fastcall TDx_Play::StartSession( DPID pGroup ) { // Original Function Definition // HRESULT StartSession( // DWORD dwFlags, // DPID idGroup // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::StartSession()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTPLAY4->StartSession( 0, pGroup ); // Handle any Known Results if (fErrorValue!=DP_OK) { // Failure. if (FOnError) FOnError( this, Name+"::StartSession()", TDx_Play_Library_ErrorString(fErrorValue), TDx_Play_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Internal Interface Access // -------------------------------------------------------------------------- LPDIRECTPLAY4 __fastcall TDx_Play::FGetInternal_LPDIRECTPLAY4() { return fLPDIRECTPLAY4; } // -------------------------------------------------------------------------- LPDIRECTPLAY4* __fastcall TDx_Play::FGetInternal_LPDIRECTPLAY4_Ptr() { return &fLPDIRECTPLAY4; } // -------------------------------------------------------------------------- void __fastcall TDx_Play::FSetInternal_LPDIRECTPLAY4( LPDIRECTPLAY4 pLPDIRECTPLAY4 ) { if (!fCreated) { fLPDIRECTPLAY4 = pLPDIRECTPLAY4; fCreated = (fLPDIRECTPLAY4!=NULL); } } // -------------------------------------------------------------------------- void __fastcall TDx_Play::Internal_LPDIRECTPLAY4_Update() { fCreated = (fLPDIRECTPLAY4!=NULL); } // -------------------------------------------------------------------------- LPDIRECTPLAY __fastcall TDx_Play::FGetInternal_LPDIRECTPLAY() { return fLPDIRECTPLAY; } // -------------------------------------------------------------------------- LPDIRECTPLAY* __fastcall TDx_Play::FGetInternal_LPDIRECTPLAY_Ptr() { return &fLPDIRECTPLAY; } // -------------------------------------------------------------------------- void __fastcall TDx_Play::FSetInternal_LPDIRECTPLAY( LPDIRECTPLAY pLPDIRECTPLAY ) { if (!fCreated) { fLPDIRECTPLAY = pLPDIRECTPLAY; fCreated = (fLPDIRECTPLAY!=NULL); } } // -------------------------------------------------------------------------- void __fastcall TDx_Play::Internal_LPDIRECTPLAY_Update() { fCreated = (fLPDIRECTPLAY4!=NULL); } // --------------------------------------------------------------------------