home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Demos / Duel / wizard.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  44.8 KB  |  1,296 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Wizard.cpp
  3. //
  4. // Desc: UI routines
  5. //
  6. // Copyright (C) 1995-2001 Microsoft Corporation. All Rights Reserved.
  7. //-----------------------------------------------------------------------------
  8. #include "duel.h"
  9. #include "prsht.h"
  10. #include "wizard.h"
  11. #include "lobby.h"
  12. #include "DPUtil.h"
  13. #include "gameproc.h"
  14.  
  15.  
  16. //-----------------------------------------------------------------------------
  17. // Globals
  18. //-----------------------------------------------------------------------------
  19. extern HINSTANCE     g_hInst;          // Program instance
  20. extern HWND          g_hwndMain;       // Main window
  21. extern LPDIRECTPLAY4 g_pDP;            // DPlay object pointer
  22. extern BOOL          g_bHostPlayer;    // Is the user hosting/joining a game
  23. extern DPID          g_LocalPlayerDPID;// Player id
  24. extern LPGUID        g_pAppGUID;       // Duel's guid
  25. extern BOOL          g_bUseProtocol;   // DPlay Protocol messaging
  26.  
  27. static BOOL          gbWaitForLobby;   // We will Wait for Settings from Lobby
  28. static HFONT         ghTitleFont;      // Font for titles on setup wizard
  29. static HFONT         ghHeadingFont;    // Font for headings on setup wizard
  30. static int           gnSession;        // Index for tree view images
  31. static int           gnPlayer;         // Index for tree view images
  32. static HKEY          ghDuelKey = NULL; // Duel registry key handle
  33. static DWORD         gdwDuelDisp;      // Key created or opened
  34. static HTREEITEM     ghtiSession;      // Points to a visible session item in
  35.                                        // tree ctl used for inserting players
  36. static HWND          ghWndSPCtl;       // Handle to service provider control
  37.  
  38.  
  39.                                        
  40.                                        
  41. //-----------------------------------------------------------------------------
  42. // Name: SetupFonts()
  43. // Desc: Initializes font structures (used for wizard controls)
  44. //-----------------------------------------------------------------------------
  45. BOOL SetupFonts()
  46. {
  47.     LOGFONT lf;
  48.     TCHAR   strFontName[MAX_FONTNAME];
  49.     HDC hDC = GetDC(g_hwndMain);
  50.     if (!hDC)
  51.         return FALSE;
  52.  
  53.     LoadString(g_hInst, IDS_WIZARD_FONTNAME, strFontName, MAX_FONTNAME);
  54.  
  55.     ZeroMemory(&lf,sizeof(lf));
  56.     lf.lfHeight = -MulDiv(11,GetDeviceCaps(hDC, LOGPIXELSY),72);
  57.     lf.lfWeight = 500;
  58.     lf.lfItalic = TRUE;
  59.     _tcscpy( lf.lfFaceName, strFontName );
  60.     ghTitleFont = CreateFontIndirect(&lf);
  61.  
  62.     ZeroMemory(&lf,sizeof(lf));
  63.     lf.lfHeight = -MulDiv(11,GetDeviceCaps(hDC, LOGPIXELSY),72);
  64.     lf.lfWeight = 500;
  65.     _tcscpy( lf.lfFaceName, strFontName );
  66.     ghHeadingFont = CreateFontIndirect(&lf);
  67.  
  68.     ReleaseDC(g_hwndMain, hDC);
  69.  
  70.     if (!ghTitleFont || !ghHeadingFont)
  71.     {
  72.         CleanupFonts();
  73.         return FALSE;
  74.     }
  75.     return TRUE;
  76. }
  77.  
  78.  
  79.  
  80.  
  81. //-----------------------------------------------------------------------------
  82. // Name: CleanupFonts()
  83. // Desc: Cleans up font structures
  84. //-----------------------------------------------------------------------------
  85. VOID CleanupFonts()
  86. {
  87.     if (ghTitleFont)
  88.         DeleteObject(ghTitleFont);
  89.     if (ghHeadingFont)
  90.         DeleteObject(ghHeadingFont);
  91.     ghTitleFont = NULL;
  92.     ghHeadingFont = NULL;
  93. }
  94.  
  95.  
  96.  
  97.  
  98. //-----------------------------------------------------------------------------
  99. // Name: RegSet()
  100. // Desc: Stores a data value in the registry
  101. //-----------------------------------------------------------------------------
  102. LONG RegSet( const TCHAR* strName, const BYTE* pData, DWORD dwSize )
  103. {
  104. #ifdef UNICODE
  105.     dwSize *= 2; // calc number of bytes
  106. #endif
  107.     return RegSetValueEx( ghDuelKey, strName, 0, REG_SZ, pData, dwSize );
  108. }
  109.  
  110.  
  111.  
  112.  
  113. //-----------------------------------------------------------------------------
  114. // Name: RegGet()
  115. // Desc: Queries a value from the registry
  116. //-----------------------------------------------------------------------------
  117. LONG RegGet( const TCHAR* strName, BYTE* pData, DWORD* pdwDataSize )
  118. {
  119.     DWORD dwType;
  120.  
  121.     return RegQueryValueEx( ghDuelKey, strName, NULL, &dwType, pData,
  122.                             pdwDataSize );
  123. }
  124.  
  125.  
  126.  
  127.  
  128. //-----------------------------------------------------------------------------
  129. // Name: DoWizard()
  130. // Desc: Creates and launches a wizard (property sheets) for user input
  131. //-----------------------------------------------------------------------------
  132. DWORD WINAPI DoWizard(LPVOID pv)
  133. {
  134.     PROPSHEETPAGE psp[4];
  135.     PROPSHEETHEADER psh;
  136.     TCHAR strTitle1[MAX_WINDOWTITLE];
  137.     TCHAR strTitle2[MAX_WINDOWTITLE];
  138.     TCHAR strTitle3[MAX_WINDOWTITLE];
  139.     TCHAR strTitle4[MAX_WINDOWTITLE];
  140.     TCHAR strTitle5[MAX_WINDOWTITLE];
  141.  
  142.     CoInitialize(NULL);
  143.     
  144.     // Setup the property pages
  145.  
  146.     LoadString(g_hInst, IDS_WIZARD_TITLE_GS, strTitle1, MAX_WINDOWTITLE); 
  147.     LoadString(g_hInst, IDS_WIZARD_TITLE_SP, strTitle2, MAX_WINDOWTITLE); 
  148.     LoadString(g_hInst, IDS_WIZARD_TITLE_JS, strTitle3, MAX_WINDOWTITLE); 
  149.     LoadString(g_hInst, IDS_WIZARD_TITLE_HS, strTitle4, MAX_WINDOWTITLE); 
  150.     LoadString(g_hInst, IDS_WIZARD_TITLE,    strTitle5, MAX_WINDOWTITLE); 
  151.  
  152.     psp[0].dwSize    = sizeof(PROPSHEETPAGE);
  153.     psp[0].dwFlags   = PSP_USETITLE;
  154.     psp[0].hInstance = g_hInst;
  155. #ifdef NONAMELESSUNION
  156.     psp[0].u.pszTemplate = MAKEINTRESOURCE(IDD_GAMESETUP);
  157.     psp[0].u2.pszIcon    = NULL; 
  158. #else
  159.     psp[0].pszTemplate = MAKEINTRESOURCE(IDD_GAMESETUP);
  160.     psp[0].pszIcon     = NULL; 
  161. #endif
  162.     psp[0].pfnDlgProc  = (DLGPROC)DlgProcGameSetup;
  163.     psp[0].pszTitle    = strTitle1;
  164.     psp[0].lParam      = 0;
  165.     psp[0].pfnCallback = NULL;
  166.  
  167.     psp[1].dwSize    = sizeof(PROPSHEETPAGE);
  168.     psp[1].dwFlags   = PSP_USETITLE;
  169.     psp[1].hInstance = g_hInst;
  170. #ifdef NONAMELESSUNION
  171.     psp[1].u.pszTemplate = MAKEINTRESOURCE(IDD_CHOOSEPROVIDER);
  172.     psp[1].u2.pszIcon    = NULL; 
  173. #else
  174.     psp[1].pszTemplate = MAKEINTRESOURCE(IDD_CHOOSEPROVIDER);
  175.     psp[1].pszIcon     = NULL; 
  176. #endif
  177.     psp[1].pfnDlgProc  = (DLGPROC)DlgProcChooseProvider;
  178.     psp[1].pszTitle    = strTitle2;
  179.     psp[1].lParam      = 0;
  180.     psp[1].pfnCallback = NULL;
  181.  
  182.     psp[2].dwSize    = sizeof(PROPSHEETPAGE);
  183.     psp[2].dwFlags   = PSP_USETITLE;
  184.     psp[2].hInstance = g_hInst;
  185. #ifdef NONAMELESSUNION
  186.     psp[2].u.pszTemplate = MAKEINTRESOURCE(IDD_JOINSESSION);
  187.     psp[2].u2.pszIcon    = NULL; 
  188. #else
  189.     psp[2].pszTemplate = MAKEINTRESOURCE(IDD_JOINSESSION);
  190.     psp[2].pszIcon     = NULL; 
  191. #endif
  192.     psp[2].pfnDlgProc  = (DLGPROC)DlgProcJoinSession;
  193.     psp[2].pszTitle    = strTitle3;
  194.     psp[2].lParam      = 0;
  195.     psp[2].pfnCallback = NULL;
  196.  
  197.     psp[3].dwSize    = sizeof(PROPSHEETPAGE);
  198.     psp[3].dwFlags   = PSP_USETITLE;
  199.     psp[3].hInstance = g_hInst;
  200. #ifdef NONAMELESSUNION
  201.     psp[3].u.pszTemplate = MAKEINTRESOURCE(IDD_HOSTSESSION);
  202.     psp[3].u2.pszIcon    = NULL; 
  203. #else
  204.     psp[3].pszTemplate = MAKEINTRESOURCE(IDD_HOSTSESSION);
  205.     psp[3].pszIcon     = NULL; 
  206. #endif
  207.     psp[3].pfnDlgProc  = (DLGPROC)DlgProcHostSession;
  208.     psp[3].pszTitle    = strTitle4;
  209.     psp[3].lParam      = 0;
  210.     psp[3].pfnCallback = NULL;
  211.     
  212.     psh.dwSize     = sizeof(PROPSHEETHEADER);
  213.     psh.dwFlags    = PSH_PROPSHEETPAGE | PSH_WIZARD;
  214.     psh.hwndParent = g_hwndMain;
  215.     psh.hInstance  = g_hInst;
  216. #ifdef NONAMELESSUNION
  217.     psh.u.pszIcon     = NULL;
  218.     psh.u2.nStartPage = 0;
  219.     psh.u3.ppsp       = (LPCPROPSHEETPAGE) &psp;
  220. #else
  221.     psh.pszIcon    = NULL;
  222.     psh.nStartPage = 0;
  223.     psh.ppsp       = (LPCPROPSHEETPAGE) &psp;
  224. #endif
  225.     psh.pszCaption  = strTitle5;
  226.     psh.nPages      = sizeof(psp) / sizeof(PROPSHEETPAGE);
  227.     psh.pfnCallback = NULL;
  228.  
  229.     // open/create duel registry key 
  230.     if( ERROR_SUCCESS != RegCreateKeyEx( HKEY_CURRENT_USER, DUEL_KEY, 0, NULL,
  231.                                          REG_OPTION_NON_VOLATILE,
  232.                                          KEY_ALL_ACCESS, NULL, &ghDuelKey,
  233.                                          &gdwDuelDisp ) )
  234.     {
  235.         TRACE(_T("Failed to create/open registry key\n"));
  236.         ShowError(IDS_WIN_ERROR);
  237.         goto ABORT;
  238.     }
  239.  
  240.     if (!SetupFonts())
  241.     {
  242.         TRACE(_T("Failed to create fonts\n"));
  243.         ShowError(IDS_WIN_ERROR);
  244.         goto ABORT;
  245.     }
  246.  
  247.     // launch the wizard
  248.     if (PropertySheet(&psh) < 0)
  249.     {
  250.         TRACE(_T("PropertySheet failed (comctl32.dll)\n"));
  251.         ShowError(IDS_WIN_ERROR);
  252.         goto ABORT;
  253.     }
  254.  
  255.     CleanupFonts();
  256.     
  257.     // Are we going to wait for a lobby to connect to us?
  258.     if (gbWaitForLobby)
  259.         gbWaitForLobby = DPLobbyWait();
  260.         // gbWaitForLobby now means we successfully got our connection settings
  261.  
  262.     // Do we have our settings or a game session?
  263.     if( gbWaitForLobby || DPUtil_IsDPlayInitialized() )
  264.     {
  265.         // success
  266.         CoUninitialize();
  267.         PostMessage(g_hwndMain, UM_LAUNCH, (WPARAM)gbWaitForLobby, 0);
  268.         gbWaitForLobby = FALSE;     // done with this flag
  269.         return 0;
  270.     }
  271.  
  272. ABORT:
  273.     // failure
  274.     CoUninitialize();
  275.     PostMessage(g_hwndMain, UM_ABORT, 0, 0);
  276.     return 1;
  277. }
  278.  
  279.  
  280.  
  281.  
  282. //-----------------------------------------------------------------------------
  283. // Name: DPEnumConnectionsCallback()
  284. // Desc: Creates SP list box entries and associates connection data with them
  285. //-----------------------------------------------------------------------------
  286. BOOL FAR PASCAL DPEnumConnectionsCallback( const GUID* pguidSP,
  287.                                            VOID* pConnection, DWORD dwSize,
  288.                                            const DPNAME* pName, DWORD dwFlags,
  289.                                            VOID* pContext )
  290. {
  291.     HWND    hWnd = (HWND)pContext;
  292.     LRESULT iIndex;
  293.     VOID*   pConnectionBuffer;
  294.  
  295.     // Store service provider name in combo box
  296. #ifdef UNICODE
  297.     iIndex = SendMessage( hWnd, LB_ADDSTRING, 0, (LPARAM)pName->lpszShortName );
  298. #else
  299.     iIndex = SendMessage( hWnd, LB_ADDSTRING, 0, (LPARAM)pName->lpszShortNameA );
  300. #endif
  301.  
  302.     if( iIndex == CB_ERR )
  303.         return TRUE;
  304.  
  305.     // Make space for Connection Shortcut
  306.     pConnectionBuffer = GlobalAllocPtr( GHND, dwSize );
  307.     if( pConnectionBuffer == NULL )
  308.         return TRUE;
  309.  
  310.     // Store pointer to GUID in combo box
  311.     memcpy( pConnectionBuffer, pConnection, dwSize );
  312.  
  313.     if( iIndex != LB_ERR )
  314.         SendMessage( hWnd, LB_SETITEMDATA, iIndex, (LPARAM)pConnectionBuffer );
  315.  
  316.     return TRUE;
  317. }
  318.  
  319.  
  320.  
  321.  
  322. //-----------------------------------------------------------------------------
  323. // Name: DlgProcChooseProvider()
  324. // Desc: Dialog procedure for the choose service provider dialog
  325. //-----------------------------------------------------------------------------
  326. BOOL CALLBACK DlgProcChooseProvider( HWND hDlg, UINT msg, WPARAM wParam,
  327.                                      LPARAM lParam )
  328. {
  329.     VOID*        pCon = NULL;
  330.     static  LONG iIndex;
  331.     static  HWND hWndCtl;
  332.     HRESULT      hr;
  333.  
  334.     switch( msg )
  335.     {
  336.         case WM_NOTIFY:
  337.             switch( ((NMHDR FAR *)lParam)->code )
  338.             {
  339.                 case PSN_SETACTIVE:
  340.                     PropSheet_SetWizButtons( GetParent(hDlg),
  341.                                              PSWIZB_BACK | PSWIZB_NEXT );
  342.                     return TRUE;
  343.  
  344.                 case PSN_WIZNEXT: 
  345.                     // Release previously selected DPlay object, if any.
  346.                     DPUtil_Release();
  347.                     if( iIndex != LB_ERR )
  348.                     {
  349.                         pCon = (VOID*)SendMessage( hWndCtl, LB_GETITEMDATA,
  350.                                                    iIndex, 0 );
  351.                         if( pCon )
  352.                         {
  353.                             // Create directplay object
  354.                             if( SUCCEEDED( DPUtil_InitDirectPlay( pCon ) ) )
  355.                             {
  356.                                 if( g_bHostPlayer ) // Skip to host page
  357.                                     SetWindowLong( hDlg, DWL_MSGRESULT,
  358.                                                    IDD_HOSTSESSION );
  359.                                 return TRUE;
  360.                             }
  361.                             else
  362.                             {
  363.                                 ShowError(IDS_DPLAY_ERROR_IDC);
  364.                             }
  365.                         }
  366.                     }
  367.                     SetWindowLong( hDlg, DWL_MSGRESULT, -1 );
  368.                     return TRUE;
  369.  
  370.                 case PSN_QUERYCANCEL:
  371.                     ReleaseSPData();
  372.                     DPUtil_Release();       // Indicates no game session
  373.                     return TRUE;
  374.             }
  375.             break;
  376.  
  377.         case WM_INITDIALOG:
  378.             SendDlgItemMessage( hDlg, IDC_SP_TITLE, WM_SETFONT,
  379.                                 (WPARAM)ghTitleFont, MAKELPARAM(TRUE,0) );
  380.  
  381.             hWndCtl = GetDlgItem( hDlg, IDC_SERVICEPROVIDERS );
  382.             if( hWndCtl == NULL )
  383.                 return TRUE;
  384.  
  385.             // Remember the service provider control. used later in freeing
  386.             // sp information.
  387.             ghWndSPCtl = hWndCtl;
  388.  
  389.             if( FAILED( hr = DPUtil_InitDirectPlay( pCon ) ) )
  390.             {
  391.                 // Class not available, so tell them to get DPlay 6 or later
  392.                 if( (hr == REGDB_E_CLASSNOTREG) || (hr == REGDB_E_IIDNOTREG) ||
  393.                     (hr == E_NOINTERFACE))
  394.                     ShowError(IDS_DPLAY_ERROR_CLSID);
  395.                 else
  396.                     ShowError(IDS_DPLAY_ERROR_IDC);
  397.                 
  398.                 SetWindowLong( hDlg, DWL_MSGRESULT, -1 );
  399.                 PostQuitMessage( -1 );
  400.                 return TRUE;
  401.             }
  402.  
  403.             //Insert all available connections into the connection listbox.
  404.             g_pDP->EnumConnections( g_pAppGUID, DPEnumConnectionsCallback,
  405.                                     hWndCtl, 0 );
  406.             SetFocus( hWndCtl );
  407.  
  408.             SendMessage( hWndCtl, LB_SETCURSEL, iIndex, 0 );
  409.             iIndex = SendMessage( hWndCtl, LB_GETCURSEL, 0, 0 );
  410.             return TRUE;
  411.  
  412.         case WM_COMMAND:
  413.             if( HIWORD(wParam) == LBN_SELCHANGE )
  414.             {
  415.                 iIndex = SendMessage( hWndCtl, LB_GETCURSEL, 0, 0 );
  416.                 return TRUE;
  417.             }
  418.             break;
  419.     }
  420.  
  421.     return FALSE;
  422. }
  423.  
  424.  
  425.  
  426.  
  427. //-----------------------------------------------------------------------------
  428. // Name: DlgProcGameSetup()
  429. // Desc: Dialog procedure for the Game Setup Dialog.
  430. //-----------------------------------------------------------------------------
  431. BOOL CALLBACK DlgProcGameSetup (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  432. {
  433.     static BOOL bWaitForLobby;
  434.     switch (msg)
  435.     {
  436.     case WM_NOTIFY:
  437.         switch (((NMHDR FAR *) lParam)->code) 
  438.         {
  439.             case PSN_SETACTIVE:
  440.                 if (bWaitForLobby)
  441.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_FINISH);
  442.                 else    
  443.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
  444.                 return(TRUE);
  445.             
  446.             case PSN_WIZNEXT: 
  447.                 if (g_bHostPlayer)
  448.                     g_bUseProtocol = (SendDlgItemMessage(hDlg, IDC_USEPROTOCOL,
  449.                                                         BM_GETCHECK, 0, 0)
  450.                                      == BST_CHECKED);
  451.                 else
  452.                     g_bUseProtocol = FALSE;
  453.                 return(TRUE);
  454.  
  455.             case PSN_WIZFINISH:     // only if WaitForLobby selected 
  456.                 gbWaitForLobby = bWaitForLobby;
  457.                 // fall thru
  458.             case PSN_QUERYCANCEL:
  459.                 ReleaseSPData();
  460.                 DPUtil_Release();       // Indicates no game session
  461.                 return(TRUE);
  462.         }
  463.         break;
  464.  
  465.     case WM_INITDIALOG:
  466.         // setup title fonts
  467.         SendDlgItemMessage(hDlg, IDC_GAMESETUP_TITLE, WM_SETFONT, (WPARAM)ghTitleFont, MAKELPARAM(TRUE,0));
  468.         SendDlgItemMessage(hDlg, IDC_JOINSESSION, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  469.         SendDlgItemMessage(hDlg, IDC_HOSTSESSION, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  470.         SendDlgItemMessage(hDlg, IDC_WAITFORLOBBY, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  471.         SendDlgItemMessage(hDlg, IDC_USEPROTOCOL, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  472.         // host by default
  473.         g_bHostPlayer = TRUE;
  474.         gbWaitForLobby = bWaitForLobby = FALSE;
  475.         SendDlgItemMessage(hDlg, IDC_HOSTSESSION, BM_SETCHECK, 1, 0);
  476.         SendDlgItemMessage(hDlg, IDC_JOINSESSION, BM_SETCHECK, 0, 0);
  477.         SendDlgItemMessage(hDlg, IDC_WAITFORLOBBY, BM_SETCHECK, 0, 0);
  478.         SendDlgItemMessage(hDlg, IDC_USEPROTOCOL, BM_SETCHECK, g_bUseProtocol, 0);
  479.         return(TRUE);
  480.  
  481.     case WM_COMMAND:
  482.         if (HIWORD(wParam) == BN_CLICKED)
  483.             switch (LOWORD(wParam))
  484.             {
  485.                 // Enable Use Protocol check box only if Hosting is selected
  486.                 // Enable Finish Button only if WaitForLobby is selected
  487.             case IDC_HOSTSESSION:
  488.                 g_bHostPlayer = TRUE;
  489.                 EnableWindow(GetDlgItem(hDlg, IDC_USEPROTOCOL), TRUE);
  490.                 if (bWaitForLobby)
  491.                 {
  492.                     bWaitForLobby = FALSE;
  493.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
  494.                 }
  495.                 return(TRUE);
  496.  
  497.             case IDC_JOINSESSION:
  498.                 if (g_bHostPlayer)
  499.                 {
  500.                     g_bHostPlayer = FALSE;
  501.                     EnableWindow(GetDlgItem(hDlg, IDC_USEPROTOCOL), FALSE);
  502.                 }
  503.                 if (bWaitForLobby)
  504.                 {
  505.                     bWaitForLobby = FALSE;
  506.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_NEXT);
  507.                 }
  508.                 return(TRUE);
  509.  
  510.             case IDC_WAITFORLOBBY:
  511.                 bWaitForLobby = TRUE;
  512.                 PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_FINISH);
  513.                 if (g_bHostPlayer)
  514.                 {
  515.                     g_bHostPlayer = FALSE;
  516.                     EnableWindow(GetDlgItem(hDlg, IDC_USEPROTOCOL), FALSE);
  517.                 }
  518.                 return(TRUE);
  519.             }
  520.         break;
  521.     }
  522.     return(FALSE);
  523. }
  524.  
  525.  
  526.  
  527.  
  528. //-----------------------------------------------------------------------------
  529. // Name: EnumPlayer()
  530. // Desc: EnumeratePlayer callback. Inserts player information into the passed
  531. //       in tree view control.
  532. //-----------------------------------------------------------------------------
  533. BOOL WINAPI EnumPlayer( DPID pidID, DWORD dwPlayerType, const DPNAME* pName,
  534.                         DWORD dwFlags, VOID* pContext )
  535. {
  536.     HWND      hWnd = (HWND)pContext;
  537.     HTREEITEM hItem;
  538.  
  539. #ifdef UNICODE
  540.     hItem = AddItemToTree( hWnd, pName->lpszShortName, 0, -1 );
  541. #else
  542.     hItem = AddItemToTree( hWnd, pName->lpszShortNameA, 0, -1 );
  543. #endif
  544.  
  545.     return TRUE;
  546. }
  547.  
  548.  
  549.  
  550.  
  551. //-----------------------------------------------------------------------------
  552. // Name: EnumSession()
  553. // Desc: EnumSessions callback. Inserts session description information in the
  554. //       passed in tree view control.
  555. //-----------------------------------------------------------------------------
  556. BOOL WINAPI EnumSession( const DPSESSIONDESC2* pDPSessionDesc,
  557.                          DWORD* pdwTimeOut, DWORD dwFlags, VOID* pContext )
  558. {
  559.     HWND      hWnd = (HWND)pContext;
  560.     HTREEITEM hItem;
  561.     TREEDATA* pdata;
  562.  
  563.     if( dwFlags & DPESC_TIMEDOUT )
  564.         return FALSE;       // don't try again
  565.  
  566.     if( hWnd == NULL )
  567.         return FALSE;
  568.  
  569.     // allocate memory to remember the guid
  570.     pdata = (TREEDATA*)malloc(sizeof(TREEDATA));
  571.     if( NULL == pdata )
  572.         return FALSE;
  573.  
  574.     pdata->guid      = pDPSessionDesc->guidInstance;
  575.     pdata->dwRefresh = 1;
  576.     
  577. #ifdef UNICODE
  578.     hItem = AddItemToTree( hWnd, pDPSessionDesc->lpszSessionName,
  579.                            (DWORD)pdata, 1);
  580. #else
  581.     hItem = AddItemToTree( hWnd, pDPSessionDesc->lpszSessionNameA,
  582.                            (DWORD)pdata, 1);
  583. #endif
  584.  
  585.     if( hItem )
  586.     {
  587.         // It was new
  588.         TreeView_SelectItem( hWnd, hItem );
  589.         // Enumerate players for new session
  590.         DPUtil_EnumPlayers( (GUID*)&pDPSessionDesc->guidInstance, EnumPlayer,
  591.                           (VOID*)hWnd, DPENUMPLAYERS_SESSION );
  592.     }
  593.     else 
  594.     {
  595.         // It was already in the tree
  596.         free( pdata );
  597.     }
  598.  
  599.     return TRUE;
  600. }
  601.  
  602.  
  603.  
  604.  
  605. //-----------------------------------------------------------------------------
  606. // Name: ResetTreeRefresh()
  607. // Desc:
  608. //-----------------------------------------------------------------------------
  609. VOID ResetTreeRefresh( HWND hwndTV )
  610. {
  611.     TV_ITEM   item;
  612.     HTREEITEM hItem;
  613.     TREEDATA* psearchdata;
  614.  
  615.     memset( &item, 0, sizeof(item) );
  616.     
  617.     // Get the first app item (child of the running apps item)
  618.     hItem = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_ROOT,(LPARAM) NULL);    
  619.     
  620.     while (hItem)
  621.     {
  622.         // gets its data
  623.         item.mask = TVIF_PARAM;
  624.         item.hItem = hItem;
  625.         SendMessage( hwndTV, TVM_GETITEM, 0, (LPARAM)&item );
  626.         // set the dwRefresh to 0
  627.         psearchdata = (TREEDATA*)item.lParam;
  628.         if (psearchdata) psearchdata->dwRefresh = 0;
  629.         SendMessage( hwndTV, TVM_SETITEM, 0, (LPARAM)&item );
  630.  
  631.         // get the next one
  632.         hItem = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem );    
  633.     }    
  634.     
  635.     return ;
  636. }
  637.  
  638.  
  639.  
  640.  
  641. //-----------------------------------------------------------------------------
  642. // Name: RemoveStaleSessions()
  643. // Desc: 
  644. //-----------------------------------------------------------------------------
  645. VOID RemoveStaleSessions( HWND hwndTV )
  646. {
  647.     TV_ITEM   item;
  648.     HTREEITEM hItem,hItemNext;
  649.     TREEDATA* psearchdata;
  650.  
  651.     memset(&item,0,sizeof(item));
  652.     
  653.     // get the first app item (child of the running apps item)
  654.     hItem = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_ROOT,(LPARAM) NULL);    
  655.     
  656.     while (hItem)
  657.     {
  658.         // get the next one
  659.         hItemNext = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem );    
  660.         
  661.         // gets its data
  662.         item.mask = TVIF_PARAM;
  663.         item.hItem = hItem;
  664.         SendMessage( hwndTV, TVM_GETITEM, 0, (LPARAM)&item );
  665.  
  666.         // if dwRefresh is still 0, it wasn't enum'ed
  667.         psearchdata = (TREEDATA*)item.lParam;
  668.         if (psearchdata && (0 == psearchdata->dwRefresh))
  669.         {
  670.             free(psearchdata);
  671.             SendMessage( hwndTV, TVM_DELETEITEM, 0, (LPARAM)hItem );
  672.         }
  673.  
  674.         hItem = hItemNext;
  675.     }    
  676.     
  677.     return;
  678. }
  679.  
  680.  
  681.  
  682.  
  683. //-----------------------------------------------------------------------------
  684. // Name: DlgProcJoinSession()
  685. // Desc: Dialog procedure for Join Session Dialog
  686. //-----------------------------------------------------------------------------
  687. BOOL CALLBACK DlgProcJoinSession( HWND hDlg, UINT msg, WPARAM wParam,
  688.                                   LPARAM lParam )
  689. {
  690.     static NM_TREEVIEW nmtv;
  691.     static HWND        hWndCtl;
  692.     static TCHAR       strPlayerName[MAX_PLAYERNAME+1];
  693.     static HANDLE      dphEvent = NULL;
  694.     static UINT        idTimer = 0;
  695.  
  696.     TV_ITEM   tvItem;
  697.     TCHAR     strSessionName[MAX_SESSIONNAME+1];
  698.     DWORD     dwPNameSize;
  699.     HRESULT   hr = DP_OK;
  700.     HTREEITEM htiCur, htiNext;
  701.     GUID*     pGuid;
  702.  
  703.     switch( msg )
  704.     {
  705.         case WM_NOTIFY:
  706.             switch (((NMHDR FAR *) lParam)->code) 
  707.             {
  708.                 case PSN_SETACTIVE:
  709.                     // Only the back button is valid at this point
  710.                     PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
  711.  
  712.                     if( hWndCtl )
  713.                         TreeView_DeleteAllItems( hWndCtl );
  714.  
  715.                     // Enum sessions and let dplay decide the timeout
  716.                     hr = DPUtil_EnumSessions( 0, EnumSession, (VOID*)hWndCtl,
  717.                                             DPENUMSESSIONS_ASYNC );
  718.                     if( FAILED(hr) )
  719.                         return FALSE;
  720.  
  721.                     // Enumerate players for all sessions
  722.                     ghtiSession = TreeView_GetFirstVisible( hWndCtl );
  723.         
  724.                     while( ghtiSession )
  725.                     {
  726.                         // delete previous players from display
  727.                         if ((htiNext = htiCur = TreeView_GetChild(hWndCtl, ghtiSession)) 
  728.                             != (HTREEITEM)0)
  729.                         {
  730.                             do
  731.                             {
  732.                                 htiNext = TreeView_GetNextSibling(hWndCtl, htiCur);
  733.                                 TreeView_DeleteItem(hWndCtl, htiCur);
  734.                                 htiCur = htiNext;
  735.                             } while (htiNext);
  736.                         }
  737.  
  738.                         tvItem.hItem = ghtiSession;
  739.                         tvItem.pszText = strSessionName;
  740.                         tvItem.cchTextMax = MAX_SESSIONNAME;
  741.                         TreeView_GetItem(hWndCtl, &tvItem);
  742.                         // enumerate players for selected session
  743.                         DPUtil_EnumPlayers( (GUID*)tvItem.lParam, EnumPlayer, (LPVOID) hWndCtl, DPENUMPLAYERS_SESSION);
  744.                         ghtiSession = TreeView_GetNextItem(hWndCtl, ghtiSession, TVGN_NEXTVISIBLE);
  745.                     }
  746.  
  747.                     // set Finish button highlite
  748.                     if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, strPlayerName, MAX_PLAYERNAME) && 
  749.                         (htiCur = TreeView_GetSelection(hWndCtl)))
  750.                     {
  751.  
  752.  
  753.                         PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  754.                     }
  755.                     else
  756.                     {
  757.                         PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  758.                     }
  759.  
  760.                     SetFocus(hWndCtl);
  761.                     
  762.                     // start up timer
  763.                     idTimer = SetTimer(hDlg, ENUM_TIMER_ID, ENUM_TIMEOUT, NULL);
  764.             
  765.                     return(TRUE);
  766.  
  767.                 case PSN_WIZFINISH:
  768.                     if (idTimer)
  769.                     {
  770.                         KillTimer(hDlg, idTimer);
  771.                         idTimer = 0;
  772.                     }
  773.                                 
  774.                     // add user selections to registry
  775.                     if (ghDuelKey) 
  776.                     {
  777.                         RegSet(TEXT("PlayerName"), (CONST BYTE *)strPlayerName, 
  778.                                 sizeof(strPlayerName));
  779.                     }
  780.         
  781.                     // get the session guid
  782.                     if (nmtv.itemNew.lParam)
  783.                     {
  784.                         // user selected a session item, so just grab its lParam
  785.                         pGuid = (GUID*)nmtv.itemNew.lParam;
  786.                     }
  787.                     else
  788.                     {
  789.                         // user selected a player item, so grab its parent's (session) lParam
  790.                         htiCur = TreeView_GetParent(hWndCtl, nmtv.itemNew.hItem);
  791.                         if (!htiCur)
  792.                         {
  793.                             // fail finish
  794.                             ShowError(IDS_WIZARD_ERROR_GSG);
  795.                             SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  796.                             return (TRUE);
  797.                         }
  798.  
  799.                         tvItem.hItem = htiCur;
  800.                         tvItem.pszText = strSessionName;
  801.                         tvItem.cchTextMax = MAX_SESSIONNAME;
  802.                         TreeView_GetItem(hWndCtl, &tvItem);                 
  803.                         pGuid = (GUID*)tvItem.lParam;
  804.                     }
  805.  
  806.                     // Open session
  807.                     if( FAILED( hr = DPUtil_OpenSession( pGuid ) ) )
  808.                     {
  809.                         // Fail finish
  810.                         ShowError(IDS_DPLAY_ERROR_JS);
  811.                         SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  812.                         return TRUE;
  813.                     }
  814.  
  815.                     // create player
  816.                     if( FAILED( hr = DPUtil_CreatePlayer( &g_LocalPlayerDPID, strPlayerName,
  817.                                                          NULL, NULL, 0 ) ) )
  818.                     {
  819.                         // fail finish
  820.                         ShowError(IDS_DPLAY_ERROR_CP);
  821.                         SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  822.                         return (TRUE);
  823.                     }
  824.  
  825.                     // everything went well, release allocated memory and finish
  826.                     ReleaseSessionData(hWndCtl);
  827.                     ReleaseSPData();                
  828.                     return(TRUE);
  829.  
  830.                 case PSN_QUERYCANCEL:
  831.                     if (idTimer)
  832.                     {
  833.                         KillTimer(hDlg, idTimer);
  834.                         idTimer = 0;
  835.                     }
  836.                     DPUtil_EnumSessions(0, EnumSession, (LPVOID)hWndCtl,
  837.                                       DPENUMSESSIONS_STOPASYNC);
  838.                     ReleaseSessionData(hWndCtl);
  839.                     ReleaseSPData();
  840.                     DPUtil_Release();       // Indicates no game session
  841.                     return(TRUE);
  842.  
  843.                 case PSN_WIZBACK:
  844.                     if (idTimer)
  845.                     {
  846.                         KillTimer(hDlg, idTimer);
  847.                         idTimer = 0;
  848.                     }
  849.                     DPUtil_EnumSessions(0, EnumSession, (LPVOID)hWndCtl,
  850.                                       DPENUMSESSIONS_STOPASYNC);
  851.                     ReleaseSessionData(hWndCtl);
  852.                     return(TRUE);
  853.  
  854.                 case TVN_SELCHANGING:
  855.                     nmtv = *((NM_TREEVIEW *) lParam);
  856.  
  857.                     // set Finish button status 
  858.                     if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, strPlayerName, MAX_PLAYERNAME) && 
  859.                         (htiCur = TreeView_GetSelection(hWndCtl)))
  860.                     {
  861.                         PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  862.                     }
  863.                     else
  864.                     {
  865.                         PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  866.                     }
  867.                     return(FALSE);
  868.  
  869.                 case NM_CLICK:
  870.                     return(FALSE);
  871.             }
  872.             break;
  873.         case WM_INITDIALOG:
  874.             // setup title fonts
  875.             SendDlgItemMessage(hDlg, IDC_JOIN_SESSION_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  876.             SendDlgItemMessage(hDlg, IDC_JOIN_PLAYER_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  877.  
  878.             // setup user's previous data
  879.             dwPNameSize = MAX_PLAYERNAME+1;
  880.             strPlayerName[0]=0;
  881.             if (ghDuelKey && (RegGet(TEXT("PlayerName"),(LPBYTE)strPlayerName,&dwPNameSize) == ERROR_SUCCESS))  
  882.                 SetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, strPlayerName);
  883.  
  884.             hWndCtl = GetDlgItem(hDlg, IDC_JOIN_SESSION);
  885.             if (hWndCtl == NULL) return(TRUE);
  886.             InitTreeViewImageLists(hWndCtl);
  887.             return(TRUE);
  888.             
  889.         case WM_TIMER:
  890.  
  891.             // guard against leftover timer messages after timer has been killed
  892.             if (!idTimer) break;
  893.             
  894.             ResetTreeRefresh(hWndCtl);
  895.             // enum sessions and let dplay decide the timeout
  896.             hr = DPUtil_EnumSessions(0, EnumSession, (LPVOID) hWndCtl,
  897.                                    DPENUMSESSIONS_ASYNC);
  898.             if (FAILED(hr) && hr != DPERR_CONNECTING)
  899.             {
  900.                 KillTimer(hDlg, idTimer);
  901.                 idTimer = 0;
  902.                 if (hr != DPERR_USERCANCEL)
  903.                     ShowError(IDS_DPLAY_ERROR_ES);
  904.             }
  905.  
  906.             RemoveStaleSessions(hWndCtl);
  907.             
  908.                 // set Finish button highlite
  909.             if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, strPlayerName, MAX_PLAYERNAME) && 
  910.                 (htiCur = TreeView_GetSelection(hWndCtl)))
  911.             {
  912.                 PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  913.             }
  914.             else
  915.             {
  916.                 PropSheet_SetWizButtons(GetParent(hDlg),PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  917.             }
  918.             
  919.             break;
  920.             
  921.         case WM_COMMAND:
  922.  
  923.             switch (LOWORD(wParam))
  924.             {
  925.                 case IDC_JOIN_PLAYERNAME:
  926.                     if (HIWORD(wParam) == EN_CHANGE)
  927.                     {
  928.                         // set Finish button status 
  929.                         if (GetDlgItemText(hDlg, IDC_JOIN_PLAYERNAME, strPlayerName, MAX_PLAYERNAME) && 
  930.                             (htiCur = TreeView_GetSelection(hWndCtl)))
  931.                         {
  932.                             PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  933.                         }
  934.                         else
  935.                         {
  936.                             PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  937.                         }
  938.                     }
  939.                     break;
  940.             }
  941.             break;
  942.     }
  943.  
  944.     return FALSE;
  945. }
  946.  
  947.  
  948.  
  949.  
  950. //-----------------------------------------------------------------------------
  951. // Name: DlgProcHostSession()
  952. // Desc: Dialog proc for Host Session Dialog
  953. //-----------------------------------------------------------------------------
  954. BOOL CALLBACK DlgProcHostSession(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  955. {
  956.     static TCHAR strSessionName[MAX_SESSIONNAME+1];
  957.     static TCHAR strPlayerName[MAX_PLAYERNAME+1];
  958.     HRESULT hr;
  959.     DWORD   dwPNameSize, dwSNameSize;
  960.  
  961.     switch( msg )
  962.     {
  963.         case WM_NOTIFY:
  964.             switch (((NMHDR FAR *) lParam)->code) 
  965.             {
  966.                 case PSN_SETACTIVE:
  967.                     if (GetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, strSessionName, MAX_SESSIONNAME) && 
  968.                         GetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, strPlayerName, MAX_PLAYERNAME))
  969.                     {
  970.                         PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  971.                     }
  972.                     else
  973.                     {
  974.                         PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  975.                     }
  976.                     return(TRUE);
  977.         
  978.                 case PSN_WIZFINISH:
  979.                     // add user selections to registry
  980.                     if (ghDuelKey) 
  981.                     {
  982.                         RegSet(TEXT("PlayerName"), (CONST BYTE *)strPlayerName, sizeof(strPlayerName));
  983.                         RegSet(TEXT("SessionName"), (CONST BYTE *)strSessionName, sizeof(strSessionName));
  984.                     }
  985.  
  986.                     // create session
  987.                     if ((hr = DPUtil_CreateSession(strSessionName)) != DP_OK)
  988.                     {
  989.                         // fail finish
  990.                         ShowError(IDS_DPLAY_ERROR_CS);
  991.                         SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  992.                         return (TRUE);
  993.                     }
  994.  
  995.                     // create player
  996.                     if( FAILED( hr = DPUtil_CreatePlayer( &g_LocalPlayerDPID, strPlayerName,
  997.                                                           NULL, NULL, 0 ) ) )
  998.                     {
  999.                         ShowError(IDS_DPLAY_ERROR_CP);
  1000.                         SetWindowLong(hDlg, DWL_MSGRESULT, -1);
  1001.                         return (TRUE);
  1002.                     }
  1003.  
  1004.                     // everything went well, release allocated memory and finish
  1005.                     ReleaseSPData();
  1006.                     return(TRUE);
  1007.                 
  1008.                 case PSN_WIZBACK:
  1009.                     SetWindowLong(hDlg, DWL_MSGRESULT, IDD_CHOOSEPROVIDER);
  1010.                     return(TRUE);
  1011.  
  1012.                 case PSN_QUERYCANCEL:
  1013.                     // release allocated memory
  1014.                     ReleaseSPData();
  1015.                     // release dplay
  1016.                     DPUtil_Release();       // Indicates no game session
  1017.                     return(TRUE);
  1018.             }
  1019.             break;
  1020.         case WM_INITDIALOG:
  1021.             // setup title font
  1022.             SendDlgItemMessage(hDlg, IDC_HOST_TITLE, WM_SETFONT, (WPARAM)ghTitleFont, MAKELPARAM(TRUE,0));
  1023.             SendDlgItemMessage(hDlg, IDC_HOST_SESSION_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  1024.             SendDlgItemMessage(hDlg, IDC_HOST_PLAYER_TITLE, WM_SETFONT, (WPARAM)ghHeadingFont, MAKELPARAM(TRUE,0));
  1025.  
  1026.             dwPNameSize = MAX_PLAYERNAME+1;
  1027.             dwSNameSize = MAX_SESSIONNAME+1;
  1028.             strPlayerName[0]=0;
  1029.             strSessionName[0]=0;
  1030.             if (ghDuelKey)
  1031.             {
  1032.                 if (RegGet(TEXT("PlayerName"), (LPBYTE)strPlayerName, &dwPNameSize) == ERROR_SUCCESS)   
  1033.                     SetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, strPlayerName);
  1034.                 if (RegGet(TEXT("SessionName"), (LPBYTE)strSessionName, &dwSNameSize) == ERROR_SUCCESS) 
  1035.                     SetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, strSessionName);
  1036.             }
  1037.             
  1038.             return(TRUE);
  1039.  
  1040.         case WM_COMMAND:
  1041.             switch (LOWORD(wParam))
  1042.             {
  1043.             case IDC_HOST_SESSIONNAME:
  1044.                 if (HIWORD(wParam) == EN_CHANGE)
  1045.                 {
  1046.                     if (GetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, strSessionName, MAX_SESSIONNAME) && 
  1047.                         GetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, strPlayerName, MAX_PLAYERNAME))
  1048.                     {
  1049.                         PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  1050.                     }
  1051.                     else
  1052.                     {
  1053.                         PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  1054.                     }
  1055.  
  1056.                     return TRUE;
  1057.                 }
  1058.                 break;
  1059.  
  1060.             case IDC_HOST_PLAYERNAME:
  1061.                 if (HIWORD(wParam) == EN_CHANGE)
  1062.                 {
  1063.                     if (GetDlgItemText(hDlg, IDC_HOST_SESSIONNAME, strSessionName, MAX_SESSIONNAME) && 
  1064.                         GetDlgItemText(hDlg, IDC_HOST_PLAYERNAME, strPlayerName, MAX_PLAYERNAME))
  1065.                     {
  1066.                         PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_FINISH);
  1067.                     }
  1068.                     else
  1069.                     {
  1070.                         PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK|PSWIZB_DISABLEDFINISH);
  1071.                     }
  1072.                 }
  1073.                 break;
  1074.             }
  1075.             break;
  1076.     }
  1077.  
  1078.     return FALSE;
  1079. }
  1080.  
  1081.  
  1082.  
  1083.  
  1084. //-----------------------------------------------------------------------------
  1085. // Name: InitTreeViewImageLists()
  1086. // Desc: Creates an image list, adds bitmaps to  it, and associates the image
  1087. //       list with a tree-view control. 
  1088. //-----------------------------------------------------------------------------
  1089. BOOL InitTreeViewImageLists(HWND hwndTV) 
  1090.     HIMAGELIST himl;  // handle of image list 
  1091.     HBITMAP hbmp;     // handle of bitmap 
  1092.  
  1093.     // Create the image list. 
  1094.     if ((himl = ImageList_Create(CX_BITMAP, CY_BITMAP, 
  1095.             FALSE, NUM_BITMAPS, 0)) == NULL) 
  1096.         return FALSE; 
  1097.  
  1098.     // Add the session and player bitmaps. 
  1099.     hbmp = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_CLOSED_SESSION)); 
  1100.     gnSession = ImageList_Add(himl, hbmp, (HBITMAP) NULL); 
  1101.     DeleteObject(hbmp); 
  1102.  
  1103.     hbmp = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_PLAYER)); 
  1104.     gnPlayer = ImageList_Add(himl, hbmp, (HBITMAP) NULL); 
  1105.     DeleteObject(hbmp); 
  1106.  
  1107.     // Fail if not all of the images were added. 
  1108.     if (ImageList_GetImageCount(himl) < 2) 
  1109.         return FALSE; 
  1110.  
  1111.     // Associate the image list with the tree-view control. 
  1112.     TreeView_SetImageList(hwndTV, himl, TVSIL_NORMAL); 
  1113.  
  1114.     return TRUE; 
  1115.    
  1116.  
  1117.  
  1118.  
  1119. //-----------------------------------------------------------------------------
  1120. // Name: FindItemInTree()
  1121. // Desc:
  1122. //-----------------------------------------------------------------------------
  1123. HTREEITEM FindItemInTree( HWND hwndTV, TREEDATA* pdata )
  1124. {
  1125.     TV_ITEM   item;
  1126.     HTREEITEM hItem;
  1127.     TREEDATA* psearchdata;
  1128.        
  1129.     memset(&item,0,sizeof(item));
  1130.     
  1131.     // get the first app item (child of the running apps item)
  1132.     hItem = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_ROOT,(LPARAM) NULL);    
  1133.     
  1134.     while (hItem)
  1135.     {
  1136.         // gets its data
  1137.         item.mask = TVIF_PARAM;
  1138.         item.hItem = hItem;
  1139.         SendMessage( hwndTV, TVM_GETITEM, 0, (LPARAM)&item );
  1140.         // is this the one?
  1141.         psearchdata = (TREEDATA*)item.lParam;
  1142.         if( IsEqualGUID( psearchdata->guid, pdata->guid ) ) 
  1143.         {
  1144.             // mark the item as seen
  1145.             psearchdata->dwRefresh = 1;
  1146.             SendMessage( hwndTV, TVM_SETITEM, 0, (LPARAM)&item );
  1147.             return hItem;
  1148.         }
  1149.         // try the next one
  1150.         hItem = (HTREEITEM)SendMessage( hwndTV, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem );    
  1151.     }    
  1152.     
  1153.     return NULL;
  1154. }
  1155.  
  1156.  
  1157.  
  1158.  
  1159. //-----------------------------------------------------------------------------
  1160. // Name: AddItemToTree()
  1161. // Desc: Adds items to a tree-view control. 
  1162. //-----------------------------------------------------------------------------
  1163. HTREEITEM AddItemToTree( HWND hwndTV, TCHAR* strItem, DWORD dwData,
  1164.                          int nLevel ) 
  1165.     static HTREEITEM hPrev         = (HTREEITEM) TVI_FIRST; 
  1166.     static HTREEITEM hPrevRootItem = NULL; 
  1167.     static HTREEITEM hPrevLev2Item = NULL; 
  1168.     HTREEITEM        hItem;
  1169.     TV_ITEM          tvi; 
  1170.     TV_INSERTSTRUCT  tvins; 
  1171.     
  1172.     if( 1 == nLevel )
  1173.     {
  1174.         hItem = FindItemInTree( hwndTV, (TREEDATA*)dwData );
  1175.         if (hItem) return NULL;
  1176.     }
  1177.     memset( &tvi,0,sizeof(tvi) );
  1178.     memset( &tvins,0,sizeof(tvins) );
  1179.  
  1180.     tvi.mask = TVIF_TEXT | TVIF_IMAGE 
  1181.         | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  1182.     
  1183.     // Set the state
  1184.     if (nLevel == 1) 
  1185.     {
  1186.         tvi.mask |= TVIF_STATE; 
  1187.         tvi.state = TVIS_SELECTED;
  1188.     }
  1189.  
  1190.     // Set the text of the item. 
  1191.     tvi.pszText = strItem; 
  1192.  
  1193.    // Set the image
  1194.     if (nLevel == 1)
  1195.     {
  1196.         tvi.iImage = gnSession; 
  1197.         tvi.iSelectedImage = gnSession; 
  1198.     }
  1199.     else
  1200.     {
  1201.         tvi.iImage = gnPlayer; 
  1202.         tvi.iSelectedImage = gnPlayer; 
  1203.     }
  1204.  
  1205.  
  1206.     // Save the heading level in the item's application-defined 
  1207.     // data area. 
  1208.     tvi.lParam = (LPARAM) dwData; 
  1209.  
  1210. #ifdef NONAMELESSUNION
  1211.     tvins.u.item = tvi; 
  1212. #else
  1213.     tvins.item = tvi; 
  1214. #endif
  1215.     tvins.hInsertAfter = hPrev; 
  1216.  
  1217.     // Set the parent item based on the specified level. 
  1218.     if (nLevel == -1)
  1219.         tvins.hParent = hPrevRootItem;
  1220.     else if (nLevel == 1) 
  1221.         tvins.hParent = TVI_ROOT; 
  1222.     else if (nLevel == 2) 
  1223.         tvins.hParent = hPrevRootItem; 
  1224.     else
  1225.         tvins.hParent = hPrevLev2Item; 
  1226.  
  1227.     // Add the item to the tree-view control. 
  1228.     hPrev = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0, 
  1229.          (LPARAM) (LPTV_INSERTSTRUCT) &tvins); 
  1230.  
  1231.     // Save the handle of the item. 
  1232.     if (nLevel == 1) 
  1233.         hPrevRootItem = hPrev; 
  1234.     else if (nLevel == 2) 
  1235.         hPrevLev2Item = hPrev; 
  1236.  
  1237.     return hPrev; 
  1238.  
  1239.  
  1240.  
  1241.  
  1242. //-----------------------------------------------------------------------------
  1243. // Name: ReleaseSessionData()
  1244. // Desc: 
  1245. //-----------------------------------------------------------------------------
  1246. VOID ReleaseSessionData(HWND hWndCtl)
  1247. {
  1248.     HTREEITEM htiSession = TreeView_GetRoot( hWndCtl );
  1249.     
  1250.     while( htiSession )
  1251.     {
  1252.         TCHAR   strSessionName[MAX_SESSIONNAME+1];
  1253.         TV_ITEM tvItem;
  1254.         tvItem.hItem      = htiSession;
  1255.         tvItem.pszText    = strSessionName;
  1256.         tvItem.cchTextMax = MAX_SESSIONNAME;
  1257.  
  1258.         TreeView_GetItem( hWndCtl, &tvItem );
  1259.         if( tvItem.lParam )
  1260.             free( (VOID*)tvItem.lParam );
  1261.         
  1262.         htiSession = TreeView_GetNextSibling( hWndCtl, htiSession );
  1263.     }
  1264. }
  1265.  
  1266.  
  1267.  
  1268.  
  1269. //-----------------------------------------------------------------------------
  1270. // Name: ReleaseSPData()
  1271. // Desc: Releases the memory allocated for service provider guids
  1272. //       depends on global variable ghWndSPControl
  1273. //-----------------------------------------------------------------------------
  1274. VOID ReleaseSPData()
  1275. {
  1276.     LPVOID lpCon = NULL;
  1277.     int count,index;
  1278.  
  1279.     if (ghWndSPCtl)
  1280.     {
  1281.         count = SendMessage(ghWndSPCtl, LB_GETCOUNT, 0, 0);
  1282.         for (index = 0; index < count; index++)
  1283.         {
  1284.             lpCon = (LPVOID) SendMessage(ghWndSPCtl, LB_GETITEMDATA, index, 0);
  1285.             if (lpCon) GlobalFreePtr(lpCon);
  1286.         }
  1287.     }
  1288. }
  1289.  
  1290.  
  1291.  
  1292.