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.

941 lines
31 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: Exports.cpp
  3. //
  4. // Copyright (c) 2000, Microsoft Corporation
  5. //
  6. // C header file that contains function prototypes that are to be exported
  7. // from msgina.dll
  8. //
  9. // History: 2000-02-04 vtan created
  10. // 2000-02-28 vtan added ShellIsFriendlyUIActive
  11. // 2000-02-29 vtan added ShellIsSingleUserNoPassword
  12. // 2000-03-02 vtan added ShellIsMultipleUsersEnabled
  13. // 2000-04-27 vtan added ShellTurnOffDialog
  14. // 2000-04-27 vtan added ShellACPIPowerButtonPressed
  15. // 2000-05-03 vtan added ShellStatusHostBegin
  16. // 2000-05-03 vtan added ShellStatusHostEnd
  17. // 2000-05-04 vtan added ShellSwitchWhenInteractiveReady
  18. // 2000-05-18 vtan added ShellDimScreen
  19. // 2000-06-02 vtan added ShellInstallAccountFilterData
  20. // 2000-07-14 vtan added ShellStatusHostShuttingDown
  21. // 2000-07-27 vtan added ShellIsSuspendAllowed
  22. // 2000-07-28 vtan added ShellEnableMultipleUsers
  23. // 2000-07-28 vtan added ShellEnableRemoteConnections
  24. // 2000-08-01 vtan added ShellEnableFriendlyUI
  25. // 2000-08-01 vtan added ShellIsRemoteConnectionsEnabled
  26. // 2000-08-03 vtan added ShellSwitchUser
  27. // 2000-08-09 vtan added ShellNotifyThemeUserChange
  28. // 2000-08-14 vtan added ShellIsUserInteractiveLogonAllowed
  29. // 2000-10-13 vtan added ShellStartThemeServer
  30. // 2000-10-17 vtan added ShellStopThemeServer
  31. // 2000-11-30 vtan removed ShellStartThemeServer
  32. // 2000-11-30 vtan removed ShellStopThemeServer
  33. // 2001-01-11 vtan renamed functions to _Shell
  34. // 2001-01-11 vtan added ShellReturnToWelcome
  35. // 2001-01-31 vtan added ShellStatusHostPowerEvent
  36. // 2001-04-03 vtan added ShellStartCredentialServer
  37. // 2001-04-04 vtan added ShellAcquireLogonMutex
  38. // 2001-04-04 vtan added ShellReleaseLogonMutex
  39. // 2001-04-12 vtan added ShellStatusHostHide
  40. // 2001-04-12 vtan added ShellStatusHostShow
  41. // --------------------------------------------------------------------------
  42. #include "StandardHeader.h"
  43. #include <msginaexports.h>
  44. #include <shlobj.h>
  45. #include <shlobjp.h>
  46. #include <winsta.h>
  47. #include <winwlx.h>
  48. #include <LPCThemes.h>
  49. #include "Compatibility.h"
  50. #include "CredentialTransfer.h"
  51. #include "DimmedWindow.h"
  52. #include "LogonMutex.h"
  53. #include "PowerButton.h"
  54. #include "PrivilegeEnable.h"
  55. #include "ReturnToWelcome.h"
  56. #include "SpecialAccounts.h"
  57. #include "StatusCode.h"
  58. #include "SystemSettings.h"
  59. #include "TokenInformation.h"
  60. #include "TurnOffDialog.h"
  61. #include "UserList.h"
  62. #include "UserSettings.h"
  63. #include "WaitInteractiveReady.h"
  64. // --------------------------------------------------------------------------
  65. // ::ShellGetUserList
  66. //
  67. // Arguments: fRemoveGuest = Always remove the "Guest" account.
  68. // pdwReturnEntryCount = Returned number of entries. This
  69. // may be NULL.
  70. // pvBuffer = Buffer containing user data. This
  71. // may be NULL.
  72. //
  73. // Returns: LONG
  74. //
  75. // Purpose: Gets the count of valid users and the user list on this
  76. // system. This calls a static member function so that the
  77. // context doesn't need to be supplied. This allows shgina (the
  78. // logonocx) to call this function as a stand-alone function.
  79. //
  80. // History: 1999-10-15 vtan created
  81. // 2000-01-31 vtan moved from Neptune to Whistler
  82. // --------------------------------------------------------------------------
  83. EXTERN_C LONG _ShellGetUserList(BOOL fRemoveGuest, DWORD *pdwUserCount, void* *pUserList)
  84. {
  85. return(CUserList::Get((fRemoveGuest != FALSE), pdwUserCount, reinterpret_cast<GINA_USER_INFORMATION**>(pUserList)));
  86. }
  87. // --------------------------------------------------------------------------
  88. // ::ShellIsSingleUserNoPassword
  89. //
  90. // Arguments: pszUsername = Name of single user with no password.
  91. // pszDomain = Domain for the user.
  92. //
  93. // Returns: BOOL
  94. //
  95. // Purpose: Returns whether this system is using friendly UI and has a
  96. // single user with no password. If there is a single user with
  97. // no password the login name is returned otherwise the parameter
  98. // is unused.
  99. //
  100. // History: 2000-02-29 vtan created
  101. // --------------------------------------------------------------------------
  102. EXTERN_C BOOL _ShellIsSingleUserNoPassword (WCHAR *pwszUsername, WCHAR *pwszDomain)
  103. {
  104. BOOL fResult;
  105. fResult = FALSE;
  106. if (CSystemSettings::IsFriendlyUIActive())
  107. {
  108. DWORD dwReturnedEntryCount;
  109. GINA_USER_INFORMATION *pUserList;
  110. if (ERROR_SUCCESS == CUserList::Get(true, &dwReturnedEntryCount, &pUserList))
  111. {
  112. if (dwReturnedEntryCount == 1)
  113. {
  114. HANDLE hToken;
  115. if (CTokenInformation::LogonUser(pUserList->pszName,
  116. pUserList->pszDomain,
  117. L"",
  118. &hToken) == ERROR_SUCCESS)
  119. {
  120. fResult = TRUE;
  121. if (pwszUsername != NULL)
  122. {
  123. (WCHAR*)lstrcpyW(pwszUsername, pUserList->pszName);
  124. }
  125. if (pwszDomain != NULL)
  126. {
  127. (WCHAR*)lstrcpyW(pwszDomain, pUserList->pszDomain);
  128. }
  129. if (hToken != NULL)
  130. {
  131. TBOOL(CloseHandle(hToken));
  132. }
  133. }
  134. }
  135. (HLOCAL)LocalFree(pUserList);
  136. }
  137. }
  138. return(fResult);
  139. }
  140. // --------------------------------------------------------------------------
  141. // ::ShellIsFriendlyUIActive
  142. //
  143. // Arguments: <none>
  144. //
  145. // Returns: BOOL
  146. //
  147. // Purpose: Returns whether the friendly UI is active.
  148. //
  149. // History: 2000-02-28 vtan created
  150. // --------------------------------------------------------------------------
  151. EXTERN_C BOOL _ShellIsFriendlyUIActive (void)
  152. {
  153. return(CSystemSettings::IsFriendlyUIActive());
  154. }
  155. // --------------------------------------------------------------------------
  156. // ::ShellIsMultipleUsersEnabled
  157. //
  158. // Arguments: <none>
  159. //
  160. // Returns: BOOL
  161. //
  162. // Purpose: Returns whether multiple users is enabled. This includes
  163. // checking a registry key as well as whether terminal services
  164. // is enabled on this machine.
  165. //
  166. // History: 2000-03-02 vtan created
  167. // --------------------------------------------------------------------------
  168. EXTERN_C BOOL _ShellIsMultipleUsersEnabled (void)
  169. {
  170. return(CSystemSettings::IsMultipleUsersEnabled());
  171. }
  172. // --------------------------------------------------------------------------
  173. // ::ShellIsRemoteConnectionsEnabled
  174. //
  175. // Arguments: <none>
  176. //
  177. // Returns: BOOL
  178. //
  179. // Purpose: Returns whether remote connections are enabled. This includes
  180. // checking a registry key as well as whether terminal services
  181. // is enabled on this machine.
  182. //
  183. // History: 2000-08-01 vtan created
  184. // --------------------------------------------------------------------------
  185. EXTERN_C BOOL _ShellIsRemoteConnectionsEnabled (void)
  186. {
  187. return(CSystemSettings::IsRemoteConnectionsEnabled());
  188. }
  189. // --------------------------------------------------------------------------
  190. // ::ShellEnableFriendlyUI
  191. //
  192. // Arguments: fEnable = Enable or disable friendly UI.
  193. //
  194. // Returns: BOOL
  195. //
  196. // Purpose: Enables or disables friendly UI via the CSystemSettings
  197. // implementaion.
  198. //
  199. // History: 2000-08-01 vtan created
  200. // --------------------------------------------------------------------------
  201. EXTERN_C BOOL _ShellEnableFriendlyUI (BOOL fEnable)
  202. {
  203. return(CSystemSettings::EnableFriendlyUI(fEnable != FALSE));
  204. }
  205. // --------------------------------------------------------------------------
  206. // ::ShellEnableMultipleUsers
  207. //
  208. // Arguments: fEnable = Enable or disable multiple users.
  209. //
  210. // Returns: BOOL
  211. //
  212. // Purpose: Enables or disables multiple users via the CSystemSettings
  213. // implementaion.
  214. //
  215. // History: 2000-07-28 vtan created
  216. // --------------------------------------------------------------------------
  217. EXTERN_C BOOL _ShellEnableMultipleUsers (BOOL fEnable)
  218. {
  219. return(CSystemSettings::EnableMultipleUsers(fEnable != FALSE));
  220. }
  221. // --------------------------------------------------------------------------
  222. // ::ShellEnableRemoteConnections
  223. //
  224. // Arguments: fEnable = Enable or disable remote connections.
  225. //
  226. // Returns: BOOL
  227. //
  228. // Purpose: Enables or disables remote connections via the CSystemSettings
  229. // implementaion.
  230. //
  231. // History: 2000-07-28 vtan created
  232. // --------------------------------------------------------------------------
  233. EXTERN_C BOOL _ShellEnableRemoteConnections (BOOL fEnable)
  234. {
  235. return(CSystemSettings::EnableRemoteConnections(fEnable != FALSE));
  236. }
  237. // --------------------------------------------------------------------------
  238. // ::ShellTurnOffDialog
  239. //
  240. // Arguments: hwndParent = HWND to parent the dialog to.
  241. //
  242. // Returns: DWORD
  243. //
  244. // Purpose: Displays the "Turn Off Computer" dialog and allows the user to
  245. // make a choice of available shut down options.
  246. //
  247. // History: 2000-03-02 vtan created
  248. // 2000-04-17 vtan moved from shell to msgina
  249. // --------------------------------------------------------------------------
  250. EXTERN_C DWORD _ShellTurnOffDialog (HWND hwndParent)
  251. {
  252. CTurnOffDialog turnOffDialog(hDllInstance);
  253. return(turnOffDialog.Show(hwndParent));
  254. }
  255. // --------------------------------------------------------------------------
  256. // ::ShellACPIPowerButtonPressed
  257. //
  258. // Arguments: pWlxContext = PGLOBALS allocated at WlxInitialize.
  259. // uiEventType = Event code for the power message.
  260. // fLocked = Is workstation locked or not.
  261. //
  262. // Returns: DWORD
  263. //
  264. // Purpose: Displays the "Turn Off Computer" dialog and allows the user to
  265. // make a choice of available shut down options. This is called
  266. // in response to an ACPI power button press. The return codes
  267. // are MSGINA_DLG_xxx return codes to winlogon.
  268. //
  269. // History: 2000-04-17 vtan created
  270. // 2001-06-12 vtan added fLocked flag
  271. // --------------------------------------------------------------------------
  272. EXTERN_C int _ShellACPIPowerButtonPressed (void *pWlxContext, UINT uiEventType, BOOL fLocked)
  273. {
  274. int iResult;
  275. CTokenInformation tokenInformation;
  276. CUserSettings userSettings;
  277. if ((uiEventType & (POWER_USER_NOTIFY_BUTTON | POWER_USER_NOTIFY_SHUTDOWN)) != 0)
  278. {
  279. // This code should not be re-entrant for multiple ACPI power button
  280. // presses while the dialog is up. Blow off any further requests.
  281. // Conditions for the prompt:
  282. // 1) This session is the active console session
  283. // 2) Power button dialog not already displayed
  284. // 3) User is not restricted from closing the taskbar (shut down options)
  285. // 4) User has the privilege to shut down the machine or the friendly UI is NOT active
  286. // 5) User is not the system OR shut down without logon is allowed
  287. if (CSystemSettings::IsActiveConsoleSession() &&
  288. !userSettings.IsRestrictedNoClose() &&
  289. (tokenInformation.UserHasPrivilege(SE_SHUTDOWN_PRIVILEGE) || !CSystemSettings::IsFriendlyUIActive()) &&
  290. (!tokenInformation.IsUserTheSystem() || CSystemSettings::IsShutdownWithoutLogonAllowed()))
  291. {
  292. DWORD dwExitWindowsFlags;
  293. if ((uiEventType & POWER_USER_NOTIFY_SHUTDOWN) != 0)
  294. {
  295. iResult = CTurnOffDialog::ShellCodeToGinaCode(SHTDN_SHUTDOWN);
  296. }
  297. else
  298. {
  299. DWORD dwResult;
  300. CPowerButton *pPowerButton;
  301. // Create a thread to handle the dialog. This is required because
  302. // the dialog must be put on the input desktop which isn't necessarily
  303. // the same as this thread's desktop. Wait for its completion.
  304. pPowerButton = new CPowerButton(pWlxContext, hDllInstance);
  305. if (pPowerButton != NULL)
  306. {
  307. (DWORD)pPowerButton->WaitForCompletion(INFINITE);
  308. // Get the dialog result and check its validity. Only execute
  309. // valid requests.
  310. dwResult = pPowerButton->GetResult();
  311. pPowerButton->Release();
  312. }
  313. else
  314. {
  315. dwResult = MSGINA_DLG_FAILURE;
  316. }
  317. iResult = dwResult;
  318. }
  319. dwExitWindowsFlags = CTurnOffDialog::GinaCodeToExitWindowsFlags(iResult);
  320. // If this is a restart or a shutdown then decide to display a warning.
  321. // If the user is the system then use EWX_SYSTEM_CALLER.
  322. // If the workstation is locked then use EWX_WINLOGON_CALLER.
  323. // Otherwise use nothing but still possibly display a warning.
  324. if ((dwExitWindowsFlags != 0) && (DisplayExitWindowsWarnings((tokenInformation.IsUserTheSystem() ? EWX_SYSTEM_CALLER : fLocked ? EWX_WINLOGON_CALLER : 0) | dwExitWindowsFlags) == FALSE))
  325. {
  326. iResult = MSGINA_DLG_FAILURE;
  327. }
  328. }
  329. else
  330. {
  331. iResult = -1;
  332. }
  333. }
  334. else
  335. {
  336. WARNINGMSG("Unknown event type in _ShellACPIPowerButtonPressed.\r\n");
  337. iResult = MSGINA_DLG_FAILURE;
  338. }
  339. return(iResult);
  340. }
  341. // --------------------------------------------------------------------------
  342. // ::ShellIsSuspendAllowed
  343. //
  344. // Arguments: <none>
  345. //
  346. // Returns: BOOL
  347. //
  348. // Purpose: Returns whether suspend is allowed. This is important to
  349. // prevent the UI host from going into an uncertain state due to
  350. // the asynchronous nature of suspend and the WM_POWERBROADCAST
  351. // messages.
  352. //
  353. // Suspend is allowed if ANY of these conditions are satisfied.
  354. //
  355. // 1) Friendly UI is NOT active
  356. // 2) No UI Host exists
  357. // 3) UI Host exists and is active (not as status host)
  358. //
  359. // History: 2000-07-27 vtan created
  360. // --------------------------------------------------------------------------
  361. EXTERN_C BOOL _ShellIsSuspendAllowed (void)
  362. {
  363. return(!CSystemSettings::IsFriendlyUIActive() || _Shell_LogonStatus_IsSuspendAllowed());
  364. }
  365. // --------------------------------------------------------------------------
  366. // ::ShellStatusHostBegin
  367. //
  368. // Arguments: uiStartType = Mode to start UI host in.
  369. //
  370. // Returns: <none>
  371. //
  372. // Purpose: Starts the status UI host if specified.
  373. //
  374. // History: 2000-05-03 vtan created
  375. // 2000-07-13 vtan add shutdown parameter
  376. // 2000-07-17 vtan changed to start type parameter
  377. // --------------------------------------------------------------------------
  378. EXTERN_C void _ShellStatusHostBegin (UINT uiStartType)
  379. {
  380. _Shell_LogonStatus_Init(uiStartType);
  381. }
  382. // --------------------------------------------------------------------------
  383. // ::ShellStatusHostEnd
  384. //
  385. // Arguments: <none>
  386. //
  387. // Returns: <none>
  388. //
  389. // Purpose: Terminates the status UI host if one was started.
  390. //
  391. // History: 2000-05-03 vtan created
  392. // 2001-01-09 vtan add end type parameter
  393. // --------------------------------------------------------------------------
  394. EXTERN_C void _ShellStatusHostEnd (UINT uiEndType)
  395. {
  396. _Shell_LogonStatus_Destroy(uiEndType);
  397. }
  398. // --------------------------------------------------------------------------
  399. // ::ShellStatusHostShuttingDown
  400. //
  401. // Arguments: <none>
  402. //
  403. // Returns: <none>
  404. //
  405. // Purpose: Tell the status UI host to display a title that the system is
  406. // shutting down.
  407. //
  408. // History: 2000-07-14 vtan created
  409. // --------------------------------------------------------------------------
  410. EXTERN_C void _ShellStatusHostShuttingDown (void)
  411. {
  412. _Shell_LogonStatus_NotifyWait();
  413. _Shell_LogonStatus_SetStateStatus(0);
  414. }
  415. // --------------------------------------------------------------------------
  416. // ::ShellStatusHostPowerEvent
  417. //
  418. // Arguments: <none>
  419. //
  420. // Returns: <none>
  421. //
  422. // Purpose: Tell the status UI host to go into "Please Wait" mode in
  423. // preparation for a power event.
  424. //
  425. // History: 2001-01-31 vtan created
  426. // --------------------------------------------------------------------------
  427. EXTERN_C void _ShellStatusHostPowerEvent (void)
  428. {
  429. _Shell_LogonStatus_NotifyWait();
  430. _Shell_LogonStatus_SetStateStatus(SHELL_LOGONSTATUS_LOCK_MAGIC_NUMBER);
  431. }
  432. // --------------------------------------------------------------------------
  433. // ::ShellSwitchWhenInteractiveReady
  434. //
  435. // Arguments: eSwitchType = Switch type.
  436. // pWlxContext = PGLOBALS allocated at WlxInitialize.
  437. //
  438. // Returns: BOOL
  439. //
  440. // Purpose: Does one of three things.
  441. //
  442. // 1) Create the switch event and registers the wait on it.
  443. // 2) Checks the switch event and switches now or when signaled.
  444. // 3) Cancels any outstanding wait and clean up.
  445. //
  446. // History: 2000-05-04 vtan created
  447. // --------------------------------------------------------------------------
  448. EXTERN_C BOOL _ShellSwitchWhenInteractiveReady (SWITCHTYPE eSwitchType, void *pWlxContext)
  449. {
  450. NTSTATUS status;
  451. switch (eSwitchType)
  452. {
  453. case SWITCHTYPE_CREATE:
  454. if (!CSystemSettings::IsSafeMode() && _Shell_LogonStatus_Exists() && CSystemSettings::IsFriendlyUIActive())
  455. {
  456. status = CWaitInteractiveReady::Create(pWlxContext);
  457. }
  458. else
  459. {
  460. status = STATUS_UNSUCCESSFUL;
  461. }
  462. break;
  463. case SWITCHTYPE_REGISTER:
  464. status = CWaitInteractiveReady::Register(pWlxContext);
  465. break;
  466. case SWITCHTYPE_CANCEL:
  467. status = CWaitInteractiveReady::Cancel();
  468. break;
  469. default:
  470. DISPLAYMSG("Unexpected switch type in _ShellSwitchWhenInteractiveReady");
  471. status = STATUS_UNSUCCESSFUL;
  472. break;
  473. }
  474. return(NT_SUCCESS(status));
  475. }
  476. // --------------------------------------------------------------------------
  477. // ::ShellDimScreen
  478. //
  479. // Arguments: ppIUnknown = IUnknown returned for release.
  480. // phwndDimmed = HWND of the dimmed window for parenting.
  481. //
  482. // Returns: HRESULT
  483. //
  484. // Purpose:
  485. //
  486. // History: 2000-05-18 vtan created
  487. // --------------------------------------------------------------------------
  488. EXTERN_C HRESULT _ShellDimScreen (IUnknown* *ppIUnknown, HWND* phwndDimmed)
  489. {
  490. HRESULT hr;
  491. CDimmedWindow *pDimmedWindow;
  492. if (IsBadWritePtr(ppIUnknown, sizeof(*ppIUnknown)) || IsBadWritePtr(phwndDimmed, sizeof(*phwndDimmed)))
  493. {
  494. hr = E_INVALIDARG;
  495. }
  496. else
  497. {
  498. *ppIUnknown = NULL;
  499. pDimmedWindow = new CDimmedWindow(hDllInstance);
  500. if (pDimmedWindow != NULL)
  501. {
  502. hr = pDimmedWindow->QueryInterface(IID_IUnknown, reinterpret_cast<void**>(ppIUnknown));
  503. if (SUCCEEDED(hr))
  504. {
  505. pDimmedWindow->Release();
  506. *phwndDimmed = pDimmedWindow->Create();
  507. }
  508. }
  509. else
  510. {
  511. hr = E_OUTOFMEMORY;
  512. }
  513. }
  514. return(hr);
  515. }
  516. // --------------------------------------------------------------------------
  517. // ::ShellInstallAccountFilterData
  518. //
  519. // Arguments: <none>
  520. //
  521. // Returns: <none>
  522. //
  523. // Purpose: Called by shgina registration to install special accounts
  524. // that need to be filtered by name.
  525. //
  526. // History: 2000-06-02 vtan created
  527. // --------------------------------------------------------------------------
  528. EXTERN_C void _ShellInstallAccountFilterData (void)
  529. {
  530. CSpecialAccounts::Install();
  531. }
  532. // --------------------------------------------------------------------------
  533. // ::ShellSwitchUser
  534. //
  535. // Arguments: fWait = Wait for console disconnect to complete.
  536. //
  537. // Returns: DWORD
  538. //
  539. // Purpose: Checks for available memory before doing a disconnect. If the
  540. // disconnect succeeds the processes running in the session have
  541. // their working set dropped.
  542. //
  543. // History: 2000-08-03 vtan created
  544. // --------------------------------------------------------------------------
  545. EXTERN_C DWORD _ShellSwitchUser (BOOL fWait)
  546. {
  547. static BOOL s_fIsServer = static_cast<BOOL>(-1);
  548. DWORD dwErrorCode;
  549. dwErrorCode = ERROR_SUCCESS;
  550. if (s_fIsServer == static_cast<BOOL>(-1))
  551. {
  552. OSVERSIONINFOEX osVersionInfoEx;
  553. ZeroMemory(&osVersionInfoEx, sizeof(osVersionInfoEx));
  554. osVersionInfoEx.dwOSVersionInfoSize = sizeof(osVersionInfoEx);
  555. if (GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&osVersionInfoEx)) != FALSE)
  556. {
  557. s_fIsServer = ((VER_NT_SERVER == osVersionInfoEx.wProductType) || (VER_NT_DOMAIN_CONTROLLER == osVersionInfoEx.wProductType));
  558. }
  559. else
  560. {
  561. dwErrorCode = GetLastError();
  562. }
  563. }
  564. if (dwErrorCode == ERROR_SUCCESS)
  565. {
  566. bool fRemote;
  567. fRemote = (GetSystemMetrics(SM_REMOTESESSION) != 0);
  568. if (s_fIsServer)
  569. {
  570. // Normal Server TS case (RemoteAdmin and TerminalServer)
  571. if (fRemote)
  572. {
  573. if (WinStationDisconnect(SERVERNAME_CURRENT, LOGONID_CURRENT, static_cast<BOOLEAN>(fWait)) == FALSE)
  574. {
  575. dwErrorCode = GetLastError();
  576. }
  577. }
  578. else
  579. {
  580. dwErrorCode = ERROR_NOT_SUPPORTED;
  581. }
  582. }
  583. else if (ShellIsMultipleUsersEnabled() && !fRemote)
  584. {
  585. NTSTATUS status;
  586. // Fast user switching case - need to do some extra work
  587. // FUS is always on the console. When the session is remoted
  588. // fall thru to PTS.
  589. status = CCompatibility::TerminateNonCompliantApplications();
  590. if (status == STATUS_PORT_DISCONNECTED)
  591. {
  592. status = CCompatibility::TerminateNonCompliantApplications();
  593. }
  594. dwErrorCode = static_cast<DWORD>(CStatusCode::ErrorCodeOfStatusCode(status));
  595. if (dwErrorCode == ERROR_SUCCESS)
  596. {
  597. if (CCompatibility::HasEnoughMemoryForNewSession())
  598. {
  599. HANDLE hEvent;
  600. TBOOL(_ShellSwitchWhenInteractiveReady(SWITCHTYPE_CANCEL, NULL));
  601. hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, CReturnToWelcome::GetEventName());
  602. if (hEvent != NULL)
  603. {
  604. TBOOL(SetEvent(hEvent));
  605. TBOOL(CloseHandle(hEvent));
  606. }
  607. }
  608. else
  609. {
  610. dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
  611. }
  612. }
  613. }
  614. else
  615. {
  616. // Normal PTS case or FUS remoted, just call the api
  617. if (WinStationDisconnect(SERVERNAME_CURRENT, LOGONID_CURRENT, static_cast<BOOLEAN>(fWait)) == FALSE)
  618. {
  619. dwErrorCode = GetLastError();
  620. }
  621. }
  622. }
  623. return(dwErrorCode);
  624. }
  625. // --------------------------------------------------------------------------
  626. // ::ShellIsUserInteractiveLogonAllowed
  627. //
  628. // Arguments: pwszUsername = User name to check interactive logon.
  629. //
  630. // Returns: int
  631. //
  632. // Purpose: Checks whether the given user has interactive logon right to
  633. // the local system. The presence of SeDenyInteractiveLogonRight
  634. // determines this.
  635. //
  636. // -1 = indeterminate state
  637. // 0 = interactive logon not allowed
  638. // 1 = interactive logon allowed.
  639. //
  640. // History: 2000-08-14 vtan created
  641. // --------------------------------------------------------------------------
  642. EXTERN_C int _ShellIsUserInteractiveLogonAllowed (const WCHAR *pwszUsername)
  643. {
  644. return(CUserList::IsInteractiveLogonAllowed(pwszUsername));
  645. }
  646. // --------------------------------------------------------------------------
  647. // ::ShellNotifyThemeUserChange
  648. //
  649. // Arguments: hToken = Token of user being logged on.
  650. // fUserLoggedOn = Indicates logon or logoff.
  651. //
  652. // Returns: <none>
  653. //
  654. // Purpose: Gives themes a chance to change the active theme based on a
  655. // user logging on or logging off. This may be required because
  656. // the default theme may be different from the user theme.
  657. //
  658. // History: 2000-08-09 vtan created
  659. // --------------------------------------------------------------------------
  660. EXTERN_C void _ShellNotifyThemeUserChange (USERLOGTYPE eUserLogType, HANDLE hToken)
  661. {
  662. static HANDLE s_hToken = NULL;
  663. switch (eUserLogType)
  664. {
  665. case ULT_LOGON:
  666. (BOOL)ThemeUserLogon(hToken);
  667. if (QueueUserWorkItem(CSystemSettings::AdjustFUSCompatibilityServiceState,
  668. NULL,
  669. WT_EXECUTELONGFUNCTION) == FALSE)
  670. {
  671. (DWORD)CSystemSettings::AdjustFUSCompatibilityServiceState(NULL);
  672. }
  673. s_hToken = hToken;
  674. break;
  675. case ULT_LOGOFF:
  676. if (s_hToken != NULL)
  677. {
  678. (DWORD)CSystemSettings::AdjustFUSCompatibilityServiceState(NULL);
  679. s_hToken = NULL;
  680. }
  681. (BOOL)ThemeUserLogoff();
  682. break;
  683. case ULT_TSRECONNECT:
  684. (BOOL)ThemeUserTSReconnect();
  685. break;
  686. case ULT_STARTSHELL:
  687. (BOOL)ThemeUserStartShell();
  688. break;
  689. default:
  690. DISPLAYMSG("Unexpected eUserLogType in ::_ShellNotifyThemeUserChange");
  691. break;
  692. }
  693. }
  694. // --------------------------------------------------------------------------
  695. // ::_ShellReturnToWelcome
  696. //
  697. // Arguments: fUnlock = Unlock status mode required.
  698. //
  699. // Returns: int
  700. //
  701. // Purpose: Handles the dialog that is brought up behind the welcome
  702. // screen. This dialog is similar to WlxLoggedOutSAS but is
  703. // specific to return to welcome.
  704. //
  705. // History: 2001-01-11 vtan created
  706. // --------------------------------------------------------------------------
  707. EXTERN_C DWORD _ShellReturnToWelcome (BOOL fUnlock)
  708. {
  709. CReturnToWelcome returnToWelcome;
  710. return(static_cast<DWORD>(returnToWelcome.Show(fUnlock != FALSE)));
  711. }
  712. // --------------------------------------------------------------------------
  713. // ::_ShellStartCredentialServer
  714. //
  715. // Arguments: pwszUsername = User name.
  716. // pwszDomain = Domain.
  717. // pwszPassword = Password.
  718. // dwTimeout = Timeout.
  719. //
  720. // Returns: DWORD
  721. //
  722. // Purpose: Starts a credential transfer server in the host process. The
  723. // caller must have SE_TCB_PRIVILEGE to execute this function.
  724. //
  725. // History: 2001-04-03 vtan created
  726. // --------------------------------------------------------------------------
  727. EXTERN_C DWORD _ShellStartCredentialServer (const WCHAR *pwszUsername, const WCHAR *pwszDomain, WCHAR *pwszPassword, DWORD dwTimeout)
  728. {
  729. DWORD dwErrorCode;
  730. CTokenInformation tokenInformation;
  731. if (tokenInformation.UserHasPrivilege(SE_TCB_PRIVILEGE))
  732. {
  733. TSTATUS(CCredentials::StaticInitialize(false));
  734. dwErrorCode = CStatusCode::ErrorCodeOfStatusCode(CCredentialServer::Start(pwszUsername, pwszDomain, pwszPassword, dwTimeout));
  735. }
  736. else
  737. {
  738. dwErrorCode = ERROR_PRIVILEGE_NOT_HELD;
  739. }
  740. return(dwErrorCode);
  741. }
  742. // --------------------------------------------------------------------------
  743. // ::_ShellAcquireLogonMutex
  744. //
  745. // Arguments: <none>
  746. //
  747. // Returns: <none>
  748. //
  749. // Purpose: Acquire the logon mutex.
  750. //
  751. // History: 2001-04-04 vtan created
  752. // --------------------------------------------------------------------------
  753. EXTERN_C void _ShellAcquireLogonMutex (void)
  754. {
  755. CLogonMutex::Acquire();
  756. }
  757. // --------------------------------------------------------------------------
  758. // ::_ShellReleaseLogonMutex
  759. //
  760. // Arguments: fSignalEvent = Signal completion event.
  761. //
  762. // Returns: <none>
  763. //
  764. // Purpose: Release the logon mutex. If required to signal the completion
  765. // event then signal it.
  766. //
  767. // History: 2001-04-04 vtan created
  768. // --------------------------------------------------------------------------
  769. EXTERN_C void _ShellReleaseLogonMutex (BOOL fSignalEvent)
  770. {
  771. if (fSignalEvent != FALSE)
  772. {
  773. CLogonMutex::SignalReply();
  774. }
  775. CLogonMutex::Release();
  776. }
  777. // --------------------------------------------------------------------------
  778. // ::_ShellSignalShutdown
  779. //
  780. // Arguments: <none>
  781. //
  782. // Returns: <none>
  783. //
  784. // Purpose: Signal the shut down event to prevent further interactive
  785. // logon requeusts.
  786. //
  787. // History: 2001-04-06 vtan created
  788. // --------------------------------------------------------------------------
  789. EXTERN_C void _ShellSignalShutdown (void)
  790. {
  791. CLogonMutex::SignalShutdown();
  792. }
  793. // --------------------------------------------------------------------------
  794. // ::_ShellStatusHostHide
  795. //
  796. // Arguments: <none>
  797. //
  798. // Returns: <none>
  799. //
  800. // Purpose:
  801. //
  802. // History: 2001-04-12 vtan created
  803. // --------------------------------------------------------------------------
  804. EXTERN_C void _ShellStatusHostHide (void)
  805. {
  806. _Shell_LogonStatus_Hide();
  807. }
  808. // --------------------------------------------------------------------------
  809. // ::_ShellStatusHostShow
  810. //
  811. // Arguments: <none>
  812. //
  813. // Returns: <none>
  814. //
  815. // Purpose:
  816. //
  817. // History: 2001-04-12 vtan created
  818. // --------------------------------------------------------------------------
  819. EXTERN_C void _ShellStatusHostShow (void)
  820. {
  821. _Shell_LogonStatus_Show();
  822. }