Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1082 lines
41 KiB
C++
1082 lines
41 KiB
C++
//----------------------------------------------------------------------------
|
|
// File: LobbyClient.cpp
|
|
//
|
|
// Desc: LobbyClient is a simple lobby client. It displays all registered DirectPlay
|
|
// applications on the local system. It allows the
|
|
// user to launch one or more of these applications using a chosen
|
|
// service provider. A launched lobbied application may be told to either
|
|
// join or host a game.
|
|
//
|
|
// Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
#define STRICT
|
|
#include <winsock.h>
|
|
#include <windows.h>
|
|
#include <basetsd.h>
|
|
#include <dplay8.h>
|
|
#include <dplobby8.h>
|
|
#include <dpaddr.h>
|
|
#include <dxerr8.h>
|
|
#include <cguid.h>
|
|
#include <tchar.h>
|
|
#include "DXUtil.h"
|
|
#include "resource.h"
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Defines, and constants
|
|
//-----------------------------------------------------------------------------
|
|
#define DPLAY_SAMPLE_KEY TEXT("Software\\Microsoft\\DirectX DirectPlay Samples")
|
|
#define WM_APP_APPDISCONNECTED (WM_APP + 1)
|
|
#define WM_APP_SETSTATUS (WM_APP + 2)
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Global variables
|
|
//-----------------------------------------------------------------------------
|
|
IDirectPlay8Peer* g_pDP = NULL; // DirectPlay peer object
|
|
IDirectPlay8LobbyClient* g_pLobbyClient = NULL; // DirectPlay lobby client
|
|
HINSTANCE g_hInst = NULL; // HINST of app
|
|
HWND g_hDlg = NULL; // HWND of main dialog
|
|
TCHAR g_strAppName[256] = TEXT("LobbyClient");
|
|
GUID* g_pCurSPGuid = NULL; // Currently selected guid
|
|
TCHAR g_strPlayerName[MAX_PATH]; // Local player name
|
|
TCHAR g_strSessionName[MAX_PATH]; // Session name
|
|
TCHAR g_strPreferredProvider[MAX_PATH]; // Provider string
|
|
TCHAR g_strLocalIP[MAX_PATH]; // Provider string
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Function-prototypes
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT WINAPI DirectPlayMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
|
|
HRESULT WINAPI DirectPlayLobbyMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
|
|
INT_PTR CALLBACK LobbyClientDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
|
|
HRESULT InitDirectPlay();
|
|
HRESULT OnInitDialog( HWND hDlg );
|
|
VOID SetupAddressFields( HWND hDlg );
|
|
HRESULT AllocAndInitConnectSettings( HWND hDlg, GUID* pAppGuid, DPL_CONNECTION_SETTINGS** ppdplConnectSettings );
|
|
VOID FreeConnectSettings( DPL_CONNECTION_SETTINGS* pSettings );
|
|
HRESULT LaunchApp( HWND hDlg );
|
|
HRESULT EnumRegisteredApplications( HWND hDlg );
|
|
HRESULT EnumServiceProviders( HWND hDlg );
|
|
HRESULT EnumAdapters( HWND hDlg, GUID* pSPGuid );
|
|
HRESULT SendMsgToApp( HWND hDlg );
|
|
HRESULT DisconnectFromApp( HWND hDlg );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: WinMain()
|
|
// Desc: Entry point for the application. Since we use a simple dialog for
|
|
// user interaction we don't need to pump messages.
|
|
//-----------------------------------------------------------------------------
|
|
INT APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst,
|
|
LPSTR pCmdLine, INT nCmdShow )
|
|
{
|
|
HRESULT hr;
|
|
HKEY hDPlaySampleRegKey;
|
|
|
|
g_hInst = hInst;
|
|
|
|
// Read persistent state information from registry
|
|
RegCreateKeyEx( HKEY_CURRENT_USER, DPLAY_SAMPLE_KEY, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
|
|
&hDPlaySampleRegKey, NULL );
|
|
DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Player Name"),
|
|
g_strPlayerName, MAX_PATH, TEXT("TestPlayer") );
|
|
DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Session Name"),
|
|
g_strSessionName, MAX_PATH, TEXT("TestGame") );
|
|
DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Preferred Provider"),
|
|
g_strPreferredProvider, MAX_PATH,
|
|
TEXT("DirectPlay8 TCP/IP Service Provider") );
|
|
|
|
// Init COM so we can use CoCreateInstance
|
|
CoInitializeEx( NULL, COINIT_MULTITHREADED );
|
|
|
|
if( FAILED( hr = InitDirectPlay() ) )
|
|
{
|
|
DXTRACE_ERR( TEXT("InitDirectPlay"), hr );
|
|
MessageBox( NULL, TEXT("Failed initializing IDirectPlay8Peer. ")
|
|
TEXT("The sample will now quit."),
|
|
g_strAppName, MB_OK | MB_ICONERROR );
|
|
return FALSE;
|
|
}
|
|
|
|
DialogBox( hInst, MAKEINTRESOURCE(IDD_LOBBY_CLIENT), NULL,
|
|
(DLGPROC) LobbyClientDlgProc );
|
|
|
|
if( g_pLobbyClient )
|
|
{
|
|
g_pLobbyClient->Close( 0 );
|
|
SAFE_RELEASE( g_pLobbyClient );
|
|
}
|
|
|
|
if( g_pDP )
|
|
{
|
|
g_pDP->Close(0);
|
|
SAFE_RELEASE( g_pDP );
|
|
}
|
|
|
|
CoUninitialize();
|
|
|
|
// Write information to the registry
|
|
DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Player Name"), g_strPlayerName );
|
|
DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Session Name"), g_strSessionName );
|
|
DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Preferred Provider"), g_strPreferredProvider );
|
|
|
|
RegCloseKey( hDPlaySampleRegKey );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InitDirectPlay()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT InitDirectPlay()
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Create and init IDirectPlay8Peer
|
|
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Peer, NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IDirectPlay8Peer,
|
|
(LPVOID*) &g_pDP ) ) )
|
|
return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
|
|
|
|
if( FAILED( hr = g_pDP->Initialize( NULL, DirectPlayMessageHandler, 0 ) ) )
|
|
return DXTRACE_ERR( TEXT("Initialize"), hr );
|
|
|
|
// Create and init IDirectPlay8LobbyClient
|
|
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8LobbyClient, NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IDirectPlay8LobbyClient,
|
|
(LPVOID*) &g_pLobbyClient ) ) )
|
|
return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
|
|
|
|
if( FAILED( hr = g_pLobbyClient->Initialize( NULL, DirectPlayLobbyMessageHandler, 0 ) ) )
|
|
return DXTRACE_ERR( TEXT("Initialize"), hr );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: LobbyClientDlgProc()
|
|
// Desc: Handles dialog messages
|
|
//-----------------------------------------------------------------------------
|
|
INT_PTR CALLBACK LobbyClientDlgProc( HWND hDlg, UINT msg,
|
|
WPARAM wParam, LPARAM lParam )
|
|
{
|
|
HRESULT hr;
|
|
|
|
switch( msg )
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
g_hDlg = hDlg;
|
|
if( FAILED( hr = OnInitDialog( hDlg ) ) )
|
|
{
|
|
DXTRACE_ERR( TEXT("OnInitDialog"), hr );
|
|
MessageBox( NULL, TEXT("Failed initializing dialog box. ")
|
|
TEXT("The sample will now quit."),
|
|
g_strAppName, MB_OK | MB_ICONERROR );
|
|
EndDialog( hDlg, 0 );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_APP_APPDISCONNECTED:
|
|
{
|
|
// This is an app defined msg that keeps the
|
|
// lobby message handler from blocking on the dialog thread.
|
|
DPNHANDLE hDisconnectId = (DPNHANDLE) lParam;
|
|
HRESULT hrReason = (HRESULT) wParam;
|
|
|
|
// Remove this connection from the list
|
|
TCHAR strBuffer[200];
|
|
wsprintf( strBuffer, TEXT("0x%x"), hDisconnectId );
|
|
int nIndex = (int) SendDlgItemMessage( g_hDlg, IDC_ACTIVE_CONNECTIONS,
|
|
LB_FINDSTRINGEXACT, -1, (LPARAM) strBuffer );
|
|
SendDlgItemMessage( g_hDlg, IDC_ACTIVE_CONNECTIONS, LB_DELETESTRING, nIndex, 0 );
|
|
|
|
// Tell the user
|
|
wsprintf( strBuffer, TEXT("0x%x was disconnected. Reason: 0x%0.8x"),
|
|
hDisconnectId, hrReason );
|
|
MessageBox( g_hDlg, strBuffer, g_strAppName, MB_OK );
|
|
break;
|
|
}
|
|
|
|
case WM_APP_SETSTATUS:
|
|
{
|
|
// This is an app defined msg that keeps the
|
|
// lobby message handler from blocking on the dialog thread.
|
|
TCHAR* strBuffer = (TCHAR*) lParam;
|
|
|
|
if( strBuffer )
|
|
{
|
|
SetDlgItemText( g_hDlg, IDC_STATUS, strBuffer );
|
|
SAFE_DELETE_ARRAY( strBuffer );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch( LOWORD(wParam) )
|
|
{
|
|
case IDC_HOST_SESSION:
|
|
SetupAddressFields( hDlg );
|
|
break;
|
|
|
|
case IDC_SP_COMBO:
|
|
{
|
|
// If the pSPGuid changed then re-enum the adapters, and
|
|
// update the address fields.
|
|
int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
|
|
GUID* pSPGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
|
|
if( pSPGuid != NULL && g_pCurSPGuid != pSPGuid )
|
|
{
|
|
g_pCurSPGuid = pSPGuid;
|
|
SetupAddressFields( hDlg );
|
|
EnumAdapters( hDlg, pSPGuid );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case IDC_LAUNCH:
|
|
if( FAILED( hr = LaunchApp( hDlg ) ) )
|
|
{
|
|
DXTRACE_ERR( TEXT("LaunchApp"), hr );
|
|
MessageBox( NULL, TEXT("Failure trying to launch app. ")
|
|
TEXT("The sample will now quit."),
|
|
g_strAppName, MB_OK | MB_ICONERROR );
|
|
EndDialog( hDlg, 0 );
|
|
}
|
|
break;
|
|
|
|
case IDC_SEND_MSG:
|
|
// Send a dummy message to a connected app for demo purposes
|
|
SendMsgToApp( hDlg );
|
|
break;
|
|
|
|
case IDC_DISCONNECT:
|
|
// Disconnect from an app
|
|
DisconnectFromApp( hDlg );
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
EndDialog( hDlg, 0 );
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
GetDlgItemText( hDlg, IDC_PLAYER_NAME, g_strPlayerName, MAX_PATH );
|
|
GetDlgItemText( hDlg, IDC_SESSION_NAME, g_strSessionName, MAX_PATH );
|
|
int nIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
|
|
SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETLBTEXT, nIndex, (LPARAM) g_strPreferredProvider );
|
|
|
|
GUID* pGuid;
|
|
int nCount,i;
|
|
nCount = (int)SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETCOUNT, 0, 0 );
|
|
for( i=0; i<nCount; i++ )
|
|
{
|
|
pGuid = (LPGUID) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETITEMDATA, i, 0 );
|
|
SAFE_DELETE( pGuid );
|
|
}
|
|
|
|
nCount = (int)SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCOUNT, 0, 0 );
|
|
for( i=0; i<nCount; i++ )
|
|
{
|
|
pGuid = (LPGUID) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, i, 0 );
|
|
SAFE_DELETE( pGuid );
|
|
}
|
|
|
|
nCount = (int)SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETCOUNT, 0, 0 );
|
|
for( i=0; i<nCount; i++ )
|
|
{
|
|
pGuid = (LPGUID) SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETITEMDATA, i, 0 );
|
|
SAFE_DELETE( pGuid );
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE; // Didn't handle message
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: OnInitDialog
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT OnInitDialog( HWND hDlg )
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Load and set the icon
|
|
HICON hIcon = LoadIcon( g_hInst, MAKEINTRESOURCE( IDI_MAIN ) );
|
|
SendMessage( hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon ); // Set big icon
|
|
SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon ); // Set small icon
|
|
|
|
CheckDlgButton( hDlg, IDC_HOST_SESSION, BST_CHECKED );
|
|
CheckRadioButton( hDlg, IDC_LAUNCH_NEW, IDC_DONT_LAUNCH, IDC_LAUNCH_NOT_FOUND );
|
|
|
|
SetDlgItemText( hDlg, IDC_PLAYER_NAME, g_strPlayerName );
|
|
SetDlgItemText( hDlg, IDC_SESSION_NAME, g_strSessionName );
|
|
|
|
if( FAILED( hr = EnumRegisteredApplications( hDlg ) ) )
|
|
return DXTRACE_ERR( TEXT("EnumRegisteredApplications"), hr );
|
|
|
|
if( FAILED( hr = EnumServiceProviders( hDlg ) ) )
|
|
return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
|
|
|
|
WSADATA WSAData;
|
|
_tcscpy( g_strLocalIP, TEXT("") );
|
|
if( WSAStartup (MAKEWORD(1,0), &WSAData) == 0)
|
|
{
|
|
CHAR strLocalHostName[MAX_PATH];
|
|
gethostname( strLocalHostName, MAX_PATH );
|
|
HOSTENT* pHostEnt = gethostbyname( strLocalHostName );
|
|
if( pHostEnt )
|
|
{
|
|
in_addr* pInAddr = (in_addr*) pHostEnt->h_addr_list[0];
|
|
char* strLocalIP = inet_ntoa( *pInAddr );
|
|
if( strLocalIP )
|
|
DXUtil_ConvertAnsiStringToGeneric( g_strLocalIP, strLocalIP );
|
|
}
|
|
|
|
WSACleanup();
|
|
}
|
|
|
|
SetupAddressFields( hDlg );
|
|
|
|
int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
|
|
GUID* pSPGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
|
|
if( pSPGuid != NULL )
|
|
{
|
|
g_pCurSPGuid = pSPGuid;
|
|
EnumAdapters( hDlg, pSPGuid );
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SetupAddressFields
|
|
// Desc: Based on the SP selected, update the address UI
|
|
//-----------------------------------------------------------------------------
|
|
VOID SetupAddressFields( HWND hDlg )
|
|
{
|
|
int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
|
|
if( nSPIndex == LB_ERR )
|
|
return;
|
|
GUID* pGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
|
|
if( pGuid == NULL )
|
|
return;
|
|
|
|
BOOL bHosting = IsDlgButtonChecked( hDlg, IDC_HOST_SESSION );
|
|
|
|
if( *pGuid == CLSID_DP8SP_TCPIP )
|
|
{
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2), TRUE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE2, TEXT("2323") );
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2_TEXT), TRUE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE2_TEXT, TEXT("Port:") );
|
|
|
|
if( bHosting )
|
|
{
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), FALSE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, TEXT("") );
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), FALSE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("") );
|
|
}
|
|
else
|
|
{
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), TRUE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, g_strLocalIP );
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), TRUE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("IP Address:") );
|
|
}
|
|
}
|
|
else if( *pGuid == CLSID_DP8SP_MODEM )
|
|
{
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), TRUE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, TEXT("") );
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), TRUE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("Phone Number:") );
|
|
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2), FALSE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE2, TEXT("") );
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2_TEXT), FALSE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE2_TEXT, TEXT("") );
|
|
}
|
|
else
|
|
{
|
|
// pGuid is CLSID_DP8SP_IPX or CLSID_DP8SP_SERIAL or unknown
|
|
// so disable all the address lines
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), FALSE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, TEXT("") );
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), FALSE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("") );
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2), FALSE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE2, TEXT("") );
|
|
EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2_TEXT), FALSE );
|
|
SetDlgItemText( hDlg, IDC_ADDRESS_LINE2_TEXT, TEXT("") );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: EnumRegisteredApplications
|
|
// Desc: Enum all the lobby launchable apps and put them in the listbox
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT EnumRegisteredApplications( HWND hDlg )
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwSize = 0;
|
|
DWORD dwPrograms = 0;
|
|
DWORD iProgram;
|
|
BYTE* pData = NULL;
|
|
|
|
hr = g_pLobbyClient->EnumLocalPrograms( NULL, pData, &dwSize, &dwPrograms, 0 );
|
|
if( hr != DPNERR_BUFFERTOOSMALL && FAILED(hr) )
|
|
return DXTRACE_ERR( TEXT("EnumLocalPrograms"), hr );
|
|
|
|
if( dwSize == 0 )
|
|
{
|
|
MessageBox( NULL, TEXT("There are no applications registered as lobby launchable. ")
|
|
TEXT("The sample will now quit."),
|
|
g_strAppName, MB_OK | MB_ICONERROR );
|
|
EndDialog( hDlg, 0 );
|
|
return S_OK;
|
|
}
|
|
|
|
pData = new BYTE[dwSize];
|
|
if( FAILED( hr = g_pLobbyClient->EnumLocalPrograms( NULL, pData, &dwSize, &dwPrograms, 0 ) ) )
|
|
return DXTRACE_ERR( TEXT("EnumLocalPrograms"), hr );
|
|
|
|
DPL_APPLICATION_INFO* pAppInfo = (DPL_APPLICATION_INFO*) pData;
|
|
for( iProgram=0; iProgram<dwPrograms; iProgram++ )
|
|
{
|
|
TCHAR strAppName[MAX_PATH];
|
|
DXUtil_ConvertWideStringToGeneric( strAppName, pAppInfo->pwszApplicationName );
|
|
|
|
// Add the name to the listbox
|
|
int nIndex = (int) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_ADDSTRING, 0, (LPARAM) strAppName );
|
|
|
|
// Store the guid in the listbox
|
|
GUID* pGuid = new GUID;
|
|
memcpy( pGuid, &pAppInfo->guidApplication, sizeof(GUID) );
|
|
SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_SETITEMDATA, nIndex, (LPARAM) pGuid );
|
|
|
|
pAppInfo++;
|
|
}
|
|
|
|
SAFE_DELETE_ARRAY( pData );
|
|
|
|
SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_SETCURSEL, 0, 0 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: EnumServiceProviders()
|
|
// Desc: Fills the combobox with service providers
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT EnumServiceProviders( HWND hDlg )
|
|
{
|
|
DPN_SERVICE_PROVIDER_INFO* pdnSPInfo = NULL;
|
|
HRESULT hr;
|
|
DWORD dwItems = 0;
|
|
DWORD dwSize = 0;
|
|
int nIndex;
|
|
|
|
// Enumerate all DirectPlay service providers, and store them in the listbox
|
|
hr = g_pDP->EnumServiceProviders( NULL, NULL, pdnSPInfo, &dwSize,
|
|
&dwItems, 0 );
|
|
if( hr != DPNERR_BUFFERTOOSMALL )
|
|
return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
|
|
|
|
pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
|
|
if( FAILED( hr = g_pDP->EnumServiceProviders( NULL, NULL, pdnSPInfo,
|
|
&dwSize, &dwItems, 0 ) ) )
|
|
return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
|
|
|
|
DPN_SERVICE_PROVIDER_INFO* pdnSPInfoEnum = pdnSPInfo;
|
|
for ( DWORD i = 0; i < dwItems; i++ )
|
|
{
|
|
TCHAR strName[MAX_PATH];
|
|
DXUtil_ConvertWideStringToGeneric( strName, pdnSPInfoEnum->pwszName );
|
|
|
|
// Found a service provider, so put it in the listbox
|
|
nIndex = (int)SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_ADDSTRING,
|
|
0, (LPARAM) strName );
|
|
|
|
// Store pointer to GUID in listbox
|
|
GUID* pGuid = new GUID;
|
|
memcpy( pGuid, &pdnSPInfoEnum->guid, sizeof(GUID) );
|
|
SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_SETITEMDATA,
|
|
nIndex, (LPARAM) pGuid );
|
|
|
|
pdnSPInfoEnum++;
|
|
}
|
|
|
|
SAFE_DELETE_ARRAY( pdnSPInfo );
|
|
|
|
// Try to select the default preferred provider
|
|
nIndex = (int)SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_FINDSTRINGEXACT, (WPARAM)-1,
|
|
(LPARAM)g_strPreferredProvider );
|
|
if( nIndex != LB_ERR )
|
|
SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_SETCURSEL, nIndex, 0 );
|
|
else
|
|
SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_SETCURSEL, 0, 0 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: EnumAdapters()
|
|
// Desc: Fills the combobox with adapters for a specified SP
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT EnumAdapters( HWND hDlg, GUID* pSPGuid )
|
|
{
|
|
DPN_SERVICE_PROVIDER_INFO* pdnSPInfo = NULL;
|
|
TCHAR strName[MAX_PATH];
|
|
HRESULT hr;
|
|
DWORD dwItems = 0;
|
|
DWORD dwSize = 0;
|
|
int nIndex;
|
|
int nAllAdaptersIndex = 0;
|
|
|
|
SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_RESETCONTENT, 0, 0 );
|
|
|
|
// Enumerate all DirectPlay service providers, and store them in the listbox
|
|
hr = g_pDP->EnumServiceProviders( pSPGuid, NULL, pdnSPInfo, &dwSize,
|
|
&dwItems, 0 );
|
|
if( hr != DPNERR_BUFFERTOOSMALL )
|
|
return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
|
|
|
|
pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
|
|
if( FAILED( hr = g_pDP->EnumServiceProviders( pSPGuid, NULL, pdnSPInfo,
|
|
&dwSize, &dwItems, 0 ) ) )
|
|
return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
|
|
|
|
DPN_SERVICE_PROVIDER_INFO* pdnSPInfoEnum = pdnSPInfo;
|
|
for ( DWORD i = 0; i < dwItems; i++ )
|
|
{
|
|
DXUtil_ConvertWideStringToGeneric( strName, pdnSPInfoEnum->pwszName );
|
|
|
|
// Found a service provider, so put it in the listbox
|
|
nIndex = (int)SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_ADDSTRING,
|
|
0, (LPARAM) strName );
|
|
|
|
if( _tcscmp( strName, TEXT("All Adapters") ) == 0 )
|
|
nAllAdaptersIndex = nIndex;
|
|
|
|
// Store pointer to GUID in listbox
|
|
GUID* pGuid = new GUID;
|
|
memcpy( pGuid, &pdnSPInfoEnum->guid, sizeof(GUID) );
|
|
|
|
SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_SETITEMDATA,
|
|
nIndex, (LPARAM) pGuid );
|
|
|
|
pdnSPInfoEnum++;
|
|
}
|
|
|
|
SAFE_DELETE_ARRAY( pdnSPInfo );
|
|
|
|
SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_SETCURSEL, nAllAdaptersIndex, 0 );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: LaunchApp
|
|
// Desc: Launch the selected app based on the UI settings
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT LaunchApp( HWND hDlg )
|
|
{
|
|
HRESULT hr;
|
|
DPNHANDLE hApplication = NULL;
|
|
|
|
BOOL bLaunchNew = IsDlgButtonChecked( hDlg, IDC_LAUNCH_NEW );
|
|
BOOL bLaunchNotFound = IsDlgButtonChecked( hDlg, IDC_LAUNCH_NOT_FOUND );
|
|
|
|
int nAppIndex = (int) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETCURSEL, 0, 0 );
|
|
GUID* pAppGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETITEMDATA, nAppIndex, 0 );
|
|
if( nAppIndex == LB_ERR || pAppGuid == NULL )
|
|
return E_INVALIDARG;
|
|
|
|
// Setup the DPL_CONNECT_INFO struct
|
|
DPL_CONNECT_INFO dnConnectInfo;
|
|
ZeroMemory( &dnConnectInfo, sizeof(DPL_CONNECT_INFO) );
|
|
dnConnectInfo.dwSize = sizeof(DPL_CONNECT_INFO);
|
|
dnConnectInfo.pvLobbyConnectData = NULL;
|
|
dnConnectInfo.dwLobbyConnectDataSize = 0;
|
|
dnConnectInfo.dwFlags = 0;
|
|
if( bLaunchNew )
|
|
dnConnectInfo.dwFlags |= DPLCONNECT_LAUNCHNEW;
|
|
if( bLaunchNotFound )
|
|
dnConnectInfo.dwFlags |= DPLCONNECT_LAUNCHNOTFOUND;
|
|
dnConnectInfo.guidApplication = *pAppGuid;
|
|
if( FAILED( hr = AllocAndInitConnectSettings( hDlg, pAppGuid, &dnConnectInfo.pdplConnectionSettings ) ) )
|
|
return S_FALSE;
|
|
|
|
hr = g_pLobbyClient->ConnectApplication( &dnConnectInfo, NULL, &hApplication,
|
|
INFINITE, 0 );
|
|
if( FAILED(hr) )
|
|
{
|
|
if( hr == DPNERR_NOCONNECTION && !bLaunchNew && !bLaunchNotFound )
|
|
{
|
|
MessageBox( NULL, TEXT("There was no waiting application. "),
|
|
g_strAppName, MB_OK | MB_ICONERROR );
|
|
}
|
|
else
|
|
{
|
|
return DXTRACE_ERR( TEXT("ConnectApplication"), hr );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TCHAR strBuffer[20];
|
|
wsprintf( strBuffer, TEXT("0x%x"), hApplication );
|
|
int nIndex = (int) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_ADDSTRING,
|
|
0, (LPARAM) strBuffer );
|
|
SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_SETITEMDATA,
|
|
nIndex, (LPARAM) hApplication );
|
|
|
|
if( LB_ERR == SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_GETCURSEL, 0, 0 ) )
|
|
SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_SETCURSEL, 0, 0 );
|
|
}
|
|
|
|
FreeConnectSettings( dnConnectInfo.pdplConnectionSettings );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: AllocAndInitConnectSettings
|
|
// Desc: Alloc and fill up a DPL_CONNECTION_SETTINGS. Call FreeConnectSettings
|
|
// later to free it.
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT AllocAndInitConnectSettings( HWND hDlg, GUID* pAppGuid,
|
|
DPL_CONNECTION_SETTINGS** ppdplConnectSettings )
|
|
{
|
|
HRESULT hr;
|
|
|
|
BOOL bHosting = IsDlgButtonChecked( hDlg, IDC_HOST_SESSION );
|
|
BOOL bNoSettings = IsDlgButtonChecked( hDlg, IDC_NO_SETTINGS );
|
|
IDirectPlay8Address* pHostAddress = NULL;
|
|
IDirectPlay8Address* pDeviceAddress = NULL;
|
|
|
|
if( bNoSettings )
|
|
{
|
|
*ppdplConnectSettings = NULL;
|
|
return S_OK;
|
|
}
|
|
|
|
int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
|
|
GUID* pSPGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
|
|
|
|
if( *pSPGuid == CLSID_DP8SP_IPX && !bHosting )
|
|
{
|
|
MessageBox( hDlg, TEXT("A typical lobby client would have sent a complete IPX address, this ") \
|
|
TEXT("lobby client does not support this. "), g_strAppName, MB_OK );
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
if( !bHosting )
|
|
{
|
|
// Create a host address if connecting to a host,
|
|
// otherwise keep it as NULL
|
|
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IDirectPlay8Address, (void **) &pHostAddress ) ) )
|
|
return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
|
|
|
|
// Set the SP to pHostAddress
|
|
if( FAILED( hr = pHostAddress->SetSP( pSPGuid ) ) )
|
|
return DXTRACE_ERR( TEXT("SetSP"), hr );
|
|
}
|
|
|
|
// Create a device address to specify which device we are using
|
|
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IDirectPlay8Address, (void **) &pDeviceAddress ) ) )
|
|
return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
|
|
|
|
// Set the SP to pDeviceAddress
|
|
if( FAILED( hr = pDeviceAddress->SetSP( pSPGuid ) ) )
|
|
return DXTRACE_ERR( TEXT("SetSP"), hr );
|
|
|
|
// Add the adapter to pHostAddress
|
|
int nAdapterIndex = (int) SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETCURSEL, 0, 0 );
|
|
GUID* pAdapterGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETITEMDATA,
|
|
nAdapterIndex, 0 );
|
|
if( FAILED( hr = pDeviceAddress->SetDevice( pAdapterGuid ) ) )
|
|
return DXTRACE_ERR( TEXT("SetDevice"), hr );
|
|
|
|
if( *pSPGuid == CLSID_DP8SP_TCPIP )
|
|
{
|
|
TCHAR strIP[MAX_PATH];
|
|
TCHAR strPort[MAX_PATH];
|
|
|
|
GetDlgItemText( hDlg, IDC_ADDRESS_LINE1, strIP, MAX_PATH );
|
|
GetDlgItemText( hDlg, IDC_ADDRESS_LINE2, strPort, MAX_PATH );
|
|
|
|
if( bHosting )
|
|
{
|
|
// Add the port to pDeviceAddress
|
|
DWORD dwPort = _ttoi( strPort );
|
|
if( FAILED( hr = pDeviceAddress->AddComponent( DPNA_KEY_PORT,
|
|
&dwPort, sizeof(dwPort),
|
|
DPNA_DATATYPE_DWORD ) ) )
|
|
return DXTRACE_ERR( TEXT("AddComponent"), hr );
|
|
}
|
|
else
|
|
{
|
|
// Add the IP address to pHostAddress
|
|
if( _tcslen( strIP ) > 0 )
|
|
{
|
|
WCHAR wstrIP[MAX_PATH];
|
|
DXUtil_ConvertGenericStringToWide( wstrIP, strIP );
|
|
|
|
if( FAILED( hr = pHostAddress->AddComponent( DPNA_KEY_HOSTNAME,
|
|
wstrIP, (wcslen(wstrIP)+1)*sizeof(WCHAR),
|
|
DPNA_DATATYPE_STRING ) ) )
|
|
return DXTRACE_ERR( TEXT("AddComponent"), hr );
|
|
}
|
|
|
|
// Add the port to pHostAddress
|
|
DWORD dwPort = _ttoi( strPort );
|
|
if( FAILED( hr = pHostAddress->AddComponent( DPNA_KEY_PORT,
|
|
&dwPort, sizeof(dwPort),
|
|
DPNA_DATATYPE_DWORD ) ) )
|
|
return DXTRACE_ERR( TEXT("AddComponent"), hr );
|
|
}
|
|
}
|
|
else if( *pSPGuid == CLSID_DP8SP_MODEM )
|
|
{
|
|
TCHAR strPhone[MAX_PATH];
|
|
GetDlgItemText( hDlg, IDC_ADDRESS_LINE1, strPhone, MAX_PATH );
|
|
|
|
if( !bHosting )
|
|
{
|
|
// Add the phonenumber to pHostAddress
|
|
if( _tcslen( strPhone ) > 0 )
|
|
{
|
|
WCHAR wstrPhone[MAX_PATH];
|
|
DXUtil_ConvertGenericStringToWide( wstrPhone, strPhone );
|
|
|
|
if( FAILED( hr = pHostAddress->AddComponent( DPNA_KEY_PHONENUMBER,
|
|
wstrPhone, (wcslen(wstrPhone)+1)*sizeof(WCHAR),
|
|
DPNA_DATATYPE_STRING ) ) )
|
|
return DXTRACE_ERR( TEXT("AddComponent"), hr );
|
|
}
|
|
}
|
|
}
|
|
else if( *pSPGuid == CLSID_DP8SP_SERIAL )
|
|
{
|
|
// This simple client doesn't have UI to query for the various
|
|
// fields needed for the serial. So we just let DPlay popup a dialog
|
|
// to ask the user which settings are needed.
|
|
}
|
|
else
|
|
{
|
|
// Unknown SP, so leave as is
|
|
}
|
|
|
|
// Setup the DPL_CONNECTION_SETTINGS
|
|
DPL_CONNECTION_SETTINGS* pSettings = new DPL_CONNECTION_SETTINGS;
|
|
ZeroMemory( pSettings, sizeof(DPL_CONNECTION_SETTINGS) );
|
|
pSettings->dwSize = sizeof(DPL_CONNECTION_SETTINGS);
|
|
pSettings->dpnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
|
|
pSettings->dwFlags = 0;
|
|
if( bHosting )
|
|
pSettings->dwFlags |= DPLCONNECTSETTINGS_HOST;
|
|
pSettings->dpnAppDesc.guidApplication = *pAppGuid;
|
|
pSettings->dpnAppDesc.guidInstance = GUID_NULL;
|
|
pSettings->pdp8HostAddress = pHostAddress;
|
|
pSettings->ppdp8DeviceAddresses = new IDirectPlay8Address*;
|
|
pSettings->ppdp8DeviceAddresses[0] = pDeviceAddress;
|
|
pSettings->cNumDeviceAddresses = 1;
|
|
|
|
// Set the pSettings->dpnAppDesc.pwszSessionName
|
|
TCHAR strSessionName[MAX_PATH];
|
|
GetDlgItemText( hDlg, IDC_SESSION_NAME, strSessionName, MAX_PATH );
|
|
if( _tcslen( strSessionName ) == 0 )
|
|
{
|
|
pSettings->dpnAppDesc.pwszSessionName = NULL;
|
|
}
|
|
else
|
|
{
|
|
WCHAR wstrSessionName[MAX_PATH];
|
|
DXUtil_ConvertGenericStringToWide( wstrSessionName, strSessionName );
|
|
pSettings->dpnAppDesc.pwszSessionName = new WCHAR[wcslen(wstrSessionName)+1];
|
|
wcscpy( pSettings->dpnAppDesc.pwszSessionName, wstrSessionName );
|
|
}
|
|
|
|
// Set the pSettings->pwszPlayerName
|
|
TCHAR strPlayerName[MAX_PATH];
|
|
GetDlgItemText( hDlg, IDC_PLAYER_NAME, strPlayerName, MAX_PATH );
|
|
if( _tcslen( strPlayerName ) == 0 )
|
|
{
|
|
pSettings->pwszPlayerName = NULL;
|
|
}
|
|
else
|
|
{
|
|
WCHAR wstrPlayerName[MAX_PATH];
|
|
DXUtil_ConvertGenericStringToWide( wstrPlayerName, strPlayerName );
|
|
pSettings->pwszPlayerName = new WCHAR[wcslen(wstrPlayerName)+1];
|
|
wcscpy( pSettings->pwszPlayerName, wstrPlayerName );
|
|
}
|
|
|
|
*ppdplConnectSettings = pSettings;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: FreeConnectSettings
|
|
// Desc: Releases everything involved in a DPL_CONNECTION_SETTINGS struct
|
|
//-----------------------------------------------------------------------------
|
|
VOID FreeConnectSettings( DPL_CONNECTION_SETTINGS* pSettings )
|
|
{
|
|
if( !pSettings )
|
|
return;
|
|
|
|
SAFE_DELETE_ARRAY( pSettings->pwszPlayerName );
|
|
SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pwszSessionName );
|
|
SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pwszPassword );
|
|
SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pvReservedData );
|
|
SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pvApplicationReservedData );
|
|
SAFE_RELEASE( pSettings->pdp8HostAddress );
|
|
SAFE_RELEASE( pSettings->ppdp8DeviceAddresses[0] );
|
|
SAFE_DELETE_ARRAY( pSettings->ppdp8DeviceAddresses );
|
|
SAFE_DELETE( pSettings );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DirectPlayMessageHandler
|
|
// Desc: Handler for DirectPlay messages. This function is called by
|
|
// the DirectPlay message handler pool of threads, so be care of thread
|
|
// synchronization problems with shared memory
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT WINAPI DirectPlayMessageHandler( PVOID pvUserContext,
|
|
DWORD dwMessageId,
|
|
PVOID pMsgBuffer )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DirectPlayLobbyMessageHandler
|
|
// Desc: Handler for DirectPlay lobby messages. This function is called by
|
|
// the DirectPlay lobby message handler pool of threads, so be careful of
|
|
// thread synchronization problems with shared memory
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT WINAPI DirectPlayLobbyMessageHandler( PVOID pvUserContext,
|
|
DWORD dwMessageId,
|
|
PVOID pMsgBuffer )
|
|
{
|
|
switch( dwMessageId )
|
|
{
|
|
case DPL_MSGID_DISCONNECT:
|
|
{
|
|
PDPL_MESSAGE_DISCONNECT pDisconnectMsg;
|
|
pDisconnectMsg = (PDPL_MESSAGE_DISCONNECT)pMsgBuffer;
|
|
|
|
// We should free any data associated with the
|
|
// app here, but there is none.
|
|
|
|
// Tell the update the UI so show that a application was disconnected
|
|
// Note: The lobby handler must not become blocked on the dialog thread,
|
|
// since the dialog thread will be blocked on lobby handler thread
|
|
// when it calls ConnectApplication(). So to avoid blocking on
|
|
// the dialog thread, we'll post a message to the dialog thread.
|
|
PostMessage( g_hDlg, WM_APP_APPDISCONNECTED, 0, pDisconnectMsg->hDisconnectId );
|
|
break;
|
|
}
|
|
|
|
case DPL_MSGID_RECEIVE:
|
|
{
|
|
PDPL_MESSAGE_RECEIVE pReceiveMsg;
|
|
pReceiveMsg = (PDPL_MESSAGE_RECEIVE)pMsgBuffer;
|
|
|
|
// The lobby app sent us data. This sample doesn't
|
|
// expected data from the app, but it is useful
|
|
// for more complex lclients.
|
|
break;
|
|
}
|
|
|
|
case DPL_MSGID_SESSION_STATUS:
|
|
{
|
|
PDPL_MESSAGE_SESSION_STATUS pStatusMsg;
|
|
pStatusMsg = (PDPL_MESSAGE_SESSION_STATUS)pMsgBuffer;
|
|
|
|
TCHAR* strBuffer = new TCHAR[200];
|
|
wsprintf( strBuffer, TEXT("0x%x: "), pStatusMsg->hSender );
|
|
switch( pStatusMsg->dwStatus )
|
|
{
|
|
case DPLSESSION_CONNECTED:
|
|
_tcscat( strBuffer, TEXT("Session connected") ); break;
|
|
case DPLSESSION_COULDNOTCONNECT:
|
|
_tcscat( strBuffer, TEXT("Session could not connect") ); break;
|
|
case DPLSESSION_DISCONNECTED:
|
|
_tcscat( strBuffer, TEXT("Session disconnected") ); break;
|
|
case DPLSESSION_TERMINATED:
|
|
_tcscat( strBuffer, TEXT("Session terminated") ); break;
|
|
case DPLSESSION_HOSTMIGRATED:
|
|
_tcscat( strBuffer, TEXT("Host migrated") ); break;
|
|
case DPLSESSION_HOSTMIGRATEDHERE:
|
|
_tcscat( strBuffer, TEXT("Host migrated to this client") ); break;
|
|
|
|
default:
|
|
{
|
|
TCHAR strStatus[30];
|
|
wsprintf( strStatus, TEXT("%d"), pStatusMsg->dwStatus );
|
|
_tcscat( strBuffer, strStatus );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Tell the update the UI so show that a application status changed
|
|
// Note: The lobby handler must not become blocked on the dialog thread,
|
|
// since the dialog thread will be blocked on lobby handler thread
|
|
// when it calls ConnectApplication(). So to avoid blocking on
|
|
// the dialog thread, we'll post a message to the dialog thread.
|
|
PostMessage( g_hDlg, WM_APP_SETSTATUS, 0, (LPARAM) strBuffer );
|
|
break;
|
|
}
|
|
|
|
case DPL_MSGID_CONNECTION_SETTINGS:
|
|
{
|
|
PDPL_MESSAGE_CONNECTION_SETTINGS pConnectionStatusMsg;
|
|
pConnectionStatusMsg = (PDPL_MESSAGE_CONNECTION_SETTINGS)pMsgBuffer;
|
|
|
|
// The app has changed the connection settings.
|
|
// This simple client doesn't handle this, but more complex clients may
|
|
// want to.
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: SendMsgToApp
|
|
// Desc: Send a dummy message to a connected app for demo purposes
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT SendMsgToApp( HWND hDlg )
|
|
{
|
|
TCHAR strBuffer[MAX_PATH];
|
|
HRESULT hr;
|
|
|
|
int nConnectIndex = (int) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_GETCURSEL, 0, 0 );
|
|
if( nConnectIndex == LB_ERR )
|
|
return S_OK;
|
|
|
|
DPNHANDLE hApplication = (DPNHANDLE) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS,
|
|
LB_GETITEMDATA, nConnectIndex, 0 );
|
|
|
|
// For demonstration purposes, just send a buffer to the app. This can be used
|
|
// by more complex lobby clients to pass custom information to apps that which
|
|
// can then recieve and process it.
|
|
BYTE buffer[20];
|
|
memset( buffer, 0x03, 20 );
|
|
if( FAILED( hr = g_pLobbyClient->Send( hApplication, buffer, 20, 0 ) ) )
|
|
{
|
|
DXTRACE_ERR( TEXT("Send"), hr );
|
|
wsprintf( strBuffer, TEXT("Failure trying to send message to 0x%0.8x."), hApplication );
|
|
MessageBox( NULL, strBuffer, g_strAppName, MB_OK | MB_ICONERROR );
|
|
}
|
|
else
|
|
{
|
|
wsprintf( strBuffer, TEXT("Successfully sent a message to 0x%0.8x."), hApplication );
|
|
MessageBox( NULL, strBuffer, g_strAppName, MB_OK | MB_ICONERROR );
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: DisconnectFromApp
|
|
// Desc: Disconnect from an app
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT DisconnectFromApp( HWND hDlg )
|
|
{
|
|
HRESULT hr;
|
|
|
|
int nConnectIndex = (int) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_GETCURSEL, 0, 0 );
|
|
if( nConnectIndex == LB_ERR )
|
|
return S_OK;
|
|
|
|
DPNHANDLE hApplication = (DPNHANDLE) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS,
|
|
LB_GETITEMDATA, nConnectIndex, 0 );
|
|
|
|
if( FAILED( hr = g_pLobbyClient->ReleaseApplication( hApplication, 0 ) ) )
|
|
{
|
|
DXTRACE_ERR( TEXT("LaunchApp"), hr );
|
|
MessageBox( NULL, TEXT("Failure trying to disconnect from app. "),
|
|
g_strAppName, MB_OK | MB_ICONERROR );
|
|
}
|
|
|
|
SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_DELETESTRING, nConnectIndex, 0 );
|
|
|
|
return S_OK;
|
|
}
|
|
|