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.

1831 lines
60 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: CWLogonDialog.cpp
  3. //
  4. // Copyright (c) 2000, Microsoft Corporation
  5. //
  6. // File that contains an internal class to implement the logon dialog
  7. // additions for consumer windows. The C entry points allow the old Windows
  8. // 2000 Win32 GINA dialog to call into this C++ code.
  9. //
  10. // History: 2000-02-04 vtan created
  11. // --------------------------------------------------------------------------
  12. #include "StandardHeader.h"
  13. #include <cfgmgr32.h>
  14. #include <ginaIPC.h>
  15. #include <ginarcid.h>
  16. #include <msginaexports.h>
  17. #include <shlobj.h>
  18. #include <shlobjp.h>
  19. #include <winwlx.h>
  20. #include "CredentialTransfer.h"
  21. #include "LogonMutex.h"
  22. #include "LogonWait.h"
  23. #include "PrivilegeEnable.h"
  24. #include "RegistryResources.h"
  25. #include "SingleThreadedExecution.h"
  26. #include "StatusCode.h"
  27. #include "StringConvert.h"
  28. #include "SystemSettings.h"
  29. #include "TokenInformation.h"
  30. #include "TurnOffDialog.h"
  31. #include "UIHost.h"
  32. #include "UserList.h"
  33. #define WM_HIDEOURSELVES (WM_USER + 10000)
  34. #define WM_SHOWOURSELVES (WM_USER + 10001)
  35. // Special logon substatus code from: ds\security\gina\msgina\stringid.h
  36. #define IDS_LOGON_LOG_FULL 1702
  37. // --------------------------------------------------------------------------
  38. // CLogonDialog
  39. //
  40. // Purpose: C++ class to handle logon dialog additions for consumer
  41. // windows.
  42. //
  43. // History: 2000-02-04 vtan created from Neptune
  44. // --------------------------------------------------------------------------
  45. class CLogonDialog : public ILogonExternalProcess
  46. {
  47. private:
  48. CLogonDialog (void);
  49. CLogonDialog (const CLogonDialog& copyObject);
  50. const CLogonDialog& operator = (const CLogonDialog& assignObject);
  51. public:
  52. CLogonDialog (HWND hwndDialog, CUIHost *pUIHost, int iDialogType);
  53. ~CLogonDialog (void);
  54. NTSTATUS StartUIHost (void);
  55. void EndUIHost (void);
  56. void ChangeWindowTitle (void);
  57. bool IsClassicLogonMode (void) const;
  58. bool RevertClassicLogonMode (void);
  59. void Handle_WM_INITDIALOG (void);
  60. void Handle_WM_DESTROY (void);
  61. void Handle_WM_HIDEOURSELVES (void);
  62. void Handle_WM_SHOWOURSELVES (void);
  63. bool Handle_WM_LOGONSERVICEREQUEST (int iRequestType, void *pvInformation, int iDataSize);
  64. void Handle_WLX_WM_SAS (WPARAM wParam);
  65. bool Handle_WM_POWERBROADCAST (WPARAM wParam);
  66. bool Handle_LogonDisplayError (NTSTATUS status, NTSTATUS subStatus);
  67. void Handle_LogonCompleted (INT_PTR iDialogResult, const WCHAR *pszUsername, const WCHAR *pszDomain);
  68. void Handle_ShuttingDown (void);
  69. void Handle_LogonShowUI (void);
  70. void Handle_LogonHideUI (void);
  71. static void SetTextFields (HWND hwndDialog, const WCHAR *pwszUsername, const WCHAR *pwszDomain, const WCHAR *pwszPassword);
  72. public:
  73. virtual bool AllowTermination (DWORD dwExitCode);
  74. virtual NTSTATUS SignalAbnormalTermination (void);
  75. virtual NTSTATUS SignalRestart (void);
  76. virtual NTSTATUS LogonRestart (void);
  77. private:
  78. bool Handle_LOGON_QUERY_LOGGED_ON (LOGONIPC_CREDENTIALS& logonIPCCredentials);
  79. bool Handle_LOGON_LOGON_USER (LOGONIPC_CREDENTIALS& logonIPCCredentials);
  80. bool Handle_LOGON_LOGOFF_USER (LOGONIPC_CREDENTIALS& logonIPCCredentials);
  81. bool Handle_LOGON_TEST_BLANK_PASSWORD (LOGONIPC_CREDENTIALS& logonIPCCredentials);
  82. bool Handle_LOGON_TEST_INTERACTIVE_LOGON_ALLOWED (LOGONIPC_CREDENTIALS& logonIPCCredentials);
  83. bool Handle_LOGON_TEST_EJECT_ALLOWED (void);
  84. bool Handle_LOGON_TEST_SHUTDOWN_ALLOWED (void);
  85. bool Handle_LOGON_TURN_OFF_COMPUTER (void);
  86. bool Handle_LOGON_EJECT_COMPUTER (void);
  87. bool Handle_LOGON_SIGNAL_UIHOST_FAILURE (void);
  88. bool Handle_LOGON_ALLOW_EXTERNAL_CREDENTIALS (void);
  89. bool Handle_LOGON_REQUEST_EXTERNAL_CREDENTIALS (void);
  90. private:
  91. HWND _hwndDialog;
  92. RECT _rcDialog;
  93. bool _fLogonSuccessful,
  94. _fFatalError,
  95. _fExternalCredentials,
  96. _fResumed,
  97. _fOldCancelButtonEnabled;
  98. int _iDialogType,
  99. _iCADCount;
  100. HANDLE _hEvent;
  101. IExternalProcess* _pIExternalProcessOld;
  102. CEvent _eventLogonComplete;
  103. CLogonWait _logonWait;
  104. CUIHost* _pUIHost;
  105. TCHAR _szDomain[DNLEN + sizeof('\0')];
  106. TCHAR* _pszWindowTitle;
  107. static bool s_fFirstLogon;
  108. };
  109. bool g_fFirstLogon = true;
  110. CCriticalSection* g_pLogonDialogLock = NULL;
  111. CLogonDialog* g_pLogonDialog = NULL;
  112. // --------------------------------------------------------------------------
  113. // CLogonDialog::CLogonDialog
  114. //
  115. // Arguments: hwndDialog = HWND to the Win32 GINA dialog.
  116. //
  117. // Returns: <none>
  118. //
  119. // Purpose: Constructor for the CLogonDialog class. This stores the HWND
  120. // and creates an event that gets signaled when the attempt
  121. // logon thread completes and posts a message back to the Win32
  122. // dialog.
  123. //
  124. // History: 2000-02-04 vtan created
  125. // --------------------------------------------------------------------------
  126. CLogonDialog::CLogonDialog (HWND hwndDialog, CUIHost *pUIHost, int iDialogType) :
  127. _hwndDialog(hwndDialog),
  128. _fLogonSuccessful(false),
  129. _fFatalError(false),
  130. _fExternalCredentials(false),
  131. _fResumed(false),
  132. _iDialogType(iDialogType),
  133. _iCADCount(0),
  134. _hEvent(NULL),
  135. _pIExternalProcessOld(NULL),
  136. _eventLogonComplete(NULL),
  137. _pUIHost(NULL),
  138. _pszWindowTitle(NULL)
  139. {
  140. pUIHost->AddRef();
  141. _pIExternalProcessOld = pUIHost->GetInterface();
  142. pUIHost->SetInterface(this);
  143. _pUIHost = pUIHost;
  144. }
  145. // --------------------------------------------------------------------------
  146. // CLogonDialog::~CLogonDialog
  147. //
  148. // Arguments: <none>
  149. //
  150. // Returns: <none>
  151. //
  152. // Purpose: Destructor for the CLogonDialog class.
  153. //
  154. // History: 2000-02-04 vtan created
  155. // --------------------------------------------------------------------------
  156. CLogonDialog::~CLogonDialog (void)
  157. {
  158. ReleaseHandle(_hEvent);
  159. ReleaseMemory(_pszWindowTitle);
  160. ASSERTMSG(_hwndDialog == NULL, "CLogonDialog destroyed with WM_DESTROY being invoked in CLogonDialog::~CLogonDialog");
  161. }
  162. // --------------------------------------------------------------------------
  163. // CLogonDialog::StartUIHost
  164. //
  165. // Arguments: <none>
  166. //
  167. // Returns: NTSTATUS
  168. //
  169. // Purpose: Start the external process that hosts the UI. This can be
  170. // anything but is presently logonui.exe. This is actually
  171. // determined in the CUIHost class.
  172. //
  173. // History: 2000-02-04 vtan created
  174. // --------------------------------------------------------------------------
  175. NTSTATUS CLogonDialog::StartUIHost (void)
  176. {
  177. NTSTATUS status;
  178. LOGONIPC_CREDENTIALS logonIPCCredentials;
  179. ASSERTMSG(_pUIHost->IsStarted(), "UI host must be started in CLogonDialog::StartUIHost");
  180. if (_pUIHost->IsHidden())
  181. {
  182. (NTSTATUS)_pUIHost->Show();
  183. }
  184. status = CCredentialClient::Get(&logonIPCCredentials);
  185. if (NT_SUCCESS(status))
  186. {
  187. _Shell_LogonStatus_NotifyNoAnimations();
  188. }
  189. _Shell_LogonStatus_SetStateLogon((_iDialogType != SHELL_LOGONDIALOG_RETURNTOWELCOME_UNLOCK) ? 0 : SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
  190. if (_iDialogType == SHELL_LOGONDIALOG_RETURNTOWELCOME_UNLOCK)
  191. {
  192. _iDialogType = SHELL_LOGONDIALOG_RETURNTOWELCOME;
  193. }
  194. if (NT_SUCCESS(status))
  195. {
  196. _Shell_LogonStatus_InteractiveLogon(logonIPCCredentials.userID.wszUsername,
  197. logonIPCCredentials.userID.wszDomain,
  198. logonIPCCredentials.wszPassword);
  199. }
  200. return(STATUS_SUCCESS);
  201. }
  202. // --------------------------------------------------------------------------
  203. // CLogonDialog::EndUIHost
  204. //
  205. // Arguments: <none>
  206. //
  207. // Returns: <none>
  208. //
  209. // Purpose: End the external UI host. Just release the reference to it.
  210. //
  211. // History: 2000-05-01 vtan created
  212. // --------------------------------------------------------------------------
  213. void CLogonDialog::EndUIHost (void)
  214. {
  215. if (_pUIHost != NULL)
  216. {
  217. if (_pIExternalProcessOld != NULL)
  218. {
  219. _pUIHost->SetInterface(_pIExternalProcessOld);
  220. _pIExternalProcessOld->Release();
  221. _pIExternalProcessOld = NULL;
  222. }
  223. _pUIHost->Release();
  224. _pUIHost = NULL;
  225. }
  226. }
  227. // --------------------------------------------------------------------------
  228. // CLogonDialog::ChangeWindowTitle
  229. //
  230. // Arguments: <none>
  231. //
  232. // Returns: <none>
  233. //
  234. // Purpose: Change the window title of the msgina dialog to something that
  235. // shgina can find.
  236. //
  237. // History: 2000-06-02 vtan created
  238. // --------------------------------------------------------------------------
  239. void CLogonDialog::ChangeWindowTitle (void)
  240. {
  241. if (_pszWindowTitle == NULL)
  242. {
  243. int iLength;
  244. // Because the title of the dialog can be localized change the name to
  245. // something that shgina expects that will NOT be localized. Don't forget
  246. // to restore this if the dialog needs to be re-shown again. If the current
  247. // value cannot be read slam the title anyway. Recovery from error will be
  248. // less than optimal.
  249. iLength = GetWindowTextLength(_hwndDialog) + sizeof('\0');
  250. _pszWindowTitle = static_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, iLength * sizeof(TCHAR)));
  251. if (_pszWindowTitle != NULL)
  252. {
  253. (int)GetWindowText(_hwndDialog, _pszWindowTitle, iLength);
  254. }
  255. TBOOL(SetWindowText(_hwndDialog, TEXT("GINA Logon")));
  256. TBOOL(GetWindowRect(_hwndDialog, &_rcDialog));
  257. TBOOL(SetWindowPos(_hwndDialog, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER));
  258. }
  259. }
  260. // --------------------------------------------------------------------------
  261. // CLogonDialog::IsClassicLogonMode
  262. //
  263. // Arguments: <none>
  264. //
  265. // Returns: bool
  266. //
  267. // Purpose: Returns whether classic logon has been externally requested
  268. // by the user (CTRL-ALT-DELETE x 2).
  269. //
  270. // History: 2001-01-12 vtan created
  271. // --------------------------------------------------------------------------
  272. bool CLogonDialog::IsClassicLogonMode (void) const
  273. {
  274. return(_iCADCount >= 2);
  275. }
  276. // --------------------------------------------------------------------------
  277. // CLogonDialog::RevertClassicLogonMode
  278. //
  279. // Arguments: <none>
  280. //
  281. // Returns: bool
  282. //
  283. // Purpose: Returns whether it handled the conversion back from classic
  284. // logon mode to the UI host.
  285. //
  286. // History: 2001-01-12 vtan created
  287. // --------------------------------------------------------------------------
  288. bool CLogonDialog::RevertClassicLogonMode (void)
  289. {
  290. bool fResult;
  291. fResult = IsClassicLogonMode();
  292. if (fResult)
  293. {
  294. _iCADCount = 0;
  295. _fExternalCredentials = false;
  296. (BOOL)EnableWindow(GetDlgItem(_hwndDialog, IDCANCEL), _fOldCancelButtonEnabled);
  297. TBOOL(PostMessage(_hwndDialog, WM_HIDEOURSELVES, 0, 0));
  298. Handle_LogonShowUI();
  299. }
  300. return(fResult);
  301. }
  302. // --------------------------------------------------------------------------
  303. // CLogonDialog::Handle_WM_INITDIALOG
  304. //
  305. // Arguments: <none>
  306. //
  307. // Returns: <none>
  308. //
  309. // Purpose: This function is invoked if the external UI host is being
  310. // used. In this case the GINA Win32 dialog size is saved and
  311. // then changed to an empty rectangle. The window is then hidden
  312. // using a posted message.
  313. //
  314. // See CLogonDialog::Handle_WM_HIDEOURSELVES for the follow up.
  315. //
  316. // History: 2000-02-04 vtan created
  317. // --------------------------------------------------------------------------
  318. void CLogonDialog::Handle_WM_INITDIALOG (void)
  319. {
  320. if (!_fFatalError && !_fExternalCredentials)
  321. {
  322. TBOOL(PostMessage(_hwndDialog, WM_HIDEOURSELVES, 0, 0));
  323. }
  324. _ShellReleaseLogonMutex(FALSE);
  325. }
  326. // --------------------------------------------------------------------------
  327. // CLogonDialog::Handle_WM_DESTROY
  328. //
  329. // Arguments: <none>
  330. //
  331. // Returns: <none>
  332. //
  333. // Purpose: This function cleans up anything in the dialog before
  334. // destruction.
  335. //
  336. // History: 2000-02-07 vtan created
  337. // --------------------------------------------------------------------------
  338. void CLogonDialog::Handle_WM_DESTROY (void)
  339. {
  340. _hwndDialog = NULL;
  341. }
  342. // --------------------------------------------------------------------------
  343. // CLogonDialog::Handle_WM_HIDEOURSELVES
  344. //
  345. // Arguments: <none>
  346. //
  347. // Returns: <none>
  348. //
  349. // Purpose: This function is invoked after the dialog is asked to hide
  350. // itself. The user will not see anything because the size of
  351. // the dialog client rectangle is an empty rectangle.
  352. //
  353. // History: 2000-02-04 vtan created
  354. // --------------------------------------------------------------------------
  355. void CLogonDialog::Handle_WM_HIDEOURSELVES (void)
  356. {
  357. (BOOL)ShowWindow(_hwndDialog, SW_HIDE);
  358. ChangeWindowTitle();
  359. }
  360. // --------------------------------------------------------------------------
  361. // CLogonDialog::Handle_WM_SHOWOURSELVES
  362. //
  363. // Arguments: <none>
  364. //
  365. // Returns: <none>
  366. //
  367. // Purpose: In case the Win32 dialog needs to be shown again this function
  368. // exists. It restores the size of the dialog and then shows the
  369. // dialog.
  370. //
  371. // History: 2000-02-04 vtan created
  372. // --------------------------------------------------------------------------
  373. void CLogonDialog::Handle_WM_SHOWOURSELVES (void)
  374. {
  375. if (_iDialogType == SHELL_LOGONDIALOG_LOGGEDOFF)
  376. {
  377. if (_pszWindowTitle != NULL)
  378. {
  379. // If handling logged off welcome screen failure show WlxLoggedOutSAS.
  380. TBOOL(SetWindowText(_hwndDialog, _pszWindowTitle));
  381. ReleaseMemory(_pszWindowTitle);
  382. TBOOL(SetWindowPos(_hwndDialog, NULL, 0, 0, _rcDialog.right - _rcDialog.left, _rcDialog.bottom - _rcDialog.top, SWP_NOMOVE | SWP_NOZORDER));
  383. (BOOL)ShowWindow(_hwndDialog, SW_SHOW);
  384. (BOOL)SetForegroundWindow(_hwndDialog);
  385. (BOOL)_Gina_SetPasswordFocus(_hwndDialog);
  386. }
  387. }
  388. else
  389. {
  390. // If handling return to welcome screen failure show WlxWkstaLockedSAS.
  391. TBOOL(EndDialog(_hwndDialog, MSGINA_DLG_LOCK_WORKSTATION));
  392. }
  393. }
  394. // --------------------------------------------------------------------------
  395. // CLogonDialog::Handle_WM_LOGONSERVICEREQUEST
  396. //
  397. // Arguments: iRequestType = Request identifier.
  398. // pvInformation = Pointer to the information in the
  399. // requesting process address space.
  400. // iDataSize = Size of the data.
  401. //
  402. // Returns: bool
  403. //
  404. // Purpose: Handler for logon service requests made thru the logon IPC.
  405. // This specifically serves the UI host.
  406. //
  407. // History: 1999-08-24 vtan created
  408. // 2000-01-31 vtan moved from Neptune to Whistler
  409. // --------------------------------------------------------------------------
  410. bool CLogonDialog::Handle_WM_LOGONSERVICEREQUEST (int iRequestType, void *pvInformation, int iDataSize)
  411. {
  412. bool fResult, fHandled;
  413. LOGONIPC_CREDENTIALS logonIPCCredentials;
  414. // Clear out our memory and extract the information from the requesting
  415. // process. This could be us if the internal logon dialog is used. The
  416. // extractor knows how to handle this.
  417. ZeroMemory(&logonIPCCredentials, sizeof(logonIPCCredentials));
  418. if (NT_SUCCESS(_pUIHost->GetData(pvInformation, &logonIPCCredentials, iDataSize)))
  419. {
  420. switch (iRequestType)
  421. {
  422. case LOGON_QUERY_LOGGED_ON:
  423. {
  424. fResult = Handle_LOGON_QUERY_LOGGED_ON(logonIPCCredentials);
  425. break;
  426. }
  427. case LOGON_LOGON_USER:
  428. {
  429. fResult = Handle_LOGON_LOGON_USER(logonIPCCredentials);
  430. break;
  431. }
  432. case LOGON_LOGOFF_USER:
  433. {
  434. fResult = Handle_LOGON_LOGOFF_USER(logonIPCCredentials);
  435. break;
  436. }
  437. case LOGON_TEST_BLANK_PASSWORD:
  438. {
  439. fResult = Handle_LOGON_TEST_BLANK_PASSWORD(logonIPCCredentials);
  440. break;
  441. }
  442. case LOGON_TEST_INTERACTIVE_LOGON_ALLOWED:
  443. {
  444. fResult = Handle_LOGON_TEST_INTERACTIVE_LOGON_ALLOWED(logonIPCCredentials);
  445. break;
  446. }
  447. case LOGON_TEST_EJECT_ALLOWED:
  448. {
  449. fResult = Handle_LOGON_TEST_EJECT_ALLOWED();
  450. break;
  451. }
  452. case LOGON_TEST_SHUTDOWN_ALLOWED:
  453. {
  454. fResult = Handle_LOGON_TEST_SHUTDOWN_ALLOWED();
  455. break;
  456. }
  457. case LOGON_TURN_OFF_COMPUTER:
  458. {
  459. fResult = Handle_LOGON_TURN_OFF_COMPUTER();
  460. break;
  461. }
  462. case LOGON_EJECT_COMPUTER:
  463. {
  464. fResult = Handle_LOGON_EJECT_COMPUTER();
  465. break;
  466. }
  467. case LOGON_SIGNAL_UIHOST_FAILURE:
  468. {
  469. fResult = Handle_LOGON_SIGNAL_UIHOST_FAILURE();
  470. break;
  471. }
  472. case LOGON_ALLOW_EXTERNAL_CREDENTIALS:
  473. {
  474. fResult = Handle_LOGON_ALLOW_EXTERNAL_CREDENTIALS();
  475. break;
  476. }
  477. case LOGON_REQUEST_EXTERNAL_CREDENTIALS:
  478. {
  479. fResult = Handle_LOGON_REQUEST_EXTERNAL_CREDENTIALS();
  480. break;
  481. }
  482. default:
  483. {
  484. DISPLAYMSG("Invalid request sent to CLogonDialog::Handle_WM_LOGONSERVICEREQUEST");
  485. break;
  486. }
  487. }
  488. // Put the result back in the UI host process' information block.
  489. fHandled = NT_SUCCESS(_pUIHost->PutData(pvInformation, &fResult, sizeof(fResult)));
  490. }
  491. else
  492. {
  493. fHandled = false;
  494. }
  495. return(fHandled);
  496. }
  497. // --------------------------------------------------------------------------
  498. // CLogonDialog::Handle_WLX_WM_SAS
  499. //
  500. // Arguments: wParam = SAS type that occurred.
  501. //
  502. // Returns: <none>
  503. //
  504. // Purpose: Invoked when a SAS is delivered to the logon dialog. This can
  505. // be done by a remote shutdown invokation. In this case the UI
  506. // host should not be restarted. Make a note of this.
  507. //
  508. // History: 2000-04-24 vtan created
  509. // --------------------------------------------------------------------------
  510. void CLogonDialog::Handle_WLX_WM_SAS (WPARAM wParam)
  511. {
  512. if ((wParam == WLX_SAS_TYPE_CTRL_ALT_DEL) && (_iDialogType == SHELL_LOGONDIALOG_LOGGEDOFF))
  513. {
  514. // CONTROL-ALT-DELETE. If not in classic mode bump up the CAD count.
  515. // If it reaches classic mode then switch. If in classic mode blow it off.
  516. if (!IsClassicLogonMode())
  517. {
  518. ++_iCADCount;
  519. if (IsClassicLogonMode())
  520. {
  521. _fExternalCredentials = true;
  522. _fOldCancelButtonEnabled = (EnableWindow(GetDlgItem(_hwndDialog, IDCANCEL), TRUE) == 0);
  523. TBOOL(PostMessage(_hwndDialog, WM_SHOWOURSELVES, 0, 0));
  524. Handle_LogonHideUI();
  525. }
  526. }
  527. }
  528. else
  529. {
  530. // Reset the CAD count if some other SAS gets in the way.
  531. _iCADCount = 0;
  532. if (wParam == WLX_SAS_TYPE_USER_LOGOFF)
  533. {
  534. _fFatalError = true;
  535. }
  536. else if (wParam == WLX_SAS_TYPE_SCRNSVR_TIMEOUT)
  537. {
  538. _pUIHost->Hide();
  539. }
  540. }
  541. }
  542. // --------------------------------------------------------------------------
  543. // CLogonDialog::Handle_WM_POWERBROADCAST
  544. //
  545. // Arguments: wParam = Powerbroadcast message.
  546. //
  547. // Returns: bool
  548. //
  549. // Purpose: Responds to APM messages. When suspend is issued it places
  550. // the UI host to status mode. When resume is received it places
  551. // the UI host in logon mode.
  552. //
  553. // The UI host should have waited and blown off requests to
  554. // display the logon list and should be waiting for this call to
  555. // release it because we pass it the same magic number to lock
  556. // it.
  557. //
  558. // History: 2000-06-30 vtan created
  559. // --------------------------------------------------------------------------
  560. bool CLogonDialog::Handle_WM_POWERBROADCAST (WPARAM wParam)
  561. {
  562. bool fResult;
  563. fResult = false;
  564. if (((PBT_APMRESUMEAUTOMATIC == wParam) || (PBT_APMRESUMECRITICAL == wParam) || (PBT_APMRESUMESUSPEND == wParam)) &&
  565. !_fResumed)
  566. {
  567. _fResumed = true;
  568. _Shell_LogonStatus_SetStateLogon(SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
  569. fResult = true;
  570. }
  571. else if (PBT_APMSUSPEND == wParam)
  572. {
  573. _Shell_LogonStatus_SetStateStatus(SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
  574. _fResumed = fResult = false;
  575. }
  576. return(fResult);
  577. }
  578. // --------------------------------------------------------------------------
  579. // CLogonDialog::Handle_LogonDisplayError
  580. //
  581. // Arguments: status = NTSTATUS of logon request.
  582. //
  583. // Returns: bool
  584. //
  585. // Purpose: Under all cases other than a bad password a failure to logon
  586. // should be displayed by a standard Win32 error dialog that
  587. // is already handled by msgina. In the case of a bad password
  588. // let the UI host handle this.
  589. //
  590. // History: 2000-02-04 vtan created
  591. // --------------------------------------------------------------------------
  592. bool CLogonDialog::Handle_LogonDisplayError (NTSTATUS status, NTSTATUS subStatus)
  593. {
  594. return(IsClassicLogonMode() || (status != STATUS_LOGON_FAILURE) || (subStatus == IDS_LOGON_LOG_FULL));
  595. }
  596. // --------------------------------------------------------------------------
  597. // CLogonDialog::Handle_LogonCompleted
  598. //
  599. // Arguments: iDialogResult = Dialog result code.
  600. //
  601. // Returns: <none>
  602. //
  603. // Purpose: This function is called when the attempt logon thread has
  604. // completed and posted a message regarding its result. The
  605. // internal event is signaled to release the actual UI host
  606. // logon request in CLogonDialog::Handle_WM_LOGONSERVICEREQUEST
  607. // and the actual success of the logon request is stored.
  608. //
  609. // History: 2000-02-04 vtan created
  610. // --------------------------------------------------------------------------
  611. void CLogonDialog::Handle_LogonCompleted (INT_PTR iDialogResult, const WCHAR *pszUsername, const WCHAR *pszDomain)
  612. {
  613. if (MSGINA_DLG_SWITCH_CONSOLE == iDialogResult)
  614. {
  615. Handle_WM_SHOWOURSELVES();
  616. _Shell_LogonDialog_Destroy();
  617. _Shell_LogonStatus_Destroy(HOST_END_TERMINATE);
  618. }
  619. else
  620. {
  621. TSTATUS(_eventLogonComplete.Set());
  622. _fLogonSuccessful = (MSGINA_DLG_SUCCESS == iDialogResult);
  623. // Always show the UI host unless double CONTROL-ALT-DELETE
  624. // was enabled and the logon was unsuccessful.
  625. if (!IsClassicLogonMode() || _fLogonSuccessful)
  626. {
  627. Handle_WM_HIDEOURSELVES();
  628. Handle_LogonShowUI();
  629. }
  630. // If successful and external credentials then instruct the UI host
  631. // to animate to the actual person in the external credentials.
  632. // Switch the UI host to logged on mode.
  633. if (_fLogonSuccessful && _fExternalCredentials)
  634. {
  635. _Shell_LogonStatus_SelectUser(pszUsername, pszDomain);
  636. _Shell_LogonStatus_SetStateLoggedOn();
  637. }
  638. }
  639. }
  640. // --------------------------------------------------------------------------
  641. // CLogonDialog::Handle_ShuttingDown
  642. //
  643. // Arguments: <none>
  644. //
  645. // Returns: <none>
  646. //
  647. // Purpose: This function handles the UI host in classic mode but was
  648. // given a request to shut down or restart.
  649. //
  650. // History: 2000-02-04 vtan created
  651. // --------------------------------------------------------------------------
  652. void CLogonDialog::Handle_ShuttingDown (void)
  653. {
  654. if (IsClassicLogonMode())
  655. {
  656. TBOOL(PostMessage(_hwndDialog, WM_HIDEOURSELVES, 0, 0));
  657. Handle_LogonShowUI();
  658. _Shell_LogonStatus_NotifyWait();
  659. _Shell_LogonStatus_SetStateStatus(SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
  660. }
  661. }
  662. // --------------------------------------------------------------------------
  663. // CLogonDialog::Handle_LogonShowUI
  664. //
  665. // Arguments: <none>
  666. //
  667. // Returns: <none>
  668. //
  669. // Purpose: This function is called after something that went wrong with
  670. // the logon process has been serviced. It is called it the UI
  671. // needs to be shown again to give the user the opportunity to
  672. // re-enter information.
  673. //
  674. // History: 2000-03-08 vtan created
  675. // --------------------------------------------------------------------------
  676. void CLogonDialog::Handle_LogonShowUI (void)
  677. {
  678. TSTATUS(_pUIHost->Show());
  679. }
  680. // --------------------------------------------------------------------------
  681. // CLogonDialog::Handle_LogonHideUI
  682. //
  683. // Arguments: <none>
  684. //
  685. // Returns: <none>
  686. //
  687. // Purpose: This function is called when something goes wrong with a logon
  688. // event that can be serviced immediately to ensure the logon
  689. // process completes smoothly. Typically this is the user is
  690. // required to change their password at first logon. This
  691. // function asks the UI host to hide all its windows.
  692. //
  693. // History: 2000-03-08 vtan created
  694. // --------------------------------------------------------------------------
  695. void CLogonDialog::Handle_LogonHideUI (void)
  696. {
  697. TSTATUS(_pUIHost->Hide());
  698. }
  699. // --------------------------------------------------------------------------
  700. // CLogonDialog::SetTextFields
  701. //
  702. // Arguments: hwndDialog = HWND to the Win32 GINA dialog.
  703. // pwszUsername = User name.
  704. // pwszDomain = User domain.
  705. // pwszPassword = User password.
  706. //
  707. // Returns: <none>
  708. //
  709. // Purpose: This function has great knowledge of the Win32 GINA
  710. // dialog and stores the parameters directly in the dialog to
  711. // simulate the actual typing of the information.
  712. //
  713. // For the domain combobox first check that a domain has been
  714. // supplied. If not find the computer name and use that as the
  715. // domain. Send CB_SELECTSTRING to the combobox to select it.
  716. //
  717. // History: 2000-02-04 vtan created
  718. // 2000-06-27 vtan added domain combobox support
  719. // --------------------------------------------------------------------------
  720. void CLogonDialog::SetTextFields (HWND hwndDialog, const WCHAR *pwszUsername, const WCHAR *pwszDomain, const WCHAR *pwszPassword)
  721. {
  722. _Gina_SetTextFields(hwndDialog, pwszUsername, pwszDomain, pwszPassword);
  723. }
  724. // --------------------------------------------------------------------------
  725. // CLogonDialog::AllowTermination
  726. //
  727. // Arguments: dwExitCode = Exit code of the process that died.
  728. //
  729. // Returns: bool
  730. //
  731. // Purpose: This function is invoked by the UI host when the process
  732. // terminates and the UI host is asking whether the termination
  733. // is acceptable.
  734. //
  735. // History: 1999-09-14 vtan created
  736. // 2000-01-31 vtan moved from Neptune to Whistler
  737. // 2000-03-09 vtan added magical exit code
  738. // --------------------------------------------------------------------------
  739. bool CLogonDialog::AllowTermination (DWORD dwExitCode)
  740. {
  741. UNREFERENCED_PARAMETER(dwExitCode);
  742. return(false);
  743. }
  744. // --------------------------------------------------------------------------
  745. // CLogonDialog::SignalAbnormalTermination
  746. //
  747. // Arguments: <none>
  748. //
  749. // Returns: NTSTATUS
  750. //
  751. // Purpose: This function is invoked by the UI host if the process
  752. // terminates and cannot be restarted. This indicates a serious
  753. // condition from which this function can attempt to recover.
  754. //
  755. // History: 1999-09-14 vtan created
  756. // 2000-01-31 vtan moved from Neptune to Whistler
  757. // --------------------------------------------------------------------------
  758. NTSTATUS CLogonDialog::SignalAbnormalTermination (void)
  759. {
  760. IExternalProcess *pIExternalProcess;
  761. ASSERTMSG(_pIExternalProcessOld != NULL, "Expecting non NULL _pIExternalProcessOld in CLogonDialog::SignalAbnormalTermination");
  762. pIExternalProcess = _pIExternalProcessOld;
  763. pIExternalProcess->AddRef();
  764. TSTATUS(_logonWait.Cancel());
  765. Handle_WM_SHOWOURSELVES();
  766. _Shell_LogonDialog_Destroy();
  767. TSTATUS(pIExternalProcess->SignalAbnormalTermination());
  768. pIExternalProcess->Release();
  769. return(STATUS_SUCCESS);
  770. }
  771. // --------------------------------------------------------------------------
  772. // CLogonDialog::SignalRestart
  773. //
  774. // Arguments: <none>
  775. //
  776. // Returns: NTSTATUS
  777. //
  778. // Purpose: Function to reset the ready event and set the UI host into
  779. // logon state. This is invoked when the UI host is restarted
  780. // after a failure.
  781. //
  782. // History: 2001-01-09 vtan created
  783. // --------------------------------------------------------------------------
  784. NTSTATUS CLogonDialog::SignalRestart (void)
  785. {
  786. NTSTATUS status;
  787. HANDLE hEvent;
  788. hEvent = _Shell_LogonStatus_ResetReadyEvent();
  789. if (hEvent != NULL)
  790. {
  791. if (DuplicateHandle(GetCurrentProcess(),
  792. hEvent,
  793. GetCurrentProcess(),
  794. &_hEvent,
  795. 0,
  796. FALSE,
  797. DUPLICATE_SAME_ACCESS) != FALSE)
  798. {
  799. status = STATUS_SUCCESS;
  800. }
  801. else
  802. {
  803. status = CStatusCode::StatusCodeOfLastError();
  804. }
  805. }
  806. else
  807. {
  808. status = STATUS_UNSUCCESSFUL;
  809. }
  810. if (NT_SUCCESS(status))
  811. {
  812. status = _logonWait.Register(_hEvent, this);
  813. }
  814. return(status);
  815. }
  816. // --------------------------------------------------------------------------
  817. // CLogonDialog::LogonRestart
  818. //
  819. // Arguments: <none>
  820. //
  821. // Returns: NTSTATUS
  822. //
  823. // Purpose:
  824. //
  825. // History: 2001-02-21 vtan created
  826. // --------------------------------------------------------------------------
  827. NTSTATUS CLogonDialog::LogonRestart (void)
  828. {
  829. _Shell_LogonStatus_SetStateLogon(0);
  830. return(STATUS_SUCCESS);
  831. }
  832. // --------------------------------------------------------------------------
  833. // CLogonDialog::Handle_LOGON_QUERY_LOGGED_ON
  834. //
  835. // Arguments: <none>
  836. //
  837. // Returns: bool
  838. //
  839. // Purpose: Handles LOGON_QUERY_LOGGED_ON.
  840. //
  841. // History: 2001-01-10 vtan created
  842. // --------------------------------------------------------------------------
  843. bool CLogonDialog::Handle_LOGON_QUERY_LOGGED_ON (LOGONIPC_CREDENTIALS& logonIPCCredentials)
  844. {
  845. // LOGON_QUERY_LOGGED_ON: Query if the user is contained in the
  846. // logged on user list. Use terminal services API to do this.
  847. return(CUserList::IsUserLoggedOn(logonIPCCredentials.userID.wszUsername, logonIPCCredentials.wszPassword));
  848. }
  849. // --------------------------------------------------------------------------
  850. // CLogonDialog::Handle_LOGON_LOGON_USER
  851. //
  852. // Arguments: <none>
  853. //
  854. // Returns: bool
  855. //
  856. // Purpose: Handles LOGON_LOGON_USER.
  857. //
  858. // History: 2001-01-10 vtan created
  859. // --------------------------------------------------------------------------
  860. bool CLogonDialog::Handle_LOGON_LOGON_USER (LOGONIPC_CREDENTIALS& logonIPCCredentials)
  861. {
  862. UNICODE_STRING passwordString;
  863. // Take the run encoded password supplied and run decode using
  864. // the provided seed. Set the password and then erase the clear
  865. // text in memory when done. Both the logged on (switch) and
  866. // NOT logged on case require the password.
  867. passwordString.Buffer = logonIPCCredentials.wszPassword;
  868. passwordString.Length = sizeof(logonIPCCredentials.wszPassword) - sizeof(L'\0');
  869. passwordString.MaximumLength = sizeof(logonIPCCredentials.wszPassword);
  870. RtlRunDecodeUnicodeString(logonIPCCredentials.ucPasswordSeed, &passwordString);
  871. logonIPCCredentials.wszPassword[logonIPCCredentials.iPasswordLength] = L'\0';
  872. // When the dialog type is SHELL_LOGONDIALOG_LOGGEDOFF use the
  873. // regular WlxLoggedOutSAS method. Filling in the underlying
  874. // dialog and let msgina do the actual logon work.
  875. if (_iDialogType == SHELL_LOGONDIALOG_LOGGEDOFF)
  876. {
  877. // LOGON_LOGON_USER: Use an event that will get signaled
  878. // when logon is completed. Logon occurs on a different thread
  879. // but this thread MUST be blocked to stop the UI host from
  880. // sending multiple logon requests. Wait for the event to get
  881. // signaled but do not block the message pump.
  882. // Set the username and password (no domain) and then
  883. // erase the password in memory.
  884. SetTextFields(_hwndDialog, logonIPCCredentials.userID.wszUsername, logonIPCCredentials.userID.wszDomain, logonIPCCredentials.wszPassword);
  885. RtlEraseUnicodeString(&passwordString);
  886. }
  887. else
  888. {
  889. // Otherwise we expect the case to be
  890. // SHELL_LOGONDIALOG_RETURNTOWELCOME. In this case authenticate
  891. // by sending the struct address to the hosting window (a stripped
  892. // down WlxLoggedOutSAS window for return to welcome) and then
  893. // fall thru to the IDOK path just like the full dialog.
  894. // This is accomplished with by sending a message to the return
  895. // to welcome stub dialog WM_COMMAND/IDCANCEL.
  896. (LRESULT)SendMessage(_hwndDialog, WM_COMMAND, IDCANCEL, reinterpret_cast<LPARAM>(&logonIPCCredentials));
  897. }
  898. // 1) Reset the signal event.
  899. // 2) Simulate the "enter" key pressed (credentials filled in above).
  900. // 3) Wait for the signal event (keep the message pump going).
  901. // 4) Extract the result.
  902. TSTATUS(_eventLogonComplete.Reset());
  903. _ShellAcquireLogonMutex();
  904. (LRESULT)SendMessage(_hwndDialog, WM_COMMAND, IDOK, NULL);
  905. TSTATUS(_eventLogonComplete.WaitWithMessages(INFINITE, NULL));
  906. if (_iDialogType == SHELL_LOGONDIALOG_RETURNTOWELCOME)
  907. {
  908. RtlEraseUnicodeString(&passwordString);
  909. }
  910. // On success tell the UI host to go to logon state.
  911. if (_fLogonSuccessful)
  912. {
  913. _Shell_LogonStatus_SetStateLoggedOn();
  914. }
  915. else
  916. {
  917. _ShellReleaseLogonMutex(FALSE);
  918. }
  919. return(_fLogonSuccessful);
  920. }
  921. // --------------------------------------------------------------------------
  922. // CLogonDialog::Handle_LOGON_LOGOFF_USER
  923. //
  924. // Arguments: <none>
  925. //
  926. // Returns: bool
  927. //
  928. // Purpose: Handles LOGON_LOGOFF_USER.
  929. //
  930. // History: 2001-01-10 vtan created
  931. // --------------------------------------------------------------------------
  932. bool CLogonDialog::Handle_LOGON_LOGOFF_USER (LOGONIPC_CREDENTIALS& logonIPCCredentials)
  933. {
  934. UNREFERENCED_PARAMETER(logonIPCCredentials);
  935. // LOGON_LOGOFF_USER: Log the logged on user off. They must be logged on
  936. // or this will do nothing.
  937. return(false); //UNIMPLEMENTED
  938. }
  939. // --------------------------------------------------------------------------
  940. // CLogonDialog::Handle_LOGON_TEST_BLANK_PASSWORD
  941. //
  942. // Arguments: <none>
  943. //
  944. // Returns: bool
  945. //
  946. // Purpose: Handles LOGON_TEST_BLANK_PASSWORD.
  947. //
  948. // History: 2001-01-10 vtan created
  949. // --------------------------------------------------------------------------
  950. bool CLogonDialog::Handle_LOGON_TEST_BLANK_PASSWORD (LOGONIPC_CREDENTIALS& logonIPCCredentials)
  951. {
  952. bool fResult;
  953. HANDLE hToken;
  954. // LOGON_TEST_BLANK_PASSWORD: Attempt to the given user on the system
  955. // with a blank password. If successful discard the token. Only return
  956. // the result.
  957. fResult = (CTokenInformation::LogonUser(logonIPCCredentials.userID.wszUsername,
  958. logonIPCCredentials.userID.wszDomain,
  959. L"",
  960. &hToken) == ERROR_SUCCESS);
  961. if (fResult && (hToken != NULL))
  962. {
  963. ReleaseHandle(hToken);
  964. }
  965. return(fResult);
  966. }
  967. // --------------------------------------------------------------------------
  968. // CLogonDialog::Handle_LOGON_TEST_INTERACTIVE_LOGON_ALLOWED
  969. //
  970. // Arguments: <none>
  971. //
  972. // Returns: bool
  973. //
  974. // Purpose: Handles LOGON_TEST_INTERACTIVE_LOGON_ALLOWED.
  975. //
  976. // History: 2001-01-10 vtan created
  977. // --------------------------------------------------------------------------
  978. bool CLogonDialog::Handle_LOGON_TEST_INTERACTIVE_LOGON_ALLOWED (LOGONIPC_CREDENTIALS& logonIPCCredentials)
  979. {
  980. int iResult;
  981. iResult = CUserList::IsInteractiveLogonAllowed(logonIPCCredentials.userID.wszUsername);
  982. return((iResult != -1) && (iResult != 0));
  983. }
  984. // --------------------------------------------------------------------------
  985. // CLogonDialog::Handle_LOGON_TEST_EJECT_ALLOWED
  986. //
  987. // Arguments: <none>
  988. //
  989. // Returns: bool
  990. //
  991. // Purpose: Handles LOGON_TEST_EJECT_ALLOWED.
  992. //
  993. // History: 2001-01-10 vtan created
  994. // --------------------------------------------------------------------------
  995. bool CLogonDialog::Handle_LOGON_TEST_EJECT_ALLOWED (void)
  996. {
  997. bool fResult;
  998. HANDLE hToken;
  999. // Check the system setting and policy for undock without logon allowed.
  1000. fResult = CSystemSettings::IsUndockWithoutLogonAllowed();
  1001. if (fResult && (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) != FALSE))
  1002. {
  1003. DWORD dwTokenPrivilegesSize;
  1004. TOKEN_PRIVILEGES *pTokenPrivileges;
  1005. // Then test the token privilege for SE_UNDOCK_NAME privilege.
  1006. dwTokenPrivilegesSize = 0;
  1007. (BOOL)GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwTokenPrivilegesSize);
  1008. pTokenPrivileges = static_cast<TOKEN_PRIVILEGES*>(LocalAlloc(LMEM_FIXED, dwTokenPrivilegesSize));
  1009. if (pTokenPrivileges != NULL)
  1010. {
  1011. DWORD dwReturnLength;
  1012. if (GetTokenInformation(hToken, TokenPrivileges, pTokenPrivileges, dwTokenPrivilegesSize, &dwReturnLength) != FALSE)
  1013. {
  1014. DWORD dwIndex;
  1015. LUID luidPrivilege;
  1016. luidPrivilege.LowPart = SE_UNDOCK_PRIVILEGE;
  1017. luidPrivilege.HighPart = 0;
  1018. for (dwIndex = 0; !fResult && (dwIndex < pTokenPrivileges->PrivilegeCount); ++dwIndex)
  1019. {
  1020. fResult = (RtlEqualLuid(&luidPrivilege, &pTokenPrivileges->Privileges[dwIndex].Luid) != FALSE);
  1021. }
  1022. // Now check to see if a physical docking stations is present.
  1023. // Also check to see if the session is a remote session.
  1024. if (fResult)
  1025. {
  1026. BOOL fIsDockStationPresent;
  1027. fIsDockStationPresent = FALSE;
  1028. (CONFIGRET)CM_Is_Dock_Station_Present(&fIsDockStationPresent);
  1029. fResult = ((fIsDockStationPresent != FALSE) && (GetSystemMetrics(SM_REMOTESESSION) == 0));
  1030. }
  1031. }
  1032. (HLOCAL)LocalFree(pTokenPrivileges);
  1033. }
  1034. TBOOL(CloseHandle(hToken));
  1035. }
  1036. return(fResult);
  1037. }
  1038. // --------------------------------------------------------------------------
  1039. // CLogonDialog::Handle_LOGON_TEST_SHUTDOWN_ALLOWED
  1040. //
  1041. // Arguments: <none>
  1042. //
  1043. // Returns: bool
  1044. //
  1045. // Purpose: Handles LOGON_TEST_SHUTDOWN_ALLOWED.
  1046. //
  1047. // History: 2001-02-22 vtan created
  1048. // --------------------------------------------------------------------------
  1049. bool CLogonDialog::Handle_LOGON_TEST_SHUTDOWN_ALLOWED (void)
  1050. {
  1051. return((GetSystemMetrics(SM_REMOTESESSION) == FALSE) &&
  1052. CSystemSettings::IsShutdownWithoutLogonAllowed());
  1053. }
  1054. // --------------------------------------------------------------------------
  1055. // CLogonDialog::Handle_LOGON_TURN_OFF_COMPUTER
  1056. //
  1057. // Arguments: <none>
  1058. //
  1059. // Returns: bool
  1060. //
  1061. // Purpose: Handles LOGON_TURN_OFF_COMPUTER.
  1062. //
  1063. // History: 2001-01-10 vtan created
  1064. // --------------------------------------------------------------------------
  1065. bool CLogonDialog::Handle_LOGON_TURN_OFF_COMPUTER (void)
  1066. {
  1067. bool fResult;
  1068. INT_PTR ipResult;
  1069. // LOGON_TURN_OFF_COMPUTER: Present the "Turn Off Computer" dialog
  1070. // and return an MSGINA_DLG_xxx code in response.
  1071. ipResult = CTurnOffDialog::ShellCodeToGinaCode(ShellTurnOffDialog(NULL));
  1072. if (ipResult != MSGINA_DLG_FAILURE)
  1073. {
  1074. DWORD dwExitWindowsFlags;
  1075. dwExitWindowsFlags = CTurnOffDialog::GinaCodeToExitWindowsFlags(static_cast<DWORD>(ipResult));
  1076. if ((dwExitWindowsFlags != 0) && (DisplayExitWindowsWarnings(EWX_SYSTEM_CALLER | dwExitWindowsFlags) == FALSE))
  1077. {
  1078. ipResult = MSGINA_DLG_FAILURE;
  1079. }
  1080. }
  1081. if (ipResult != MSGINA_DLG_FAILURE)
  1082. {
  1083. TBOOL(EndDialog(_hwndDialog, ipResult));
  1084. _fLogonSuccessful = fResult = true;
  1085. _Shell_LogonStatus_NotifyWait();
  1086. _Shell_LogonStatus_SetStateStatus(SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
  1087. }
  1088. else
  1089. {
  1090. fResult = false;
  1091. }
  1092. return(fResult);
  1093. }
  1094. // --------------------------------------------------------------------------
  1095. // CLogonDialog::Handle_LOGON_EJECT_COMPUTER
  1096. //
  1097. // Arguments: <none>
  1098. //
  1099. // Returns: bool
  1100. //
  1101. // Purpose: Handles LOGON_EJECT_COMPUTER.
  1102. //
  1103. // History: 2001-01-10 vtan created
  1104. // --------------------------------------------------------------------------
  1105. bool CLogonDialog::Handle_LOGON_EJECT_COMPUTER (void)
  1106. {
  1107. return(CM_Request_Eject_PC() == ERROR_SUCCESS);
  1108. }
  1109. // --------------------------------------------------------------------------
  1110. // CLogonDialog::Handle_LOGON_SIGNAL_UIHOST_FAILURE
  1111. //
  1112. // Arguments: <none>
  1113. //
  1114. // Returns: bool
  1115. //
  1116. // Purpose: Handles LOGON_SIGNAL_UIHOST_FAILURE.
  1117. //
  1118. // History: 2001-01-10 vtan created
  1119. // --------------------------------------------------------------------------
  1120. bool CLogonDialog::Handle_LOGON_SIGNAL_UIHOST_FAILURE (void)
  1121. {
  1122. // LOGON_SIGNAL_UIHOST_FAILURE: The UI host is signaling us
  1123. // that it has an error from which it cannot recover.
  1124. _fFatalError = true;
  1125. TBOOL(PostMessage(_hwndDialog, WM_SHOWOURSELVES, 0, 0));
  1126. return(true);
  1127. }
  1128. // --------------------------------------------------------------------------
  1129. // CLogonDialog::Handle_LOGON_ALLOW_EXTERNAL_CREDENTIALS
  1130. //
  1131. // Arguments: <none>
  1132. //
  1133. // Returns: bool
  1134. //
  1135. // Purpose: Handles LOGON_ALLOW_EXTERNAL_CREDENTIALS.
  1136. //
  1137. // History: 2001-01-10 vtan created
  1138. // --------------------------------------------------------------------------
  1139. bool CLogonDialog::Handle_LOGON_ALLOW_EXTERNAL_CREDENTIALS (void)
  1140. {
  1141. // LOGON_ALLOW_EXTERNAL_CREDENTIALS: Return whether external
  1142. // credentials are allowed. Requesting external credentials
  1143. // (below) will cause classic GINA to be shown for the input.
  1144. return(CSystemSettings::IsDomainMember());
  1145. }
  1146. // --------------------------------------------------------------------------
  1147. // CLogonDialog::Handle_LOGON_REQUEST_EXTERNAL_CREDENTIALS
  1148. //
  1149. // Arguments: <none>
  1150. //
  1151. // Returns: bool
  1152. //
  1153. // Purpose: Handles LOGON_REQUEST_EXTERNAL_CREDENTIALS.
  1154. //
  1155. // History: 2001-01-10 vtan created
  1156. // --------------------------------------------------------------------------
  1157. bool CLogonDialog::Handle_LOGON_REQUEST_EXTERNAL_CREDENTIALS (void)
  1158. {
  1159. // LOGON_REQUEST_EXTERNAL_CREDENTIALS: The UI host is
  1160. // requesting credentials from an external source (namely)
  1161. // msgina. Hide the UI host and show the GINA dialog.
  1162. _fExternalCredentials = true;
  1163. TBOOL(PostMessage(_hwndDialog, WM_SHOWOURSELVES, 0, 0));
  1164. Handle_LogonHideUI();
  1165. return(true);
  1166. }
  1167. // --------------------------------------------------------------------------
  1168. // CreateLogonHost
  1169. //
  1170. // Arguments: hwndDialog = HWND to Win32 GINA dialog.
  1171. // iDialogType = Type of dialog.
  1172. //
  1173. // Returns: int
  1174. //
  1175. // Purpose: This function handles the actual creation and allocation of
  1176. // resources for handling the friendly UI dialog. It behaves
  1177. // differently depending on whether the dialog is in
  1178. // WlxLoggedOutSAS mode or return to welcome mode.
  1179. //
  1180. // History: 2001-01-11 vtan created
  1181. // --------------------------------------------------------------------------
  1182. int CreateLogonHost (HWND hwndDialog, int iResult, int iDialogType)
  1183. {
  1184. if (g_pLogonDialogLock != NULL)
  1185. {
  1186. CLogonDialog *pLogonDialog;
  1187. CUIHost *pUIHost;
  1188. g_pLogonDialogLock->Acquire();
  1189. pUIHost = reinterpret_cast<CUIHost*>(_Shell_LogonStatus_GetUIHost());
  1190. if (pUIHost != NULL)
  1191. {
  1192. ASSERTMSG(g_pLogonDialog == NULL, "static CLogonDialog already exists in _Shell_LogonDialog__Init");
  1193. g_pLogonDialog = pLogonDialog = new CLogonDialog(hwndDialog, pUIHost, iDialogType);
  1194. pUIHost->Release();
  1195. }
  1196. else
  1197. {
  1198. pLogonDialog = NULL;
  1199. }
  1200. if (pLogonDialog != NULL)
  1201. {
  1202. NTSTATUS status;
  1203. // Add a reference to prevent the object from being destroyed.
  1204. pLogonDialog->AddRef();
  1205. pLogonDialog->ChangeWindowTitle();
  1206. // CLogonDialog::StartUIHost can enter a wait state. Release the lock to
  1207. // allow g_pLogonDialog to be modified externally by SignalAbnormalTermination
  1208. // should the UI host fail and the callback on the IOCompletion port be executed.
  1209. g_pLogonDialogLock->Release();
  1210. status = pLogonDialog->StartUIHost();
  1211. g_pLogonDialogLock->Acquire();
  1212. // Make sure to re-acquire the lock so that reading from g_pLogonDialog
  1213. // is consistent. If failure happens after this then it'll just wait.
  1214. // Then check to see the result of CLogonDialog::StartUIHost and the
  1215. // global g_pLogonDialog. If both of these are valid then everything
  1216. // is set for the external host. Otherwise bail and show classic UI.
  1217. if (NT_SUCCESS(status) && (g_pLogonDialog != NULL))
  1218. {
  1219. iResult = SHELL_LOGONDIALOG_EXTERNALHOST;
  1220. pLogonDialog->Handle_WM_INITDIALOG();
  1221. }
  1222. else
  1223. {
  1224. pLogonDialog->Handle_WM_SHOWOURSELVES();
  1225. _Shell_LogonDialog_Destroy();
  1226. }
  1227. pLogonDialog->Release();
  1228. }
  1229. g_pLogonDialogLock->Release();
  1230. }
  1231. return(iResult);
  1232. }
  1233. // --------------------------------------------------------------------------
  1234. // ::_Shell_LogonDialog_StaticInitialize
  1235. //
  1236. // Arguments: <none>
  1237. //
  1238. // Returns: NTSTATUS
  1239. //
  1240. // Purpose: Initialize the critical section for g_pLogonDialog.
  1241. //
  1242. // History: 2001-04-27 vtan created
  1243. // --------------------------------------------------------------------------
  1244. EXTERN_C NTSTATUS _Shell_LogonDialog_StaticInitialize (void)
  1245. {
  1246. NTSTATUS status;
  1247. ASSERTMSG(g_pLogonDialogLock == NULL, "g_pLogonDialogLock already exists in _Shell_LogonDialog_StaticInitialize");
  1248. g_pLogonDialogLock = new CCriticalSection;
  1249. if (g_pLogonDialogLock != NULL)
  1250. {
  1251. status = g_pLogonDialogLock->Status();
  1252. if (!NT_SUCCESS(status))
  1253. {
  1254. delete g_pLogonDialogLock;
  1255. g_pLogonDialogLock = NULL;
  1256. }
  1257. }
  1258. else
  1259. {
  1260. status = STATUS_NO_MEMORY;
  1261. }
  1262. return(status);
  1263. }
  1264. // --------------------------------------------------------------------------
  1265. // ::_Shell_LogonDialog_StaticTerminate
  1266. //
  1267. // Arguments: <none>
  1268. //
  1269. // Returns: NTSTATUS
  1270. //
  1271. // Purpose: Delete the critical section for g_pLogonDialog.
  1272. //
  1273. // History: 2001-04-27 vtan created
  1274. // --------------------------------------------------------------------------
  1275. EXTERN_C NTSTATUS _Shell_LogonDialog_StaticTerminate (void)
  1276. {
  1277. if (g_pLogonDialogLock != NULL)
  1278. {
  1279. delete g_pLogonDialogLock;
  1280. g_pLogonDialogLock = NULL;
  1281. }
  1282. return(STATUS_SUCCESS);
  1283. }
  1284. // --------------------------------------------------------------------------
  1285. // ::_Shell_LogonDialog_Init
  1286. //
  1287. // Arguments: hwndDialog = HWND to Win32 GINA dialog.
  1288. // iDialogType = Type of dialog.
  1289. //
  1290. // Returns: int
  1291. //
  1292. // Purpose: This function is invoked from the WM_INITDIALOG handler of
  1293. // the Win32 dialog. It determines whether the consumer windows
  1294. // UI host should handle the logon by checking a few settings.
  1295. //
  1296. // If this is consumer windows then it checks for a single user
  1297. // with no password (actually attempting to log them on). If this
  1298. // succeeds then this information is set into the Win32 dialog
  1299. // and the direction to go to logon is returned.
  1300. //
  1301. // Otherwise it creates the required object to handle an external
  1302. // UI host and starts it. If that succeeds then the UI host code
  1303. // is returned.
  1304. //
  1305. // This function is only invoked in the workgroup case.
  1306. //
  1307. // History: 2000-02-04 vtan created
  1308. // 2000-03-06 vtan added safe mode handler
  1309. // --------------------------------------------------------------------------
  1310. EXTERN_C int _Shell_LogonDialog_Init (HWND hwndDialog, int iDialogType)
  1311. {
  1312. int iResult;
  1313. iResult = SHELL_LOGONDIALOG_NONE;
  1314. if (iDialogType == SHELL_LOGONDIALOG_LOGGEDOFF)
  1315. {
  1316. bool fIsRemote, fIsSessionZero;
  1317. fIsRemote = (GetSystemMetrics(SM_REMOTESESSION) != 0);
  1318. fIsSessionZero = (NtCurrentPeb()->SessionId == 0);
  1319. if ((!fIsRemote || fIsSessionZero || CSystemSettings::IsForceFriendlyUI()) && CSystemSettings::IsFriendlyUIActive())
  1320. {
  1321. // There was no wait for the UI host to signal it was ready.
  1322. // Before switching to logon mode wait for the host.
  1323. if (_Shell_LogonStatus_WaitForUIHost() != FALSE)
  1324. {
  1325. // If the wait succeeds then go and send the UI host to logon mode.
  1326. if (g_fFirstLogon && fIsSessionZero)
  1327. {
  1328. WCHAR *pszUsername;
  1329. pszUsername = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, (UNLEN + sizeof('\0')) * sizeof(WCHAR)));
  1330. if (pszUsername != NULL)
  1331. {
  1332. WCHAR *pszDomain;
  1333. pszDomain = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, (DNLEN + sizeof('\0')) * sizeof(WCHAR)));
  1334. if (pszDomain != NULL)
  1335. {
  1336. // Check for single user with no password. Handle this
  1337. // case by filling in the buffers passed to us and return
  1338. // _Shell_LOGONDIALOG_LOGON directing a logon attempt.
  1339. if (ShellIsSingleUserNoPassword(pszUsername, pszDomain))
  1340. {
  1341. CLogonDialog::SetTextFields(hwndDialog, pszUsername, pszDomain, L"");
  1342. iResult = SHELL_LOGONDIALOG_LOGON;
  1343. _Shell_LogonStatus_SetStateLoggedOn();
  1344. }
  1345. (HLOCAL)LocalFree(pszDomain);
  1346. }
  1347. (HLOCAL)LocalFree(pszUsername);
  1348. }
  1349. }
  1350. // Otherwise attempt to start the UI host. If this
  1351. // is successful then return the external host
  1352. // code back to the caller which will hide the dialog.
  1353. if (iResult == SHELL_LOGONDIALOG_NONE)
  1354. {
  1355. iResult = CreateLogonHost(hwndDialog, iResult, iDialogType);
  1356. }
  1357. }
  1358. }
  1359. // Once this point is reached don't ever check again.
  1360. g_fFirstLogon = false;
  1361. }
  1362. else if ((iDialogType == SHELL_LOGONDIALOG_RETURNTOWELCOME) || (iDialogType == SHELL_LOGONDIALOG_RETURNTOWELCOME_UNLOCK))
  1363. {
  1364. iResult = CreateLogonHost(hwndDialog, iResult, iDialogType);
  1365. }
  1366. return(iResult);
  1367. }
  1368. // --------------------------------------------------------------------------
  1369. // ::_Shell_LogonDialog_Destroy
  1370. //
  1371. // Arguments: <none>
  1372. //
  1373. // Returns: <none>
  1374. //
  1375. // Purpose: Release memory and/or resources occupied by the UI host
  1376. // handling and reset it.
  1377. //
  1378. // History: 2000-02-04 vtan created
  1379. // --------------------------------------------------------------------------
  1380. EXTERN_C void _Shell_LogonDialog_Destroy (void)
  1381. {
  1382. if (g_pLogonDialogLock != NULL)
  1383. {
  1384. CSingleThreadedExecution lock(*g_pLogonDialogLock);
  1385. if (g_pLogonDialog != NULL)
  1386. {
  1387. g_pLogonDialog->Handle_WM_DESTROY();
  1388. g_pLogonDialog->EndUIHost();
  1389. g_pLogonDialog->Release();
  1390. g_pLogonDialog = NULL;
  1391. }
  1392. }
  1393. }
  1394. // --------------------------------------------------------------------------
  1395. // ::_Shell_LogonDialog_UIHostActive
  1396. //
  1397. // Arguments: <none>
  1398. //
  1399. // Returns: BOOL
  1400. //
  1401. // Purpose: Returns whether the UI host has been activated. This will
  1402. // prevent an incorrect password from stealing focus from the
  1403. // UI host. The Win32 GINA dialog will try to set focus in that
  1404. // case but this is not desired.
  1405. //
  1406. // History: 2000-02-04 vtan created
  1407. // --------------------------------------------------------------------------
  1408. EXTERN_C BOOL _Shell_LogonDialog_UIHostActive (void)
  1409. {
  1410. return((g_pLogonDialog != NULL) && !g_pLogonDialog->IsClassicLogonMode());
  1411. }
  1412. // --------------------------------------------------------------------------
  1413. // ::_Shell_LogonDialog_Cancel
  1414. //
  1415. // Arguments: <none>
  1416. //
  1417. // Returns: BOOL
  1418. //
  1419. // Purpose: Returns whether the cancel button was handled by the UI host.
  1420. // This is used when CAD x 2 needs to be cancelled and the UI
  1421. // host restored.
  1422. //
  1423. // History: 2001-02-01 vtan created
  1424. // --------------------------------------------------------------------------
  1425. EXTERN_C BOOL _Shell_LogonDialog_Cancel (void)
  1426. {
  1427. return((g_pLogonDialog != NULL) && g_pLogonDialog->RevertClassicLogonMode());
  1428. }
  1429. // --------------------------------------------------------------------------
  1430. // ::_Shell_LogonDialog_DlgProc
  1431. //
  1432. // Arguments: See the platform SDK under DialogProc.
  1433. //
  1434. // Returns: BOOL
  1435. //
  1436. // Purpose: The Win32 GINA dialog code calls this function for uiMessage
  1437. // parameters it doesn't understand. This gives us the chance to
  1438. // add messages that only we understand and process them.
  1439. //
  1440. // History: 2000-02-04 vtan created
  1441. // --------------------------------------------------------------------------
  1442. EXTERN_C BOOL _Shell_LogonDialog_DlgProc (HWND hwndDialog, UINT uiMessage, WPARAM wParam, LPARAM lParam)
  1443. {
  1444. UNREFERENCED_PARAMETER(hwndDialog);
  1445. BOOL fResult;
  1446. fResult = FALSE;
  1447. if (g_pLogonDialog != NULL)
  1448. {
  1449. switch (uiMessage)
  1450. {
  1451. case WM_HIDEOURSELVES:
  1452. g_pLogonDialog->Handle_WM_HIDEOURSELVES();
  1453. fResult = TRUE;
  1454. break;
  1455. case WM_SHOWOURSELVES:
  1456. g_pLogonDialog->Handle_WM_SHOWOURSELVES();
  1457. fResult = TRUE;
  1458. break;
  1459. case WM_LOGONSERVICEREQUEST:
  1460. fResult = g_pLogonDialog->Handle_WM_LOGONSERVICEREQUEST(HIWORD(wParam), reinterpret_cast<void*>(lParam), LOWORD(wParam));
  1461. break;
  1462. case WLX_WM_SAS:
  1463. g_pLogonDialog->Handle_WLX_WM_SAS(wParam);
  1464. fResult = TRUE;
  1465. break;
  1466. case WM_POWERBROADCAST:
  1467. fResult = g_pLogonDialog->Handle_WM_POWERBROADCAST(wParam);
  1468. break;
  1469. default:
  1470. break;
  1471. }
  1472. }
  1473. return(fResult);
  1474. }
  1475. // --------------------------------------------------------------------------
  1476. // ::_Shell_LogonDialog_LogonDisplayError
  1477. //
  1478. // Arguments: status = NTSTATUS of logon request.
  1479. //
  1480. // Returns: BOOL
  1481. //
  1482. // Purpose: Passes the NTSTATUS onto the CLogonDialog handler if there is
  1483. // one present.
  1484. //
  1485. // History: 2000-02-04 vtan created
  1486. // --------------------------------------------------------------------------
  1487. EXTERN_C BOOL _Shell_LogonDialog_LogonDisplayError (NTSTATUS status, NTSTATUS subStatus)
  1488. {
  1489. BOOL fResult;
  1490. fResult = TRUE;
  1491. if (g_pLogonDialog != NULL)
  1492. {
  1493. fResult = g_pLogonDialog->Handle_LogonDisplayError(status, subStatus);
  1494. }
  1495. else
  1496. {
  1497. _Shell_LogonStatus_Hide();
  1498. }
  1499. return(fResult);
  1500. }
  1501. // --------------------------------------------------------------------------
  1502. // ::_Shell_LogonDialog_LogonCompleted
  1503. //
  1504. // Arguments: iDialogResult = Dialog result code.
  1505. // pszUsername = User name that tried to log on.
  1506. // pszDomain = Domain of user.
  1507. //
  1508. // Returns: BOOL
  1509. //
  1510. // Purpose: Passes the dialog result code onto the CLogonDialog handler
  1511. // if there is one present.
  1512. //
  1513. // History: 2000-02-04 vtan created
  1514. // --------------------------------------------------------------------------
  1515. EXTERN_C void _Shell_LogonDialog_LogonCompleted (INT_PTR iDialogResult, const WCHAR *pszUsername, const WCHAR *pszDomain)
  1516. {
  1517. if (g_pLogonDialog != NULL)
  1518. {
  1519. g_pLogonDialog->Handle_LogonCompleted(iDialogResult, pszUsername, pszDomain);
  1520. }
  1521. else
  1522. {
  1523. _Shell_LogonStatus_Show();
  1524. }
  1525. g_fFirstLogon = false;
  1526. }
  1527. // --------------------------------------------------------------------------
  1528. // ::_Shell_LogonDialog_ShuttingDown
  1529. //
  1530. // Arguments: iDialogResult = Dialog result code.
  1531. // pszUsername = User name that tried to log on.
  1532. // pszDomain = Domain of user.
  1533. //
  1534. // Returns: BOOL
  1535. //
  1536. // Purpose: Passes the dialog result code onto the CLogonDialog handler
  1537. // if there is one present.
  1538. //
  1539. // History: 2000-02-04 vtan created
  1540. // --------------------------------------------------------------------------
  1541. EXTERN_C void _Shell_LogonDialog_ShuttingDown (void)
  1542. {
  1543. if (g_pLogonDialog != NULL)
  1544. {
  1545. g_pLogonDialog->Handle_ShuttingDown();
  1546. }
  1547. }
  1548. // --------------------------------------------------------------------------
  1549. // ::_Shell_LogonDialog_ShowUIHost
  1550. //
  1551. // Arguments: <none>
  1552. //
  1553. // Returns: <none>
  1554. //
  1555. // Purpose: Show the external UI host if present. Otherwise do nothing.
  1556. //
  1557. // History: 2000-06-26 vtan created
  1558. // --------------------------------------------------------------------------
  1559. EXTERN_C void _Shell_LogonDialog_ShowUIHost (void)
  1560. {
  1561. if (g_pLogonDialog != NULL)
  1562. {
  1563. g_pLogonDialog->Handle_LogonShowUI();
  1564. }
  1565. }
  1566. // --------------------------------------------------------------------------
  1567. // ::_Shell_LogonDialog_HideUIHost
  1568. //
  1569. // Arguments: <none>
  1570. //
  1571. // Returns: <none>
  1572. //
  1573. // Purpose: Hide the external UI host if present. Otherwise do nothing.
  1574. //
  1575. // History: 2000-03-08 vtan created
  1576. // --------------------------------------------------------------------------
  1577. EXTERN_C void _Shell_LogonDialog_HideUIHost (void)
  1578. {
  1579. if (g_pLogonDialog != NULL)
  1580. {
  1581. g_pLogonDialog->Handle_LogonHideUI();
  1582. }
  1583. }