Source code of Windows XP (NT5)
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.

571 lines
9.3 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. shutdown.cpp
  5. Abstract:
  6. IIS Shutdown/restart dialog
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "inetmgr.h"
  18. #include "sdprg.h"
  19. #include "shutdown.h"
  20. //
  21. // Shutdown in microseconds
  22. //
  23. #define IIS_SHUTDOWN_TIMEOUT 30000L // 30 Ms
  24. #ifdef _DEBUG
  25. #define new DEBUG_NEW
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29. CIISShutdownDlg::CIISShutdownDlg(
  30. IN LPCTSTR lpszServer,
  31. IN CWnd * pParent OPTIONAL
  32. )
  33. /*++
  34. Routine Description:
  35. Constructor
  36. Arguments:
  37. LPCTSTR lpszServer : Server name
  38. CWnd * pParent : Optional parent window
  39. Return Value:
  40. N/A
  41. --*/
  42. : CDialog(CIISShutdownDlg::IDD, pParent),
  43. m_fServicesRestarted(FALSE),
  44. m_fLocalMachine(::IsServerLocal(lpszServer)),
  45. m_strServer(lpszServer)
  46. {
  47. //{{AFX_DATA_INIT(CIISShutdownDlg)
  48. //}}AFX_DATA_INIT
  49. }
  50. void
  51. CIISShutdownDlg::DoDataExchange(
  52. IN CDataExchange * pDX
  53. )
  54. /*++
  55. Routine Description:
  56. Initialise/Store control data
  57. Arguments:
  58. CDataExchange * pDX - DDX/DDV control structure
  59. Return Value:
  60. None
  61. --*/
  62. {
  63. CDialog::DoDataExchange(pDX);
  64. //{{AFX_DATA_MAP(CIISShutdownDlg)
  65. DDX_Control(pDX, IDC_COMBO_RESTART, m_combo_Restart);
  66. DDX_Control(pDX, IDC_STATIC_DETAILS, m_static_Details);
  67. //}}AFX_DATA_MAP
  68. }
  69. void
  70. CIISShutdownDlg::SetDetailsText()
  71. /*++
  72. Routine Description:
  73. Set the details text to correspond to what's in the combo box
  74. Arguments:
  75. None
  76. Return Value:
  77. None
  78. --*/
  79. {
  80. UINT nSel = m_combo_Restart.GetCurSel();
  81. ASSERT(nSel >= 0 && nSel < NUM_ISC_ITEMS);
  82. m_static_Details.SetWindowText(m_strDetails[nSel]);
  83. }
  84. //
  85. // Message Map
  86. //
  87. BEGIN_MESSAGE_MAP(CIISShutdownDlg, CDialog)
  88. //{{AFX_MSG_MAP(CIISShutdownDlg)
  89. ON_CBN_SELCHANGE(IDC_COMBO_RESTART, OnSelchangeComboRestart)
  90. ON_CBN_DBLCLK(IDC_COMBO_RESTART, OnDblclkComboRestart)
  91. ON_BN_CLICKED(ID_HELP, OnHelp)
  92. //}}AFX_MSG_MAP
  93. END_MESSAGE_MAP()
  94. CRITICAL_SECTION gcs;
  95. UINT
  96. __cdecl
  97. StopIISServices(
  98. IN LPVOID pParam
  99. )
  100. /*++
  101. Routine Description:
  102. Worker thread to perform IIS Service Control Command
  103. Arguments:
  104. LPVOID * pParam : Casts to IISCOMMAND (see above)
  105. Return Value:
  106. UINT
  107. --*/
  108. {
  109. IISCOMMAND * pCmd = (IISCOMMAND *)pParam;
  110. //MessageBeep(0);
  111. //
  112. // This thread needs its own CoInitialize
  113. //
  114. CError err(CoInitialize(NULL));
  115. CIISSvcControl isc(pCmd->szServer);
  116. err = isc.QueryResult();
  117. // Block access to pCmd:
  118. // if user will click on "End Now" then process will
  119. // be killed and pCmd could by deleted async in parent
  120. // code -- this is why we need gcs
  121. EnterCriticalSection(&gcs);
  122. if (err.Succeeded())
  123. {
  124. err = isc.Stop(IIS_SHUTDOWN_TIMEOUT, TRUE);
  125. }
  126. //
  127. // Clean Up, returning the error code
  128. //
  129. EnterCriticalSection(&pCmd->cs);
  130. pCmd->fFinished = TRUE;
  131. pCmd->hReturn = err;
  132. LeaveCriticalSection(&pCmd->cs);
  133. LeaveCriticalSection(&gcs);
  134. return 0;
  135. }
  136. HRESULT
  137. CIISShutdownDlg::PerformCommand(
  138. IN int iCmd
  139. )
  140. /*++
  141. Routine Description:
  142. Perform restart command
  143. Arguments:
  144. int iCmd - One of the following commands:
  145. ISC_START
  146. ISC_STOP
  147. ISC_SHUTDOWN
  148. ISC_RESTART
  149. Return Value:
  150. HRESULT
  151. --*/
  152. {
  153. //
  154. // Make sure the service is supported
  155. //
  156. BeginWaitCursor();
  157. CIISSvcControl isc(m_strServer);
  158. EndWaitCursor();
  159. CError err(isc.QueryResult());
  160. if (err.Failed())
  161. {
  162. return err;
  163. }
  164. //
  165. // Create command structure to hand off to
  166. // worker thread
  167. //
  168. IISCOMMAND * pCommand = new IISCOMMAND;
  169. if (!pCommand)
  170. {
  171. err = ERROR_NOT_ENOUGH_MEMORY;
  172. return err;
  173. }
  174. ZeroMemory(pCommand, sizeof(IISCOMMAND));
  175. lstrcpy(pCommand->szServer, m_strServer);
  176. pCommand->dwMilliseconds = IIS_SHUTDOWN_TIMEOUT;
  177. pCommand->pParent = this;
  178. InitializeCriticalSection(&pCommand->cs);
  179. InitializeCriticalSection(&gcs);
  180. CShutProgressDlg dlg(pCommand);
  181. CWinThread * pStopThread = NULL;
  182. BOOL fStartServices = FALSE;
  183. INT_PTR nReturn = IDCANCEL;
  184. //
  185. // Fire off the thread that does the actual work, while we
  186. // put up the progress UI
  187. //
  188. switch(iCmd)
  189. {
  190. case ISC_RESTART:
  191. ++fStartServices;
  192. //
  193. // Fall through...
  194. //
  195. case ISC_STOP:
  196. //
  197. // Stop the services in the workerthread
  198. //
  199. pStopThread = AfxBeginThread(&StopIISServices, pCommand);
  200. nReturn = dlg.DoModal();
  201. break;
  202. case ISC_START:
  203. ++fStartServices;
  204. break;
  205. case ISC_SHUTDOWN:
  206. BeginWaitCursor();
  207. err = isc.Reboot(IIS_SHUTDOWN_TIMEOUT, m_fLocalMachine);
  208. EndWaitCursor();
  209. break;
  210. default:
  211. //
  212. // Internal error!
  213. //
  214. ASSERT(FALSE && "Invalid command code!");
  215. err = ERROR_INVALID_FUNCTION;
  216. }
  217. //
  218. // Determine if a kill is necessary (timed-out or user
  219. // pressed 'Kill')
  220. //
  221. BeginWaitCursor();
  222. if (nReturn == IDOK)
  223. {
  224. TRACEEOLID("Killing now!");
  225. err = isc.Kill();
  226. Sleep(1000L);
  227. }
  228. else
  229. {
  230. //
  231. // Waiting for the thread to finish
  232. //
  233. if (pStopThread != NULL)
  234. {
  235. BOOL fDone = FALSE;
  236. while(!fDone)
  237. {
  238. TRACEEOLID("Checking to see if thread has finished");
  239. EnterCriticalSection(&pCommand->cs);
  240. if (pCommand->fFinished)
  241. {
  242. err = pCommand->hReturn;
  243. ++fDone;
  244. }
  245. LeaveCriticalSection(&pCommand->cs);
  246. //
  247. // Pause a bit...
  248. //
  249. if (!fDone)
  250. {
  251. Sleep(500);
  252. }
  253. }
  254. }
  255. }
  256. //
  257. // Everything should be stopped, start it up again
  258. // if necessary.
  259. //
  260. if (err.Succeeded() && fStartServices)
  261. {
  262. err = isc.Start(IIS_SHUTDOWN_TIMEOUT);
  263. m_fServicesRestarted = err.Succeeded();
  264. }
  265. EndWaitCursor();
  266. //
  267. // Clean Up
  268. //
  269. EnterCriticalSection(&gcs);
  270. DeleteCriticalSection(&pCommand->cs);
  271. delete pCommand;
  272. LeaveCriticalSection(&gcs);
  273. DeleteCriticalSection(&gcs);
  274. return err;
  275. }
  276. //
  277. // Message Handlers
  278. //
  279. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  280. BOOL
  281. CIISShutdownDlg::OnInitDialog()
  282. /*++
  283. Routine Description:
  284. WM_INITDIALOG handler. Initialize the dialog.
  285. Arguments:
  286. None.
  287. Return Value:
  288. TRUE if no focus is to be set automatically, FALSE if the focus
  289. is already set.
  290. --*/
  291. {
  292. CDialog::OnInitDialog();
  293. //
  294. // Load combobox text and details
  295. //
  296. CString strFmt, str;
  297. //
  298. // This may take a second or two...
  299. //
  300. BeginWaitCursor();
  301. CIISSvcControl isc(m_strServer);
  302. EndWaitCursor();
  303. CError err(isc.QueryResult());
  304. if (err.Failed())
  305. {
  306. //
  307. // Failed to obtain interface -- quit now.
  308. //
  309. if (err.HResult() == REGDB_E_CLASSNOTREG
  310. || err.HResult() == CS_E_PACKAGE_NOTFOUND
  311. )
  312. {
  313. //
  314. // Friendly message about the interface not being supported
  315. //
  316. AfxMessageBox(IDS_ERR_NO_SHUTDOWN);
  317. }
  318. else
  319. {
  320. err.MessageBox();
  321. }
  322. EndDialog(IDCANCEL);
  323. }
  324. /* TEST code
  325. if (isc.Succeeded())
  326. {
  327. //LPBYTE pbBuffer;
  328. BYTE abBuffer[4096];
  329. DWORD dwReq;
  330. DWORD dwNumServices;
  331. HRESULT hr = isc.Status(sizeof(abBuffer), abBuffer, &dwReq, &dwNumServices);
  332. TRACEEOLID(hr);
  333. }
  334. */
  335. UINT nOption = IDS_IIS_START;
  336. UINT nDetails = IDS_IIS_START_DETAILS;
  337. for (int i = ISC_START; i <= ISC_RESTART; ++i)
  338. {
  339. VERIFY(strFmt.LoadString(nOption++));
  340. str.Format(strFmt, (LPCTSTR)m_strServer);
  341. VERIFY(m_strDetails[i].LoadString(nDetails++));
  342. m_combo_Restart.AddString(str);
  343. }
  344. m_combo_Restart.SetCurSel(ISC_RESTART);
  345. m_combo_Restart.SetFocus();
  346. SetDetailsText();
  347. return FALSE;
  348. }
  349. void
  350. CIISShutdownDlg::OnSelchangeComboRestart()
  351. /*++
  352. Routine Description:
  353. Selection change notification handler. Change the text in the details
  354. static text to reflect the new selection in the combo box
  355. Arguments:
  356. None
  357. Return Value:
  358. None
  359. --*/
  360. {
  361. SetDetailsText();
  362. }
  363. void
  364. CIISShutdownDlg::OnDblclkComboRestart()
  365. /*++
  366. Routine Description:
  367. Double-click notification handler. Maps to OK
  368. Arguments:
  369. None
  370. Return Value:
  371. None
  372. --*/
  373. {
  374. //
  375. // Go with the current selection
  376. //
  377. OnOK();
  378. }
  379. void
  380. CIISShutdownDlg::OnOK()
  381. /*++
  382. Routine Description:
  383. "OK" button has been pressed, and perform the selected action.
  384. Arguments:
  385. None
  386. Return Value:
  387. None
  388. --*/
  389. {
  390. int iCmd = m_combo_Restart.GetCurSel();
  391. CError err = PerformCommand(iCmd);
  392. if (!err.MessageBoxOnFailure())
  393. {
  394. //
  395. // No error, dismiss the dialog
  396. //
  397. CDialog::OnOK();
  398. }
  399. //
  400. // Failed -- do not dismiss the dialog
  401. //
  402. }