home *** CD-ROM | disk | FTP | other *** search
/ Beginning Direct3D Game Programming / Direct3D.iso / directx / dxf / samples / multimedia / directplay / lobbyclient / lobbyclient.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-04  |  41.3 KB  |  1,076 lines

  1. //----------------------------------------------------------------------------
  2. // File: LobbyClient.cpp
  3. //
  4. // Desc: 
  5. //
  6. // Copyright (c) 1999-2000 Microsoft Corp. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #include <winsock.h>
  10. #include <windows.h>
  11. #include <basetsd.h>
  12. #include <dplay8.h>
  13. #include <dplobby8.h>
  14. #include <dpaddr.h>
  15. #include <dxerr8.h>
  16. #include <cguid.h>
  17. #include <tchar.h>
  18. #include "DXUtil.h"
  19. #include "resource.h"
  20.  
  21.  
  22.  
  23. //-----------------------------------------------------------------------------
  24. // Defines, and constants
  25. //-----------------------------------------------------------------------------
  26. #define DPLAY_SAMPLE_KEY        TEXT("Software\\Microsoft\\DirectX DirectPlay Samples")
  27. #define WM_APP_APPDISCONNECTED  (WM_APP + 1)
  28. #define WM_APP_SETSTATUS        (WM_APP + 2)
  29.  
  30.  
  31.  
  32.  
  33. //-----------------------------------------------------------------------------
  34. // Global variables
  35. //-----------------------------------------------------------------------------
  36. IDirectPlay8Peer*  g_pDP                         = NULL;    // DirectPlay peer object
  37. IDirectPlay8LobbyClient* g_pLobbyClient          = NULL;    // DirectPlay lobby client
  38. HINSTANCE          g_hInst                       = NULL;    // HINST of app
  39. HWND               g_hDlg                        = NULL;    // HWND of main dialog
  40. TCHAR              g_strAppName[256]             = TEXT("LobbyClient");
  41. GUID*              g_pCurSPGuid                  = NULL;    // Currently selected guid
  42. TCHAR              g_strPlayerName[MAX_PATH];               // Local player name
  43. TCHAR              g_strSessionName[MAX_PATH];              // Session name
  44. TCHAR              g_strPreferredProvider[MAX_PATH];        // Provider string
  45. TCHAR              g_strLocalIP[MAX_PATH];                  // Provider string
  46.  
  47.  
  48.  
  49.  
  50. //-----------------------------------------------------------------------------
  51. // Function-prototypes
  52. //-----------------------------------------------------------------------------
  53. HRESULT WINAPI   DirectPlayMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
  54. HRESULT WINAPI   DirectPlayLobbyMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
  55. INT_PTR CALLBACK LobbyClientDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
  56. HRESULT          InitDirectPlay();
  57. HRESULT          OnInitDialog( HWND hDlg );
  58. VOID             SetupAddressFields( HWND hDlg );
  59. HRESULT          AllocAndInitConnectSettings( HWND hDlg, GUID* pAppGuid, DPL_CONNECTION_SETTINGS** ppdplConnectSettings );
  60. VOID             FreeConnectSettings( DPL_CONNECTION_SETTINGS* pSettings );
  61. HRESULT          LaunchApp( HWND hDlg );
  62. HRESULT          EnumRegisteredApplications( HWND hDlg );
  63. HRESULT          EnumServiceProviders( HWND hDlg );
  64. HRESULT          EnumAdapters( HWND hDlg, GUID* pSPGuid );
  65. HRESULT          SendMsgToApp( HWND hDlg );
  66. HRESULT          DisconnectFromApp( HWND hDlg );
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74. //-----------------------------------------------------------------------------
  75. // Name: WinMain()
  76. // Desc: Entry point for the application.  Since we use a simple dialog for 
  77. //       user interaction we don't need to pump messages.
  78. //-----------------------------------------------------------------------------
  79. INT APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, 
  80.                       LPSTR pCmdLine, INT nCmdShow )
  81. {
  82.     HRESULT hr;
  83.     HKEY    hDPlaySampleRegKey;
  84.  
  85.     g_hInst = hInst; 
  86.  
  87.     // Read persistent state information from registry
  88.     RegCreateKeyEx( HKEY_CURRENT_USER, DPLAY_SAMPLE_KEY, 0, NULL,
  89.                     REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, 
  90.                     &hDPlaySampleRegKey, NULL );
  91.     DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Player Name"), 
  92.                              g_strPlayerName, MAX_PATH, TEXT("TestPlayer") );
  93.     DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Session Name"), 
  94.                              g_strSessionName, MAX_PATH, TEXT("TestGame") );
  95.     DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Preferred Provider"), 
  96.                              g_strPreferredProvider, MAX_PATH, 
  97.                              TEXT("DirectPlay8 TCP/IP Service Provider") );
  98.  
  99.     // Init COM so we can use CoCreateInstance
  100.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  101.  
  102.     if( FAILED( hr = InitDirectPlay() ) )
  103.     {
  104.         DXTRACE_ERR( TEXT("InitDirectPlay"), hr );
  105.         MessageBox( NULL, TEXT("Failed initializing IDirectPlay8Peer. ")
  106.                     TEXT("The sample will now quit."),
  107.                     g_strAppName, MB_OK | MB_ICONERROR );
  108.         return FALSE;
  109.     }
  110.  
  111.     DialogBox( hInst, MAKEINTRESOURCE(IDD_LOBBY_CLIENT), NULL, 
  112.                (DLGPROC) LobbyClientDlgProc );
  113.  
  114.     if( g_pLobbyClient )
  115.     {
  116.         g_pLobbyClient->Close( 0 );
  117.         SAFE_RELEASE( g_pLobbyClient );
  118.     }
  119.  
  120.     if( g_pDP )
  121.     {
  122.         g_pDP->Close(0);
  123.         SAFE_RELEASE( g_pDP );
  124.     }
  125.  
  126.     CoUninitialize();
  127.  
  128.     // Write information to the registry
  129.     DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Player Name"), g_strPlayerName );
  130.     DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Session Name"), g_strSessionName );
  131.     DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Preferred Provider"), g_strPreferredProvider );
  132.  
  133.     return TRUE;
  134. }
  135.  
  136.  
  137.  
  138.  
  139. //-----------------------------------------------------------------------------
  140. // Name: InitDirectPlay()
  141. // Desc: 
  142. //-----------------------------------------------------------------------------
  143. HRESULT InitDirectPlay()
  144. {
  145.     HRESULT hr;
  146.  
  147.     // Create and init IDirectPlay8Peer
  148.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Peer, NULL, 
  149.                                        CLSCTX_INPROC_SERVER,
  150.                                        IID_IDirectPlay8Peer, 
  151.                                        (LPVOID*) &g_pDP ) ) )
  152.         return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  153.  
  154.     if( FAILED( hr = g_pDP->Initialize( NULL, DirectPlayMessageHandler, 0 ) ) )
  155.         return DXTRACE_ERR( TEXT("Initialize"), hr );
  156.  
  157.     // Create and init IDirectPlay8LobbyClient
  158.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8LobbyClient, NULL, 
  159.                                        CLSCTX_INPROC_SERVER,
  160.                                        IID_IDirectPlay8LobbyClient, 
  161.                                        (LPVOID*) &g_pLobbyClient ) ) )
  162.         return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  163.  
  164.     if( FAILED( hr = g_pLobbyClient->Initialize( NULL, DirectPlayLobbyMessageHandler, 0 ) ) )
  165.         return DXTRACE_ERR( TEXT("Initialize"), hr );
  166.  
  167.     return S_OK;
  168. }
  169.  
  170.  
  171.  
  172.  
  173. //-----------------------------------------------------------------------------
  174. // Name: LobbyClientDlgProc()
  175. // Desc: Handles dialog messages
  176. //-----------------------------------------------------------------------------
  177. INT_PTR CALLBACK LobbyClientDlgProc( HWND hDlg, UINT msg, 
  178.                                      WPARAM wParam, LPARAM lParam )
  179. {
  180.     HRESULT hr;
  181.  
  182.     switch( msg ) 
  183.     {
  184.         case WM_INITDIALOG:
  185.         {
  186.             g_hDlg = hDlg;
  187.             if( FAILED( hr = OnInitDialog( hDlg ) ) )
  188.             {
  189.                 DXTRACE_ERR( TEXT("OnInitDialog"), hr );
  190.                 MessageBox( NULL, TEXT("Failed initializing dialog box. ")
  191.                             TEXT("The sample will now quit."),
  192.                             g_strAppName, MB_OK | MB_ICONERROR );
  193.                 EndDialog( hDlg, 0 );
  194.             }
  195.             break;
  196.         }
  197.  
  198.         case WM_APP_APPDISCONNECTED:
  199.         {
  200.             // This is an app defined msg that keeps the 
  201.             // lobby message handler from blocking on the dialog thread.
  202.             DPNHANDLE hDisconnectId = (DPNHANDLE) lParam;
  203.             HRESULT   hrReason      = (HRESULT) wParam;
  204.  
  205.             // Remove this connection from the list
  206.             TCHAR strBuffer[200];
  207.             wsprintf( strBuffer, "0x%x", hDisconnectId );
  208.             int nIndex = (int) SendDlgItemMessage( g_hDlg, IDC_ACTIVE_CONNECTIONS, 
  209.                                                    LB_FINDSTRINGEXACT, -1, (LPARAM) strBuffer );
  210.             SendDlgItemMessage( g_hDlg, IDC_ACTIVE_CONNECTIONS, LB_DELETESTRING, nIndex, 0 );
  211.  
  212.             // Tell the user
  213.             wsprintf( strBuffer, "0x%x was disconnected. Reason: 0x%0.8x", 
  214.                       hDisconnectId, hrReason );
  215.             MessageBox( g_hDlg, strBuffer, g_strAppName, MB_OK );
  216.             break;
  217.         }
  218.  
  219.         case WM_APP_SETSTATUS:
  220.         {
  221.             // This is an app defined msg that keeps the 
  222.             // lobby message handler from blocking on the dialog thread.
  223.             TCHAR* strBuffer = (TCHAR*) lParam;                     
  224.  
  225.             if( strBuffer )
  226.             {
  227.                 SetDlgItemText( g_hDlg, IDC_STATUS, strBuffer );
  228.                 SAFE_DELETE_ARRAY( strBuffer );
  229.             }
  230.             break;
  231.         }
  232.  
  233.         case WM_COMMAND:
  234.         {
  235.             switch( LOWORD(wParam) )
  236.             {
  237.                 case IDC_HOST_SESSION:
  238.                     SetupAddressFields( hDlg );
  239.                     break;
  240.  
  241.                 case IDC_SP_COMBO:
  242.                 {
  243.                     // If the pSPGuid changed then re-enum the adapters, and
  244.                     // update the address fields.
  245.                     int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
  246.                     GUID* pSPGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
  247.                     if( pSPGuid != NULL && g_pCurSPGuid != pSPGuid )
  248.                     {
  249.                         g_pCurSPGuid = pSPGuid;
  250.                         SetupAddressFields( hDlg );
  251.                         EnumAdapters( hDlg, pSPGuid );
  252.                     }
  253.                     break;
  254.                 }
  255.  
  256.                 case IDC_LAUNCH:
  257.                     if( FAILED( hr = LaunchApp( hDlg ) ) )
  258.                     {
  259.                         DXTRACE_ERR( TEXT("LaunchApp"), hr );
  260.                         MessageBox( NULL, TEXT("Failure trying to launch app. ")
  261.                                     TEXT("The sample will now quit."),
  262.                                     g_strAppName, MB_OK | MB_ICONERROR );
  263.                         EndDialog( hDlg, 0 );
  264.                     }
  265.                     break;
  266.  
  267.                 case IDC_SEND_MSG:
  268.                     // Send a dummy message to a connected app for demo purposes
  269.                     SendMsgToApp( hDlg );
  270.                     break;
  271.  
  272.                 case IDC_DISCONNECT:
  273.                     // Disconnect from an app
  274.                     DisconnectFromApp( hDlg );
  275.                     break;
  276.  
  277.                 case IDCANCEL:
  278.                     EndDialog( hDlg, 0 );
  279.                     return TRUE;
  280.             }
  281.             break;
  282.         }
  283.  
  284.         case WM_DESTROY:
  285.         {
  286.             GetDlgItemText( hDlg, IDC_PLAYER_NAME, g_strPlayerName, MAX_PATH );
  287.             GetDlgItemText( hDlg, IDC_SESSION_NAME, g_strSessionName, MAX_PATH );
  288.             int nIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
  289.             SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETLBTEXT, nIndex, (LPARAM) g_strPreferredProvider );
  290.  
  291.             GUID* pGuid;
  292.             int nCount,i;
  293.             nCount = (int)SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETCOUNT, 0, 0 );
  294.             for( i=0; i<nCount; i++ )
  295.             {
  296.                 pGuid = (LPGUID) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETITEMDATA, i, 0 );
  297.                 SAFE_DELETE( pGuid );
  298.             }
  299.  
  300.             nCount = (int)SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCOUNT, 0, 0 );
  301.             for( i=0; i<nCount; i++ )
  302.             {
  303.                 pGuid = (LPGUID) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, i, 0 );
  304.                 SAFE_DELETE( pGuid );
  305.             }
  306.  
  307.             nCount = (int)SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETCOUNT, 0, 0 );
  308.             for( i=0; i<nCount; i++ )
  309.             {
  310.                 pGuid = (LPGUID) SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETITEMDATA, i, 0 );
  311.                 SAFE_DELETE( pGuid );
  312.             }
  313.  
  314.             break;
  315.         }
  316.     }
  317.  
  318.     return FALSE; // Didn't handle message
  319. }
  320.  
  321.  
  322.  
  323.  
  324. //-----------------------------------------------------------------------------
  325. // Name: OnInitDialog
  326. // Desc: 
  327. //-----------------------------------------------------------------------------
  328. HRESULT OnInitDialog( HWND hDlg )
  329. {
  330.     HRESULT hr;
  331.  
  332.     // Load and set the icon
  333.     HICON hIcon = LoadIcon( g_hInst, MAKEINTRESOURCE( IDI_MAIN ) );
  334.     SendMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  335.     SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  336.  
  337.     CheckDlgButton( hDlg, IDC_HOST_SESSION, BST_CHECKED );
  338.     CheckRadioButton( hDlg, IDC_LAUNCH_NEW, IDC_DONT_LAUNCH, IDC_LAUNCH_NOT_FOUND );
  339.  
  340.     SetDlgItemText( hDlg, IDC_PLAYER_NAME, g_strPlayerName );
  341.     SetDlgItemText( hDlg, IDC_SESSION_NAME, g_strSessionName );
  342.  
  343.     if( FAILED( hr = EnumRegisteredApplications( hDlg ) ) )
  344.         return DXTRACE_ERR( TEXT("EnumRegisteredApplications"), hr );
  345.  
  346.     if( FAILED( hr = EnumServiceProviders( hDlg ) ) )
  347.         return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
  348.     
  349.     WSADATA WSAData;
  350.     _tcscpy( g_strLocalIP, TEXT("") );
  351.     if( WSAStartup (MAKEWORD(1,0), &WSAData) == 0) 
  352.     {
  353.         CHAR strLocalHostName[MAX_PATH];
  354.         gethostname( strLocalHostName, MAX_PATH );
  355.         HOSTENT* pHostEnt = gethostbyname( strLocalHostName );
  356.         if( pHostEnt )
  357.         {
  358.             in_addr* pInAddr = (in_addr*) pHostEnt->h_addr_list[0];
  359.             char* strLocalIP = inet_ntoa( *pInAddr );
  360.             if( strLocalIP )
  361.                 DXUtil_ConvertAnsiStringToGeneric( g_strLocalIP, strLocalIP );
  362.         }
  363.  
  364.         WSACleanup();
  365.     }
  366.     
  367.     SetupAddressFields( hDlg );
  368.  
  369.     int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
  370.     GUID* pSPGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
  371.     if( pSPGuid != NULL )
  372.     {
  373.         g_pCurSPGuid = pSPGuid;
  374.         EnumAdapters( hDlg, pSPGuid );
  375.     }
  376.  
  377.     return S_OK;
  378. }
  379.  
  380.  
  381.  
  382.  
  383. //-----------------------------------------------------------------------------
  384. // Name: SetupAddressFields
  385. // Desc: Based on the SP selected, update the address UI 
  386. //-----------------------------------------------------------------------------
  387. VOID SetupAddressFields( HWND hDlg )
  388. {
  389.     int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
  390.     if( nSPIndex == LB_ERR )
  391.         return;
  392.     GUID* pGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
  393.     if( pGuid == NULL )
  394.         return;
  395.  
  396.     BOOL bHosting = IsDlgButtonChecked( hDlg, IDC_HOST_SESSION );
  397.  
  398.     if( *pGuid == CLSID_DP8SP_TCPIP )
  399.     {
  400.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2), TRUE );
  401.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2, TEXT("2323") );
  402.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2_TEXT), TRUE );
  403.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2_TEXT, TEXT("Port:") );
  404.  
  405.         if( bHosting )
  406.         {
  407.             EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), FALSE );
  408.             SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, TEXT("") );
  409.             EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), FALSE );
  410.             SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("") );
  411.         }
  412.         else
  413.         {
  414.             EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), TRUE );
  415.             SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, g_strLocalIP );
  416.             EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), TRUE );
  417.             SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("IP Address:") );
  418.         }
  419.     }
  420.     else if( *pGuid == CLSID_DP8SP_MODEM )
  421.     {
  422.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), TRUE );
  423.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, TEXT("") );
  424.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), TRUE );
  425.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("Phone Number:") );
  426.  
  427.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2), FALSE );
  428.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2, TEXT("") );
  429.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2_TEXT), FALSE );
  430.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2_TEXT, TEXT("") );
  431.     }
  432.     else 
  433.     {
  434.         // pGuid is CLSID_DP8SP_IPX or CLSID_DP8SP_SERIAL or unknown 
  435.         // so disable all the address lines 
  436.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1), FALSE );
  437.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE1, TEXT("") );
  438.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE1_TEXT), FALSE );
  439.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE1_TEXT, TEXT("") );
  440.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2), FALSE );
  441.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2, TEXT("") );
  442.         EnableWindow( GetDlgItem(hDlg, IDC_ADDRESS_LINE2_TEXT), FALSE );
  443.         SetDlgItemText( hDlg, IDC_ADDRESS_LINE2_TEXT, TEXT("") );
  444.     }
  445. }
  446.  
  447.  
  448.  
  449.  
  450. //-----------------------------------------------------------------------------
  451. // Name: EnumRegisteredApplications
  452. // Desc: Enum all the lobby launchable apps and put them in the listbox
  453. //-----------------------------------------------------------------------------
  454. HRESULT EnumRegisteredApplications( HWND hDlg )
  455. {
  456.     HRESULT hr;
  457.     DWORD   dwSize     = 0;
  458.     DWORD   dwPrograms = 0;
  459.     DWORD   iProgram;
  460.     BYTE*   pData   = NULL;
  461.  
  462.     hr = g_pLobbyClient->EnumLocalPrograms( NULL, pData, &dwSize, &dwPrograms, 0 );
  463.     if( hr != DPNERR_BUFFERTOOSMALL && FAILED(hr) )
  464.         return DXTRACE_ERR( TEXT("EnumLocalPrograms"), hr );
  465.  
  466.     if( dwSize == 0 )
  467.     {
  468.         MessageBox( NULL, TEXT("There are no applications registered as lobby launchable. ")
  469.                     TEXT("The sample will now quit."),
  470.                     g_strAppName, MB_OK | MB_ICONERROR );
  471.         EndDialog( hDlg, 0 );
  472.         return S_OK;
  473.     }
  474.  
  475.     pData = new BYTE[dwSize];
  476.     if( FAILED( hr = g_pLobbyClient->EnumLocalPrograms( NULL, pData, &dwSize, &dwPrograms, 0 ) ) )
  477.         return DXTRACE_ERR( TEXT("EnumLocalPrograms"), hr );
  478.  
  479.     DPL_APPLICATION_INFO* pAppInfo = (DPL_APPLICATION_INFO*) pData;
  480.     for( iProgram=0; iProgram<dwPrograms; iProgram++ )
  481.     {
  482.         TCHAR strAppName[MAX_PATH];
  483.         DXUtil_ConvertWideStringToGeneric( strAppName, pAppInfo->pwszApplicationName );
  484.  
  485.         // Add the name to the listbox
  486.         int nIndex = (int) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_ADDSTRING, 0, (LPARAM) strAppName );
  487.  
  488.         // Store the guid in the listbox
  489.         GUID* pGuid = new GUID;
  490.         memcpy( pGuid, &pAppInfo->guidApplication, sizeof(GUID) );
  491.         SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_SETITEMDATA, nIndex, (LPARAM) pGuid );
  492.  
  493.         pAppInfo++;
  494.     }
  495.  
  496.     SAFE_DELETE_ARRAY( pData );
  497.  
  498.     SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_SETCURSEL, 0, 0 );
  499.  
  500.     return S_OK;
  501. }
  502.  
  503.  
  504.  
  505.  
  506. //-----------------------------------------------------------------------------
  507. // Name: EnumServiceProviders()
  508. // Desc: Fills the combobox with service providers
  509. //-----------------------------------------------------------------------------
  510. HRESULT EnumServiceProviders( HWND hDlg )
  511. {
  512.     DPN_SERVICE_PROVIDER_INFO* pdnSPInfo = NULL;
  513.     HRESULT hr;
  514.     DWORD   dwItems = 0;
  515.     DWORD   dwSize  = 0;
  516.     int     nIndex;
  517.  
  518.     // Enumerate all DirectPlay service providers, and store them in the listbox
  519.     hr = g_pDP->EnumServiceProviders( NULL, NULL, pdnSPInfo, &dwSize,
  520.                                       &dwItems, 0 );
  521.     if( hr != DPNERR_BUFFERTOOSMALL )
  522.         return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
  523.  
  524.     pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
  525.     if( FAILED( hr = g_pDP->EnumServiceProviders( NULL, NULL, pdnSPInfo,
  526.                                                   &dwSize, &dwItems, 0 ) ) )
  527.         return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
  528.  
  529.     DPN_SERVICE_PROVIDER_INFO* pdnSPInfoEnum = pdnSPInfo;
  530.     for ( DWORD i = 0; i < dwItems; i++ )
  531.     {
  532.         TCHAR strName[MAX_PATH];
  533.         DXUtil_ConvertWideStringToGeneric( strName, pdnSPInfoEnum->pwszName );
  534.  
  535.         // Found a service provider, so put it in the listbox
  536.         nIndex = (int)SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_ADDSTRING, 
  537.                                               0, (LPARAM) strName );
  538.  
  539.         // Store pointer to GUID in listbox
  540.         GUID* pGuid = new GUID;
  541.         memcpy( pGuid, &pdnSPInfoEnum->guid, sizeof(GUID) );
  542.         SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_SETITEMDATA, 
  543.                             nIndex, (LPARAM) pGuid );
  544.  
  545.         pdnSPInfoEnum++;
  546.     }
  547.  
  548.     SAFE_DELETE_ARRAY( pdnSPInfo );
  549.  
  550.     // Try to select the default preferred provider
  551.     nIndex = (int)SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_FINDSTRINGEXACT, (WPARAM)-1,
  552.                                       (LPARAM)g_strPreferredProvider );
  553.     if( nIndex != LB_ERR )
  554.         SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_SETCURSEL, nIndex, 0 );
  555.     else
  556.         SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_SETCURSEL, 0, 0 );
  557.  
  558.     return S_OK;
  559. }
  560.  
  561.  
  562.  
  563.  
  564. //-----------------------------------------------------------------------------
  565. // Name: EnumAdapters()
  566. // Desc: Fills the combobox with adapters for a specified SP
  567. //-----------------------------------------------------------------------------
  568. HRESULT EnumAdapters( HWND hDlg, GUID* pSPGuid )
  569. {
  570.     DPN_SERVICE_PROVIDER_INFO* pdnSPInfo = NULL;
  571.     TCHAR   strName[MAX_PATH];
  572.     HRESULT hr;
  573.     DWORD   dwItems = 0;
  574.     DWORD   dwSize  = 0;
  575.     int     nIndex;
  576.     int     nAllAdaptersIndex = 0;
  577.  
  578.     SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_RESETCONTENT, 0, 0 );
  579.  
  580.     // Enumerate all DirectPlay service providers, and store them in the listbox
  581.     hr = g_pDP->EnumServiceProviders( pSPGuid, NULL, pdnSPInfo, &dwSize,
  582.                                       &dwItems, 0 );
  583.     if( hr != DPNERR_BUFFERTOOSMALL )
  584.         return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
  585.  
  586.     pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
  587.     if( FAILED( hr = g_pDP->EnumServiceProviders( pSPGuid, NULL, pdnSPInfo,
  588.                                                   &dwSize, &dwItems, 0 ) ) )
  589.         return DXTRACE_ERR( TEXT("EnumServiceProviders"), hr );
  590.  
  591.     DPN_SERVICE_PROVIDER_INFO* pdnSPInfoEnum = pdnSPInfo;
  592.     for ( DWORD i = 0; i < dwItems; i++ )
  593.     {
  594.         DXUtil_ConvertWideStringToGeneric( strName, pdnSPInfoEnum->pwszName );
  595.  
  596.         // Found a service provider, so put it in the listbox
  597.         nIndex = (int)SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_ADDSTRING, 
  598.                                           0, (LPARAM) strName );
  599.  
  600.         if( _tcscmp( strName, "All Adapters" ) == 0 )
  601.             nAllAdaptersIndex = nIndex;
  602.  
  603.         // Store pointer to GUID in listbox
  604.         GUID* pGuid = new GUID;
  605.         memcpy( pGuid, &pdnSPInfoEnum->guid, sizeof(GUID) );
  606.  
  607.         SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_SETITEMDATA, 
  608.                             nIndex, (LPARAM) pGuid );
  609.  
  610.         pdnSPInfoEnum++;
  611.     }
  612.  
  613.     SAFE_DELETE_ARRAY( pdnSPInfo );
  614.  
  615.     SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_SETCURSEL, nAllAdaptersIndex, 0 );
  616.  
  617.     return S_OK;
  618. }
  619.  
  620.  
  621.  
  622.  
  623. //-----------------------------------------------------------------------------
  624. // Name: LaunchApp
  625. // Desc: Launch the selected app based on the UI settings
  626. //-----------------------------------------------------------------------------
  627. HRESULT LaunchApp( HWND hDlg )
  628. {
  629.     HRESULT   hr;
  630.     DPNHANDLE hApplication = NULL;
  631.  
  632.     BOOL bLaunchNew      = IsDlgButtonChecked( hDlg, IDC_LAUNCH_NEW );
  633.     BOOL bLaunchNotFound = IsDlgButtonChecked( hDlg, IDC_LAUNCH_NOT_FOUND );
  634.  
  635.     int nAppIndex = (int) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETCURSEL, 0, 0 );
  636.     GUID* pAppGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_APP_LIST, LB_GETITEMDATA, nAppIndex, 0 );
  637.     if( nAppIndex == LB_ERR || pAppGuid == NULL )
  638.         return E_INVALIDARG;
  639.  
  640.     // Setup the DPL_CONNECT_INFO struct
  641.     DPL_CONNECT_INFO dnConnectInfo;
  642.     ZeroMemory( &dnConnectInfo, sizeof(DPL_CONNECT_INFO) );
  643.     dnConnectInfo.dwSize = sizeof(DPL_CONNECT_INFO);
  644.     dnConnectInfo.pvLobbyConnectData = NULL;
  645.     dnConnectInfo.dwLobbyConnectDataSize = 0;
  646.     dnConnectInfo.dwFlags = 0;
  647.     if( bLaunchNew )
  648.         dnConnectInfo.dwFlags |= DPLCONNECT_LAUNCHNEW;
  649.     if( bLaunchNotFound )
  650.         dnConnectInfo.dwFlags |= DPLCONNECT_LAUNCHNOTFOUND;
  651.     dnConnectInfo.guidApplication = *pAppGuid;
  652.     if( FAILED( hr = AllocAndInitConnectSettings( hDlg, pAppGuid, &dnConnectInfo.pdplConnectionSettings ) ) ) 
  653.         return S_FALSE;
  654.  
  655.     hr = g_pLobbyClient->ConnectApplication( &dnConnectInfo, NULL, &hApplication, 
  656.                                              INFINITE, 0 );
  657.     if( FAILED(hr) )
  658.     {
  659.         if( hr == DPNERR_NOCONNECTION && !bLaunchNew && !bLaunchNotFound )
  660.         {
  661.             MessageBox( NULL, TEXT("There was no waiting application. "),
  662.                         g_strAppName, MB_OK | MB_ICONERROR );
  663.         }
  664.         else
  665.         {
  666.             return DXTRACE_ERR( TEXT("ConnectApplication"), hr );
  667.         }
  668.     }
  669.     else
  670.     {
  671.         TCHAR strBuffer[20];
  672.         wsprintf( strBuffer, "0x%x", hApplication );
  673.         int nIndex = (int) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_ADDSTRING, 
  674.                                          0, (LPARAM) strBuffer );
  675.         SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_SETITEMDATA, 
  676.                             nIndex, (LPARAM) hApplication );
  677.  
  678.         if( LB_ERR == SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_GETCURSEL, 0, 0 ) )
  679.             SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_SETCURSEL, 0, 0 );
  680.     }
  681.  
  682.     FreeConnectSettings( dnConnectInfo.pdplConnectionSettings );
  683.  
  684.     return S_OK;
  685. }
  686.  
  687.  
  688.  
  689.  
  690. //-----------------------------------------------------------------------------
  691. // Name: AllocAndInitConnectSettings
  692. // Desc: Alloc and fill up a DPL_CONNECTION_SETTINGS.  Call FreeConnectSettings
  693. //       later to free it.
  694. //-----------------------------------------------------------------------------
  695. HRESULT AllocAndInitConnectSettings( HWND hDlg, GUID* pAppGuid, 
  696.                                      DPL_CONNECTION_SETTINGS** ppdplConnectSettings ) 
  697. {
  698.     HRESULT hr;
  699.  
  700.     BOOL bHosting    = IsDlgButtonChecked( hDlg, IDC_HOST_SESSION );
  701.     BOOL bNoSettings = IsDlgButtonChecked( hDlg, IDC_NO_SETTINGS );
  702.     IDirectPlay8Address* pHostAddress   = NULL;
  703.     IDirectPlay8Address* pDeviceAddress = NULL;
  704.  
  705.     if( bNoSettings )
  706.     {
  707.         *ppdplConnectSettings = NULL;
  708.         return S_OK;
  709.     }
  710.  
  711.     int nSPIndex = (int) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETCURSEL, 0, 0 );
  712.     GUID* pSPGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_SP_COMBO, CB_GETITEMDATA, nSPIndex, 0 );
  713.  
  714.     if( *pSPGuid == CLSID_DP8SP_IPX && !bHosting )
  715.     {
  716.         MessageBox( hDlg, "A typical lobby client would have sent a complete IPX address, this " \
  717.                           "lobby client does not support this. ", g_strAppName, MB_OK );
  718.         return E_NOTIMPL;
  719.     }
  720.  
  721.     if( !bHosting )
  722.     {
  723.         // Create a host address if connecting to a host, 
  724.         // otherwise keep it as NULL
  725.         if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC_SERVER, 
  726.                                            IID_IDirectPlay8Address, (void **) &pHostAddress ) ) )
  727.             return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  728.  
  729.         // Set the SP to pHostAddress
  730.         if( FAILED( hr = pHostAddress->SetSP( pSPGuid ) ) )
  731.             return DXTRACE_ERR( TEXT("SetSP"), hr );
  732.     }
  733.  
  734.     // Create a device address to specify which device we are using 
  735.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC_SERVER, 
  736.                                        IID_IDirectPlay8Address, (void **) &pDeviceAddress ) ) )
  737.         return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
  738.  
  739.     // Set the SP to pDeviceAddress
  740.     if( FAILED( hr = pDeviceAddress->SetSP( pSPGuid ) ) )
  741.         return DXTRACE_ERR( TEXT("SetSP"), hr );
  742.  
  743.     // Add the adapter to pHostAddress
  744.     int nAdapterIndex = (int) SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETCURSEL, 0, 0 );
  745.     GUID* pAdapterGuid = (GUID*) SendDlgItemMessage( hDlg, IDC_ADAPTER_COMBO, CB_GETITEMDATA, 
  746.                                                      nAdapterIndex, 0 );
  747.     if( FAILED( hr = pDeviceAddress->SetDevice( pAdapterGuid ) ) )
  748.         return DXTRACE_ERR( TEXT("SetDevice"), hr );
  749.  
  750.     if( *pSPGuid == CLSID_DP8SP_TCPIP )
  751.     {
  752.         TCHAR strIP[MAX_PATH];
  753.         TCHAR strPort[MAX_PATH];
  754.  
  755.         GetDlgItemText( hDlg, IDC_ADDRESS_LINE1, strIP, MAX_PATH );
  756.         GetDlgItemText( hDlg, IDC_ADDRESS_LINE2, strPort, MAX_PATH );
  757.  
  758.         if( bHosting )
  759.         {
  760.             // Add the port to pDeviceAddress
  761.             DWORD dwPort = atoi( strPort );
  762.             if( FAILED( hr = pDeviceAddress->AddComponent( DPNA_KEY_PORT, 
  763.                                                            &dwPort, sizeof(dwPort),
  764.                                                            DPNA_DATATYPE_DWORD ) ) )
  765.                 return DXTRACE_ERR( TEXT("AddComponent"), hr );
  766.         }
  767.         else
  768.         {
  769.             // Add the IP address to pHostAddress
  770.             if( _tcslen( strIP ) > 0 )
  771.             {
  772.                 WCHAR wstrIP[MAX_PATH];
  773.                 DXUtil_ConvertGenericStringToWide( wstrIP, strIP );
  774.  
  775.                 if( FAILED( hr = pHostAddress->AddComponent( DPNA_KEY_HOSTNAME, 
  776.                                                              wstrIP, (wcslen(wstrIP)+1)*sizeof(WCHAR), 
  777.                                                              DPNA_DATATYPE_STRING ) ) )
  778.                     return DXTRACE_ERR( TEXT("AddComponent"), hr );
  779.             }
  780.  
  781.             // Add the port to pHostAddress
  782.             DWORD dwPort = atoi( strPort );
  783.             if( FAILED( hr = pHostAddress->AddComponent( DPNA_KEY_PORT, 
  784.                                                          &dwPort, sizeof(dwPort),
  785.                                                          DPNA_DATATYPE_DWORD ) ) )
  786.                 return DXTRACE_ERR( TEXT("AddComponent"), hr );
  787.         }
  788.     }
  789.     else if( *pSPGuid == CLSID_DP8SP_MODEM )
  790.     {
  791.         TCHAR strPhone[MAX_PATH];
  792.         GetDlgItemText( hDlg, IDC_ADDRESS_LINE1, strPhone, MAX_PATH );
  793.  
  794.         if( !bHosting )
  795.         {
  796.             // Add the phonenumber to pHostAddress
  797.             if( _tcslen( strPhone ) > 0 )
  798.             {
  799.                 WCHAR wstrPhone[MAX_PATH];
  800.                 DXUtil_ConvertGenericStringToWide( wstrPhone, strPhone );
  801.  
  802.                 if( FAILED( hr = pHostAddress->AddComponent( DPNA_KEY_PHONENUMBER, 
  803.                                                              wstrPhone, (wcslen(wstrPhone)+1)*sizeof(WCHAR), 
  804.                                                              DPNA_DATATYPE_STRING ) ) )
  805.                     return DXTRACE_ERR( TEXT("AddComponent"), hr );
  806.             }
  807.         }
  808.     }
  809.     else if( *pSPGuid == CLSID_DP8SP_SERIAL )
  810.     {
  811.         // This simple client doesn't have UI to query for the various
  812.         // fields needed for the serial.  So we just let DPlay popup a dialog
  813.         // to ask the user which settings are needed.
  814.     }
  815.     else
  816.     {
  817.         // Unknown SP, so leave as is
  818.     }
  819.  
  820.     // Setup the DPL_CONNECTION_SETTINGS
  821.     DPL_CONNECTION_SETTINGS* pSettings = new DPL_CONNECTION_SETTINGS;
  822.     ZeroMemory( pSettings, sizeof(DPL_CONNECTION_SETTINGS) );
  823.     pSettings->dwSize = sizeof(DPL_CONNECTION_SETTINGS);
  824.     pSettings->dpnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  825.     pSettings->dwFlags = 0;
  826.     if( bHosting )
  827.         pSettings->dwFlags |= DPLCONNECTSETTINGS_HOST;
  828.     pSettings->dpnAppDesc.guidApplication = *pAppGuid;
  829.     pSettings->dpnAppDesc.guidInstance    = GUID_NULL;
  830.     pSettings->pdp8HostAddress = pHostAddress;
  831.     pSettings->ppdp8DeviceAddresses = new IDirectPlay8Address*;
  832.     pSettings->ppdp8DeviceAddresses[0] = pDeviceAddress;
  833.     pSettings->cNumDeviceAddresses = 1;
  834.  
  835.     // Set the pSettings->dpnAppDesc.pwszSessionName
  836.     TCHAR strSessionName[MAX_PATH];
  837.     GetDlgItemText( hDlg, IDC_SESSION_NAME, strSessionName, MAX_PATH );
  838.     if( _tcslen( strSessionName ) == 0 )
  839.     {
  840.         pSettings->dpnAppDesc.pwszSessionName = NULL;
  841.     }
  842.     else
  843.     {
  844.         WCHAR wstrSessionName[MAX_PATH];
  845.         DXUtil_ConvertGenericStringToWide( wstrSessionName, strSessionName );
  846.         pSettings->dpnAppDesc.pwszSessionName = new WCHAR[wcslen(wstrSessionName)+1];
  847.         wcscpy( pSettings->dpnAppDesc.pwszSessionName, wstrSessionName );
  848.     }
  849.  
  850.     // Set the pSettings->pwszPlayerName
  851.     TCHAR strPlayerName[MAX_PATH];
  852.     GetDlgItemText( hDlg, IDC_PLAYER_NAME, strPlayerName, MAX_PATH );
  853.     if( _tcslen( strPlayerName ) == 0 )
  854.     {
  855.         pSettings->pwszPlayerName = NULL;
  856.     }
  857.     else
  858.     {
  859.         WCHAR wstrPlayerName[MAX_PATH];
  860.         DXUtil_ConvertGenericStringToWide( wstrPlayerName, strPlayerName );
  861.         pSettings->pwszPlayerName = new WCHAR[wcslen(wstrPlayerName)+1];
  862.         wcscpy( pSettings->pwszPlayerName, wstrPlayerName );
  863.     }
  864.  
  865.     *ppdplConnectSettings = pSettings;
  866.  
  867.     return S_OK;
  868. }
  869.  
  870.  
  871.  
  872.  
  873. //-----------------------------------------------------------------------------
  874. // Name: FreeConnectSettings
  875. // Desc: Releases everything involved in a DPL_CONNECTION_SETTINGS struct
  876. //-----------------------------------------------------------------------------
  877. VOID FreeConnectSettings( DPL_CONNECTION_SETTINGS* pSettings )
  878. {
  879.     if( !pSettings )
  880.         return;
  881.  
  882.     SAFE_DELETE_ARRAY( pSettings->pwszPlayerName ); 
  883.     SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pwszSessionName );
  884.     SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pwszPassword );
  885.     SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pvReservedData );
  886.     SAFE_DELETE_ARRAY( pSettings->dpnAppDesc.pvApplicationReservedData );
  887.     SAFE_RELEASE( pSettings->pdp8HostAddress );
  888.     SAFE_RELEASE( pSettings->ppdp8DeviceAddresses[0] );
  889.     SAFE_DELETE_ARRAY( pSettings->ppdp8DeviceAddresses );
  890.     SAFE_DELETE( pSettings );
  891. }
  892.  
  893.  
  894.  
  895.  
  896. //-----------------------------------------------------------------------------
  897. // Name: DirectPlayMessageHandler
  898. // Desc: Handler for DirectPlay messages.  This function is called by
  899. //       the DirectPlay message handler pool of threads, so be care of thread
  900. //       synchronization problems with shared memory
  901. //-----------------------------------------------------------------------------
  902. HRESULT WINAPI DirectPlayMessageHandler( PVOID pvUserContext, 
  903.                                          DWORD dwMessageId, 
  904.                                          PVOID pMsgBuffer )
  905. {
  906.     return S_OK;
  907. }
  908.  
  909.  
  910.  
  911.  
  912. //-----------------------------------------------------------------------------
  913. // Name: DirectPlayLobbyMessageHandler
  914. // Desc: Handler for DirectPlay lobby messages.  This function is called by
  915. //       the DirectPlay lobby message handler pool of threads, so be careful of 
  916. //       thread synchronization problems with shared memory
  917. //-----------------------------------------------------------------------------
  918. HRESULT WINAPI DirectPlayLobbyMessageHandler( PVOID pvUserContext, 
  919.                                               DWORD dwMessageId, 
  920.                                               PVOID pMsgBuffer )
  921. {
  922.     switch( dwMessageId )
  923.     {
  924.         case DPL_MSGID_DISCONNECT:
  925.         {
  926.             PDPL_MESSAGE_DISCONNECT pDisconnectMsg;
  927.             pDisconnectMsg = (PDPL_MESSAGE_DISCONNECT)pMsgBuffer;
  928.  
  929.             // We should free any data associated with the 
  930.             // app here, but there is none.
  931.  
  932.             // Tell the update the UI so show that a application was disconnected
  933.             // Note: The lobby handler must not become blocked on the dialog thread, 
  934.             // since the dialog thread will be blocked on lobby handler thread
  935.             // when it calls ConnectApplication().  So to avoid blocking on
  936.             // the dialog thread, we'll post a message to the dialog thread.
  937.             PostMessage( g_hDlg, WM_APP_APPDISCONNECTED, 0, pDisconnectMsg->hDisconnectId );            
  938.             break;
  939.         }
  940.  
  941.         case DPL_MSGID_RECEIVE:
  942.         {
  943.             PDPL_MESSAGE_RECEIVE pReceiveMsg;
  944.             pReceiveMsg = (PDPL_MESSAGE_RECEIVE)pMsgBuffer;
  945.  
  946.             // The lobby app sent us data.  This sample doesn't
  947.             // expected data from the app, but it is useful 
  948.             // for more complex lclients.
  949.             break;
  950.         }
  951.  
  952.         case DPL_MSGID_SESSION_STATUS:
  953.         {
  954.             PDPL_MESSAGE_SESSION_STATUS pStatusMsg;
  955.             pStatusMsg = (PDPL_MESSAGE_SESSION_STATUS)pMsgBuffer;
  956.  
  957.             TCHAR* strBuffer = new TCHAR[200];
  958.             wsprintf( strBuffer, "0x%x: ", pStatusMsg->hSender );
  959.             switch( pStatusMsg->dwStatus )
  960.             {
  961.                 case DPLSESSION_CONNECTED:
  962.                     _tcscat( strBuffer, TEXT("Session connected") ); break;
  963.                 case DPLSESSION_COULDNOTCONNECT:
  964.                     _tcscat( strBuffer, TEXT("Session could not connect") ); break;
  965.                 case DPLSESSION_DISCONNECTED:
  966.                     _tcscat( strBuffer, TEXT("Session disconnected") ); break;
  967.                 case DPLSESSION_TERMINATED:
  968.                     _tcscat( strBuffer, TEXT("Session terminated") ); break;
  969.                 case DPLSESSION_HOSTMIGRATED:
  970.                     _tcscat( strBuffer, TEXT("Host migrated") ); break;
  971.                 case DPLSESSION_HOSTMIGRATEDHERE:
  972.                     _tcscat( strBuffer, TEXT("Host migrated to this client") ); break;
  973.  
  974.                 default:
  975.                 {
  976.                     TCHAR strStatus[30];
  977.                     wsprintf( strStatus, TEXT("%d"), pStatusMsg->dwStatus );
  978.                     _tcscat( strBuffer, strStatus );
  979.                     break;
  980.                 }
  981.             }
  982.  
  983.             // Tell the update the UI so show that a application status changed
  984.             // Note: The lobby handler must not become blocked on the dialog thread, 
  985.             // since the dialog thread will be blocked on lobby handler thread
  986.             // when it calls ConnectApplication().  So to avoid blocking on
  987.             // the dialog thread, we'll post a message to the dialog thread.
  988.             PostMessage( g_hDlg, WM_APP_SETSTATUS, 0, (LPARAM) strBuffer );            
  989.             break;
  990.         }
  991.  
  992.         case DPL_MSGID_CONNECTION_SETTINGS:
  993.         {
  994.             PDPL_MESSAGE_CONNECTION_SETTINGS pConnectionStatusMsg;
  995.             pConnectionStatusMsg = (PDPL_MESSAGE_CONNECTION_SETTINGS)pMsgBuffer;
  996.  
  997.             // The app has changed the connection settings.  
  998.             // This simple client doesn't handle this, but more complex clients may
  999.             // want to.
  1000.             break;
  1001.         }
  1002.     }
  1003.  
  1004.     return S_OK;
  1005. }
  1006.  
  1007.  
  1008.  
  1009.  
  1010. //-----------------------------------------------------------------------------
  1011. // Name: SendMsgToApp
  1012. // Desc: Send a dummy message to a connected app for demo purposes 
  1013. //-----------------------------------------------------------------------------
  1014. HRESULT SendMsgToApp( HWND hDlg )
  1015. {
  1016.     TCHAR strBuffer[MAX_PATH];
  1017.     HRESULT hr;
  1018.  
  1019.     int nConnectIndex = (int) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_GETCURSEL, 0, 0 );
  1020.     if( nConnectIndex == LB_ERR )
  1021.         return S_OK;
  1022.  
  1023.     DPNHANDLE hApplication = (DPNHANDLE) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, 
  1024.                                                              LB_GETITEMDATA, nConnectIndex, 0 );
  1025.  
  1026.     // For demonstration purposes, just send a buffer to the app.  This can be used
  1027.     // by more complex lobby clients to pass custom information to apps that which
  1028.     // can then recieve and process it.
  1029.     BYTE buffer[20];
  1030.     memset( buffer, 0x03, 20 );
  1031.     if( FAILED( hr = g_pLobbyClient->Send( hApplication, buffer, 20, 0 ) ) )
  1032.     {
  1033.         DXTRACE_ERR( TEXT("Send"), hr );
  1034.         wsprintf( strBuffer, TEXT("Failure trying to send message to 0x%0.8x."), hApplication );
  1035.         MessageBox( NULL, strBuffer, g_strAppName, MB_OK | MB_ICONERROR );
  1036.     }
  1037.     else
  1038.     {
  1039.         wsprintf( strBuffer, TEXT("Successfully sent a message to 0x%0.8x."), hApplication );
  1040.         MessageBox( NULL, strBuffer, g_strAppName, MB_OK | MB_ICONERROR );
  1041.     }
  1042.  
  1043.     return S_OK;
  1044. }
  1045.  
  1046.  
  1047.  
  1048.  
  1049. //-----------------------------------------------------------------------------
  1050. // Name: DisconnectFromApp
  1051. // Desc: Disconnect from an app
  1052. //-----------------------------------------------------------------------------
  1053. HRESULT DisconnectFromApp( HWND hDlg )
  1054. {
  1055.     HRESULT hr;
  1056.  
  1057.     int nConnectIndex = (int) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_GETCURSEL, 0, 0 );
  1058.     if( nConnectIndex == LB_ERR )
  1059.         return S_OK;
  1060.  
  1061.     DPNHANDLE hApplication = (DPNHANDLE) SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, 
  1062.                                                              LB_GETITEMDATA, nConnectIndex, 0 );
  1063.  
  1064.     if( FAILED( hr = g_pLobbyClient->ReleaseApplication( hApplication, 0 ) ) )
  1065.     {
  1066.         DXTRACE_ERR( TEXT("LaunchApp"), hr );
  1067.         MessageBox( NULL, TEXT("Failure trying to disconnect from app. "), 
  1068.                     g_strAppName, MB_OK | MB_ICONERROR );
  1069.     }
  1070.  
  1071.     SendDlgItemMessage( hDlg, IDC_ACTIVE_CONNECTIONS, LB_DELETESTRING, nConnectIndex, 0 );
  1072.  
  1073.     return S_OK;
  1074. }
  1075.  
  1076.