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

  1. //-----------------------------------------------------------------------------
  2. // File: DPConnect.cpp
  3. //
  4. // Desc: Support file to prompt the user for the DirectPlay connection 
  5. //       and the DirectPlay session they want to join or create. 
  6. //
  7. //       Call DPConnect_StartDirectPlayConnect() to start the series of 
  8. //       dialogs boxes.  At the end the player will be connected to an active
  9. //       DirectPlay session that the user either created or joined.  Or the 
  10. //       function may also return an EXITCODE as defined below in the event
  11. //       of error or user cancel.  
  12. //
  13. // Copyright (c) 1999 Microsoft Corp. All rights reserved.
  14. //-----------------------------------------------------------------------------
  15. #define IDIRECTPLAY2_OR_GREATER
  16. #include <windows.h>
  17. #include <basetsd.h>
  18. #include <dplobby.h>
  19. #include <dplay.h>
  20. #include <stdio.h>
  21. #include "resource.h"
  22.  
  23.  
  24.  
  25.  
  26. //-----------------------------------------------------------------------------
  27. // Defines, and constants
  28. //-----------------------------------------------------------------------------
  29. #define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
  30. #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
  31. #define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
  32.  
  33. #define MAX_PLAYER_NAME      14
  34. #define MAX_SESSION_NAME     256
  35.  
  36. struct DPSessionInfo
  37. {
  38.     GUID guidSession;
  39.     TCHAR szSession[MAX_SESSION_NAME];
  40.     DPSessionInfo* pDPSINext;
  41. };
  42.  
  43.  
  44.  
  45.  
  46. //-----------------------------------------------------------------------------
  47. // Global variables
  48. //-----------------------------------------------------------------------------
  49. #define EXITCODE_FORWARD      1  // Dialog success, so go forward
  50. #define EXITCODE_BACKUP       2  // Dialog canceled, show previous dialog
  51. #define EXITCODE_QUIT         3  // Dialog quit, close app
  52. #define EXITCODE_ERROR        4  // Dialog error, terminate app
  53. #define EXITCODE_LOBBYCONNECT 5  // Dialog connected from lobby, connect success
  54.  
  55. extern LPDIRECTPLAY4A       g_pDP;
  56. extern LPDPLCONNECTION      g_pDPLConnection;
  57. extern LPDIRECTPLAYLOBBY3   g_pDPLobby;
  58. extern GUID                 g_AppGUID; 
  59. extern HANDLE               g_hDPMessageEvent;
  60. extern TCHAR                g_strPreferredProvider[MAX_SESSION_NAME];
  61. extern TCHAR                g_strSessionName[MAX_SESSION_NAME];
  62. extern TCHAR                g_strLocalPlayerName[MAX_PLAYER_NAME];
  63. extern DPID                 g_LocalPlayerDPID; 
  64. extern BOOL                 g_bHostPlayer;
  65. extern TCHAR                g_strAppName[256];
  66. extern BOOL                 g_bUseProtocol;
  67.  
  68. DPSessionInfo               g_DPSIHead;
  69. BOOL                        g_bSearchingForSessions;
  70. BOOL                        g_bWaitForConnectionSettings;
  71.  
  72.  
  73.  
  74.  
  75. //-----------------------------------------------------------------------------
  76. // Function-prototypes
  77. //-----------------------------------------------------------------------------
  78. int             DPConnect_StartDirectPlayConnect( HINSTANCE hInst, BOOL bBackTrack );
  79.  
  80. INT_PTR CALLBACK DPConnect_ConnectionsDlgProc( HWND, UINT, WPARAM, LPARAM );
  81. BOOL FAR PASCAL DPConnect_EnumConnectionsCallback( LPCGUID, VOID*, DWORD, LPCDPNAME, DWORD, VOID* );
  82. HRESULT         DPConnect_ConnectionsDlgFillListBox( HWND hDlg );
  83. HRESULT         DPConnect_ConnectionsDlgOnOK( HWND hDlg );
  84. VOID            DPConnect_ConnectionsDlgCleanup( HWND hDlg );
  85.  
  86. INT_PTR CALLBACK DPConnect_SessionsDlgProc( HWND, UINT, WPARAM, LPARAM );
  87. INT_PTR CALLBACK DPConnect_CreateSessionDlgProc( HWND, UINT, WPARAM, LPARAM );
  88. BOOL FAR PASCAL DPConnect_EnumSessionsCallback( LPCDPSESSIONDESC2, DWORD*, DWORD, VOID* );
  89. VOID            DPConnect_SessionsDlgInitListbox( HWND hDlg );
  90. HRESULT         DPConnect_SessionsDlgShowGames( HWND hDlg );
  91. HRESULT         DPConnect_SessionsDlgJoinGame( HWND hDlg );
  92. HRESULT         DPConnect_SessionsDlgCreateGame( HWND hDlg );
  93. VOID            DPConnect_SessionsDlgCleanup();
  94.  
  95. INT_PTR CALLBACK DPConnect_LobbyWaitDlgProc( HWND, UINT, WPARAM, LPARAM );
  96. HRESULT         DPConnect_CheckForLobbyLaunch( BOOL* pbLaunchedByLobby );
  97. HRESULT         DPConnect_DoLobbyLaunch();
  98. HRESULT         DPConnect_WaitForLobbyLaunch( HWND hParentDlg );
  99. HRESULT         DPConnect_GetLobbyConnectionSettingsMessage();
  100.  
  101.  
  102.  
  103.  
  104. //-----------------------------------------------------------------------------
  105. // Name: DPConnect_StartDirectPlayConnect()
  106. // Desc: Prompts the user for the DirectPlay connection and the DirectPlay 
  107. //       session they want to join or create.  This function returns one
  108. //       of the EXITCODEs as #defined above
  109. //-----------------------------------------------------------------------------
  110. int DPConnect_StartDirectPlayConnect( HINSTANCE hInst, BOOL bBackTrack = FALSE )
  111. {
  112.     int nExitCode;
  113.     int nStep;
  114.  
  115.     // Setup the g_DPSIHead circular linked list
  116.     ZeroMemory( &g_DPSIHead, sizeof( DPSessionInfo ) );
  117.     g_DPSIHead.pDPSINext = &g_DPSIHead;
  118.     
  119.     // If the back track flag is true, then the user has already been through
  120.     // the connect process once, and has back tracked out of the main 'game' 
  121.     // so we need start at the last dialog box
  122.     if( bBackTrack )
  123.         nStep = 1;
  124.     else
  125.         nStep = 0;
  126.  
  127.     // Show the dialog boxes to connect
  128.     while( TRUE )
  129.     {
  130.         switch( nStep )
  131.         {
  132.             case 0:
  133.                 // Display the multiplayer connect dialog box.
  134.                 nExitCode = (int)DialogBox( hInst, MAKEINTRESOURCE(IDD_MULTIPLAYER_CONNECT), 
  135.                                             NULL, (DLGPROC)DPConnect_ConnectionsDlgProc );
  136.                 break;
  137.  
  138.             case 1:
  139.                 // Display the multiplayer games dialog box.
  140.                 nExitCode = (int)DialogBox( hInst, MAKEINTRESOURCE(IDD_MULTIPLAYER_GAMES), 
  141.                                             NULL, (DLGPROC)DPConnect_SessionsDlgProc );
  142.                 break;
  143.         }
  144.  
  145.         if( nExitCode == EXITCODE_ERROR || 
  146.             nExitCode == EXITCODE_QUIT )
  147.             return nExitCode;
  148.  
  149.         if( nExitCode == EXITCODE_BACKUP )
  150.             nStep--;
  151.         else
  152.             nStep++;
  153.  
  154.         if( nExitCode == EXITCODE_LOBBYCONNECT )
  155.             return EXITCODE_LOBBYCONNECT;
  156.  
  157.         if( nStep == 2 )
  158.             break;
  159.     }
  160.  
  161.     return EXITCODE_FORWARD;
  162. }
  163.  
  164.  
  165.  
  166.  
  167. //-----------------------------------------------------------------------------
  168. // Name: DPConnect_ConnectionsDlgProc()
  169. // Desc: Handles messages for the multiplayer connect dialog
  170. //-----------------------------------------------------------------------------
  171. INT_PTR CALLBACK DPConnect_ConnectionsDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  172. {
  173.     HRESULT hr;
  174.  
  175.     switch( msg )
  176.     {
  177.         case WM_INITDIALOG:
  178.             {
  179.                 SetDlgItemText( hDlg, IDC_PLAYER_NAME_EDIT, g_strLocalPlayerName );
  180.  
  181.                 // Load and set the icon
  182. #ifdef _WIN64
  183.                 HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  184. #else
  185.                 HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  186. #endif
  187.                 HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN ) );
  188.                 SendMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  189.                 SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  190.  
  191.                 // Set the window title
  192.                 TCHAR strWindowTitle[256];
  193.                 sprintf( strWindowTitle, "%s - Multiplayer Connect", g_strAppName );
  194.                 SetWindowText( hDlg, strWindowTitle );
  195.  
  196.                 if( FAILED( hr = DPConnect_ConnectionsDlgFillListBox( hDlg ) ) )
  197.                     EndDialog( hDlg, EXITCODE_ERROR );
  198.             }
  199.             break;
  200.  
  201.         case WM_COMMAND:
  202.             switch( LOWORD(wParam) )
  203.             {
  204.                 case IDC_CONNECTION_LIST:
  205.                     if( HIWORD(wParam) != LBN_DBLCLK )
  206.                         break;
  207.                     // Fall through
  208.  
  209.                 case IDOK:
  210.                     if( FAILED( hr = DPConnect_ConnectionsDlgOnOK( hDlg ) ) )
  211.                         EndDialog( hDlg, EXITCODE_ERROR );
  212.  
  213.                     break;
  214.  
  215.                 case IDCANCEL:
  216.                     EndDialog( hDlg, EXITCODE_QUIT );
  217.                     break;
  218.  
  219.                 default:
  220.                     return FALSE; // Message not handled
  221.             }
  222.             break;
  223.         
  224.         case WM_DESTROY:
  225.             DPConnect_ConnectionsDlgCleanup( hDlg );
  226.             break;
  227.  
  228.         default:
  229.             return FALSE; // Message not handled
  230.     }
  231.  
  232.     // Message was handled
  233.     return TRUE; 
  234. }
  235.  
  236.  
  237.  
  238.  
  239. //-----------------------------------------------------------------------------
  240. // Name: DPConnect_ConnectionsDlgFillListBox()
  241. // Desc: Fills the DirectPlay connection listbox, and also adds
  242. //       a "Wait for Lobby" connection option.
  243. //-----------------------------------------------------------------------------
  244. HRESULT DPConnect_ConnectionsDlgFillListBox( HWND hDlg )
  245. {
  246.     HRESULT       hr;
  247.     HWND          hWndListBox = GetDlgItem( hDlg, IDC_CONNECTION_LIST );
  248.     LPDIRECTPLAY4 pDP = NULL;
  249.     int           nIndex;
  250.  
  251.     // Create a IDirectPlay object
  252.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_ALL, 
  253.                                        IID_IDirectPlay4A, (VOID**)&pDP ) ) )
  254.     {
  255.         if( hr == E_NOINTERFACE )
  256.         {
  257.             MessageBox( NULL, TEXT("This application requires DirectPlay 6 or later. "
  258.                         "The sample will now quit."),
  259.                         TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  260.         }
  261.  
  262.         return hr;
  263.     }
  264.  
  265.     // Enumerate all DirectPlay connections, and store them in the listbox
  266.     if( FAILED( hr = pDP->EnumConnections( &g_AppGUID, DPConnect_EnumConnectionsCallback, 
  267.                                            hWndListBox, 0 ) ) )
  268.     {
  269.         SAFE_RELEASE( pDP );
  270.         return hr;
  271.     }
  272.  
  273.     SAFE_RELEASE( pDP );
  274.     
  275.     // Add "Wait for Lobby Connection" selection in list box
  276.     SendMessage( hWndListBox, LB_ADDSTRING, 0, 
  277.                  (LPARAM)"Wait for Lobby Connection" );
  278.  
  279.     SetFocus( hWndListBox );
  280.     nIndex = (int)SendMessage( hWndListBox, LB_FINDSTRINGEXACT, -1, 
  281.                                (LPARAM)g_strPreferredProvider );
  282.     if( nIndex != LB_ERR ) 
  283.         SendMessage( hWndListBox, LB_SETCURSEL, nIndex, 0 );
  284.     else
  285.         SendMessage( hWndListBox, LB_SETCURSEL, 0, 0 );
  286.  
  287.     return S_OK;
  288. }
  289.  
  290.  
  291.  
  292.  
  293. //-----------------------------------------------------------------------------
  294. // Name: DPConnect_EnumConnectionsCallback()
  295. // Desc: Enumerates through all DirectPlay connections types, 
  296. //       and stores them in the listbox
  297. //-----------------------------------------------------------------------------
  298. BOOL FAR PASCAL DPConnect_EnumConnectionsCallback( LPCGUID   pguidSP, 
  299.                                                    VOID*     pConnection, 
  300.                                                    DWORD     dwConnectionSize, 
  301.                                                    LPCDPNAME pName, 
  302.                                                    DWORD     dwFlags, 
  303.                                                    VOID*     pvContext )
  304. {
  305.     HRESULT       hr;
  306.     LPDIRECTPLAY4 pDP = NULL;
  307.     VOID*         pConnectionBuffer = NULL;
  308.     HWND          hWndListBox = (HWND)pvContext;
  309.     LRESULT       iIndex;
  310.  
  311.     // Create a IDirectPlay object
  312.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_ALL, 
  313.                                        IID_IDirectPlay4A, (VOID**)&pDP ) ) )
  314.         return FALSE; // Error, stop enumerating
  315.     
  316.     // Test the if the connection is available by attempting to initialize 
  317.     // the connection
  318.     if( FAILED( hr = pDP->InitializeConnection( pConnection, 0 ) ) )
  319.     {
  320.         SAFE_RELEASE( pDP );
  321.         return TRUE; // Unavailable connection, keep enumerating
  322.     }
  323.  
  324.     // Don't need the IDirectPlay interface anymore, so release it
  325.     SAFE_RELEASE( pDP ); 
  326.     
  327.     // Found a good connection, so put it in the listbox
  328.     iIndex = SendMessage( hWndListBox, LB_ADDSTRING, 0, 
  329.                           (LPARAM)pName->lpszShortNameA );
  330.     if( iIndex == CB_ERR )
  331.         return FALSE; // Error, stop enumerating
  332.  
  333.     pConnectionBuffer = new BYTE[ dwConnectionSize ];
  334.     if( pConnectionBuffer == NULL )
  335.         return FALSE; // Error, stop enumerating
  336.  
  337.     // Store pointer to GUID in listbox
  338.     memcpy( pConnectionBuffer, pConnection, dwConnectionSize );
  339.     SendMessage( hWndListBox, LB_SETITEMDATA, iIndex, 
  340.                  (LPARAM)pConnectionBuffer );
  341.  
  342.     return TRUE; // Keep enumerating
  343. }
  344.  
  345.  
  346.  
  347.  
  348. //-----------------------------------------------------------------------------
  349. // Name: DPConnect_ConnectionsDlgOnOK()
  350. // Desc: Stores the player name g_strPlayerName, and in creates a IDirectPlay
  351. //       object based on the connection type the user selected. 
  352. //-----------------------------------------------------------------------------
  353. HRESULT DPConnect_ConnectionsDlgOnOK( HWND hDlg )
  354. {
  355.     VOID*   pConnection = NULL;
  356.     LRESULT iIndex;
  357.     HRESULT hr;
  358.  
  359.     GetDlgItemText( hDlg, IDC_PLAYER_NAME_EDIT, g_strLocalPlayerName, 
  360.                     MAX_PLAYER_NAME );
  361.  
  362.     if( strlen( g_strLocalPlayerName ) == 0 )
  363.     {
  364.         MessageBox( hDlg, TEXT("You must enter a valid player name."),
  365.                     TEXT("DirectPlay Sample"), MB_OK );
  366.         return S_OK;
  367.     }
  368.  
  369.     HWND hWndListBox = GetDlgItem( hDlg, IDC_CONNECTION_LIST );
  370.  
  371.     iIndex = SendMessage( hWndListBox, LB_GETCURSEL, 0, 0 );
  372.     SendMessage( hWndListBox, LB_GETTEXT, iIndex, (LPARAM)g_strPreferredProvider );
  373.  
  374.     pConnection = (VOID*) SendMessage( hWndListBox, LB_GETITEMDATA, iIndex, 0 );
  375.     if( NULL == pConnection )
  376.     {
  377.         if( FAILED( hr = DPConnect_WaitForLobbyLaunch( hDlg ) ) )
  378.         {
  379.             if( hr == DPERR_USERCANCEL )
  380.                 return S_OK;
  381.  
  382.             return hr;
  383.         }
  384.  
  385.         EndDialog( hDlg, EXITCODE_LOBBYCONNECT );
  386.         return S_OK;
  387.     }
  388.  
  389.     // Release previously selected DirectPlay object, if any.
  390.     SAFE_RELEASE( g_pDP );
  391.  
  392.     // Create the DirectPlay object
  393.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_ALL, 
  394.                                        IID_IDirectPlay4A, (VOID**)&g_pDP ) ) )
  395.         return hr;
  396.     
  397.     // Initialize the connection based on the selected connection type
  398.     if( FAILED( hr = g_pDP->InitializeConnection( pConnection, 0 ) ) )
  399.         return hr;
  400.  
  401.     EndDialog( hDlg, EXITCODE_FORWARD );
  402.  
  403.     return S_OK;
  404. }
  405.  
  406.  
  407.  
  408.  
  409. //-----------------------------------------------------------------------------
  410. // Name: DPConnect_ConnectionsDlgCleanup()
  411. // Desc: Deletes the connection buffers from the listbox
  412. //-----------------------------------------------------------------------------
  413. VOID DPConnect_ConnectionsDlgCleanup( HWND hDlg )
  414. {
  415.     VOID*   pConnectionBuffer = NULL;
  416.     DWORD   iIndex;
  417.     DWORD   dwCount;
  418.  
  419.     HWND hWndListBox = GetDlgItem( hDlg, IDC_CONNECTION_LIST );
  420.  
  421.     dwCount = (DWORD)SendMessage( hWndListBox, LB_GETCOUNT, 0, 0 );
  422.     for( iIndex = 0; iIndex < dwCount; iIndex++ )
  423.     {
  424.         pConnectionBuffer = (VOID*) SendMessage( hWndListBox, LB_GETITEMDATA, 
  425.                                                  iIndex, 0 );
  426.         SAFE_DELETE_ARRAY( pConnectionBuffer );
  427.     }
  428. }
  429.  
  430.  
  431.  
  432.  
  433. //-----------------------------------------------------------------------------
  434. // Name: DPConnect_SessionsDlgProc()
  435. // Desc: Handles messages fro the multiplayer games dialog
  436. //-----------------------------------------------------------------------------
  437. INT_PTR CALLBACK DPConnect_SessionsDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  438. {
  439.     HRESULT hr;
  440.  
  441.     switch( msg )
  442.     {
  443.         case WM_INITDIALOG:
  444.             {
  445.                 // Load and set the icon
  446. #ifdef _WIN64
  447.                 HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  448. #else
  449.                 HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  450. #endif
  451.                 HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN ) );
  452.                 SendMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  453.                 SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  454.  
  455.                 // Set the window title
  456.                 TCHAR strWindowTitle[256];
  457.                 sprintf( strWindowTitle, "%s - Multiplayer Games", g_strAppName );
  458.                 SetWindowText( hDlg, strWindowTitle );
  459.  
  460.                 g_bSearchingForSessions = FALSE;
  461.                 SetDlgItemText( hDlg, IDC_SEARCH_CHECK, "Start Search" );
  462.                 DPConnect_SessionsDlgInitListbox( hDlg );
  463.             }
  464.             break;
  465.  
  466.         case WM_TIMER:
  467.             if( FAILED( hr = DPConnect_SessionsDlgShowGames( hDlg ) ) )
  468.             {
  469.                 KillTimer( hDlg, 1 );
  470.                 MessageBox( hDlg, TEXT("Error enumerating DirectPlay games."),
  471.                             TEXT("DirectPlay Sample"), 
  472.                             MB_OK | MB_ICONERROR );
  473.             }
  474.             break;
  475.  
  476.         case WM_COMMAND:
  477.             switch( LOWORD(wParam) )
  478.             {
  479.                 case IDC_SEARCH_CHECK:
  480.                     g_bSearchingForSessions = !g_bSearchingForSessions;
  481.  
  482.                     if( g_bSearchingForSessions )
  483.                     {
  484.                         // Start the timer, and start the async enumeratation
  485.                         SetDlgItemText( hDlg, IDC_SEARCH_CHECK, "Searching..." );
  486.                         SetTimer( hDlg, 1, 250, NULL );
  487.                         if( FAILED( hr = DPConnect_SessionsDlgShowGames( hDlg ) ) )
  488.                         {
  489.                             KillTimer( hDlg, 1 );
  490.                             MessageBox( hDlg, TEXT("Error enumerating DirectPlay games."),
  491.                                         TEXT("DirectPlay Sample"), 
  492.                                         MB_OK | MB_ICONERROR );
  493.                         }
  494.                     }
  495.                     else
  496.                     {
  497.                         // Stop the timer, and stop the async enumeration
  498.                         KillTimer( hDlg, 1 );
  499.  
  500.                         DPSESSIONDESC2 dpsd;
  501.                         ZeroMemory( &dpsd, sizeof(dpsd) );
  502.                         dpsd.dwSize          = sizeof(dpsd);
  503.                         dpsd.guidApplication = g_AppGUID;
  504.                         hr = g_pDP->EnumSessions( &dpsd, 0, DPConnect_EnumSessionsCallback, 
  505.                                                   NULL,  DPENUMSESSIONS_STOPASYNC );
  506.                         if( hr != DPERR_GENERIC && FAILED(hr) ) 
  507.                             EndDialog( hDlg, EXITCODE_ERROR );
  508.  
  509.                         SetDlgItemText( hDlg, IDC_SEARCH_CHECK, "Start Search" );
  510.  
  511.                         DPConnect_SessionsDlgInitListbox( hDlg );
  512.                     }
  513.                     break;
  514.  
  515.                 case IDC_GAMES_LIST:
  516.                     if( HIWORD(wParam) != LBN_DBLCLK )
  517.                         break;
  518.                     // Fall through
  519.  
  520.                 case IDC_JOIN:
  521.                     if( FAILED( hr = DPConnect_SessionsDlgJoinGame( hDlg ) ) )
  522.                     {
  523.                         MessageBox( hDlg, TEXT("Unable to join game."),
  524.                                     TEXT("DirectPlay Sample"), 
  525.                                     MB_OK | MB_ICONERROR );
  526.                     }                    
  527.                     break;
  528.  
  529.                 case IDC_CREATE:
  530.                     if( FAILED( hr = DPConnect_SessionsDlgCreateGame( hDlg ) ) )
  531.                     {
  532.                         MessageBox( hDlg, TEXT("Unable to create game."),
  533.                                     TEXT("DirectPlay Sample"), 
  534.                                     MB_OK | MB_ICONERROR );
  535.                     }
  536.                     break;
  537.  
  538.                 case IDCANCEL: // The close button was press
  539.                     EndDialog( hDlg, EXITCODE_QUIT );
  540.                     break;
  541.  
  542.                 case IDC_BACK: // "Cancel" button was pressed
  543.                     EndDialog( hDlg, EXITCODE_BACKUP );
  544.                     break;
  545.  
  546.                 default:
  547.                     return FALSE; // Message not handled
  548.             }
  549.             break;
  550.         
  551.         case WM_DESTROY:
  552.             KillTimer( hDlg, 1 );                    
  553.             DPConnect_SessionsDlgCleanup();
  554.             break;
  555.  
  556.         default:
  557.             return FALSE; // Message not handled
  558.     }
  559.  
  560.     // Message was handled
  561.     return TRUE; 
  562. }
  563.  
  564.  
  565.  
  566.  
  567. //-----------------------------------------------------------------------------
  568. // Name: DPConnect_SessionsDlgInitListbox()
  569. // Desc: Initializes the listbox
  570. //-----------------------------------------------------------------------------
  571. VOID DPConnect_SessionsDlgInitListbox( HWND hDlg )
  572. {
  573.     HWND          hWndListBox = GetDlgItem( hDlg, IDC_GAMES_LIST );
  574.     LPDIRECTPLAY4 pDP = NULL;
  575.     
  576.     // Clear the contents from the list box, and 
  577.     // display "Looking for games" text in listbox
  578.     SendMessage( hWndListBox, LB_RESETCONTENT, 0, 0 );
  579.     if( g_bSearchingForSessions )
  580.     {
  581.         SendMessage( hWndListBox, LB_ADDSTRING, 0, 
  582.                      (LPARAM)"Looking for games..." );
  583.     }
  584.     else
  585.     {
  586.         SendMessage( hWndListBox, LB_ADDSTRING, 0, 
  587.                      (LPARAM)"Click Start Search to see a list of games.  "
  588.                              "Click Create to start a new game." );
  589.     }
  590.  
  591.     SendMessage( hWndListBox, LB_SETITEMDATA,  0, NULL );
  592.     SendMessage( hWndListBox, LB_SETCURSEL,    0, 0 );
  593.  
  594.     // Disable the join button until sessions are found
  595.     EnableWindow( GetDlgItem( hDlg, IDC_JOIN ), FALSE );
  596. }
  597.  
  598.  
  599.  
  600.  
  601. //-----------------------------------------------------------------------------
  602. // Name: DPConnect_SessionsDlgShowGames()
  603. // Desc: Enumerates the DirectPlay sessions, and displays them in the listbox
  604. //-----------------------------------------------------------------------------
  605. HRESULT DPConnect_SessionsDlgShowGames( HWND hDlg )
  606. {
  607.     HRESULT        hr;
  608.     HWND           hWndListBox = GetDlgItem( hDlg, IDC_GAMES_LIST );
  609.     DPSESSIONDESC2 dpsd;
  610.     DPSessionInfo* pDPSISelected = NULL;
  611.     int            nItemSelected;
  612.     GUID           guidSelectedSession;
  613.     BOOL           bFindSelectedGUID;
  614.     BOOL           bFoundSelectedGUID;
  615.  
  616.     // Try to keep the same session selected unless it goes away or 
  617.     // there is no real session currently selected
  618.     bFindSelectedGUID  = FALSE;
  619.     bFoundSelectedGUID = TRUE;
  620.  
  621.     nItemSelected = (int)SendMessage( hWndListBox, LB_GETCURSEL, 0, 0 );
  622.     if( nItemSelected != LB_ERR )
  623.     {
  624.         pDPSISelected = (DPSessionInfo*) SendMessage( hWndListBox, LB_GETITEMDATA, 
  625.                                                       nItemSelected, 0 );
  626.         if( pDPSISelected != NULL )
  627.         {
  628.             guidSelectedSession = pDPSISelected->guidSession;
  629.             bFindSelectedGUID = TRUE;
  630.         }
  631.     }
  632.     
  633.     // Remove the previous games from the linked list
  634.     DPConnect_SessionsDlgCleanup();
  635.  
  636.     // Enum sessions and let DirectPlay decide the timeout
  637.     ZeroMemory( &dpsd, sizeof(dpsd) );
  638.     dpsd.dwSize          = sizeof(dpsd);
  639.     dpsd.guidApplication = g_AppGUID;
  640.  
  641.     // Enumerate all the active DirectPlay games on the selected connection
  642.     hr = g_pDP->EnumSessions( &dpsd, 0, DPConnect_EnumSessionsCallback, NULL, 
  643.                               DPENUMSESSIONS_ALL | DPENUMSESSIONS_ASYNC );    
  644.     if( FAILED(hr) )
  645.     {
  646.         if( hr == DPERR_USERCANCEL )
  647.         {
  648.             // The user canceled the DirectPlay connection dialog, 
  649.             // so stop the search
  650.             if( g_bSearchingForSessions )
  651.             {
  652.                 CheckDlgButton( hDlg, IDC_SEARCH_CHECK, BST_UNCHECKED );
  653.                 SendMessage( hDlg, WM_COMMAND, IDC_SEARCH_CHECK, 0 );
  654.             }
  655.  
  656.             return S_OK;
  657.         }
  658.         else 
  659.         {
  660.             DPConnect_SessionsDlgInitListbox( hDlg );
  661.             if ( hr == DPERR_CONNECTING )
  662.                 return S_OK;
  663.  
  664.             return hr;
  665.         }
  666.     }
  667.  
  668.     // Tell listbox not to redraw itself since the contents are going to change
  669.     SendMessage( hWndListBox, WM_SETREDRAW, FALSE, 0 );
  670.  
  671.     // Add the enumerated sessions to the listbox
  672.     if( g_DPSIHead.pDPSINext != &g_DPSIHead )
  673.     {
  674.         // Clear the contents from the list box and enable the join button
  675.         SendMessage( hWndListBox, LB_RESETCONTENT, 0, 0 );
  676.         EnableWindow( GetDlgItem( hDlg, IDC_JOIN ), TRUE );
  677.         
  678.         DPSessionInfo* pDPSI = g_DPSIHead.pDPSINext;
  679.         while ( pDPSI != &g_DPSIHead )
  680.         {
  681.             // Add session to the list box
  682.             int nIndex = (int)SendMessage( hWndListBox, LB_ADDSTRING, 0, 
  683.                                            (LPARAM)pDPSI->szSession );
  684.             SendMessage( hWndListBox, LB_SETITEMDATA, nIndex, (LPARAM)pDPSI );
  685.  
  686.             if( bFindSelectedGUID )
  687.             {
  688.                 // Look for the session the was selected before
  689.                 if( pDPSI->guidSession == guidSelectedSession )
  690.                 {
  691.                     SendMessage( hWndListBox, LB_SETCURSEL, nIndex, 0 );
  692.                     bFoundSelectedGUID = TRUE;
  693.                 }
  694.             }
  695.  
  696.             pDPSI = pDPSI->pDPSINext;
  697.         }
  698.  
  699.         if( !bFindSelectedGUID || !bFoundSelectedGUID )
  700.             SendMessage( hWndListBox, LB_SETCURSEL, 0, 0 );
  701.     }
  702.     else
  703.     {
  704.         // There are no active session, so just reset the listbox
  705.         DPConnect_SessionsDlgInitListbox( hDlg );
  706.     }
  707.  
  708.     // Tell listbox to redraw itself now since the contents have changed
  709.     SendMessage( hWndListBox, WM_SETREDRAW, TRUE, 0 );
  710.     InvalidateRect( hWndListBox, NULL, FALSE );
  711.  
  712.     return S_OK;
  713. }
  714.  
  715.  
  716.  
  717.  
  718. //-----------------------------------------------------------------------------
  719. // Name: DPConnect_EnumSessionsCallback()
  720. // Desc: Enumerates the sessions, and stores them in the linked list, g_DPSIHead
  721. //-----------------------------------------------------------------------------
  722. BOOL FAR PASCAL DPConnect_EnumSessionsCallback( LPCDPSESSIONDESC2 pdpsd, 
  723.                                                 DWORD* pdwTimeout, 
  724.                                                 DWORD dwFlags, 
  725.                                                 VOID* pvContext )
  726. {
  727.     DPSessionInfo* pDPSINew = NULL;
  728.     
  729.     if( dwFlags & DPESC_TIMEDOUT )
  730.         return FALSE; // The enumeration has timed out, so stop the enumeration.
  731.     
  732.     // Found a good session, save it
  733.     pDPSINew = new DPSessionInfo; 
  734.     if( NULL == pDPSINew )
  735.         return FALSE;
  736.  
  737.     ZeroMemory( pDPSINew, sizeof(DPSessionInfo) );
  738.  
  739.     // Copy the information into pDPSINew
  740.     pDPSINew->guidSession = pdpsd->guidInstance;
  741.     sprintf( pDPSINew->szSession, "%s (%d/%d)", pdpsd->lpszSessionNameA, 
  742.              pdpsd->dwCurrentPlayers, pdpsd->dwMaxPlayers );
  743.  
  744.     // Add pDPSINew to the circular linked list, g_pDPSIFirst
  745.     pDPSINew->pDPSINext = g_DPSIHead.pDPSINext;
  746.     g_DPSIHead.pDPSINext = pDPSINew;
  747.     
  748.     return TRUE;
  749. }
  750.  
  751.  
  752.  
  753.  
  754. //-----------------------------------------------------------------------------
  755. // Name: DPConnect_SessionsDlgJoinGame()
  756. // Desc: Joins the selected DirectPlay session
  757. //-----------------------------------------------------------------------------
  758. HRESULT DPConnect_SessionsDlgJoinGame( HWND hDlg )
  759. {
  760.     DPSESSIONDESC2 dpsd;
  761.     DPNAME         dpname;
  762.     HRESULT        hr;
  763.     HWND           hWndListBox = GetDlgItem( hDlg, IDC_GAMES_LIST );
  764.     DPSessionInfo* pDPSISelected = NULL;
  765.     int            nItemSelected;
  766.  
  767.     nItemSelected = (int)SendMessage( hWndListBox, LB_GETCURSEL, 0, 0 );
  768.     
  769.     // Add status text in list box
  770.     pDPSISelected = (DPSessionInfo*) SendMessage( hWndListBox, LB_GETITEMDATA, 
  771.                                                   nItemSelected, 0 );
  772.  
  773.     if( NULL == pDPSISelected )
  774.     {
  775.         MessageBox( hDlg, TEXT("There are no games to join."),
  776.                     TEXT("DirectPlay Sample"), MB_OK );
  777.         return S_OK;
  778.     }
  779.  
  780.     // Setup the DPSESSIONDESC2, and get the session guid from 
  781.     // the selected listbox item
  782.     ZeroMemory( &dpsd, sizeof(dpsd) );
  783.     dpsd.dwSize          = sizeof(dpsd);
  784.     dpsd.guidInstance    = pDPSISelected->guidSession;
  785.     dpsd.guidApplication = g_AppGUID;
  786.  
  787.     // Join the session
  788.     g_bHostPlayer = FALSE;
  789.     if( FAILED( hr = g_pDP->Open( &dpsd, DPOPEN_JOIN ) ) )
  790.         return hr;
  791.  
  792.     // Create player based on g_strLocalPlayerName.  
  793.     // Store the player's DPID in g_LocalPlayerDPID.
  794.     // Also all DirectPlay messages for this player will signal g_hDPMessageEvent
  795.     ZeroMemory( &dpname, sizeof(DPNAME) );
  796.     dpname.dwSize         = sizeof(DPNAME);
  797.     dpname.lpszShortNameA = g_strLocalPlayerName;
  798.     
  799.     if( FAILED( hr = g_pDP->CreatePlayer( &g_LocalPlayerDPID, &dpname, 
  800.                                           g_hDPMessageEvent, NULL, 0, 0 ) ) )
  801.         return hr;
  802.  
  803.     // DirectPlay connect successful, so end dialog
  804.     EndDialog( hDlg, EXITCODE_FORWARD );
  805.  
  806.     return S_OK;
  807. }
  808.  
  809.  
  810.  
  811.  
  812. //-----------------------------------------------------------------------------
  813. // Name: DPConnect_SessionsDlgCreateGame()
  814. // Desc: Asks the user the session name, and creates a new DirectPlay session
  815. //-----------------------------------------------------------------------------
  816. HRESULT DPConnect_SessionsDlgCreateGame( HWND hDlg )
  817. {
  818.     DPSESSIONDESC2 dpsd;
  819.     DPNAME         dpname;
  820.     HRESULT        hr;
  821.     int            nResult; 
  822.     HINSTANCE      hInst;
  823.  
  824. #ifdef _WIN64
  825.     hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  826. #else
  827.     hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  828. #endif
  829.  
  830.     // Display a modal multiplayer connect dialog box.
  831.     EnableWindow( hDlg, FALSE ); 
  832.     nResult = (int)DialogBox( hInst, MAKEINTRESOURCE(IDD_MULTIPLAYER_CREATE), 
  833.                          hDlg, (DLGPROC)DPConnect_CreateSessionDlgProc );
  834.     EnableWindow( hDlg, TRUE ); 
  835.  
  836.     if( nResult == IDCANCEL )
  837.         return S_OK;
  838.  
  839.     // Setup the DPSESSIONDESC2 based on g_AppGUID, and g_strSessionName.
  840.     // The DPSESSION_KEEPALIVE flag keeps the session alive if players abnormally exit
  841.     ZeroMemory( &dpsd, sizeof(dpsd) );
  842.     dpsd.dwSize           = sizeof(dpsd);
  843.     dpsd.guidApplication  = g_AppGUID;
  844.     dpsd.lpszSessionNameA = g_strSessionName;
  845.     dpsd.dwMaxPlayers     = 10;
  846.     dpsd.dwFlags          = DPSESSION_KEEPALIVE | DPSESSION_MIGRATEHOST;
  847.     if( g_bUseProtocol )
  848.         dpsd.dwFlags |= DPSESSION_DIRECTPLAYPROTOCOL;
  849.  
  850.     // Create a new session
  851.     g_bHostPlayer = TRUE;
  852.     if( FAILED( hr = g_pDP->Open( &dpsd, DPOPEN_CREATE ) ) )
  853.         return hr;
  854.  
  855.     // Create player based on g_strLocalPlayerName.  
  856.     // Store the player's DPID in g_LocalPlayerDPID.
  857.     // Also all DirectPlay messages for this player will signal g_hDPMessageEvent
  858.     ZeroMemory( &dpname, sizeof(DPNAME) );
  859.     dpname.dwSize         = sizeof(DPNAME);
  860.     dpname.lpszShortNameA = g_strLocalPlayerName;
  861.  
  862.     if( FAILED( hr = g_pDP->CreatePlayer( &g_LocalPlayerDPID, &dpname, 
  863.                                           g_hDPMessageEvent, NULL, 0, 
  864.                                           DPPLAYER_SERVERPLAYER ) ) )
  865.         return hr;
  866.  
  867.     // DirectPlay connect successful, so end dialog
  868.     EndDialog( hDlg, EXITCODE_FORWARD );
  869.  
  870.     return S_OK;
  871. }
  872.  
  873.  
  874.  
  875.  
  876. //-----------------------------------------------------------------------------
  877. // Name: DPConnect_CreateSessionDlgProc()
  878. // Desc: Handles messages fro the multiplayer create game dialog
  879. //-----------------------------------------------------------------------------
  880. INT_PTR CALLBACK DPConnect_CreateSessionDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  881. {
  882.     DWORD dwNameLength;
  883.  
  884.     switch( msg ) 
  885.     {
  886.         case WM_INITDIALOG:
  887.             SetDlgItemText( hDlg, IDC_EDIT_SESSION_NAME, g_strSessionName );
  888.             return TRUE;
  889.  
  890.         case WM_COMMAND:
  891.             switch( LOWORD(wParam) )
  892.             {
  893.                 case IDOK:
  894.                     dwNameLength = GetDlgItemText( hDlg, IDC_EDIT_SESSION_NAME, 
  895.                                                    g_strSessionName, 
  896.                                                    MAX_SESSION_NAME );
  897.                     if( dwNameLength == 0 )
  898.                         return TRUE; // Don't accept blank session names
  899.  
  900.                     g_bUseProtocol = TRUE;
  901.  
  902.                     EndDialog( hDlg, IDOK );
  903.                     return TRUE;
  904.  
  905.                 case IDCANCEL:
  906.                     EndDialog( hDlg, IDCANCEL );
  907.                     return TRUE;
  908.             }
  909.             break;
  910.     }
  911.  
  912.     return FALSE; // Didn't handle message
  913. }
  914.  
  915.  
  916.  
  917.  
  918. //-----------------------------------------------------------------------------
  919. // Name: DPConnect_SessionsDlgCleanup()
  920. // Desc: Deletes the linked list, g_DPSIHead
  921. //-----------------------------------------------------------------------------
  922. VOID DPConnect_SessionsDlgCleanup()
  923. {
  924.     DPSessionInfo* pDPSI = g_DPSIHead.pDPSINext;
  925.     DPSessionInfo* pDPSIDelete;
  926.  
  927.     while ( pDPSI != &g_DPSIHead )
  928.     {
  929.         pDPSIDelete = pDPSI;       
  930.         pDPSI = pDPSI->pDPSINext;
  931.  
  932.         SAFE_DELETE( pDPSIDelete );
  933.     }
  934.  
  935.     // Re-link the g_DPSIHead circular linked list
  936.     g_DPSIHead.pDPSINext = &g_DPSIHead;
  937. }
  938.  
  939.  
  940.  
  941.  
  942. //-----------------------------------------------------------------------------
  943. // Name: DPConnect_WaitForLobbyLaunch()
  944. // Desc: Wait for the a lobby connection and connect when found
  945. //-----------------------------------------------------------------------------
  946. HRESULT DPConnect_WaitForLobbyLaunch( HWND hParentDlg )
  947. {
  948.     HRESULT hr;
  949.     BOOL    bLaunchedByLobby;
  950.  
  951.     // Create a new lobby object
  952.     SAFE_RELEASE( g_pDPLobby );
  953.  
  954.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayLobby, NULL,
  955.                                        CLSCTX_INPROC_SERVER, IID_IDirectPlayLobby3A,
  956.                                        (VOID**)&g_pDPLobby ) ) )
  957.         return hr;
  958.  
  959.     // Put the application into wait mode
  960.     if( FAILED( hr = g_pDPLobby->WaitForConnectionSettings( 0 ) ) )
  961.         return hr;
  962.  
  963.     // Use the IDD_LOBBY_WAIT_STATUS dialog to check for a connection message
  964.     g_bWaitForConnectionSettings = TRUE;
  965.  
  966.     EnableWindow( hParentDlg, FALSE );
  967.  
  968.     // Display a dialog box and wait for the connection settings
  969.     DialogBoxParam( NULL, MAKEINTRESOURCE( IDD_LOBBY_WAIT_STATUS ), hParentDlg,
  970.                     (DLGPROC)DPConnect_LobbyWaitDlgProc, (LPARAM)&hr );
  971.    
  972.     EnableWindow( hParentDlg, TRUE );
  973.  
  974.     if( FAILED(hr) )
  975.     {
  976.         g_pDPLobby->WaitForConnectionSettings( DPLWAIT_CANCEL );
  977.         SAFE_RELEASE( g_pDPLobby );
  978.  
  979.         return hr;
  980.     }
  981.  
  982.     // The lobby server has launched the game, so check for a lobby
  983.     // launch to continue on to connect to the session and create the player
  984.     if( FAILED( hr = DPConnect_CheckForLobbyLaunch( &bLaunchedByLobby ) ) )
  985.         return hr; // This may be DPERR_USERCANCEL if the user canceled the dialog
  986.  
  987.     return S_OK;
  988. }
  989.  
  990.  
  991.  
  992.  
  993. //-----------------------------------------------------------------------------
  994. // Name: DPConnect_CheckForLobbyLaunch()
  995. // Desc: Determines if we were launched by a lobby. If so, gets the connection
  996. //       settings and creates our player using the information from the lobby
  997. //-----------------------------------------------------------------------------
  998. HRESULT DPConnect_CheckForLobbyLaunch( BOOL* pbLaunchedByLobby )
  999. {
  1000.     HRESULT hr;
  1001.     DWORD   dwSize;
  1002.  
  1003.     if( NULL == pbLaunchedByLobby ) 
  1004.         return E_FAIL;
  1005.  
  1006.     // Create a new lobby object
  1007.     SAFE_RELEASE( g_pDPLobby );
  1008.  
  1009.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayLobby, NULL,
  1010.                                        CLSCTX_INPROC_SERVER, IID_IDirectPlayLobby3A,
  1011.                                        (VOID**)&g_pDPLobby ) ) )
  1012.     {
  1013.         if( hr == E_NOINTERFACE )
  1014.         {
  1015.             MessageBox( NULL, TEXT("This application requires DirectPlay 6 or later. "
  1016.                         "The sample will now quit."),
  1017.                         TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  1018.         }
  1019.  
  1020.         return hr;
  1021.     }
  1022.  
  1023.     // Get connection settings from the lobby (into g_pdplConnection)
  1024.     hr = g_pDPLobby->GetConnectionSettings( 0, NULL, &dwSize );
  1025.     if( FAILED(hr) && (DPERR_BUFFERTOOSMALL != hr) )
  1026.     {
  1027.         if( DPERR_NOTLOBBIED == hr )
  1028.         {
  1029.             *pbLaunchedByLobby = FALSE;
  1030.  
  1031.             // Cleanup since we were not launched from the lobby
  1032.             SAFE_DELETE_ARRAY( g_pDPLConnection );
  1033.             SAFE_RELEASE( g_pDPLobby );
  1034.  
  1035.             return S_OK;
  1036.         }
  1037.  
  1038.         return hr; 
  1039.     }
  1040.  
  1041.     // Allocate memory for the connection
  1042.     SAFE_DELETE_ARRAY( g_pDPLConnection );
  1043.     g_pDPLConnection = (DPLCONNECTION*)new BYTE[ dwSize ];
  1044.  
  1045.     // Get the connection settings
  1046.     if( FAILED( hr = g_pDPLobby->GetConnectionSettings( 0, g_pDPLConnection, 
  1047.                                                         &dwSize ) ) )
  1048.         return hr;
  1049.  
  1050.     *pbLaunchedByLobby = TRUE;
  1051.  
  1052.     if( FAILED( hr = DPConnect_DoLobbyLaunch() ) )
  1053.     {
  1054.         // Cleanup 
  1055.         SAFE_DELETE_ARRAY( g_pDPLConnection );
  1056.         SAFE_RELEASE( g_pDPLobby );
  1057.  
  1058.         return hr; // This may be DPERR_USERCANCEL if the user canceled the dialog
  1059.     }
  1060.  
  1061.     return S_OK;
  1062. }
  1063.  
  1064.  
  1065.  
  1066.  
  1067. //-----------------------------------------------------------------------------
  1068. // Name: DPConnect_DoLobbyLaunch()
  1069. // Desc: The app was launched by the lobby server, so connect to the session
  1070. //       and create the player
  1071. //-----------------------------------------------------------------------------
  1072. HRESULT DPConnect_DoLobbyLaunch()
  1073. {
  1074.     HRESULT hr;
  1075.  
  1076.     // Detrimine if this is the host player 
  1077.     g_bHostPlayer = ( (g_pDPLConnection->dwFlags & DPLCONNECTION_CREATESESSION) != 0 );
  1078.  
  1079.     // Set our session flags
  1080.     g_pDPLConnection->lpSessionDesc->dwFlags = DPSESSION_KEEPALIVE | 
  1081.                                                DPSESSION_MIGRATEHOST;
  1082.  
  1083.     // Let lobby know our connection flags
  1084.     if( FAILED( hr = g_pDPLobby->SetConnectionSettings( 0, 0, g_pDPLConnection ) ) )
  1085.         return hr;
  1086.  
  1087.     // If we're hosting, just call ConnectEx syncronously.  Otherwise, display
  1088.     // the connecting dialog and do the connect asynchronously.
  1089.     if( g_bHostPlayer )
  1090.     {
  1091.         // Connect to the lobby syncronously
  1092.         if( FAILED( hr = g_pDPLobby->ConnectEx( 0, IID_IDirectPlay4A, 
  1093.                                                 (VOID**)&g_pDP, NULL ) ) )
  1094.             return hr;
  1095.     }
  1096.     else
  1097.     {
  1098.         // Use the IDD_LOBBY_WAIT_STATUS dialog to attempt to connect to 
  1099.         // the new session
  1100.         g_bWaitForConnectionSettings = FALSE;
  1101.  
  1102.         // Connect to the lobby asyncronously
  1103.         DialogBoxParam( NULL, MAKEINTRESOURCE( IDD_LOBBY_WAIT_STATUS ), NULL,
  1104.                         (DLGPROC)DPConnect_LobbyWaitDlgProc, (LPARAM)&hr );
  1105.         if( FAILED(hr) )
  1106.             return hr; // This may be DPERR_USERCANCEL if the user canceled the dialog
  1107.     }
  1108.  
  1109.     strcpy( g_strLocalPlayerName, g_pDPLConnection->lpPlayerName->lpszShortNameA );
  1110.  
  1111.     // Create our player
  1112.     DPNAME dpname;
  1113.     ZeroMemory( &dpname, sizeof(DPNAME) );
  1114.     dpname.dwSize         = sizeof(DPNAME);
  1115.     dpname.lpszShortNameA = g_strLocalPlayerName;
  1116.  
  1117.     if( FAILED( hr = g_pDP->CreatePlayer( &g_LocalPlayerDPID, &dpname, 
  1118.                                           NULL, NULL, 0, 0 ) ) )
  1119.         return hr;
  1120.  
  1121.     // Successfully lobby launch, note that we don't release the lobby object
  1122.     return S_OK;
  1123. }
  1124.  
  1125.  
  1126.  
  1127.  
  1128. //-----------------------------------------------------------------------------
  1129. // Name: DPConnect_LobbyWaitDlgProc()
  1130. // Desc: Handles dialog messages.  This dialog starts a timer that attempts to
  1131. //       either receive a lobby connection settings message or 
  1132. //       connect to new session via the lobby connection depending on the 
  1133. //       g_bWaitForConnectionSettings flag.
  1134. //-----------------------------------------------------------------------------
  1135. INT_PTR CALLBACK DPConnect_LobbyWaitDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  1136. {
  1137.     static HRESULT* phr = NULL;
  1138.  
  1139.     switch( msg )
  1140.     {
  1141.         case WM_INITDIALOG:
  1142.             // Save the HRESULT pointer
  1143.             phr = (HRESULT*)lParam;           
  1144.  
  1145.             if( g_bWaitForConnectionSettings )
  1146.                 SetDlgItemText( hDlg, IDC_WAIT_TEXT, TEXT("Waiting for connection...") );
  1147.             else
  1148.                 SetDlgItemText( hDlg, IDC_WAIT_TEXT, TEXT("Finding Game...") );
  1149.  
  1150.             // Create a timer.  The dialog will attempt to connect at every WM_TIMER
  1151.             SetTimer( hDlg, 0, 250, NULL );
  1152.             break;
  1153.  
  1154.         case WM_DESTROY:
  1155.             KillTimer( hDlg, 0 );
  1156.             break;
  1157.  
  1158.         case WM_TIMER:
  1159.             // Attempt to connect to the game
  1160.             if( g_bWaitForConnectionSettings )
  1161.             {
  1162.                 *phr = DPConnect_GetLobbyConnectionSettingsMessage();
  1163.                 if( *phr == S_OK )
  1164.                     EndDialog( hDlg, 0 );
  1165.             }
  1166.             else
  1167.             {
  1168.                 *phr = g_pDPLobby->ConnectEx( DPCONNECT_RETURNSTATUS, IID_IDirectPlay4A, 
  1169.                                               (VOID**)&g_pDP, NULL );
  1170.                 if( *phr == DPERR_CONNECTING )
  1171.                     break; // Try again on the next WM_TIMER message
  1172.  
  1173.                 EndDialog( hDlg, 0 );
  1174.             }
  1175.  
  1176.             break;
  1177.         
  1178.         case WM_COMMAND:
  1179.             switch( LOWORD(wParam) )
  1180.             {
  1181.                 case IDC_LOBBYCONNECTCANCEL:
  1182.                 case IDCANCEL:
  1183.                     // the async Connect will be stopped when the
  1184.                     // IDirectPlayLobby3 interface is released.
  1185.                     
  1186.                     // Set the HRESULT to user cancel and close the dialog
  1187.                     *phr = DPERR_USERCANCEL;
  1188.                     EndDialog( hDlg, 0 );
  1189.                     break;
  1190.  
  1191.                 default:
  1192.                     return FALSE; // Message not handled
  1193.             }
  1194.             break;
  1195.  
  1196.         default:
  1197.             return FALSE; // Message not handled
  1198.     }
  1199.  
  1200.     return TRUE; // Message handled
  1201. }
  1202.  
  1203.  
  1204.  
  1205.  
  1206. //-----------------------------------------------------------------------------
  1207. // Name: DPConnect_GetLobbyConnectionSettingsMessage()
  1208. // Desc: Attepts to get a lobby connection settings message.  If it does 
  1209. //       it returns S_OK otherwise it returns S_FALSE 
  1210. //-----------------------------------------------------------------------------
  1211. HRESULT DPConnect_GetLobbyConnectionSettingsMessage()
  1212. {
  1213.     HRESULT hr = NOERROR;
  1214.     LPVOID  pvMsgBuffer = NULL;
  1215.     DWORD   dwMsgBufferSize = 0;
  1216.     DWORD   dwMsgFlags;
  1217.  
  1218.     while( TRUE )
  1219.     {
  1220.         hr = g_pDPLobby->ReceiveLobbyMessage( 0, 0, &dwMsgFlags,
  1221.                                               pvMsgBuffer, &dwMsgBufferSize );
  1222.         if( hr == DPERR_BUFFERTOOSMALL ) 
  1223.         {
  1224.             // The current buffer was too small, 
  1225.             // so reallocate it and try again
  1226.             SAFE_DELETE_ARRAY( pvMsgBuffer );
  1227.  
  1228.             pvMsgBuffer = new BYTE[ dwMsgBufferSize ];
  1229.             if( pvMsgBuffer == NULL )
  1230.                 return E_OUTOFMEMORY;
  1231.  
  1232.             continue; // Now that the buffer is bigger, try again
  1233.         }
  1234.  
  1235.         if( DPERR_NOMESSAGES == hr )
  1236.             break;
  1237.  
  1238.         if( FAILED(hr) )
  1239.             break;
  1240.  
  1241.         // Found a messages, check to see if its a CONNECTIONSETTINGS message
  1242.         if( dwMsgFlags & DPLMSG_SYSTEM )
  1243.         {
  1244.             // If it is found then stop looking for it
  1245.             if( ( (DPLMSG_GENERIC*)pvMsgBuffer)->dwType == DPLSYS_NEWCONNECTIONSETTINGS )
  1246.                 break;
  1247.         }
  1248.     }
  1249.  
  1250.     // Cleanup buffer
  1251.     SAFE_DELETE_ARRAY( pvMsgBuffer );
  1252.  
  1253.     // Return S_FALSE if there we no connection settings messages
  1254.     if( DPERR_NOMESSAGES == hr )
  1255.         return S_FALSE;
  1256.  
  1257.     // If the message was recieved the hr should be S_OK
  1258.     return hr; 
  1259. }
  1260.  
  1261.  
  1262.