Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

576 lines
16 KiB

  1. /*
  2. ****************************************************************************
  3. | Copyright (C) 2001 Microsoft Corporation
  4. |
  5. | Module Name:
  6. |
  7. | UI.cpp
  8. |
  9. | Abstract:
  10. | This is the UI code for the IIS6 Monitor tool
  11. |
  12. | Author:
  13. | Ivo Jeglov (ivelinj)
  14. |
  15. | Revision History:
  16. | November 2001
  17. |
  18. ****************************************************************************
  19. */
  20. #include "stdafx.h"
  21. #include "resource.h"
  22. #include <windowsx.h>
  23. #include "UI.h"
  24. #include "Utils.h"
  25. // Property pages DLG procs
  26. INT_PTR CALLBACK WelcomeDlgProc ( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam );
  27. INT_PTR CALLBACK LicenseDlgProc ( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam );
  28. INT_PTR CALLBACK PolicyDlgProc ( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam );
  29. INT_PTR CALLBACK SettingsDlgProc ( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam );
  30. INT_PTR CALLBACK InstallDlgProc ( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam );
  31. INT_PTR CALLBACK ResultDlgProc ( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam );
  32. // Other DLG procs
  33. INT_PTR CALLBACK FatDlgProc ( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam );
  34. INT_PTR CALLBACK ProgressDlgProc ( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam );
  35. // Helpers
  36. BOOL CheckForFAT ( HINSTANCE hInst, HWND hwndParent );
  37. // Shared data for all the wizard pages
  38. struct _FontData
  39. {
  40. HFONT hTitle;
  41. HFONT hTips;
  42. };
  43. // Settings data
  44. struct _Settings
  45. {
  46. BOOL bEnableTrail;
  47. DWORD dwKeepFilesPeriod;
  48. };
  49. struct _SharedData
  50. {
  51. _FontData Fonts;
  52. _Settings Settings;
  53. LPCTSTR szError;
  54. HINSTANCE hInst;
  55. };
  56. // Helpers
  57. void LoadTextInCtrl ( UINT nResID, HWND hCtrl );
  58. void AjustLicenseWizBtn ( HWND hwndPage );
  59. void InitFonts ( _FontData& FontData );
  60. void SetWndFontFromLPARAM ( HWND hwndCtrl, LPARAM lParam, BOOL bTitle );
  61. void DoInstallUI( HINSTANCE hInstance )
  62. {
  63. const BYTE PAGE_COUNT = 6;
  64. PROPSHEETPAGEW psp = { 0 }; // Defines the property sheet pages
  65. HPROPSHEETPAGE ahPsp[ PAGE_COUNT ] = { 0 }; // An array to hold the page's HPROPSHEETPAGE handles
  66. PROPSHEETHEADERW psh = { 0 }; // Defines the property sheet
  67. _SharedData WizData = { 0 }; // The settings data structure
  68. // Create the fonts
  69. InitFonts( /*r*/WizData.Fonts );
  70. WizData.hInst = hInstance;
  71. // Create the Wizard pages
  72. ///////////////////////////////////////////////////////////////////
  73. // Welcome page
  74. psp.dwSize = sizeof( psp );
  75. psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER | PSP_USETITLE;
  76. psp.hInstance = hInstance;
  77. psp.lParam = reinterpret_cast<LPARAM>( &WizData );
  78. psp.pfnDlgProc = WelcomeDlgProc;
  79. psp.pszTemplate = MAKEINTRESOURCEW( IDD_WPAGE_WELCOME );
  80. psp.pszTitle = MAIN_TITLE;
  81. ahPsp[ 0 ] = ::CreatePropertySheetPageW( &psp );
  82. // License page
  83. psp.pfnDlgProc = LicenseDlgProc;
  84. psp.pszTemplate = MAKEINTRESOURCEW( IDD_WPAGE_LICENSE );
  85. ahPsp[ 1 ] = ::CreatePropertySheetPageW( &psp );
  86. // Policy page
  87. psp.pfnDlgProc = PolicyDlgProc;
  88. psp.pszTemplate = MAKEINTRESOURCEW( IDD_WPAGE_POLICY );
  89. ahPsp[ 2 ] = ::CreatePropertySheetPageW( &psp );
  90. // Settings Page
  91. psp.pszTemplate = MAKEINTRESOURCEW( IDD_WPAGE_SETUP );
  92. psp.pfnDlgProc = SettingsDlgProc;
  93. ahPsp[ 3 ] = ::CreatePropertySheetPageW( &psp );
  94. // Install Page
  95. psp.pszTemplate = MAKEINTRESOURCEW( IDD_WPAGE_INSTALL );
  96. psp.pfnDlgProc = InstallDlgProc;
  97. ahPsp[ 4 ] = ::CreatePropertySheetPageW( &psp );
  98. // Result page
  99. psp.pszTemplate = MAKEINTRESOURCEW( IDD_WPAGE_RESULT );
  100. psp.pfnDlgProc = ResultDlgProc;
  101. ahPsp[ 5 ] = ::CreatePropertySheetPageW( &psp );
  102. // Create the property sheet
  103. psh.dwSize = sizeof( psh );
  104. psh.hInstance = hInstance;
  105. psh.hwndParent = NULL;
  106. psh.phpage = ahPsp;
  107. psh.dwFlags = PSH_DEFAULT | PSH_NOCONTEXTHELP | PSH_WIZARD97 | PSH_USEICONID;
  108. psh.pszIcon = MAKEINTRESOURCEW( IDI_SETUP );
  109. psh.nStartPage = 0;
  110. psh.nPages = PAGE_COUNT;
  111. // Show the wizard.
  112. VERIFY( ::PropertySheetW( &psh ) != -1 );
  113. ::DeleteObject( WizData.Fonts.hTips );
  114. ::DeleteObject( WizData.Fonts.hTitle );
  115. }
  116. INT_PTR CALLBACK WelcomeDlgProc( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam )
  117. {
  118. static _SharedData* pData = NULL;
  119. switch( uMsg )
  120. {
  121. case WM_INITDIALOG:
  122. // Set the title font
  123. SetWndFontFromLPARAM( ::GetDlgItem( hwndDlg, IDC_TITLE ), lParam, TRUE );
  124. SetWndFontFromLPARAM( ::GetDlgItem( hwndDlg, IDC_TIP ), lParam, FALSE );
  125. // Load the info text
  126. LoadTextInCtrl( IDR_INFO, ::GetDlgItem( hwndDlg, IDC_INFO ) );
  127. // Init the shared data here
  128. _ASSERT( NULL == pData );
  129. pData = reinterpret_cast<_SharedData*>( reinterpret_cast<PROPSHEETPAGE*>( lParam )->lParam );
  130. break;
  131. case WM_NOTIFY:
  132. switch ( reinterpret_cast<NMHDR*>( lParam )->code )
  133. {
  134. case PSN_SETACTIVE:
  135. PropSheet_SetWizButtons( ::GetParent( hwndDlg ), PSWIZB_NEXT );
  136. break;
  137. case PSN_WIZNEXT:
  138. // Here is the place to test the requirements
  139. _ASSERT( pData != NULL );
  140. pData->szError = CanInstall();
  141. // If no error - check if on FAT
  142. if ( ( NULL == pData->szError ) && !CheckForFAT( pData->hInst, hwndDlg ) )
  143. {
  144. // If we are here - the user don't want to install IISMon on FAT
  145. pData->szError = _T("Installation canceled by the user");
  146. }
  147. if ( pData->szError != NULL )
  148. {
  149. // Error - Go to the result page
  150. PropSheet_SetCurSel( ::GetParent( hwndDlg ), NULL, 5 );
  151. }
  152. break;
  153. };
  154. break;
  155. case WM_CTLCOLORDLG:
  156. case WM_CTLCOLORSTATIC:
  157. // Change the dlg background to white
  158. return reinterpret_cast<INT_PTR>( ::GetStockObject( WHITE_BRUSH ) );
  159. break;
  160. };
  161. return 0;
  162. }
  163. INT_PTR CALLBACK LicenseDlgProc( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam )
  164. {
  165. switch( uMsg )
  166. {
  167. case WM_INITDIALOG:
  168. // Load the License text into the edit control
  169. LoadTextInCtrl( IDR_LICENSE, ::GetDlgItem( hwndDlg, IDC_LICENSE ) );
  170. break;
  171. case WM_COMMAND:
  172. // Will handle only the state changes of the check box button
  173. if ( HIWORD( wParam ) == BN_CLICKED )
  174. {
  175. AjustLicenseWizBtn( hwndDlg );
  176. }
  177. break;
  178. case WM_NOTIFY:
  179. LPNMHDR pNM = reinterpret_cast<NMHDR*>( lParam );
  180. switch( pNM->code )
  181. {
  182. case PSN_SETACTIVE:
  183. AjustLicenseWizBtn( hwndDlg );
  184. break;
  185. }
  186. break;
  187. };
  188. return 0;
  189. }
  190. INT_PTR CALLBACK PolicyDlgProc( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam )
  191. {
  192. switch( uMsg )
  193. {
  194. case WM_INITDIALOG:
  195. // Load the License text into the edit control
  196. LoadTextInCtrl( IDR_POLICY, ::GetDlgItem( hwndDlg, IDC_POLICY ) );
  197. break;
  198. };
  199. return 0;
  200. }
  201. INT_PTR CALLBACK SettingsDlgProc( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam )
  202. {
  203. int i = 0;
  204. static LPCTSTR aszEntries[] = { _T("One week"),
  205. _T("Two weeks"),
  206. _T("One month" ),
  207. _T("Two months" ),
  208. _T("Never" ) };
  209. // How many days represent each of the combo box options above
  210. static UINT anAuditFilesTime[] = { 7, 14, 30, 60, 0 };
  211. _ASSERT( ARRAY_SIZE( anAuditFilesTime ) == ARRAY_SIZE( aszEntries ) );
  212. static _SharedData* pData = NULL;
  213. switch( uMsg )
  214. {
  215. case WM_INITDIALOG:
  216. // Fill the combo box
  217. for ( i = 0; i < ARRAY_SIZE( aszEntries ); ++i )
  218. {
  219. VERIFY( ::SendMessage( ::GetDlgItem( hwndDlg, IDC_KEEPFILES ),
  220. CB_ADDSTRING,
  221. 0,
  222. reinterpret_cast<LPARAM>( aszEntries[ i ] ) ) != CB_ERR );
  223. }
  224. // Set the default selection to the first one
  225. VERIFY( ::SendMessage( ::GetDlgItem( hwndDlg, IDC_KEEPFILES ),
  226. CB_SETCURSEL,
  227. 0,
  228. 0 ) != CB_ERR );
  229. SetWndFontFromLPARAM( ::GetDlgItem( hwndDlg, IDC_WARNING ), lParam, FALSE );
  230. // Enable the audit trail
  231. ::SendMessage( ::GetDlgItem( hwndDlg, IDC_ENABLE_TRAIL ),
  232. BM_SETCHECK,
  233. BST_CHECKED,
  234. 0 );
  235. // Init the shared data here
  236. _ASSERT( NULL == pData );
  237. pData = reinterpret_cast<_SharedData*>( reinterpret_cast<PROPSHEETPAGE*>( lParam )->lParam );
  238. break;
  239. case WM_COMMAND:
  240. if ( HIWORD( wParam ) == BN_CLICKED )
  241. {
  242. // Enable/ Disable the combo box depending on the 'Enable trail' state
  243. BOOL bChecked = ( ::IsDlgButtonChecked( hwndDlg, IDC_ENABLE_TRAIL ) == BST_CHECKED );
  244. ::EnableWindow( ::GetDlgItem( hwndDlg, IDC_KEEPFILES ), bChecked );
  245. }
  246. break;
  247. case WM_NOTIFY:
  248. LPNMHDR pNM = reinterpret_cast<NMHDR*>( lParam );
  249. switch( pNM->code )
  250. {
  251. case PSN_SETACTIVE:
  252. // For this dialog both Next and Back are enabled
  253. PropSheet_SetWizButtons( ::GetParent( hwndDlg ), PSWIZB_NEXT | PSWIZB_BACK );
  254. break;
  255. case PSN_WIZNEXT:
  256. // Store the settings in the shared data struct
  257. _ASSERT( pData != NULL );
  258. pData->Settings.bEnableTrail = ( ::IsDlgButtonChecked( hwndDlg, IDC_ENABLE_TRAIL ) == BST_CHECKED );
  259. if ( pData->Settings.bEnableTrail )
  260. {
  261. LRESULT nSel = ::SendMessage( ::GetDlgItem( hwndDlg, IDC_KEEPFILES ),
  262. CB_GETCURSEL,
  263. 0,
  264. 0 );
  265. _ASSERT( nSel != CB_ERR );
  266. _ASSERT( nSel < ARRAY_SIZE( anAuditFilesTime ) );
  267. pData->Settings.dwKeepFilesPeriod = anAuditFilesTime[ nSel ];
  268. }
  269. else
  270. {
  271. pData->Settings.dwKeepFilesPeriod = 0;
  272. }
  273. break;
  274. }
  275. break;
  276. };
  277. return 0;
  278. }
  279. INT_PTR CALLBACK InstallDlgProc( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam )
  280. {
  281. static LPCWSTR _WARNING =
  282. L"The World Wide Web Publishing Service (W3SVC) is either stopped or disabled on your server. W3SVC provides \
  283. Web conectivity and administration through IIS. If you do not plan to run W3SVC, you should not install IIS 6.0 \
  284. Monitor. To cancel installation, click Cancel.\n\nTo complete the installation of the IIS 6.0 Monitor, \
  285. click Next.\n\nIf you would like to modify your audit trail settings, click Back.";
  286. // If W3SVC is not running or if it is disabled - add a warning
  287. if ( ( WM_INITDIALOG == uMsg ) && !IsW3SVCEnabled() )
  288. {
  289. RECT rc;
  290. VERIFY( ::GetWindowRect( ::GetDlgItem( hwndDlg, IDC_FRAME ), &rc ) );
  291. VERIFY( ::SetWindowTextW( ::GetDlgItem( hwndDlg, IDC_INFO ), _WARNING ) );
  292. VERIFY( ::SetWindowPos( ::GetDlgItem( hwndDlg, IDC_FRAME ),
  293. NULL,
  294. 0,
  295. 0,
  296. rc.right - rc.left,
  297. rc.bottom - rc.top + 60,
  298. SWP_NOMOVE | SWP_NOZORDER ) );
  299. }
  300. return 0;
  301. }
  302. INT_PTR CALLBACK ResultDlgProc( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam )
  303. {
  304. _SharedData* pData = NULL;
  305. switch( uMsg )
  306. {
  307. case WM_INITDIALOG:
  308. // Init the shared data here
  309. _ASSERT( NULL == pData );
  310. pData = reinterpret_cast<_SharedData*>( reinterpret_cast<PROPSHEETPAGE*>( lParam )->lParam );
  311. // Set the title font
  312. SetWndFontFromLPARAM( ::GetDlgItem( hwndDlg, IDC_RESULT ), lParam, TRUE );
  313. // If a previous error - set it. Else - try to install
  314. if ( NULL == pData->szError )
  315. {
  316. // Show the status window
  317. HWND hwndStatus = ::CreateDialog( pData->hInst, MAKEINTRESOURCE( IDD_PROGRESS ), hwndDlg, ProgressDlgProc );
  318. ::ShowWindow( hwndStatus, SW_SHOW );
  319. ::RedrawWindow( hwndStatus, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW );
  320. _ASSERT( hwndStatus != NULL );
  321. pData->szError = Install( pData->hInst, pData->Settings.bEnableTrail, pData->Settings.dwKeepFilesPeriod );
  322. // Hide the status window
  323. ::DestroyWindow( hwndStatus );
  324. }
  325. if ( pData->szError != NULL )
  326. {
  327. TCHAR szBuffer[ 2048 ];
  328. ::_stprintf( szBuffer,
  329. _T("IIS 6.0 Monitor installation failed because of the following error:\n\n%s"),
  330. pData->szError );
  331. VERIFY( ::SetWindowText( ::GetDlgItem( hwndDlg, IDC_RESULT ), _T("Installation Unsuccessful!") ) );
  332. VERIFY( ::SetWindowText( ::GetDlgItem( hwndDlg, IDC_INFO ), szBuffer ) );
  333. }
  334. break;
  335. case WM_NOTIFY:
  336. if ( PSN_SETACTIVE == reinterpret_cast<NMHDR*>( lParam )->code )
  337. {
  338. // Change the Next button to Finish. Back is not enabled - this is a result screen
  339. PropSheet_SetWizButtons( ::GetParent( hwndDlg ), PSWIZB_FINISH );
  340. }
  341. break;
  342. case WM_CTLCOLORDLG:
  343. case WM_CTLCOLORSTATIC:
  344. // Change the dlg background to white
  345. return reinterpret_cast<INT_PTR>( ::GetStockObject( WHITE_BRUSH ) );
  346. };
  347. return 0;
  348. }
  349. INT_PTR CALLBACK FatDlgProc( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam )
  350. {
  351. RECT rc;
  352. const UINT nNoDetailsHeight = 170;
  353. const UINT nWithDetailsHeight = 310;
  354. VERIFY( ::GetWindowRect( hwndDlg, &rc ) );
  355. switch( uMsg )
  356. {
  357. case WM_INITDIALOG:
  358. LoadTextInCtrl( IDR_FATDETAILS, ::GetDlgItem( hwndDlg, IDC_DETAILS ) );
  359. ::SetWindowPos( hwndDlg, NULL, 0, 0, rc.right - rc.left, nNoDetailsHeight, SWP_NOMOVE | SWP_NOZORDER );
  360. break;
  361. case WM_COMMAND:
  362. switch( LOWORD( wParam ) )
  363. {
  364. case IDOK:
  365. case IDCANCEL:
  366. ::EndDialog( hwndDlg, LOWORD( wParam ) );
  367. break;
  368. case IDC_TOGGLE:
  369. // Alter current state ( current state is obtained using the window height )
  370. bool bDetailsVisible = !( ( rc.bottom - rc.top ) > nNoDetailsHeight );
  371. VERIFY( ::SetWindowText( ::GetDlgItem( hwndDlg, IDC_TOGGLE ),
  372. bDetailsVisible ? _T("Details <<") : _T("Details >>" ) ) );
  373. ::SetWindowPos( hwndDlg,
  374. NULL,
  375. 0,
  376. 0,
  377. rc.right - rc.left,
  378. bDetailsVisible ? nWithDetailsHeight : nNoDetailsHeight,
  379. SWP_NOMOVE | SWP_NOZORDER );
  380. break;
  381. }
  382. break;
  383. };
  384. return FALSE;
  385. }
  386. INT_PTR CALLBACK ProgressDlgProc( IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam )
  387. {
  388. // Nothing to do here
  389. return FALSE;
  390. }
  391. BOOL CheckForFAT( HINSTANCE hInst, HWND hwndParent )
  392. {
  393. BOOL bRes = TRUE;
  394. // If the file system is FAT - warn the user
  395. if ( !IsNTFS() )
  396. {
  397. INT_PTR nDlgRes = ::DialogBox( hInst, MAKEINTRESOURCE( IDD_FAT_WARNING ), hwndParent, FatDlgProc );
  398. bRes = ( IDOK == nDlgRes );
  399. }
  400. return bRes;
  401. }
  402. void LoadTextInCtrl( UINT nResID, HWND hwndCtrl )
  403. {
  404. _ASSERT( hwndCtrl != NULL );
  405. HRSRC hRes = ::FindResource( NULL, MAKEINTRESOURCE( nResID ), RT_RCDATA );
  406. _ASSERT( hRes != NULL );
  407. // Get the resource data
  408. HGLOBAL hData = ::LoadResource( NULL, hRes );
  409. _ASSERT( hData != NULL );
  410. LPVOID pvData = ::LockResource( hData );
  411. _ASSERT( pvData != NULL );
  412. // The text is ANSI!
  413. VERIFY( ::SetWindowTextA( hwndCtrl, reinterpret_cast<LPCSTR>( pvData ) ) );
  414. }
  415. void AjustLicenseWizBtn( HWND hwndPage )
  416. {
  417. // Enable / Disable the next button depending ot check box state
  418. bool bChecked = ( ::IsDlgButtonChecked( hwndPage, IDC_ACCEPT ) == BST_CHECKED );
  419. PropSheet_SetWizButtons( ::GetParent( hwndPage ), bChecked ? PSWIZB_NEXT | PSWIZB_BACK : PSWIZB_BACK );
  420. }
  421. void InitFonts( _FontData& FontData )
  422. {
  423. // Create the font for the wizard title texts and for the text of tipd
  424. NONCLIENTMETRICS ncm = { 0 };
  425. ncm.cbSize = sizeof( ncm );
  426. ::SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0 );
  427. LOGFONT TitleLogFont = ncm.lfMessageFont;
  428. TitleLogFont.lfWeight = FW_BOLD;
  429. lstrcpy( TitleLogFont.lfFaceName, _T("Verdana Bold") );
  430. // Create the tips font
  431. FontData.hTips = ::CreateFontIndirect( &TitleLogFont );
  432. // Create the intro/end title font
  433. HDC hdc = ::GetDC(NULL); // Gets the screen DC
  434. INT FontSize = 12;
  435. TitleLogFont.lfHeight = 0 - GetDeviceCaps( hdc, LOGPIXELSY ) * FontSize / 72;
  436. FontData.hTitle = ::CreateFontIndirect( &TitleLogFont );
  437. ::ReleaseDC( NULL, hdc );
  438. }
  439. void SetWndFontFromLPARAM( HWND hwndCtrl, LPARAM lParam, BOOL bTitle )
  440. {
  441. PROPSHEETPAGE* pPage = reinterpret_cast<PROPSHEETPAGE*>( lParam );
  442. _FontData Fonts = reinterpret_cast<_SharedData*>( pPage->lParam )->Fonts;
  443. SetWindowFont( hwndCtrl, bTitle ? Fonts.hTitle : Fonts.hTips, TRUE );
  444. }