home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / dplaunch / dplaunch.c next >
Encoding:
C/C++ Source or Header  |  1997-07-15  |  27.6 KB  |  837 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1996-1997 Microsoft Corporation.  All Rights Reserved.
  4.  *
  5.  *  File:       dplaunch.c
  6.  *  Content:    Implementation of a DirectPlay launching utility
  7.  *
  8.  ***************************************************************************/
  9.  
  10. #define INITGUID
  11.  
  12. #include <windows.h>
  13. #include <windowsx.h>
  14. #include <objbase.h>
  15. #include <cguid.h>
  16.  
  17. #include "dplay.h"
  18. #include "dplobby.h"
  19.  
  20. #include "resource.h"
  21.  
  22. // constants
  23. #define NAMEMAX            200            // maximum size of a string name
  24. #define ADDRESSTYPEMAX    10            // maximum no. address types
  25.  
  26. // GUID for sessions this application creates
  27. // {D559FC00-DC12-11cf-9C4E-00A0C905425E}
  28. DEFINE_GUID(MY_SESSION_GUID, 
  29. 0xd559fc00, 0xdc12, 0x11cf, 0x9c, 0x4e, 0x0, 0xa0, 0xc9, 0x5, 0x42, 0x5e);
  30.  
  31. // structures
  32.  
  33. // list of address types
  34. typedef struct {
  35.     DWORD    dwCount;
  36.     GUID    guidAddressTypes[ADDRESSTYPEMAX];
  37. } ADDRESSTYPELIST, *LPADDRESSTYPELIST;
  38.  
  39. // prototypes
  40. BOOL CALLBACK        LauncherWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  41. HRESULT                InitializeLauncherWindow(HWND hWnd, LPDIRECTPLAYLOBBY2A *lplpDPlayLobby);
  42. HRESULT                UpdateAddressInfo(HWND hWnd, LPDIRECTPLAYLOBBY2A lpDPlayLobby);
  43. void                DestroyLauncherWindow(HWND hWnd, LPDIRECTPLAYLOBBY2A lpDPlayLobby);
  44. void                LaunchDirectPlayApplication(HWND hWnd, LPDIRECTPLAYLOBBY2A lpDPlayLobby);
  45. HRESULT                GetComboBoxGuid(HWND hWnd, LONG iDialogItem, LPGUID lpguidServiceProvider);
  46. HRESULT                FillModemComboBox(HWND hWnd, LPDIRECTPLAYLOBBY2A lpDPlayLobby, LPGUID lpguidServiceProvider);
  47.  
  48.  
  49. // ---------------------------------------------------------------------------
  50. // WinMain
  51. // ---------------------------------------------------------------------------
  52. // Description:             Main windows entry point.
  53. // Arguments:
  54. //  HINSTANCE               [in] Standard windows stuff
  55. //  HINSTANCE               [in]
  56. //  LPSTR                   [in]
  57. //  int                     [in]
  58. // Returns:
  59. //  int                        
  60. int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  61.                     LPSTR lpCmdLine, int nCmdShow )
  62. {
  63.     return DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_LAUNCHERDIALOG), NULL, LauncherWndProc, (LPARAM) hInstance);
  64. }
  65.  
  66.  
  67. // ---------------------------------------------------------------------------
  68. // LauncherWndProc
  69. // ---------------------------------------------------------------------------
  70. // Description:             Message callback function for Launcher dialog.
  71. // Arguments:
  72. //  HWND                    [in] Dialog window handle.
  73. //  UINT                    [in] Window message identifier.
  74. //  WPARAM                  [in] Depends on message.
  75. //  LPARAM                  [in] Depends on message.
  76. // Returns:
  77. //  BOOL                    TRUE if message was processed internally.
  78. BOOL CALLBACK LauncherWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  79. {
  80.     static HINSTANCE            hInst;
  81.     static LPDIRECTPLAYLOBBY2A    lpDPlayLobby;
  82.     HRESULT                        hr;
  83.  
  84.     switch(uMsg)
  85.     {
  86.         case WM_INITDIALOG:
  87.             // Save the instance handle
  88.             hInst = (HINSTANCE)lParam;
  89.                         
  90.             // Initialize dialog with launcher information
  91.             lpDPlayLobby = NULL;
  92.             hr = InitializeLauncherWindow(hWnd, &lpDPlayLobby);
  93.             break;
  94.  
  95.         case WM_DESTROY:
  96.             // Destroy launcher information in dialog
  97.             DestroyLauncherWindow(hWnd, lpDPlayLobby);
  98.  
  99.             // Return failure
  100.             EndDialog(hWnd, FALSE);
  101.  
  102.             break;
  103.  
  104.         case WM_COMMAND:
  105.             switch(LOWORD(wParam))
  106.             {
  107.                 case IDC_SPCOMBO:
  108.  
  109.                     switch (HIWORD(wParam))
  110.                     {
  111.                     case CBN_SELCHANGE:
  112.                         // update the address info display
  113.                         UpdateAddressInfo(hWnd, lpDPlayLobby);
  114.                         break;
  115.                     }
  116.                     break;
  117.  
  118.                 case IDC_RUNAPPBUTTON:
  119.                     // get settings and launch application
  120.                     LaunchDirectPlayApplication(hWnd, lpDPlayLobby);
  121.  
  122.                     break;
  123.  
  124.                 case IDCANCEL:
  125.                     // Return failure
  126.                     EndDialog(hWnd, TRUE);
  127.  
  128.                     break;
  129.             }
  130.  
  131.             break;
  132.     }
  133.  
  134.     // Allow for default processing
  135.     return FALSE;
  136. }
  137.  
  138. // ---------------------------------------------------------------------------
  139. // EnumApp
  140. // ---------------------------------------------------------------------------
  141. // Description:             Enumeration callback called by DirectPlay.
  142. //                            Enumerates the applications registered with DirectPlay.
  143. // Arguments:
  144. //  LPDPLAPPINFO            [in] information about the application
  145. //  LPVOID                    [in] user-defined context
  146. //  DWORD                    [in] flags
  147. // Returns:
  148. //  BOOL                    TRUE to continue enumerating
  149. BOOL FAR PASCAL EnumApp(LPCDPLAPPINFO lpAppInfo, LPVOID lpContext, DWORD dwFlags)
  150. {
  151.     HWND            hWnd = lpContext;
  152.     LRESULT            iIndex;
  153.     LPGUID            lpGuid;
  154.  
  155.     // store application name in combo box
  156.     iIndex = SendDlgItemMessage(hWnd, IDC_APPCOMBO, CB_ADDSTRING, 0, (LPARAM) lpAppInfo->lpszAppNameA);
  157.     if (iIndex == LB_ERR)
  158.         goto Failure;
  159.  
  160.     // make space for application GUID
  161.     lpGuid = (LPGUID) GlobalAllocPtr(GHND, sizeof(GUID));
  162.     if (lpGuid == NULL)
  163.         goto Failure;
  164.  
  165.     // store pointer to GUID in combo box
  166.     *lpGuid = lpAppInfo->guidApplication;
  167.     SendDlgItemMessage(hWnd, IDC_APPCOMBO, CB_SETITEMDATA, (WPARAM) iIndex, (LPARAM) lpGuid);
  168.  
  169. Failure:
  170.     return (TRUE);
  171. }
  172.  
  173. // ---------------------------------------------------------------------------
  174. // EnumSP
  175. // ---------------------------------------------------------------------------
  176. // Description:             Enumeration callback called by DirectPlay.
  177. //                            Enumerates service providers registered with DirectPlay.
  178. // Arguments:
  179. //  LPGUID                    [in] GUID of service provider
  180. //  LPTSTR                    [in] name of service provider
  181. //  DWORD                    [in] major version of DirectPlay
  182. //  DWORD                    [in] minor version of DirectPlay
  183. //  LPVOID                    [in] user-defined context
  184. // Returns:
  185. //  BOOL                    TRUE to continue enumerating
  186. BOOL FAR PASCAL EnumSP(LPGUID lpSPGuid, LPTSTR lptszDesc, DWORD dwMajorVersion,
  187.                    DWORD dwMinorVersion, LPVOID lpContext)
  188. {
  189.     HWND            hWnd = lpContext;
  190.     LRESULT            iIndex;
  191.     LPGUID            lpGuid;
  192.  
  193.     // store service provider name in combo box
  194.     iIndex = SendDlgItemMessage(hWnd, IDC_SPCOMBO, CB_ADDSTRING, 0, (LPARAM) lptszDesc);
  195.     if (iIndex == LB_ERR)
  196.         goto Failure;
  197.  
  198.     // make space for service provider GUID
  199.     lpGuid = (LPGUID) GlobalAllocPtr(GHND, sizeof(GUID));
  200.     if (lpGuid == NULL)
  201.         goto Failure;
  202.  
  203.     // store pointer to GUID in combo box
  204.     *lpGuid = *lpSPGuid;
  205.     SendDlgItemMessage(hWnd, IDC_SPCOMBO, CB_SETITEMDATA, (WPARAM) iIndex, (LPARAM) lpGuid);
  206.  
  207. Failure:
  208.     return (TRUE);
  209. }
  210.  
  211. // ---------------------------------------------------------------------------
  212. // InitializeLauncherWindow
  213. // ---------------------------------------------------------------------------
  214. // Description:             Initializes the window for the Launcher.
  215. // Arguments:
  216. //  HWND                    [in] Window handle.
  217. //  LPDIRECTPLAYLOBBY2A        [out] IDirectPlayLobby interface.
  218. // Returns:
  219. //  HRESULT                    any errors initializing the window
  220. HRESULT InitializeLauncherWindow(HWND hWnd, LPDIRECTPLAYLOBBY2A *lplpDPlayLobby)
  221. {
  222.     LPDIRECTPLAYLOBBYA    lpDPlayLobbyA = NULL;
  223.     LPDIRECTPLAYLOBBY2A    lpDPlayLobby2A = NULL;
  224.     HRESULT                hr;
  225.         
  226.     // get ANSI DirectPlayLobby interface
  227.     hr = DirectPlayLobbyCreate(NULL, &lpDPlayLobbyA, NULL, NULL, 0);
  228.     if FAILED(hr)
  229.         goto Failure;
  230.  
  231.     // get ANSI DirectPlayLobby2 interface
  232.     hr = lpDPlayLobbyA->lpVtbl->QueryInterface(lpDPlayLobbyA,
  233.                             &IID_IDirectPlayLobby2A, (LPVOID *) &lpDPlayLobby2A);
  234.     if FAILED(hr)
  235.         goto Failure;
  236.  
  237.     // don't need DirectPlayLobby interface anymore
  238.     lpDPlayLobbyA->lpVtbl->Release(lpDPlayLobbyA);
  239.     lpDPlayLobbyA = NULL;
  240.  
  241.     // put all the DirectPlay applications in a combo box
  242.     lpDPlayLobby2A->lpVtbl->EnumLocalApplications(lpDPlayLobby2A, EnumApp, hWnd, 0);
  243.  
  244.     // put all the service providers in a combo box
  245.     DirectPlayEnumerate(EnumSP, hWnd);
  246.  
  247.     // initialize the controls
  248.     SendDlgItemMessage(hWnd, IDC_APPCOMBO, CB_SETCURSEL, (WPARAM) 0, 0);
  249.     SendDlgItemMessage(hWnd, IDC_SPCOMBO, CB_SETCURSEL, (WPARAM) 0, 0);
  250.     SendDlgItemMessage(hWnd, IDC_HOSTRADIO, BM_SETCHECK, (WPARAM) BST_CHECKED, 0);
  251.  
  252.     // update the address info display
  253.     hr = UpdateAddressInfo(hWnd, lpDPlayLobby2A);
  254.  
  255.     // return the ANSI lobby interface
  256.     *lplpDPlayLobby = lpDPlayLobby2A;
  257.  
  258.     return (DP_OK);
  259.  
  260. Failure:
  261.     if (lpDPlayLobbyA)
  262.         lpDPlayLobbyA->lpVtbl->Release(lpDPlayLobbyA);
  263.     if (lpDPlayLobby2A)
  264.         lpDPlayLobby2A->lpVtbl->Release(lpDPlayLobby2A);
  265.  
  266.     return (hr);
  267. }
  268.  
  269. // ---------------------------------------------------------------------------
  270. // DestroyLauncherWindow
  271. // ---------------------------------------------------------------------------
  272. // Description:             Destroys the launcher window.
  273. // Arguments:
  274. //  HWND                    [in] Window handle.
  275. //  LPDIRECTPLAYLOBBY2A      [in] DirectPlay Lobby interface to destroy
  276. // Returns:
  277. //  Nothing
  278. void DestroyLauncherWindow(HWND hWnd, LPDIRECTPLAYLOBBY2A lpDPlayLobby)
  279. {
  280.     WPARAM    index;
  281.     LRESULT    lpData;
  282.  
  283.     // destroy the GUID's stored with each app name
  284.     index = 0;
  285.     while (TRUE)
  286.     {
  287.         lpData = SendDlgItemMessage(hWnd, IDC_APPCOMBO, CB_GETITEMDATA, (WPARAM) index, 0);
  288.         if ((lpData == CB_ERR) || (lpData == 0))
  289.             break;
  290.  
  291.         GlobalFreePtr((LPVOID) lpData);
  292.         index += 1;
  293.     }
  294.  
  295.     // destroy the GUID's stored with each service provider name
  296.     index = 0;
  297.     while (TRUE)
  298.     {
  299.         lpData = SendDlgItemMessage(hWnd, IDC_SPCOMBO, CB_GETITEMDATA, (WPARAM) index, 0);
  300.         if ((lpData == CB_ERR) || (lpData == 0))
  301.             break;
  302.  
  303.         GlobalFreePtr((LPVOID) lpData);
  304.         index += 1;
  305.     }
  306.  
  307.     // release the lobby interface
  308.     if (lpDPlayLobby)
  309.         lpDPlayLobby->lpVtbl->Release(lpDPlayLobby);
  310. }
  311.  
  312. // ---------------------------------------------------------------------------
  313. // EnumAddressTypes
  314. // ---------------------------------------------------------------------------
  315. // Description:             Enumeration callback called by DirectPlayLobby.
  316. //                            Enumerates the address types supported by the
  317. //                            given Service Provider and returns them in a list.
  318. // Arguments:
  319. //  REFGUID                 [in] GUID of the address type
  320. //  LPVOID                    [in] user-defined context
  321. //  DWORD                    [in] flags
  322. // Returns:
  323. //  BOOL                    FALSE to stop enumerating after the first callback
  324. BOOL FAR PASCAL EnumAddressTypes(REFGUID guidAddressType, LPVOID lpContext,
  325.                                 DWORD dwFlags)
  326. {
  327.     LPADDRESSTYPELIST    lpAddressTypes = (LPADDRESSTYPELIST) lpContext;
  328.  
  329.     // make sure there is room
  330.     if (lpAddressTypes->dwCount < ADDRESSTYPEMAX)
  331.     {
  332.         // save the address type guid in the list
  333.         lpAddressTypes->guidAddressTypes[lpAddressTypes->dwCount] = *guidAddressType;
  334.         lpAddressTypes->dwCount++;
  335.     }
  336.  
  337.     return (TRUE);
  338. }
  339.  
  340. // ---------------------------------------------------------------------------
  341. // UpdateAddressInfo
  342. // ---------------------------------------------------------------------------
  343. // Description:             Updates address information elements in dialog.
  344. //                            Calls EnumAddressTypes() to determine what address
  345. //                            information should be displayed and arranges dialog
  346. //                            to display and collect the needed information.
  347. // Arguments:
  348. //  HWND                    [in] window handle
  349. //  LPDIRECTPLAYLOBBY2A        [in] DirectPlay Lobby interface to use
  350. // Returns:
  351. //  HRESULT                    DP_OK if it succeedes, otherwise the error
  352. HRESULT UpdateAddressInfo(HWND hWnd, LPDIRECTPLAYLOBBY2A lpDPlayLobby)
  353. {
  354.     GUID            guidServiceProvider, guidAddressType;
  355.     ADDRESSTYPELIST    addressTypeList;
  356.     DWORD            i;
  357.     HRESULT            hr;
  358.  
  359.     // get guid of currently selected service provider
  360.     hr = GetComboBoxGuid(hWnd, IDC_SPCOMBO, &guidServiceProvider);
  361.     if FAILED(hr)
  362.         goto Failure;
  363.  
  364.     // get the list of address types for this service provider
  365.     ZeroMemory(&addressTypeList, sizeof(ADDRESSTYPELIST));
  366.     hr = lpDPlayLobby->lpVtbl->EnumAddressTypes(lpDPlayLobby,
  367.             EnumAddressTypes, &guidServiceProvider, &addressTypeList, 0L);
  368.     if FAILED(hr)
  369.         goto Failure;
  370.  
  371.     // clear and hide address dialog items
  372.     SendDlgItemMessage(hWnd, IDC_ADDRESSCOMBO, CB_RESETCONTENT,
  373.                                 (WPARAM) 0, (LPARAM) 0);
  374.     ShowWindow(GetDlgItem(hWnd, IDC_ADDRESSCOMBO), SW_HIDE);
  375.     ShowWindow(GetDlgItem(hWnd, IDC_ADDRESSCOMBOLABEL), SW_HIDE);
  376.  
  377.     SetDlgItemText(hWnd, IDC_ADDRESSEDIT, "");
  378.     ShowWindow(GetDlgItem(hWnd, IDC_ADDRESSEDIT), SW_HIDE);
  379.     ShowWindow(GetDlgItem(hWnd, IDC_ADDRESSEDITLABEL), SW_HIDE);
  380.  
  381.     // loop over the address types
  382.     for (i = 0; i < addressTypeList.dwCount; i++)
  383.     {
  384.         guidAddressType = addressTypeList.guidAddressTypes[i];
  385.  
  386.         // phone number
  387.         if (IsEqualGUID(&guidAddressType, &DPAID_Phone))
  388.         {
  389.             SetDlgItemText(hWnd, IDC_ADDRESSEDITLABEL, "Phone number");
  390.             ShowWindow(GetDlgItem(hWnd, IDC_ADDRESSEDIT), SW_SHOW);
  391.             ShowWindow(GetDlgItem(hWnd, IDC_ADDRESSEDITLABEL), SW_SHOW);
  392.         }
  393.  
  394.         // modem
  395.         else if (IsEqualGUID(&guidAddressType, &DPAID_Modem))
  396.         {
  397.             SetDlgItemText(hWnd, IDC_ADDRESSCOMBOLABEL, "Modem");
  398.             ShowWindow(GetDlgItem(hWnd, IDC_ADDRESSCOMBO), SW_SHOW);
  399.             ShowWindow(GetDlgItem(hWnd, IDC_ADDRESSCOMBOLABEL), SW_SHOW);
  400.             FillModemComboBox(hWnd, lpDPlayLobby, &guidServiceProvider);
  401.         }
  402.  
  403.         // internet address
  404.         else if (IsEqualGUID(&guidAddressType, &DPAID_INet))
  405.         {
  406.             SetDlgItemText(hWnd, IDC_ADDRESSEDITLABEL, "IP address");
  407.             ShowWindow(GetDlgItem(hWnd, IDC_ADDRESSEDIT), SW_SHOW);
  408.             ShowWindow(GetDlgItem(hWnd, IDC_ADDRESSEDITLABEL), SW_SHOW);
  409.         }
  410.     }
  411.  
  412. Failure:
  413.     return (hr);
  414. }
  415.  
  416. // ---------------------------------------------------------------------------
  417. // CreateAddress
  418. // ---------------------------------------------------------------------------
  419. // Description:             Creates a DPADDRESS using the address information
  420. //                            from the dialog.
  421. // Arguments:
  422. //  HWND                    [in] window handle
  423. //  LPDIRECTPLAYLOBBY2A      [in] DirectPlay Lobby interface to use
  424. //  LPGUID                    [in] GUID of servicer provider to create address for
  425. //  LPVOID*                    [out] pointer to return address in
  426. //  LPDWORD                    [out] pointer to return address size in
  427. // Returns:
  428. //  HRESULT                    any error creating the address
  429. HRESULT CreateAddress(HWND hWnd, LPDIRECTPLAYLOBBY2A lpDPlayLobby,
  430.                       LPGUID lpguidServiceProvider,
  431.                       LPVOID *lplpAddress, LPDWORD lpdwAddressSize)
  432. {
  433.     GUID                        guidAddressType;
  434.     ADDRESSTYPELIST                addressTypeList;
  435.     DPCOMPOUNDADDRESSELEMENT    addressElements[1 + ADDRESSTYPEMAX];
  436.     CHAR                        szPhoneNumberString[NAMEMAX];
  437.     CHAR                        szModemString[NAMEMAX];
  438.     CHAR                        szIPAddressString[NAMEMAX];
  439.     LPVOID                        lpAddress = NULL;
  440.     DWORD                        dwAddressSize = 0;
  441.     DWORD                        i, dwElementCount;
  442.     HRESULT                        hr;
  443.  
  444.     // get the list of address types for this service provider
  445.     ZeroMemory(&addressTypeList, sizeof(ADDRESSTYPELIST));
  446.     hr = lpDPlayLobby->lpVtbl->EnumAddressTypes(lpDPlayLobby,
  447.             EnumAddressTypes, lpguidServiceProvider, &addressTypeList, 0L);
  448.     if FAILED(hr)
  449.         goto Failure;
  450.  
  451.     dwElementCount = 0;
  452.  
  453.     // all DPADDRESS's must have a service provider chunk
  454.     addressElements[dwElementCount].guidDataType = DPAID_ServiceProvider;
  455.     addressElements[dwElementCount].dwDataSize = sizeof(GUID);
  456.     addressElements[dwElementCount].lpData = lpguidServiceProvider;
  457.     dwElementCount++;
  458.  
  459.     // loop over the address types
  460.     for (i = 0; i < addressTypeList.dwCount; i++)
  461.     {
  462.         guidAddressType = addressTypeList.guidAddressTypes[i];
  463.  
  464.         // phone number
  465.         if (IsEqualGUID(&guidAddressType, &DPAID_Phone))
  466.         {
  467.             // add a phone number chunk
  468.             GetDlgItemText(hWnd, IDC_ADDRESSEDIT, szPhoneNumberString, NAMEMAX);
  469.             addressElements[dwElementCount].guidDataType = DPAID_Phone;
  470.             addressElements[dwElementCount].dwDataSize = lstrlen(szPhoneNumberString) + 1;
  471.             addressElements[dwElementCount].lpData = szPhoneNumberString;
  472.             dwElementCount++;
  473.         }
  474.  
  475.         // modem
  476.         else if (IsEqualGUID(&guidAddressType, &DPAID_Modem))
  477.         {
  478.             // add a modem chunk
  479.             GetDlgItemText(hWnd, IDC_ADDRESSCOMBO, szModemString, NAMEMAX);
  480.             addressElements[dwElementCount].guidDataType = DPAID_Modem;
  481.             addressElements[dwElementCount].dwDataSize = lstrlen(szModemString) + 1;
  482.             addressElements[dwElementCount].lpData = szModemString;
  483.             dwElementCount++;
  484.         }
  485.  
  486.         // internet address
  487.         else if (IsEqualGUID(&guidAddressType, &DPAID_INet))
  488.         {
  489.             // add an IP address chunk
  490.             GetDlgItemText(hWnd, IDC_ADDRESSEDIT, szIPAddressString, NAMEMAX);
  491.             addressElements[dwElementCount].guidDataType = DPAID_INet;
  492.             addressElements[dwElementCount].dwDataSize = lstrlen(szIPAddressString) + 1;
  493.             addressElements[dwElementCount].lpData = szIPAddressString;
  494.             dwElementCount++;
  495.         }
  496.     }
  497.  
  498.     // bail if no address data is available
  499.     if (dwElementCount == 1)
  500.         return (DPERR_GENERIC);
  501.     
  502.     // see how much room is needed to store this address
  503.     hr = lpDPlayLobby->lpVtbl->CreateCompoundAddress(lpDPlayLobby,
  504.                         addressElements, dwElementCount,
  505.                         NULL, &dwAddressSize);
  506.     if (hr != DPERR_BUFFERTOOSMALL)
  507.         goto Failure;
  508.  
  509.     // allocate space
  510.     lpAddress = GlobalAllocPtr(GHND, dwAddressSize);
  511.     if (lpAddress == NULL)
  512.     {
  513.         hr = DPERR_NOMEMORY;
  514.         goto Failure;
  515.     }
  516.  
  517.     // create the address
  518.     hr = lpDPlayLobby->lpVtbl->CreateCompoundAddress(lpDPlayLobby,
  519.                         addressElements, dwElementCount,
  520.                         lpAddress, &dwAddressSize);
  521.     if FAILED(hr)
  522.         goto Failure;
  523.  
  524.     // return the address info
  525.     *lplpAddress = lpAddress;
  526.     *lpdwAddressSize = dwAddressSize;
  527.  
  528.     return (DP_OK);
  529.  
  530. Failure:
  531.     if (lpAddress)
  532.         GlobalFreePtr(lpAddress);
  533.  
  534.     return (hr);
  535. }
  536.  
  537. // ---------------------------------------------------------------------------
  538. // RunApplication
  539. // ---------------------------------------------------------------------------
  540. // Description:             Wrapper for the IDirectPlayLobby::RunApplication() method.
  541. // Arguments:
  542. //  LPDIRECTPLAYLOBBY2A        [in] DirectPlay Lobby interface to use
  543. //  LPGUID                    [in] GUID of application to launch
  544. //  LPGUID                    [in] GUID of session to host with
  545. //  LPSTR                    [in] GUID of service provider to connect with
  546. //  LPVOID                    [in] service-provider address to connect to
  547. //  DWORD                    [in] length of address
  548. //  LPSTR                    [in] name of session to host
  549. //  LPSTR                    [in] name of our player
  550. //  BOOL                    [in] TRUE to host session, FALSE to join
  551. // Returns:
  552. //  HRESULT                    any error running the application
  553. HRESULT RunApplication(LPDIRECTPLAYLOBBY2A lpDPlayLobby,
  554.                        LPGUID lpguidApplication,
  555.                        LPGUID lpguidInstance,
  556.                        LPGUID lpguidServiceProvider,
  557.                        LPVOID lpAddress,
  558.                        DWORD  dwAddressSize,
  559.                        LPSTR  lpszSessionName,
  560.                        LPSTR  lpszPlayerName,
  561.                        BOOL      bHostSession)
  562. {
  563.     DWORD                appID;
  564.     DPSESSIONDESC2        sessionInfo;
  565.     DPNAME                playerName;
  566.     DPLCONNECTION        connectInfo;
  567.     HRESULT                hr;
  568.  
  569.     if (lpDPlayLobby == NULL)
  570.         return (DPERR_NOINTERFACE);
  571.  
  572.     // fill out session description
  573.     ZeroMemory(&sessionInfo, sizeof(DPSESSIONDESC2));
  574.     sessionInfo.dwSize = sizeof(DPSESSIONDESC2);    // Size of structure
  575.     sessionInfo.dwFlags = 0;                        // DPSESSION_xxx flags
  576.     sessionInfo.guidInstance = *lpguidInstance;        // ID for the session instance
  577.     sessionInfo.guidApplication = *lpguidApplication;// GUID of the DirectPlay application.
  578.     sessionInfo.dwMaxPlayers = 0;                    // Maximum # players allowed in session
  579.     sessionInfo.dwCurrentPlayers = 0;                // Current # players in session (read only)
  580.     sessionInfo.lpszSessionNameA = lpszSessionName;    // ANSI name of the session
  581.     sessionInfo.lpszPasswordA = NULL;                // ANSI password of the session (optional)
  582.     sessionInfo.dwReserved1 = 0;                    // Reserved for future MS use.
  583.     sessionInfo.dwReserved2 = 0;
  584.     sessionInfo.dwUser1 = 0;                        // For use by the application
  585.     sessionInfo.dwUser2 = 0;
  586.     sessionInfo.dwUser3 = 0;
  587.     sessionInfo.dwUser4 = 0;
  588.  
  589.     // fill out player name
  590.     ZeroMemory(&playerName, sizeof(DPNAME));
  591.     playerName.dwSize = sizeof(DPNAME);                // Size of structure
  592.     playerName.dwFlags = 0;                            // Not used. Must be zero.
  593.     playerName.lpszShortNameA = lpszPlayerName;        // ANSI short or friendly name
  594.     playerName.lpszLongNameA = lpszPlayerName;        // ANSI long or formal name
  595.     
  596.     // fill out connection description
  597.     ZeroMemory(&connectInfo, sizeof(DPLCONNECTION));
  598.     connectInfo.dwSize = sizeof(DPLCONNECTION);        // Size of this structure
  599.     if (bHostSession)
  600.         connectInfo.dwFlags = DPLCONNECTION_CREATESESSION; // Create a new session
  601.     else
  602.         connectInfo.dwFlags = DPLCONNECTION_JOINSESSION; // Join existing session
  603.     connectInfo.lpSessionDesc = &sessionInfo;        // Pointer to session desc to use on connect
  604.     connectInfo.lpPlayerName = &playerName;            // Pointer to Player name structure
  605.     connectInfo.guidSP = *lpguidServiceProvider;    // GUID of the DPlay SP to use
  606.     connectInfo.lpAddress = lpAddress;                // Address for service provider
  607.     connectInfo.dwAddressSize = dwAddressSize;        // Size of address data
  608.  
  609.     // launch and connect the game
  610.     hr = lpDPlayLobby->lpVtbl->RunApplication(lpDPlayLobby,
  611.                                         0,            // Flags
  612.                                         &appID,        // App ID
  613.                                         &connectInfo,    // Connection data
  614.                                         NULL);        // Connect event
  615.     return (hr);
  616. }
  617.  
  618. // ---------------------------------------------------------------------------
  619. // LaunchDirectPlayApplication
  620. // ---------------------------------------------------------------------------
  621. // Description:             Gathers information from the dialog and runs the application.
  622. // Arguments:
  623. //  HWND                    [in] Window handle.
  624. //  LPDIRECTPLAYLOBBY2A      [in] DirectPlay Lobby interface to use
  625. // Returns:
  626. //  Nothing
  627. void LaunchDirectPlayApplication(HWND hWnd, LPDIRECTPLAYLOBBY2A lpDPlayLobby)
  628. {
  629.     GUID                guidApplication, guidSession, guidServiceProvider;
  630.     LPSTR                lpPlayerName, lpSessionName;
  631.     LPVOID                lpAddress = NULL;
  632.     DWORD                dwAddressSize = 0;
  633.     CHAR                szPlayerName[NAMEMAX], szSessionName[NAMEMAX];
  634.     LRESULT                iHost;
  635.     HRESULT                hr;
  636.  
  637.     SetDlgItemText(hWnd, IDC_STATUSEDIT, "Launching...");
  638.  
  639.     // get guid of application to launch
  640.     hr = GetComboBoxGuid(hWnd, IDC_APPCOMBO, &guidApplication);
  641.     if FAILED(hr)
  642.         goto Failure;
  643.  
  644.     // get guid of service provider to use
  645.     hr = GetComboBoxGuid(hWnd, IDC_SPCOMBO, &guidServiceProvider);
  646.     if FAILED(hr)
  647.         goto Failure;
  648.  
  649.     // get address to use with this service provider
  650.     hr = CreateAddress(hWnd, lpDPlayLobby, &guidServiceProvider,
  651.                        &lpAddress, &dwAddressSize);
  652.     // ignore the error because lpAddress will just be null
  653.  
  654.     // get guid of session to create.
  655.     guidSession = MY_SESSION_GUID;
  656.     
  657.     // get name of our player
  658.     GetDlgItemText(hWnd, IDC_PLAYEREDIT, szPlayerName, NAMEMAX);
  659.     lpPlayerName = szPlayerName;
  660.  
  661.     // get host vs. join flag
  662.     iHost = SendDlgItemMessage(hWnd, IDC_HOSTRADIO, BM_GETCHECK, (WPARAM) 0, 0);
  663.     if (iHost == BST_CHECKED)
  664.     {
  665.         iHost = TRUE;            // we are hosting a session
  666.  
  667.         // get name of session
  668.         GetDlgItemText(hWnd, IDC_SESSIONEDIT, szSessionName, NAMEMAX);
  669.         lpSessionName = szSessionName;
  670.     }
  671.     else
  672.     {
  673.         iHost = FALSE;            // we are joining an existing session
  674.         lpSessionName = NULL;    // don't need a session name if we are joining
  675.     }
  676.  
  677.     // launch the application
  678.     hr = RunApplication(lpDPlayLobby,
  679.                         &guidApplication,
  680.                         &guidSession,
  681.                         &guidServiceProvider,
  682.                         lpAddress, dwAddressSize,
  683.                         lpSessionName, lpPlayerName,
  684.                         iHost);
  685.     if FAILED(hr)
  686.         goto Failure;
  687.  
  688.     SetDlgItemText(hWnd, IDC_STATUSEDIT, "Launch successful");
  689.  
  690.     if (lpAddress)
  691.         GlobalFreePtr(lpAddress);
  692.     return;
  693.  
  694. Failure:
  695.     if (lpAddress)
  696.         GlobalFreePtr(lpAddress);
  697.  
  698.     SetDlgItemText(hWnd, IDC_STATUSEDIT, "Launch failed");
  699.  
  700.     return;
  701. }
  702.  
  703. // ---------------------------------------------------------------------------
  704. // GetComboBoxGuid
  705. // ---------------------------------------------------------------------------
  706. // Description:             Returns GUID stored with a combo box item
  707. // Arguments:
  708. //  HWND                    [in]  Window handle.
  709. //  LONG                    [in]  Dialog box item ID of combo box
  710. //  LPGUID                    [out] GUID stored with item in combo box
  711. // Returns:
  712. //  HRESULT                    any error getting the GUID
  713. HRESULT GetComboBoxGuid(HWND hWnd, LONG iDialogItem, LPGUID lpguidReturn)
  714. {
  715.     LONG    iIndex;
  716.  
  717.     // get index of selected item
  718.     iIndex = SendDlgItemMessage(hWnd, iDialogItem, CB_GETCURSEL,
  719.                                 (WPARAM) 0, (LPARAM) 0);
  720.     if (iIndex == CB_ERR)
  721.         return (DPERR_GENERIC);
  722.  
  723.     // get data associated with this item
  724.     iIndex = SendDlgItemMessage(hWnd, iDialogItem, CB_GETITEMDATA,
  725.                                 (WPARAM) iIndex, (LPARAM) 0);
  726.     if ((iIndex == CB_ERR) || (iIndex == 0))
  727.         return (DPERR_GENERIC);
  728.  
  729.     // data is a pointer to a guid
  730.     *lpguidReturn = *((LPGUID) iIndex);
  731.  
  732.     return (DP_OK);
  733. }
  734.  
  735. // ---------------------------------------------------------------------------
  736. // EnumModemAddress
  737. // ---------------------------------------------------------------------------
  738. // Description:             Enumeration callback called by DirectPlayLobby.
  739. //                            Enumerates the DirectPlay address chunks. If the
  740. //                            chunk contains modem strings, add them to the control.
  741. // Arguments:
  742. //  REFGUID                 [in] GUID of the address type
  743. //  DWORD                    [in] size of chunk
  744. //  LPVOID                    [in] pointer to chunk
  745. //  LPVOID                    [in] user-defined context
  746. // Returns:
  747. //  BOOL                    FALSE to stop enumerating after the first callback
  748. BOOL FAR PASCAL EnumModemAddress(REFGUID lpguidDataType, DWORD dwDataSize,
  749.                             LPCVOID lpData, LPVOID lpContext)
  750. {
  751.     HWND    hWnd = (HWND) lpContext;
  752.     LPSTR    lpszStr = (LPSTR) lpData;
  753.  
  754.     // modem
  755.     if (IsEqualGUID(lpguidDataType, &DPAID_Modem))
  756.     {
  757.         // loop over all strings in list
  758.         while (lstrlen(lpszStr))
  759.         {
  760.             // store modem name in combo box
  761.             SendDlgItemMessage(hWnd, IDC_ADDRESSCOMBO, CB_ADDSTRING, 0, (LPARAM) lpszStr);
  762.  
  763.             // skip to next string
  764.             lpszStr += lstrlen(lpszStr) + 1;
  765.         }
  766.     }
  767.  
  768.     return (TRUE);
  769. }
  770.  
  771. // ---------------------------------------------------------------------------
  772. // FillModemComboBox
  773. // ---------------------------------------------------------------------------
  774. // Description:             Fills combo box with modem names
  775. // Arguments:
  776. //  HWND                    [in]  Window handle.
  777. //  LPDIRECTPLAYLOBBY2A     [in]  DirectPlay Lobby interface to use
  778. //  LPGUID                    [out] GUID of service provider to use
  779. // Returns:
  780. //  HRESULT                    any error
  781. HRESULT FillModemComboBox(HWND hWnd, LPDIRECTPLAYLOBBY2A lpDPlayLobby, LPGUID lpguidServiceProvider)
  782. {
  783.     LPDIRECTPLAY        lpDPlay1 = NULL;
  784.     LPDIRECTPLAY3A        lpDPlay3A = NULL;
  785.     LPVOID                lpAddress = NULL;
  786.     DWORD                dwAddressSize = 0;
  787.     HRESULT                hr;
  788.  
  789.     // get a DirectPlay interface for this service provider
  790.     hr = DirectPlayCreate(lpguidServiceProvider, &lpDPlay1, NULL);
  791.     if FAILED(hr)
  792.         goto Failure;
  793.  
  794.     // query for an ANSI DirectPlay3 interface
  795.     hr = lpDPlay1->lpVtbl->QueryInterface(lpDPlay1, &IID_IDirectPlay3A, (LPVOID *) &lpDPlay3A);
  796.     if FAILED(hr)
  797.         goto Failure;
  798.  
  799.     // get size of player address for player zero
  800.     hr = lpDPlay3A->lpVtbl->GetPlayerAddress(lpDPlay3A, DPID_ALLPLAYERS, NULL, &dwAddressSize);
  801.     if (hr != DPERR_BUFFERTOOSMALL)
  802.         goto Failure;
  803.  
  804.     // make room for it
  805.     lpAddress = GlobalAllocPtr(GHND, dwAddressSize);
  806.     if (lpAddress == NULL)
  807.     {
  808.         hr = DPERR_NOMEMORY;
  809.         goto Failure;
  810.     }
  811.  
  812.     // get the address
  813.     hr = lpDPlay3A->lpVtbl->GetPlayerAddress(lpDPlay3A, DPID_ALLPLAYERS, lpAddress, &dwAddressSize);
  814.     if FAILED(hr)
  815.         goto Failure;
  816.     
  817.     // get modem strings from address and put them in the combo box
  818.     hr = lpDPlayLobby->lpVtbl->EnumAddress(lpDPlayLobby, EnumModemAddress, 
  819.                              lpAddress, dwAddressSize, hWnd);
  820.     if FAILED(hr)
  821.         goto Failure;
  822.  
  823.     // select first item in list
  824.     SendDlgItemMessage(hWnd, IDC_ADDRESSCOMBO, CB_SETCURSEL, (WPARAM) 0, 0);
  825.  
  826. Failure:
  827.     if (lpDPlay1)
  828.         lpDPlay1->lpVtbl->Release(lpDPlay1);
  829.     if (lpDPlay3A)
  830.         lpDPlay3A->lpVtbl->Release(lpDPlay3A);
  831.     if (lpAddress)
  832.         GlobalFreePtr(lpAddress);
  833.  
  834.     return (hr);
  835. }
  836.  
  837.