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.

1361 lines
39 KiB

  1. // UMDialog.cpp : implementation file
  2. // Author: J. Eckhardt, ECO Kommunikation
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. //
  5. // History:
  6. // Changes
  7. // Yuri Khramov
  8. // 01-jun-99: DisplayName key used in the Dialog (Localization)
  9. // 11-jun-99: DlgHasClosed code changed to work with app closure
  10. // 15-jun-99: Timer delay increased 1000ms
  11. //
  12. // Bug fixes and Changes Anil Kumar 1999
  13. //---------------------------------------------------------------------
  14. #include <afxwin.h> // MFC core and standard components
  15. #include <afxext.h> // MFC extensions
  16. #include "UManDlg.h"
  17. #include "UMDialog.h"
  18. #include "UMAbout.h"
  19. #include "_UMDlg.h"
  20. #include "_UMClnt.h"
  21. #include "_UMTool.h"
  22. #include "UMS_Ctrl.h"
  23. #include "w95trace.h"
  24. #include <WinSvc.h>
  25. #include <htmlhelp.h>
  26. #include <initguid.h>
  27. #include <ole2.h>
  28. #include "deskswitch.c"
  29. #include "ManageShellLinks.h"
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. // --------------------------------------------
  36. // constants
  37. #define IDC_ABOUT 10
  38. #define UPDATE_CLIENT_LIST_TIMER 1
  39. // --------------------------------------------
  40. // variables
  41. static DWORD g_cClients = 0;
  42. static umclient_tsp g_rgClients = NULL;
  43. static DWORD s_dwStartMode = START_BY_OTHER;
  44. static BOOL s_fShowWarningAgain = TRUE;
  45. extern CUMDlgApp theApp;
  46. // --------------------------------------------
  47. // C prototypes
  48. static BOOL InitClientData(void);
  49. static BOOL StartClientsOnShow();
  50. static BOOL WriteClientData(BOOL fRunningSecure);
  51. static BOOL IsStartAuto();
  52. static BOOL CantStopClient(umclient_tsp client);
  53. static int GetClientNameFromAccelerator(WPARAM wVK);
  54. extern "C" BOOL StartAppAsUser( LPCTSTR appPath,
  55. LPTSTR cmdLine,
  56. LPSTARTUPINFO lpStartupInfo,
  57. LPPROCESS_INFORMATION lpProcessInformation);
  58. // Help ID's for context sensitive help
  59. DWORD g_rgHelpIds[] = {
  60. IDC_NAME_STATUS, 3,
  61. IDC_START, 1001,
  62. IDC_STOP, 1002,
  63. IDC_START_AT_LOGON, 1003, // TODO UE needs to update CS help
  64. IDC_START_WITH_UM, 1004,
  65. IDC_START_ON_LOCK, 1005, // TODO UE needs to add to CS help
  66. IDOK, 1100,
  67. IDCANCEL, 1200,
  68. ID_HELP, 1300,
  69. };
  70. // ---------------------------------------------------------------
  71. extern "C"{
  72. //--------------------------------
  73. HWND g_hWndDlg = NULL;
  74. HWND aboutWnd = NULL;
  75. static HANDLE s_hDlgThread = NULL;
  76. static HDESK s_hdeskSave = 0;
  77. static HDESK s_hdeskInput = 0;
  78. // UnassignDesktop gets called after the thread has exited to
  79. // close desktop handles opened in AssignDesktop.
  80. inline void UnassignDesktop()
  81. {
  82. if (s_hdeskInput)
  83. {
  84. CloseDesktop(s_hdeskInput);
  85. s_hdeskInput = 0;
  86. }
  87. }
  88. BOOL AssignDesktop(DWORD dwThreadId)
  89. {
  90. s_hdeskSave = GetThreadDesktop(dwThreadId);
  91. s_hdeskInput = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED);
  92. if (!s_hdeskInput)
  93. {
  94. s_hdeskInput = OpenDesktop(_TEXT("Winlogon"),0,FALSE,MAXIMUM_ALLOWED);
  95. }
  96. if (s_hdeskInput)
  97. {
  98. BOOL fSet = SetThreadDesktop(s_hdeskInput);
  99. }
  100. return (s_hdeskInput)?TRUE:FALSE;
  101. }
  102. //--------------------------------
  103. DWORD UManDlgThread(LPVOID /* UNUSED */ in)
  104. {
  105. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  106. UMDialog dlg;
  107. // assign thread to the input desktop (have to do
  108. // this here so it works on the winlogon desktop)
  109. if (AssignDesktop(GetCurrentThreadId()))
  110. {
  111. // initialize COM *after* assign to input desktop
  112. // because CoInitialize creates a hidden window on
  113. // the current desktop.
  114. CoInitialize(NULL);
  115. InitCommonControls();
  116. if (InitClientData())
  117. {
  118. Sleep(10);
  119. dlg.DoModal();
  120. if (g_rgClients)
  121. {
  122. VirtualFree(g_rgClients,0,MEM_RELEASE);
  123. g_rgClients = NULL;
  124. }
  125. g_cClients = 0;
  126. g_hWndDlg = NULL;
  127. s_hDlgThread = NULL;
  128. }
  129. CoUninitialize(); // uninitialize COM
  130. }
  131. return 1;
  132. }
  133. void StopDialog()
  134. {
  135. if (aboutWnd)
  136. {
  137. EndDialog(aboutWnd,0);
  138. aboutWnd = NULL;
  139. Sleep(10);
  140. }
  141. if (g_hWndDlg)
  142. {
  143. ::PostMessage(g_hWndDlg, WM_CLOSE, 0, 0);
  144. g_hWndDlg = NULL;
  145. Sleep(10);
  146. UnassignDesktop();
  147. }
  148. if (g_rgClients)
  149. {
  150. VirtualFree(g_rgClients,0,MEM_RELEASE);
  151. g_rgClients = NULL;
  152. }
  153. g_cClients = 0;
  154. }
  155. //--------------------------------
  156. #if defined(_X86_)
  157. __declspec (dllexport)
  158. #endif
  159. // UManDlg - Opens or closes the utilman dialog.
  160. //
  161. // fShowDlg - TRUE if dialog should be shown, FALSE if dialog should be closed
  162. // fWaitForDlgClose - TRUE if the function should not return until the dialog
  163. // is closed or a desktop switch happens else FALSE.
  164. // dwVersion - The utilman version
  165. //
  166. // returns TRUE if the dialog was opened or closed
  167. // returns FALSE if the dialog could not be opened or it wasn't open
  168. //
  169. BOOL UManDlg(BOOL fShowDlg, BOOL fWaitForDlgClose, DWORD dwVersion)
  170. {
  171. BOOL fRv = FALSE;
  172. if (dwVersion != UMANDLG_VERSION)
  173. return FALSE;
  174. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  175. if (fShowDlg)
  176. {
  177. if (!s_hDlgThread)
  178. {
  179. s_hDlgThread = CreateThread(NULL, 0, UManDlgThread, NULL, 0, NULL);
  180. }
  181. else
  182. {
  183. SetForegroundWindow((aboutWnd)?aboutWnd:g_hWndDlg);
  184. }
  185. if (s_hDlgThread && fWaitForDlgClose)
  186. {
  187. // This code is executed on the default desktop for the following cases:
  188. //
  189. // 1. Utilman #1 run from the start menu
  190. // 2. Utilman #2 run from the start menu (utilman #1 is SYSTEM)
  191. // 3. Utilman #2 run by utilman #1 in user's context
  192. //
  193. // Wait for either the dialog to close or a desktop switch then return.
  194. // This will end this instance of utilman. If there is a utilman
  195. // running as SYSTEM it will bring up the dialog on the other desktop.
  196. HANDLE rghEvents[2];
  197. rghEvents[0] = s_hDlgThread;
  198. rghEvents[1] = OpenEvent(SYNCHRONIZE, FALSE, __TEXT("WinSta0_DesktopSwitch"));
  199. while (TRUE)
  200. {
  201. DWORD dwObj = MsgWaitForMultipleObjects(2, rghEvents, FALSE, INFINITE, QS_ALLINPUT );
  202. switch (dwObj)
  203. {
  204. case WAIT_OBJECT_0 + 1: // the desktop is changing; close the dialog
  205. StopDialog();
  206. // intentional fall thru to cleanup code
  207. case WAIT_OBJECT_0: // the thread exited; clean up and return
  208. CloseHandle(s_hDlgThread);
  209. s_hDlgThread = 0;
  210. CloseHandle(rghEvents[1]);
  211. return TRUE;
  212. break;
  213. default: // process messages
  214. {
  215. MSG msg;
  216. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  217. {
  218. TranslateMessage(&msg);
  219. DispatchMessage(&msg);
  220. }
  221. }
  222. break;
  223. }
  224. }
  225. }
  226. }
  227. else
  228. {
  229. // This code is executed when utilman is running on the secure desktop. In
  230. // that case, utilman brings up the dialog as a thread from its process.
  231. // When the desktop switch is detected utilman calls this function to close
  232. // the dialog. It will be restarted again on the new desktop.
  233. fRv = (g_hWndDlg && s_hDlgThread);
  234. StopDialog();
  235. }
  236. return fRv;
  237. }
  238. BOOL IsDialogUp()
  239. {
  240. return (g_hWndDlg && s_hDlgThread)?TRUE:FALSE;
  241. }
  242. }//extern "C"
  243. /////////////////////////////////////////////////////////////////////////////
  244. // CWarningDlg dialog
  245. CWarningDlg::CWarningDlg(CWnd* pParent /*=NULL*/)
  246. : CDialog(CWarningDlg::IDD, pParent)
  247. {
  248. //{{AFX_DATA_INIT(CWarningDlg)
  249. m_fDontWarnAgain = TRUE;
  250. //}}AFX_DATA_INIT
  251. }
  252. void CWarningDlg::DoDataExchange(CDataExchange* pDX)
  253. {
  254. CDialog::DoDataExchange(pDX);
  255. //{{AFX_DATA_MAP(CWarningDlg)
  256. DDX_Check(pDX, IDC_CHK_WARN, m_fDontWarnAgain);
  257. //}}AFX_DATA_MAP
  258. }
  259. BEGIN_MESSAGE_MAP(CWarningDlg, CDialog)
  260. //{{AFX_MSG_MAP(CWarningDlg)
  261. // NOTE: the ClassWizard will add message map macros here
  262. //}}AFX_MSG_MAP
  263. END_MESSAGE_MAP()
  264. /////////////////////////////////////////////////////////////////////////////
  265. // CWarningDlg message handlers
  266. /////////////////////////////////////////////////////////////////////////////
  267. // UMDialog dialog
  268. // --------------------------------------------
  269. UMDialog::UMDialog(CWnd* pParent /*=NULL*/)
  270. : CDialog(UMDialog::IDD, pParent)
  271. , m_fRunningSecure(FALSE)
  272. {
  273. m_szUMStr.LoadString(IDS_UM);
  274. //{{AFX_DATA_INIT(UMDialog)
  275. // NOTE: the ClassWizard will add member initialization here
  276. //}}AFX_DATA_INIT
  277. }
  278. UMDialog::~UMDialog()
  279. {
  280. m_lbClientList.Detach();
  281. }
  282. // --------------------------------------------
  283. void UMDialog::DoDataExchange(CDataExchange* pDX)
  284. {
  285. CDialog::DoDataExchange(pDX);
  286. //{{AFX_DATA_MAP(UMDialog)
  287. // NOTE: the ClassWizard will add DDX and DDV calls here
  288. //}}AFX_DATA_MAP
  289. }
  290. // --------------------------------------------
  291. BEGIN_MESSAGE_MAP(UMDialog, CDialog)
  292. //{{AFX_MSG_MAP(UMDialog)
  293. ON_WM_CLOSE()
  294. ON_BN_CLICKED(IDC_START, OnStart)
  295. ON_BN_CLICKED(IDC_STOP, OnStop)
  296. ON_WM_TIMER()
  297. ON_WM_HELPINFO()
  298. ON_COMMAND( ID_HELP, OnHelp )
  299. ON_LBN_SELCHANGE(IDC_NAME_STATUS, OnSelchangeNameStatus)
  300. ON_BN_CLICKED(IDC_START_AT_LOGON, OnStartAtLogon)
  301. ON_BN_CLICKED(IDC_START_WITH_UM, OnStartWithUm)
  302. ON_WM_CONTEXTMENU()
  303. ON_MESSAGE(WM_SYSCOMMAND,OnSysCommand)
  304. ON_BN_CLICKED(IDC_START_ON_LOCK, OnStartOnLock)
  305. ON_WM_SHOWWINDOW()
  306. //}}AFX_MSG_MAP
  307. END_MESSAGE_MAP()
  308. /////////////////////////////////////////////////////////////////////////////
  309. // UMDialog message handlers
  310. BOOL UMDialog::PreTranslateMessage(MSG* pMsg)
  311. {
  312. // Override that allows use of function keys to launch applets when on
  313. // the logon desktop. Only pay attention to key up to avoid dup calls.
  314. if (m_fRunningSecure && WM_KEYUP == pMsg->message)
  315. {
  316. int iClient = GetClientNameFromAccelerator(pMsg->wParam);
  317. if (iClient >= 0)
  318. {
  319. m_lbClientList.SelectString(-1, g_rgClients[iClient].machine.DisplayName);
  320. OnStart();
  321. return TRUE;
  322. }
  323. }
  324. return CDialog::PreTranslateMessage(pMsg);
  325. }
  326. BOOL UMDialog::OnInitDialog()
  327. {
  328. CDialog::OnInitDialog();
  329. // set the flag indicating if we are running in secure mode
  330. desktop_ts desktop;
  331. QueryCurrentDesktop(&desktop, TRUE);
  332. m_fRunningSecure = RunSecure(desktop.type);
  333. if (s_fShowWarningAgain && s_dwStartMode == START_BY_MENU)
  334. {
  335. CWarningDlg dlgWarn;
  336. dlgWarn.m_fDontWarnAgain = !s_fShowWarningAgain;
  337. dlgWarn.DoModal();
  338. s_fShowWarningAgain = !dlgWarn.m_fDontWarnAgain;
  339. }
  340. g_hWndDlg = m_hWnd;
  341. // change system menu
  342. CMenu *hSysMenu = GetSystemMenu(FALSE);
  343. if (hSysMenu)
  344. {
  345. CString str;
  346. hSysMenu->AppendMenu(MF_SEPARATOR);
  347. str.LoadString(IDS_ABOUT_STRING);
  348. hSysMenu->AppendMenu(MF_STRING,IDC_ABOUT,LPCTSTR(str));
  349. }
  350. // handle any "start when utility manager starts" applets
  351. StartClientsOnShow();
  352. // attach ListBox to member data and populate w/list of applications
  353. m_lbClientList.Attach(GetDlgItem(IDC_NAME_STATUS)->m_hWnd);
  354. ListClients();
  355. // Disable Help button if we are at WinLogon because the help
  356. // dialog supports "Jump to URL..." exposing security risk.
  357. // The m_fRunningSecure variable is TRUE if UI shouldn't expose help.
  358. if (m_fRunningSecure)
  359. {
  360. EnableDlgItem(ID_HELP, FALSE, IDOK);
  361. }
  362. // Disable "Start when UtilMan starts" unless user is an admin
  363. // and we are running in non-secure mode.
  364. if (s_dwStartMode != START_BY_MENU)
  365. {
  366. GetDlgItem(IDC_START_WITH_UM)->EnableWindow(IsAdmin() && !m_fRunningSecure);
  367. }
  368. // Bring dialog to top and center on desktop window
  369. RECT rectUmanDlg,rectDesktop;
  370. GetDesktopWindow()->GetWindowRect(&rectDesktop);
  371. GetWindowRect(&rectUmanDlg);
  372. long lDlgWidth = rectUmanDlg.right - rectUmanDlg.left;
  373. long lDlgHieght = rectUmanDlg.bottom - rectUmanDlg.top;
  374. if (!m_fRunningSecure)
  375. {
  376. rectUmanDlg.left = (rectDesktop.right - lDlgWidth)/2;
  377. rectUmanDlg.top = (rectDesktop.bottom - lDlgHieght)/2;
  378. } else
  379. {
  380. rectUmanDlg.left = rectDesktop.left + (long)(lDlgWidth/10);
  381. rectUmanDlg.top = rectDesktop.bottom - lDlgHieght - (long)(lDlgHieght/10);
  382. }
  383. // This looks a bit odd (SetForegroundWindow should also be activating
  384. // the window) but if you don't call SetActiveWindow on the secure
  385. // desktop then the second, etc... WinKey+U will bring up UM hidden
  386. // behind the welcome "screen".
  387. SetActiveWindow();
  388. SetForegroundWindow();
  389. SetWindowPos(&wndTopMost,rectUmanDlg.left,rectUmanDlg.top,0,0,SWP_NOSIZE);
  390. if (!m_fRunningSecure)
  391. {
  392. // on default desktop the above SetWindowPos makes the dialog initially
  393. // on top and this call allows other apps to then be on top.
  394. SetWindowPos(&wndNoTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
  395. }
  396. // start checking every so often to see if we need to update our display
  397. SetTimer(UPDATE_CLIENT_LIST_TIMER, 3000, NULL);
  398. return TRUE; // return TRUE unless you set the focus to a control
  399. }
  400. // -----------------------------------------------------
  401. void UMDialog::OnSysCommand(UINT nID,LPARAM lParam)
  402. {
  403. if (nID == IDC_ABOUT)
  404. {
  405. UMAbout dlg;
  406. dlg.DoModal();
  407. aboutWnd = NULL;
  408. }
  409. else
  410. {
  411. CDialog::OnSysCommand(nID,lParam);
  412. }
  413. }//UMDialog::OnSysCommand
  414. // ------------------------------------
  415. // --------------------------------------------
  416. // CanStartOnLockedDesktop - returns TRUE if applets can
  417. // be configured to be auto-started on the secure desktop
  418. //
  419. inline BOOL CanStartOnLockedDesktop(int iWhichClient, BOOL fRunningSecure)
  420. {
  421. // user can ask for auto start on secure desktop if they are logged on, the
  422. // applet is OK'd to run on the secure desktop and the machine isn't using
  423. // fast user switching (FUS) (w/FUS Ctrl+Alt+Del disconnects the user session
  424. // rather than switching desktops).
  425. BOOL fCanStartOnLockedDesktop =
  426. (
  427. !fRunningSecure &&
  428. g_rgClients[iWhichClient].user.fCanRunSecure &&
  429. CanLockDesktopWithoutDisconnect()
  430. )?TRUE:FALSE;
  431. return fCanStartOnLockedDesktop;
  432. }
  433. // --------------------------------------------
  434. // OnSelchangeNameStatus is called when the user navigates the list
  435. // box items by clicking with the mouse or using up/down arrows.
  436. //
  437. void UMDialog::OnSelchangeNameStatus()
  438. {
  439. // Get the currently selected item and update the controls for
  440. // the currently selected item.
  441. int iSel;
  442. if (GetSelectedClient((int)g_cClients, iSel))
  443. {
  444. // Group box label
  445. CString str(g_rgClients[iSel].machine.DisplayName);
  446. CString optStr;
  447. optStr.Format(IDS_OPTIONS, str);
  448. GetDlgItem(IDC_OPTIONS)->SetWindowText(optStr);
  449. // only enable options when started via WinKey+U
  450. if (s_dwStartMode != START_BY_MENU)
  451. {
  452. // Disable "start at logon" at secure desktop to avoid mischief
  453. if (!m_fRunningSecure)
  454. {
  455. GetDlgItem(IDC_START_AT_LOGON)->EnableWindow(TRUE);
  456. } else
  457. {
  458. // this may be set in an upgrade situation; clear it
  459. g_rgClients[iSel].user.fStartAtLogon = FALSE;
  460. GetDlgItem(IDC_START_AT_LOGON)->EnableWindow(FALSE);
  461. }
  462. // Enable "start on locked desktop" if at default desktop and
  463. // when applet can run on secure desktop
  464. if (CanStartOnLockedDesktop(iSel, m_fRunningSecure))
  465. {
  466. GetDlgItem(IDC_START_ON_LOCK)->EnableWindow(TRUE);
  467. } else
  468. {
  469. // this may be set in an upgrade situation; clear it
  470. g_rgClients[iSel].user.fStartOnLockDesktop = FALSE;
  471. GetDlgItem(IDC_START_ON_LOCK)->EnableWindow(FALSE);
  472. }
  473. // Start option checkboxes
  474. CheckDlgButton(IDC_START_AT_LOGON, (g_rgClients[iSel].user.fStartAtLogon)?TRUE:FALSE);
  475. CheckDlgButton(IDC_START_ON_LOCK, (g_rgClients[iSel].user.fStartOnLockDesktop)?TRUE:FALSE);
  476. CheckDlgButton(IDC_START_WITH_UM, (g_rgClients[iSel].user.fStartWithUtilityManager)?TRUE:FALSE);
  477. } else
  478. {
  479. GetDlgItem(IDC_START_AT_LOGON)->EnableWindow(FALSE);
  480. GetDlgItem(IDC_START_ON_LOCK)->EnableWindow(FALSE);
  481. GetDlgItem(IDC_START_WITH_UM)->EnableWindow(FALSE);
  482. CheckDlgButton(IDC_START_AT_LOGON, FALSE);
  483. CheckDlgButton(IDC_START_ON_LOCK, FALSE);
  484. CheckDlgButton(IDC_START_WITH_UM, FALSE);
  485. }
  486. // Start and stop buttons
  487. DWORD dwState = g_rgClients[iSel].state;
  488. if ((dwState == UM_CLIENT_RUNNING)
  489. && (g_rgClients[iSel].runCount >= g_rgClients[iSel].machine.MaxRunCount))
  490. EnableDlgItem(IDC_START, FALSE, IDC_NAME_STATUS);
  491. else
  492. EnableDlgItem(IDC_START, TRUE, IDC_NAME_STATUS);
  493. if ((dwState == UM_CLIENT_NOT_RUNNING) || CantStopClient(&g_rgClients[iSel]))
  494. EnableDlgItem(IDC_STOP, FALSE, IDC_NAME_STATUS);
  495. else
  496. EnableDlgItem(IDC_STOP, TRUE, IDC_NAME_STATUS);
  497. }// else ignore selections not in a valid range
  498. }
  499. // --------------------------------------------
  500. void UMDialog::OnClose()
  501. {
  502. // behave like cancel
  503. CDialog::OnClose();
  504. }//UMDialog::OnClose
  505. // --------------------------------------------
  506. // OnStart is called when the Start button is clicked. It starts
  507. // the client ap then lets the timer update saved state.
  508. //
  509. void UMDialog::OnStart()
  510. {
  511. int iSel;
  512. if (GetSelectedClient((int)g_cClients, iSel))
  513. {
  514. if (StartClient(m_hWnd, &g_rgClients[iSel]))
  515. {
  516. KillTimer(UPDATE_CLIENT_LIST_TIMER);
  517. EnableDlgItem(IDC_STOP, TRUE, IDC_NAME_STATUS);
  518. ListClients();
  519. SetTimer(UPDATE_CLIENT_LIST_TIMER, 3000, NULL);
  520. if (g_rgClients[iSel].runCount+1 >= g_rgClients[iSel].machine.MaxRunCount)
  521. EnableDlgItem(IDC_START, FALSE, IDC_STOP);
  522. }
  523. else if (g_rgClients[iSel].runCount < g_rgClients[iSel].machine.MaxRunCount)
  524. {
  525. // Unable to start
  526. CString str;
  527. str.LoadString((m_fRunningSecure)?IDS_SECUREMODE:IDS_ERRSTART);
  528. MessageBox(str, m_szUMStr, MB_OK);
  529. }
  530. }
  531. }
  532. // --------------------------------------------
  533. // OnStop is called when the Stop button is clicked. It stops
  534. // the client ap then lets the timer update saved state.
  535. //
  536. void UMDialog::OnStop()
  537. {
  538. int iSel;
  539. if (GetSelectedClient((int)g_cClients, iSel))
  540. {
  541. if (StopClient(&g_rgClients[iSel]))
  542. {
  543. KillTimer(UPDATE_CLIENT_LIST_TIMER);
  544. GetDlgItem(IDC_START)->EnableWindow(TRUE);
  545. ListClients();
  546. EnableDlgItem(IDC_STOP, FALSE, IDOK);
  547. SetTimer(UPDATE_CLIENT_LIST_TIMER, 3000, NULL);
  548. }
  549. else
  550. {
  551. // Unable to stop
  552. CString str;
  553. str.LoadString(IDS_ERRSTOP);
  554. MessageBox(str, m_szUMStr, MB_OK);
  555. }
  556. }
  557. }
  558. void UMDialog::SaveCurrentState()
  559. {
  560. int iSel;
  561. if (GetSelectedClient((int)g_cClients, iSel))
  562. {
  563. g_rgClients[iSel].user.fStartAtLogon
  564. = (IsDlgButtonChecked(IDC_START_AT_LOGON))?TRUE:FALSE;
  565. g_rgClients[iSel].user.fStartWithUtilityManager
  566. = (IsDlgButtonChecked(IDC_START_WITH_UM))?TRUE:FALSE;
  567. g_rgClients[iSel].user.fStartOnLockDesktop
  568. = (IsDlgButtonChecked(IDC_START_ON_LOCK))?TRUE:FALSE;
  569. }
  570. }
  571. // --------------------------------------------
  572. // OnOK is called when the user clicks the OK button to
  573. // dismiss the UtilMan dialog.
  574. //
  575. void UMDialog::OnOK()
  576. {
  577. SaveCurrentState();
  578. WriteClientData(m_fRunningSecure);
  579. CDialog::OnOK();
  580. }//UMDialog::OnOK
  581. // ----------------------------------------------------------------------------
  582. // OnTimer is called to check the status of client apps that are displayed
  583. // in the UI. This keeps the UI consistent with the running client app's.
  584. //
  585. void UMDialog::OnTimer(UINT nIDEvent)
  586. {
  587. if (nIDEvent == UPDATE_CLIENT_LIST_TIMER)
  588. {
  589. UINT uiElapsed = 3000;
  590. KillTimer(UPDATE_CLIENT_LIST_TIMER);
  591. // get current status and pick up new apps
  592. if (CheckStatus(g_rgClients, g_cClients))
  593. {
  594. ListClients(); // something has changed - update the UI
  595. uiElapsed = 500;
  596. }
  597. SetTimer(UPDATE_CLIENT_LIST_TIMER, uiElapsed, NULL);
  598. }
  599. CDialog::OnTimer(nIDEvent);
  600. }
  601. // --------------------------------------------
  602. // OnHelpInfo provides context sensitive help. It only does
  603. // this if not on the WinLogon desktop.
  604. //
  605. BOOL UMDialog::OnHelpInfo(HELPINFO* pHelpInfo)
  606. {
  607. if (m_fRunningSecure)
  608. return FALSE;
  609. if ( pHelpInfo->iCtrlId == IDC_OPTIONS )
  610. return TRUE;
  611. ::WinHelp((HWND)pHelpInfo->hItemHandle, __TEXT("utilmgr.hlp"), HELP_WM_HELP,
  612. (DWORD_PTR) (LPSTR) g_rgHelpIds);
  613. return TRUE;
  614. }
  615. // --------------------------------------------
  616. // OnHelpInfo provides context sensitive help when the user
  617. // right-clicks the dialog. It only does this if not on the
  618. // WinLogon desktop.
  619. //
  620. void UMDialog::OnContextMenu(CWnd* pWnd, CPoint point)
  621. {
  622. if (m_fRunningSecure)
  623. return;
  624. ::WinHelp(pWnd->m_hWnd, __TEXT("utilmgr.hlp"), HELP_CONTEXTMENU
  625. , (DWORD_PTR) (LPSTR) g_rgHelpIds);
  626. }
  627. // --------------------------------------------
  628. // OnHelp provides standard help. It only does this if not
  629. // on the WinLogon desktop.
  630. //
  631. void UMDialog::OnHelp()
  632. {
  633. if (m_fRunningSecure)
  634. return;
  635. ::HtmlHelp(m_hWnd , TEXT("utilmgr.chm"), HH_DISPLAY_TOPIC, 0);
  636. }
  637. // ----------------------------------
  638. void UMDialog::EnableDlgItem(DWORD dwEnableMe, BOOL fEnable, DWORD dwFocusHere)
  639. {
  640. // when disabling a control that currently has focs switch it to dwFocusHere
  641. if (!fEnable && (GetFocus() == GetDlgItem(dwEnableMe)))
  642. GetDlgItem(dwFocusHere)->SetFocus();
  643. GetDlgItem(dwEnableMe)->EnableWindow(fEnable);
  644. }
  645. void UMDialog::SetStateStr(int iClient)
  646. {
  647. switch (g_rgClients[iClient].state)
  648. {
  649. case UM_CLIENT_NOT_RUNNING:
  650. m_szStateStr.Format(IDS_NOT_RUNNING, g_rgClients[iClient].machine.DisplayName);
  651. break;
  652. case UM_CLIENT_RUNNING:
  653. m_szStateStr.Format(IDS_RUNNING, g_rgClients[iClient].machine.DisplayName);
  654. break;
  655. case UM_CLIENT_NOT_RESPONDING:
  656. m_szStateStr.Format(IDS_NOT_RESPONDING, g_rgClients[iClient].machine.DisplayName);
  657. break;
  658. default:
  659. m_szStateStr.Empty();
  660. break;
  661. }
  662. }
  663. // --------------------------------------------
  664. void UMDialog::ListClients()
  665. {
  666. // Re-do the client list box with latest state info
  667. int iCurSel = m_lbClientList.GetCurSel();
  668. if (iCurSel == LB_ERR)
  669. iCurSel = 0;
  670. m_lbClientList.ResetContent();
  671. for (DWORD i = 0; i < g_cClients; i++)
  672. {
  673. SetStateStr(i);
  674. if (!m_szStateStr.IsEmpty())
  675. {
  676. m_lbClientList.AddString(m_szStateStr);
  677. }
  678. }
  679. m_lbClientList.SetCurSel(iCurSel);
  680. // Refresh button states in case they've changed
  681. // (this happens on desktop switch)
  682. OnSelchangeNameStatus();
  683. }
  684. // --------------------------------------------
  685. // UpdateClientState updates the client list box with the current state
  686. // of the application (running, not running, not responding)
  687. //
  688. void UMDialog::UpdateClientState(int iSel)
  689. {
  690. SetStateStr(iSel);
  691. m_lbClientList.DeleteString(iSel);
  692. m_lbClientList.InsertString(iSel, m_szStateStr);
  693. m_lbClientList.SetCurSel(iSel);
  694. }
  695. // --------------------------------------------
  696. // OnStartAtLogon updates the state of the client in memory when the
  697. // Start with Windows checkbox is checked or unchecked.
  698. //
  699. void UMDialog::OnStartAtLogon()
  700. {
  701. SaveCurrentState();
  702. }
  703. // --------------------------------------------
  704. // OnStartWithUm updates the state of the client in memory when the
  705. // Start with Utility Manager checkbox is checked or unchecked.
  706. //
  707. void UMDialog::OnStartWithUm()
  708. {
  709. SaveCurrentState();
  710. }
  711. // --------------------------------------------
  712. // OnStartOnLock updates the state of the client in memory when the
  713. // Start when I lock my desktop checkbox is checked or unchecked.
  714. //
  715. void UMDialog::OnStartOnLock()
  716. {
  717. SaveCurrentState();
  718. }
  719. // --------------------------------------------
  720. // OnShowWindow
  721. // This was added for a timing problem where utilman came up running in the system context on the users desktop
  722. // this code here makes sure that that cannot happen by cheching right when the dialog is about to appear
  723. //
  724. void UMDialog::OnShowWindow(BOOL bShow, UINT nStatus)
  725. {
  726. HDESK hdesk;
  727. SID *desktopSID = NULL;
  728. hdesk = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED);
  729. // this is expected to fail for the winlogon desktop and thats ok
  730. if (hdesk)
  731. {
  732. TCHAR desktopName[NAME_LEN];
  733. DWORD nl, SIDLen = 0;
  734. if (!GetUserObjectInformation(hdesk, UOI_NAME, desktopName, NAME_LEN, &nl))
  735. goto StopDialog;
  736. if (!GetUserObjectInformation(hdesk, UOI_USER_SID, desktopSID, 0, &SIDLen))
  737. {
  738. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  739. goto StopDialog;
  740. }
  741. if (SIDLen > 0 && !lstrcmpi(desktopName, TEXT("Default")))
  742. {
  743. desktopSID = (SID*)new BYTE[SIDLen];
  744. if (!desktopSID)
  745. goto StopDialog;
  746. if (!GetUserObjectInformation(hdesk, UOI_USER_SID, desktopSID, SIDLen, &SIDLen))
  747. goto StopDialog;
  748. BOOL fError;
  749. HANDLE hUserToken = GetUserAccessToken(TRUE, &fError);
  750. if (fError)
  751. goto StopDialog;
  752. // We get a token only if there is a logged on user.
  753. // If there is not then we can come up as system with no worries.
  754. if (!hUserToken)
  755. goto LetDialogComeup;
  756. BOOL fStatus = FALSE;
  757. BOOL fIsInteractiveUser = FALSE;
  758. PSID psidInteractive = InteractiveUserSid(TRUE);
  759. if (!psidInteractive)
  760. goto StopDialog;
  761. fStatus = CheckTokenMembership(hUserToken, psidInteractive, &fIsInteractiveUser);
  762. //If the logged on user is the interactive user and we are running as system then it is a
  763. // security risk to show UI. This can happen when rappidly switching desktops.
  764. if ( fStatus && fIsInteractiveUser && IsSystem())
  765. goto StopDialog;
  766. }
  767. }
  768. LetDialogComeup:
  769. if (desktopSID)
  770. delete [] desktopSID;
  771. return;
  772. StopDialog:
  773. StopDialog();
  774. if (desktopSID)
  775. delete [] desktopSID;
  776. }
  777. /////////////////////////////////////////////////////////////////////////////
  778. // C code
  779. //-----------------------------------------------------------------
  780. __inline void ReplaceDisplayName(LPTSTR szName, int iRID)
  781. {
  782. TCHAR szBuf[MAX_APPLICATION_NAME_LEN];
  783. if (LoadString(AfxGetInstanceHandle(), iRID, szBuf, MAX_APPLICATION_NAME_LEN))
  784. lstrcpy(szName, szBuf);
  785. }
  786. void SetLocalizedDisplayName()
  787. {
  788. // Make localization easier; don't require them to localize registry entries.
  789. // Instead, replace our copy with the localized version. This appears to be
  790. // duplicate code to that in umanrun.c however, that part of the code always
  791. // runs as system and therefore the DisplayName is set to the default system
  792. // language. This part of the code (the UI) runs as the logged on user when
  793. // there is one so these resources will be the user's language. The resources
  794. // and associated code should be removed from utilman.exe and this code and
  795. // resources (from umandlg.dll) should be used.
  796. for (DWORD i=0;i<g_cClients;i++)
  797. {
  798. if ( lstrcmp( g_rgClients[i].machine.ApplicationName, TEXT("Magnifier") ) == 0 )
  799. {
  800. ReplaceDisplayName(g_rgClients[i].machine.DisplayName, IDS_DISPLAY_NAME_MAGNIFIER);
  801. }
  802. else if ( lstrcmp( g_rgClients[i].machine.ApplicationName, TEXT("Narrator") ) == 0 )
  803. {
  804. ReplaceDisplayName(g_rgClients[i].machine.DisplayName, IDS_DISPLAY_NAME_NARRATOR);
  805. }
  806. else if ( lstrcmp( g_rgClients[i].machine.ApplicationName, TEXT("On-Screen Keyboard") ) == 0 )
  807. {
  808. ReplaceDisplayName(g_rgClients[i].machine.DisplayName, IDS_DISPLAY_NAME_OSK);
  809. }
  810. }
  811. }
  812. static BOOL InitClientData(void)
  813. {
  814. BOOL fRv = TRUE;
  815. // On initial run allocate and initialize client array
  816. if (!g_rgClients || !g_cClients)
  817. {
  818. umc_header_tsp pHdr = 0;
  819. umclient_tsp c = 0;
  820. DWORD_PTR accessID,accessID2;
  821. g_cClients = 0;
  822. g_rgClients = NULL;
  823. fRv = FALSE;
  824. pHdr = (umc_header_tsp)AccessIndependentMemory(
  825. UMC_HEADER_FILE,
  826. sizeof(umc_header_ts),
  827. FILE_MAP_READ,
  828. &accessID);
  829. if (!pHdr)
  830. {
  831. goto Cleanup;
  832. }
  833. s_dwStartMode = pHdr->dwStartMode; // capture the Utilman start mode
  834. s_fShowWarningAgain = pHdr->fShowWarningAgain; // and warning dialog flag
  835. if (!pHdr->numberOfClients)
  836. {
  837. goto Cleanup;
  838. }
  839. c = (umclient_tsp)AccessIndependentMemory(
  840. UMC_CLIENT_FILE,
  841. sizeof(umclient_ts)*pHdr->numberOfClients,
  842. FILE_MAP_READ,
  843. &accessID2);
  844. if (!c)
  845. {
  846. goto Cleanup;
  847. }
  848. g_rgClients = (umclient_tsp)VirtualAlloc(NULL, sizeof(umclient_ts)*pHdr->numberOfClients, MEM_RESERVE,PAGE_READWRITE);
  849. if (!g_rgClients)
  850. {
  851. goto Cleanup;
  852. }
  853. if (!VirtualAlloc(g_rgClients, sizeof(umclient_ts)*pHdr->numberOfClients, MEM_COMMIT, PAGE_READWRITE))
  854. {
  855. goto Cleanup;
  856. }
  857. fRv = TRUE;
  858. g_cClients = pHdr->numberOfClients;
  859. memcpy(g_rgClients,c,sizeof(umclient_ts)*pHdr->numberOfClients);
  860. SetLocalizedDisplayName();
  861. Cleanup:
  862. if (pHdr)
  863. {
  864. UnAccessIndependentMemory(pHdr, accessID);
  865. }
  866. if (c)
  867. {
  868. UnAccessIndependentMemory(c, accessID2);
  869. }
  870. if (!fRv && g_rgClients)
  871. {
  872. VirtualFree(g_rgClients, 0, MEM_RELEASE);
  873. g_rgClients = NULL;
  874. g_cClients = 0;
  875. }
  876. }
  877. // "Start when I log on" is per-user setting so get that
  878. // each time the dialog is brought up
  879. CManageShellLinks CManageLinks(STARTUP_FOLDER);
  880. for (DWORD i=0;i<g_cClients;i++)
  881. {
  882. g_rgClients[i].user.fStartAtLogon
  883. = CManageLinks.LinkExists(g_rgClients[i].machine.ApplicationName);
  884. }
  885. return fRv;
  886. }
  887. // RegSetUMDwordValue - helper function to set a DWORD string value creating it if necessary
  888. //
  889. BOOL RegSetUMDwordValue(HKEY hKey, LPCTSTR pszKey, LPCTSTR pszString, DWORD dwNewValue)
  890. {
  891. HKEY hSubkey;
  892. int iRv;
  893. DWORD dwValue = dwNewValue;
  894. iRv = RegCreateKeyEx(
  895. hKey
  896. , pszKey
  897. , 0, NULL
  898. , REG_OPTION_NON_VOLATILE
  899. , KEY_ALL_ACCESS
  900. , NULL, &hSubkey, NULL);
  901. if (iRv == ERROR_SUCCESS)
  902. {
  903. RegSetValueEx(
  904. hSubkey
  905. , pszString
  906. , 0, REG_DWORD
  907. , (BYTE *)&dwValue
  908. , sizeof(DWORD));
  909. RegCloseKey(hSubkey);
  910. }
  911. return (iRv == ERROR_SUCCESS)?TRUE:FALSE;
  912. }
  913. void WriteUserRegData(HKEY hKeyCU, BOOL fDoAppletData)
  914. {
  915. HKEY hkey;
  916. DWORD dwRv = RegCreateKeyEx(hKeyCU
  917. , UM_HKCU_REGISTRY_KEY
  918. , 0 , NULL
  919. , REG_OPTION_NON_VOLATILE
  920. , KEY_ALL_ACCESS, NULL
  921. , &hkey, NULL);
  922. if (dwRv == ERROR_SUCCESS)
  923. {
  924. dwRv = RegSetValueEx(
  925. hkey
  926. , UMR_VALUE_SHOWWARNING
  927. , 0, REG_DWORD
  928. , (BYTE *)&s_fShowWarningAgain
  929. , sizeof(DWORD));
  930. if (fDoAppletData)
  931. {
  932. for (DWORD i = 0; i < g_cClients; i++)
  933. {
  934. RegSetUMDwordValue(
  935. hkey
  936. , g_rgClients[i].machine.ApplicationName
  937. , UMR_VALUE_STARTLOCK
  938. , g_rgClients[i].user.fStartOnLockDesktop);
  939. }
  940. }
  941. RegCloseKey(hkey);
  942. }
  943. }
  944. // --------------------------------------------
  945. static BOOL CopyClientData()
  946. {
  947. umclient_tsp c;
  948. DWORD_PTR accessID;
  949. if (!g_cClients || !g_rgClients)
  950. return TRUE;
  951. c = (umclient_tsp)AccessIndependentMemory(
  952. UMC_CLIENT_FILE,
  953. sizeof(umclient_ts)*g_cClients,
  954. FILE_MAP_READ|FILE_MAP_WRITE,
  955. &accessID);
  956. if (!c)
  957. return FALSE;
  958. memcpy(c,g_rgClients,sizeof(umclient_ts)*g_cClients);
  959. UnAccessIndependentMemory(c, accessID);
  960. return TRUE;
  961. }
  962. static void CopyHeaderData()
  963. {
  964. umc_header_tsp pHdr;
  965. DWORD_PTR accessID;
  966. pHdr = (umc_header_tsp)AccessIndependentMemory(
  967. UMC_HEADER_FILE,
  968. sizeof(umc_header_ts),
  969. FILE_MAP_READ|FILE_MAP_WRITE,
  970. &accessID);
  971. if (pHdr)
  972. {
  973. pHdr->fShowWarningAgain = s_fShowWarningAgain;
  974. UnAccessIndependentMemory(pHdr, accessID);
  975. }
  976. }
  977. // ----------------------------------
  978. // WriteClientData - save settings to the registry
  979. //
  980. static BOOL WriteClientData(BOOL fRunningSecure)
  981. {
  982. // It only makes sense to do this if there are any applets being managed
  983. // (shouldn't get here) and if there is a logged on user (otherwise the
  984. // settings cannot be changed)
  985. if (!g_cClients || !g_rgClients || fRunningSecure)
  986. return TRUE;
  987. // The SYSTEM instance of utilman needs to be updated in case the user
  988. // changed any options. This is so subsequent instances of the UI will
  989. // get the correct options without having to read the registry.
  990. CopyHeaderData();
  991. CopyClientData();
  992. //
  993. // Write utilman settings data. Put "Start when UtilMan starts" in HKLM,
  994. // "Start when I lock desktop" in HKCU, and "Start when I log on" into
  995. // a startup link in the logged on user's shell folder.
  996. //
  997. // "Start when UtilMan starts" settings... (only for admins)
  998. DWORD i;
  999. if (IsWindowEnabled(GetDlgItem(g_hWndDlg, IDC_START_WITH_UM)))
  1000. {
  1001. HKEY hHKLM;
  1002. DWORD dwRv = RegCreateKeyEx(HKEY_LOCAL_MACHINE
  1003. , UM_REGISTRY_KEY
  1004. , 0 , NULL
  1005. , REG_OPTION_NON_VOLATILE
  1006. , KEY_ALL_ACCESS, NULL
  1007. , &hHKLM, NULL);
  1008. if (dwRv == ERROR_SUCCESS)
  1009. {
  1010. for (i = 0; i < g_cClients; i++)
  1011. {
  1012. RegSetUMDwordValue(
  1013. hHKLM
  1014. , g_rgClients[i].machine.ApplicationName
  1015. , UMR_VALUE_STARTUM
  1016. , g_rgClients[i].user.fStartWithUtilityManager);
  1017. }
  1018. RegCloseKey(hHKLM);
  1019. }
  1020. }
  1021. //
  1022. // "Start when I lock my desktop" settings... (any logged on user)
  1023. // and Don't show me the warning anymore setting
  1024. //
  1025. WriteUserRegData(HKEY_CURRENT_USER, IsWindowEnabled(GetDlgItem(g_hWndDlg, IDC_START_ON_LOCK)));
  1026. //
  1027. // manage shell folder link updates (logged on user only)
  1028. //
  1029. if (IsWindowEnabled(GetDlgItem(g_hWndDlg, IDC_START_AT_LOGON)))
  1030. {
  1031. CManageShellLinks CManageLinks(STARTUP_FOLDER);
  1032. for (i = 0; i < g_cClients; i++)
  1033. {
  1034. LPTSTR pszAppName = g_rgClients[i].machine.ApplicationName;
  1035. BOOL fLinkExists = CManageLinks.LinkExists(pszAppName);
  1036. // if should start at logon and there isn't a link then create one
  1037. // and if shouldn't start at logon and there is a link then delete it
  1038. if (g_rgClients[i].user.fStartAtLogon && !fLinkExists)
  1039. {
  1040. TCHAR pszAppPath[MAX_PATH];
  1041. LPTSTR pszApp = 0;
  1042. // Following is TRUE *only* if pszAppPath is non-null string value
  1043. if (GetClientApplicationPath(pszAppName , pszAppPath , MAX_PATH))
  1044. {
  1045. TCHAR pszFullPath[MAX_PATH*2+1]; // path + filename
  1046. TCHAR pszStartIn[MAX_PATH];
  1047. int ctch, ctchAppPath = lstrlen(pszAppPath);
  1048. // if pszAppPath is just base name and extension then prepend system path
  1049. if (wcscspn(pszAppPath, TEXT("\\")) != (size_t)ctchAppPath
  1050. || wcscspn(pszAppPath, TEXT(":")) != (size_t)ctchAppPath)
  1051. {
  1052. TCHAR szDrive[_MAX_DRIVE], szDir[_MAX_DIR];
  1053. _wsplitpath(pszAppPath, szDrive, szDir, NULL, NULL);
  1054. lstrcpy(pszStartIn, szDrive);
  1055. lstrcat(pszStartIn, szDir);
  1056. pszApp = pszAppPath;
  1057. } else
  1058. {
  1059. ctch = GetSystemDirectory(pszStartIn, MAX_PATH);
  1060. lstrcpy(pszFullPath, pszStartIn); // save path to build full path
  1061. if (ctch + ctchAppPath + 2 > MAX_PATH*2)
  1062. {
  1063. DBPRINTF(TEXT("WriteClientData: Path is too short!\r\n"));
  1064. } else
  1065. {
  1066. if (*(pszFullPath + ctch - 1) != '\\')
  1067. lstrcat(pszFullPath, TEXT("\\"));
  1068. lstrcat(pszFullPath, pszAppPath);
  1069. pszApp = pszFullPath;
  1070. }
  1071. }
  1072. if (pszApp)
  1073. {
  1074. // remove ending '\' from StartIn path
  1075. ctch = lstrlen(pszStartIn) - 1;
  1076. if (*(pszStartIn + ctch) == '\\')
  1077. *(pszStartIn + ctch) = 0;
  1078. CManageLinks.CreateLink(
  1079. pszAppName
  1080. , pszApp
  1081. , pszStartIn
  1082. , g_rgClients[i].machine.DisplayName
  1083. , TEXT("/UM"));
  1084. }
  1085. }
  1086. } else if (!g_rgClients[i].user.fStartAtLogon && fLinkExists)
  1087. {
  1088. CManageLinks.RemoveLink(pszAppName);
  1089. }
  1090. }
  1091. }
  1092. return TRUE;
  1093. }
  1094. // --------------------------------------------
  1095. static BOOL CantStopClient(umclient_tsp client)
  1096. {
  1097. switch (client->machine.ApplicationType)
  1098. {
  1099. case APPLICATION_TYPE_APPLICATION:
  1100. break;
  1101. case APPLICATION_TYPE_SERVICE:
  1102. {
  1103. SERVICE_STATUS ssStatus;
  1104. SC_HANDLE hService;
  1105. SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  1106. if (!hSCM)
  1107. return TRUE;
  1108. hService = OpenService(hSCM, client->machine.ApplicationName, SERVICE_ALL_ACCESS);
  1109. CloseServiceHandle(hSCM);
  1110. if (!hService)
  1111. return TRUE;
  1112. if (!QueryServiceStatus(hService, &ssStatus) ||
  1113. !(ssStatus.dwControlsAccepted & SERVICE_ACCEPT_STOP))
  1114. {
  1115. CloseServiceHandle(hService);
  1116. return TRUE;
  1117. }
  1118. CloseServiceHandle(hService);
  1119. break;
  1120. }
  1121. }
  1122. return FALSE;
  1123. }//CantStopClient
  1124. // We don't want UtilMan to startType to be Automatic
  1125. // It should only be made Automatic if it is required, When the user
  1126. // selects "Start when NT starts" through the GUI :a-anilk
  1127. static BOOL IsStartAuto()
  1128. {
  1129. #ifdef NEVER // MICW Don't start service anymore at logon because of TS
  1130. DWORD nClient;
  1131. for(nClient = 0; nClient < g_cClients; nClient++)
  1132. {
  1133. if ( g_rgClients[nClient].user.fStartAtLogon == TRUE )
  1134. return TRUE;
  1135. }
  1136. #endif
  1137. return FALSE;
  1138. }
  1139. static int GetClientNameFromAccelerator(WPARAM wVK)
  1140. {
  1141. for (int i=0;i<(int)g_cClients;i++)
  1142. if (g_rgClients[i].machine.AcceleratorKey == wVK)
  1143. return i;
  1144. return -1;
  1145. }
  1146. static BOOL StartClientsOnShow()
  1147. {
  1148. BOOL fOK = TRUE;
  1149. for (int i=0;i<(int)g_cClients;i++)
  1150. {
  1151. if ( g_rgClients[i].user.fStartWithUtilityManager
  1152. && !StartClient(g_hWndDlg, &g_rgClients[i]))
  1153. fOK = FALSE;
  1154. }
  1155. return fOK;
  1156. }