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

1776 lines
55 KiB

  1. /*************************************************************************
  2. *
  3. * api.c
  4. *
  5. * WinStation Control API's for WIN32 subsystem.
  6. *
  7. * Copyright (c) 1985 - 1999, Microsoft Corporation
  8. *
  9. *************************************************************************/
  10. /*
  11. * Includes.
  12. */
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #include "ntuser.h"
  16. #include <winsta.h>
  17. #include <wstmsg.h>
  18. #include <icadd.h>
  19. #include <winbasep.h>
  20. #define SESSION_ROOT L"\\Sessions"
  21. #define MAX_SESSION_PATH 256
  22. NTSTATUS CsrPopulateDosDevices(VOID);
  23. NTSTATUS CleanupSessionObjectDirectories(VOID);
  24. BOOL CtxInitUser32(VOID);
  25. USHORT gHRes = 0;
  26. USHORT gVRes = 0;
  27. USHORT gColorDepth = 0;
  28. #if DBG
  29. ULONG gulConnectCount = 0;
  30. #endif // DBG
  31. DWORD gLUIDDeviceMapsEnabled = 0;
  32. /*
  33. * The following are gotten from ICASRV.
  34. */
  35. HANDLE G_IcaVideoChannel = NULL;
  36. HANDLE G_IcaMouseChannel = NULL;
  37. HANDLE G_IcaKeyboardChannel = NULL;
  38. HANDLE G_IcaBeepChannel = NULL;
  39. HANDLE G_IcaCommandChannel = NULL;
  40. HANDLE G_IcaThinwireChannel = NULL;
  41. WCHAR G_WinStationName[WINSTATIONNAME_LENGTH];
  42. HANDLE G_DupIcaVideoChannel = NULL;
  43. HANDLE G_DupIcaCommandChannel = NULL;
  44. HANDLE G_ConsoleShadowVideoChannel;
  45. HANDLE G_ConsoleShadowMouseChannel;
  46. HANDLE G_ConsoleShadowKeyboardChannel;
  47. HANDLE G_ConsoleShadowBeepChannel;
  48. HANDLE G_ConsoleShadowCommandChannel;
  49. HANDLE G_ConsoleShadowThinwireChannel;
  50. BOOL G_fCursorShadow;
  51. HANDLE G_DupConsoleShadowVideoChannel = NULL;
  52. HANDLE G_DupConsoleShadowCommandChannel = NULL;
  53. /*
  54. * Definition for the WinStation control API's dispatch table
  55. */
  56. typedef NTSTATUS (*PWIN32WINSTATION_API)(IN OUT PWINSTATION_APIMSG ApiMsg);
  57. typedef struct _WIN32WINSTATION_DISPATCH {
  58. PWIN32WINSTATION_API pWin32ApiProc;
  59. } WIN32WINSTATION_DISPATCH, *PWIN32WINSTATION_DISPATCH;
  60. NTSTATUS W32WinStationDoConnect(IN OUT PWINSTATION_APIMSG);
  61. NTSTATUS W32WinStationDoDisconnect(IN OUT PWINSTATION_APIMSG);
  62. NTSTATUS W32WinStationDoReconnect(IN OUT PWINSTATION_APIMSG);
  63. NTSTATUS W32WinStationExitWindows(IN OUT PWINSTATION_APIMSG);
  64. NTSTATUS W32WinStationTerminate(IN OUT PWINSTATION_APIMSG);
  65. NTSTATUS W32WinStationNtSecurity(IN OUT PWINSTATION_APIMSG);
  66. NTSTATUS W32WinStationDoMessage(IN OUT PWINSTATION_APIMSG);
  67. NTSTATUS W32WinStationThinwireStats(IN OUT PWINSTATION_APIMSG);
  68. NTSTATUS W32WinStationShadowSetup(IN OUT PWINSTATION_APIMSG);
  69. NTSTATUS W32WinStationShadowStart(IN OUT PWINSTATION_APIMSG);
  70. NTSTATUS W32WinStationShadowStop(IN OUT PWINSTATION_APIMSG);
  71. NTSTATUS W32WinStationShadowCleanup(IN OUT PWINSTATION_APIMSG);
  72. NTSTATUS W32WinStationPassthruEnable(IN OUT PWINSTATION_APIMSG);
  73. NTSTATUS W32WinStationPassthruDisable(IN OUT PWINSTATION_APIMSG);
  74. // This is the counter part to SMWinStationBroadcastSystemMessage
  75. NTSTATUS W32WinStationBroadcastSystemMessage(IN OUT PWINSTATION_APIMSG);
  76. // This is the counter part to SMWinStationSendWindowMessage
  77. NTSTATUS W32WinStationSendWindowMessage(IN OUT PWINSTATION_APIMSG);
  78. NTSTATUS W32WinStationSetTimezone(IN OUT PWINSTATION_APIMSG);
  79. NTSTATUS W32WinStationDoNotify(IN OUT PWINSTATION_APIMSG);
  80. NTSTATUS W32WinStationDoLoadStringNMessage(IN OUT PWINSTATION_APIMSG);
  81. HANDLE CreateTermSrvReadyEvent();
  82. /*
  83. * WinStation API Dispatch Table
  84. *
  85. * Only the API's that WIN32 implements as opposed to ICASRV
  86. * are entered here. The rest are NULL so that the same WinStation API
  87. * numbers may be used by ICASRV and WIN32. If this table is
  88. * changed, the table below must be modified too, as well as the API
  89. * dispatch table in the ICASRV.
  90. */
  91. WIN32WINSTATION_DISPATCH Win32WinStationDispatch[SMWinStationMaxApiNumber] = {
  92. NULL, // create
  93. NULL, // reset
  94. NULL, // disconnect
  95. NULL, // WCharLog
  96. NULL, // ApiWinStationGetSMCommand,
  97. NULL, // ApiWinStationBrokenConnection,
  98. NULL, // ApiWinStationIcaReplyMessage,
  99. NULL, // ApiWinStationIcaShadowHotkey,
  100. W32WinStationDoConnect,
  101. W32WinStationDoDisconnect,
  102. W32WinStationDoReconnect,
  103. W32WinStationExitWindows,
  104. W32WinStationTerminate,
  105. W32WinStationNtSecurity,
  106. W32WinStationDoMessage,
  107. NULL,
  108. W32WinStationThinwireStats,
  109. W32WinStationShadowSetup,
  110. W32WinStationShadowStart,
  111. W32WinStationShadowStop,
  112. W32WinStationShadowCleanup,
  113. W32WinStationPassthruEnable,
  114. W32WinStationPassthruDisable,
  115. W32WinStationSetTimezone,
  116. NULL, // [AraBern] this was missing: SMWinStationInitialProgram
  117. NULL, // [AraBern] this was missing: SMWinStationNtsdDebug
  118. W32WinStationBroadcastSystemMessage,
  119. W32WinStationSendWindowMessage,
  120. W32WinStationDoNotify,
  121. W32WinStationDoLoadStringNMessage,
  122. NULL, // SMWinStationWindowInvalid
  123. };
  124. #if DBG
  125. PSZ Win32WinStationAPIName[SMWinStationMaxApiNumber] = {
  126. "SmWinStationCreate",
  127. "SmWinStationReset",
  128. "SmWinStationDisconnect",
  129. "SmWinStationWCharLog",
  130. "SmWinStationGetSMCommand",
  131. "SmWinStationBrokenConnection",
  132. "SmWinStationIcaReplyMessage",
  133. "SmWinStationIcaShadowHotkey",
  134. "SmWinStationDoConnect",
  135. "SmWinStationDoDisconnect",
  136. "SmWinStationDoReconnect",
  137. "SmWinStationExitWindows",
  138. "SmWinStationTerminate",
  139. "SmWinStationNtSecurity",
  140. "SmWinStationDoMessage",
  141. "SmWinstationDoBreakPoint",
  142. "SmWinStationThinwireStats",
  143. "SmWinStationShadowSetup",
  144. "SmWinStationShadowStart",
  145. "SmWinStationShadowStop",
  146. "SmWinStationShadowCleanup",
  147. "SmWinStationPassthruEnable",
  148. "SmWinStationPassthruDisable",
  149. "SMWinStationSetTimeZone",
  150. "SMWinStationInitialProgram",
  151. "SMWinStationNtsdDebug",
  152. "W32WinStationBroadcastSystemMessage",
  153. "W32WinStationSendWindowMessage",
  154. "W32WinStationDoNotify",
  155. "W32WinStationDoLoadStringNMessage",
  156. "SMWinStationWindowInvalid",
  157. };
  158. #endif
  159. NTSTATUS TerminalServerRequestThread(PVOID);
  160. NTSTATUS Win32CommandChannelThread(PVOID);
  161. NTSTATUS Win32ConsoleShadowChannelThread(PVOID);
  162. NTSTATUS RemoteDoMessage(PWINSTATION_APIMSG pMsg);
  163. NTSTATUS RemoteDoLoadStringNMessage(PWINSTATION_APIMSG pMsg);
  164. NTSTATUS MultiUserSpoolerInit();
  165. extern HANDLE g_hDoMessageEvent;
  166. NTSTATUS RemoteDoBroadcastSystemMessage(PWINSTATION_APIMSG pMsg);
  167. NTSTATUS RemoteDoSendWindowMessage(PWINSTATION_APIMSG pMsg);
  168. BOOL CancelExitWindows(VOID);
  169. /*****************************************************************************
  170. *
  171. * WinStationAPIInit
  172. *
  173. * Creates and initializes the WinStation API port and thread.
  174. *
  175. * ENTRY:
  176. * No Parameters
  177. *
  178. * EXIT:
  179. * STATUS_SUCCESS - no error
  180. *
  181. ****************************************************************************/
  182. NTSTATUS
  183. WinStationAPIInit(
  184. VOID)
  185. {
  186. NTSTATUS Status;
  187. CLIENT_ID ClientId;
  188. HANDLE ThreadHandle;
  189. KPRIORITY Priority;
  190. ULONG LUIDDeviceMapsEnabled;
  191. #if DBG
  192. static BOOL Inited = FALSE;
  193. #endif
  194. #if DBG
  195. UserAssert(Inited == FALSE);
  196. Inited = TRUE;
  197. #endif
  198. gSessionId = NtCurrentPeb()->SessionId;
  199. //
  200. // Check if LUID DosDevices are enabled.
  201. //
  202. Status = NtQueryInformationProcess(NtCurrentProcess(),
  203. ProcessLUIDDeviceMapsEnabled,
  204. &LUIDDeviceMapsEnabled,
  205. sizeof(LUIDDeviceMapsEnabled),
  206. NULL);
  207. if (NT_SUCCESS(Status)) {
  208. gLUIDDeviceMapsEnabled = LUIDDeviceMapsEnabled;
  209. }
  210. Status = RtlCreateUserThread(NtCurrentProcess(),
  211. NULL,
  212. TRUE,
  213. 0,
  214. 0,
  215. 0,
  216. TerminalServerRequestThread,
  217. NULL,
  218. &ThreadHandle,
  219. &ClientId);
  220. if (!NT_SUCCESS(Status)) {
  221. RIPMSGF1(RIP_WARNING,
  222. "Failed to create TerminalServerRequestThread, Status = 0x%x",
  223. Status);
  224. goto Exit;
  225. }
  226. /*
  227. * Add thread to server thread pool.
  228. */
  229. CsrAddStaticServerThread(ThreadHandle, &ClientId, 0);
  230. /*
  231. * Boost priority of ICA SRV Request thread
  232. */
  233. Priority = THREAD_BASE_PRIORITY_MAX;
  234. Status = NtSetInformationThread(ThreadHandle, ThreadBasePriority,
  235. &Priority, sizeof(Priority));
  236. if (!NT_SUCCESS(Status)) {
  237. RIPMSGF1(RIP_WARNING,
  238. "Failed to set thread priority, Status = 0x%x",
  239. Status);
  240. goto Exit;
  241. }
  242. /*
  243. * Resume the thread now that we've initialized things.
  244. */
  245. NtResumeThread(ThreadHandle, NULL);
  246. Exit:
  247. return Status;
  248. }
  249. NTSTATUS
  250. TerminalServerRequestThread(
  251. PVOID ThreadParameter)
  252. {
  253. UNICODE_STRING PortName;
  254. SECURITY_QUALITY_OF_SERVICE DynamicQos;
  255. WINSTATIONAPI_CONNECT_INFO info;
  256. ULONG ConnectInfoLength;
  257. WINSTATION_APIMSG ApiMsg;
  258. PWIN32WINSTATION_DISPATCH pDispatch;
  259. NTSTATUS Status;
  260. REMOTE_PORT_VIEW ServerView;
  261. HANDLE CsrStartHandle, hevtTermSrvInit;
  262. HANDLE hLPCPort = NULL;
  263. UNREFERENCED_PARAMETER(ThreadParameter);
  264. if (NtCurrentPeb()->SessionId == 0) {
  265. hevtTermSrvInit = CreateTermSrvReadyEvent();
  266. } else {
  267. hevtTermSrvInit = OpenEvent(SYNCHRONIZE, FALSE, L"Global\\TermSrvReadyEvent");
  268. }
  269. if (hevtTermSrvInit == NULL) {
  270. RIPMSG1(RIP_WARNING,
  271. "Couldn't create TermSrvReadyEvent. Error = 0x%x",
  272. GetLastError());
  273. Status = STATUS_NO_MEMORY;
  274. goto Exit;
  275. }
  276. NtWaitForSingleObject(hevtTermSrvInit, FALSE, NULL);
  277. NtClose(hevtTermSrvInit);
  278. /*
  279. * Connect to terminal server API port.
  280. */
  281. DynamicQos.ImpersonationLevel = SecurityImpersonation;
  282. DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  283. DynamicQos.EffectiveOnly = TRUE;
  284. RtlInitUnicodeString(&PortName, L"\\SmSsWinStationApiPort");
  285. /*
  286. * Init the REMOTE_VIEW structure.
  287. */
  288. ServerView.Length = sizeof(ServerView);
  289. ServerView.ViewSize = 0;
  290. ServerView.ViewBase = 0;
  291. /*
  292. * Fill in the ConnectInfo structure with our access request mask.
  293. */
  294. info.Version = CITRIX_WINSTATIONAPI_VERSION;
  295. info.RequestedAccess = 0;
  296. ConnectInfoLength = sizeof(WINSTATIONAPI_CONNECT_INFO);
  297. Status = NtConnectPort(&hLPCPort,
  298. &PortName,
  299. &DynamicQos,
  300. NULL, // ClientView
  301. &ServerView,
  302. NULL, // Max message length [select default]
  303. (PVOID)&info,
  304. &ConnectInfoLength);
  305. if (!NT_SUCCESS(Status)) {
  306. RIPMSG1(RIP_WARNING, "TerminalServerRequestThread: Failed to connect to LPC port: Status = 0x%x", Status);
  307. UserExitWorkerThread(Status);
  308. return Status;
  309. }
  310. //
  311. // Terminal Server calls into Session Manager to create a new Hydra session.
  312. // The session manager creates and resume a new session and returns to Terminal
  313. // server the session id of the new session. There is a race condition where
  314. // CSR can resume and call into terminal server before terminal server can
  315. // store the session id in its internal structure. To prevent this CSR will
  316. // wait here on a named event which will be set by Terminal server once it
  317. // gets the sessionid for the newly created session
  318. //
  319. if (NtCurrentPeb()->SessionId != 0) {
  320. CsrStartHandle = CreateEvent(NULL, TRUE, FALSE, L"CsrStartEvent");
  321. if (!CsrStartHandle) {
  322. RIPMSG1(RIP_WARNING,
  323. "Failed to create CsrStartEvent. Error = 0x%x",
  324. GetLastError());
  325. Status = STATUS_INSUFFICIENT_RESOURCES;
  326. goto Exit;
  327. } else {
  328. Status = NtWaitForSingleObject(CsrStartHandle, FALSE, NULL);
  329. NtClose(CsrStartHandle);
  330. if (!NT_SUCCESS(Status)) {
  331. RIPMSG1(RIP_WARNING,
  332. "Wait for CsrStartEvent failed: Status = 0x%x", Status);
  333. }
  334. }
  335. }
  336. RtlZeroMemory(&ApiMsg, sizeof(ApiMsg));
  337. for (;;) {
  338. /*
  339. * Initialize LPC message fields.
  340. */
  341. ApiMsg.h.u1.s1.DataLength = sizeof(ApiMsg) - sizeof(PORT_MESSAGE);
  342. ApiMsg.h.u1.s1.TotalLength = sizeof(ApiMsg);
  343. ApiMsg.h.u2.s2.Type = 0; // Kernel will fill in message type
  344. ApiMsg.h.u2.s2.DataInfoOffset = 0;
  345. ApiMsg.ApiNumber = SMWinStationGetSMCommand;
  346. Status = NtRequestWaitReplyPort(hLPCPort,
  347. (PPORT_MESSAGE)&ApiMsg,
  348. (PPORT_MESSAGE)&ApiMsg);
  349. if (!NT_SUCCESS(Status)) {
  350. RIPMSG1(RIP_WARNING,
  351. "TerminalServerRequestThread wait failed: Status 0x%x", Status);
  352. break;
  353. }
  354. if (ApiMsg.ApiNumber >= SMWinStationMaxApiNumber) {
  355. RIPMSG1(RIP_WARNING,
  356. "TerminalServerRequestThread: Bad API number %d", ApiMsg.ApiNumber);
  357. ApiMsg.ReturnedStatus = STATUS_NOT_IMPLEMENTED;
  358. } else {
  359. /*
  360. * We must VALIDATE which ones are implemented here.
  361. */
  362. pDispatch = &Win32WinStationDispatch[ApiMsg.ApiNumber];
  363. if (pDispatch->pWin32ApiProc) {
  364. BOOL bRestoreDesktop = FALSE;
  365. USERTHREAD_USEDESKTOPINFO utudi;
  366. Status = STATUS_SUCCESS;
  367. /*
  368. * For all the win32k callouts - with the exception of
  369. * terminate and timezone setting - set this thread to the
  370. * current desktop.
  371. */
  372. if (ApiMsg.ApiNumber != SMWinStationTerminate && ApiMsg.ApiNumber != SMWinStationSetTimeZone) {
  373. BOOL bAttachDesktop = TRUE;
  374. if (ApiMsg.ApiNumber == SMWinStationDoConnect) {
  375. WINSTATIONDOCONNECTMSG* m = &ApiMsg.u.DoConnect;
  376. if (!m->ConsoleShadowFlag) {
  377. bAttachDesktop = FALSE;
  378. }
  379. }
  380. if (bAttachDesktop) {
  381. utudi.hThread = NULL;
  382. utudi.drdRestore.pdeskRestore = NULL;
  383. Status = NtUserSetInformationThread(NtCurrentThread(),
  384. UserThreadUseActiveDesktop,
  385. &utudi, sizeof(utudi));
  386. if (NT_SUCCESS(Status)) {
  387. bRestoreDesktop = TRUE;
  388. }
  389. }
  390. }
  391. /*
  392. * Call the API
  393. */
  394. if (Status == STATUS_SUCCESS) {
  395. ApiMsg.ReturnedStatus = (pDispatch->pWin32ApiProc)(&ApiMsg);
  396. } else {
  397. ApiMsg.ReturnedStatus = Status;
  398. }
  399. if (bRestoreDesktop) {
  400. NtUserSetInformationThread(NtCurrentThread(),
  401. UserThreadUseDesktop,
  402. &utudi,
  403. sizeof(utudi));
  404. }
  405. /*
  406. * Let's bail ...
  407. */
  408. if (ApiMsg.ApiNumber == SMWinStationTerminate) {
  409. break;
  410. }
  411. } else {
  412. // This control API is not implemented in WIN32
  413. ApiMsg.ReturnedStatus = STATUS_NOT_IMPLEMENTED;
  414. }
  415. }
  416. }
  417. Exit:
  418. if (hLPCPort) {
  419. NtClose(hLPCPort);
  420. }
  421. UserExitWorkerThread(Status);
  422. return Status;
  423. }
  424. #if DBG
  425. VOID
  426. W32WinStationDumpReconnectInfo(
  427. WINSTATIONDORECONNECTMSG *pDoReconnect,
  428. BOOLEAN bReconnect)
  429. {
  430. PSTR pCallerName;
  431. if (bReconnect) {
  432. pCallerName = "W32WinStationDoReconnect";
  433. } else {
  434. pCallerName = "W32WinStationDoConnect";
  435. }
  436. DbgPrint(pCallerName);
  437. DbgPrint(" - Display resolution information for session %d :\n", gSessionId);
  438. DbgPrint("\tProtocolType : %04d\n", pDoReconnect->ProtocolType);
  439. DbgPrint("\tHRes : %04d\n", pDoReconnect->HRes);
  440. DbgPrint("\tVRes : %04d\n", pDoReconnect->VRes);
  441. DbgPrint("\tColorDepth : %04d\n", pDoReconnect->ColorDepth);
  442. DbgPrint("\tKeyboardType : %d\n", pDoReconnect->KeyboardType);
  443. DbgPrint("\tKeyboardSubType : %d\n", pDoReconnect->KeyboardSubType);
  444. DbgPrint("\tKeyboardFunctionKey : %d\n", pDoReconnect->KeyboardFunctionKey);
  445. }
  446. #else
  447. #define W32WinStationDumpReconnectInfo(p, b)
  448. #endif // DBG
  449. NTSTATUS
  450. W32WinStationDoConnect(
  451. PWINSTATION_APIMSG pMsg)
  452. {
  453. NTSTATUS Status = STATUS_SUCCESS;
  454. WINSTATIONDOCONNECTMSG* m = &pMsg->u.DoConnect;
  455. WCHAR DisplayDriverName[10];
  456. CLIENT_ID ClientId;
  457. HANDLE ThreadHandle = NULL;
  458. KPRIORITY Priority;
  459. DOCONNECTDATA DoConnectData;
  460. WINSTATIONDORECONNECTMSG mDoReconnect;
  461. HANDLE hDisplayChangeEvent = NULL;
  462. if (!m->ConsoleShadowFlag) {
  463. UserAssert(gulConnectCount == 0);
  464. if ((gLUIDDeviceMapsEnabled == 0) && (gSessionId != 0)) {
  465. /*
  466. * Populate the sessions \DosDevices from
  467. * the current consoles settings
  468. */
  469. Status = CsrPopulateDosDevices();
  470. if (!NT_SUCCESS(Status)) {
  471. RIPMSG1(RIP_WARNING, "CsrPopulateDosDevices failed with Status %lx", Status);
  472. goto Exit;
  473. }
  474. }
  475. G_IcaVideoChannel = m->hIcaVideoChannel;
  476. G_IcaMouseChannel = m->hIcaMouseChannel;
  477. G_IcaKeyboardChannel = m->hIcaKeyboardChannel;
  478. G_IcaBeepChannel = m->hIcaBeepChannel;
  479. G_IcaCommandChannel = m->hIcaCommandChannel;
  480. G_IcaThinwireChannel = m->hIcaThinwireChannel;
  481. RtlZeroMemory(G_WinStationName, sizeof(G_WinStationName));
  482. memcpy(G_WinStationName, m->WinStationName,
  483. min(sizeof(G_WinStationName), sizeof(m->WinStationName)));
  484. Status = NtDuplicateObject( NtCurrentProcess(),
  485. G_IcaVideoChannel,
  486. NtCurrentProcess(),
  487. &G_DupIcaVideoChannel,
  488. 0,
  489. 0,
  490. DUPLICATE_SAME_ACCESS );
  491. if (!NT_SUCCESS(Status)) {
  492. RIPMSG1(RIP_WARNING, "NtDuplicateObject failed with Status %lx", Status);
  493. goto Exit;
  494. }
  495. Status = NtDuplicateObject( NtCurrentProcess(),
  496. G_IcaCommandChannel,
  497. NtCurrentProcess(),
  498. &G_DupIcaCommandChannel,
  499. 0,
  500. 0,
  501. DUPLICATE_SAME_ACCESS );
  502. if (!NT_SUCCESS(Status)) {
  503. RIPMSG1(RIP_WARNING, "NtDuplicateObject failed with Status %lx", Status);
  504. NtClose(G_DupIcaVideoChannel);
  505. G_DupIcaVideoChannel = NULL;
  506. goto Exit;
  507. }
  508. } else {
  509. G_ConsoleShadowVideoChannel = m->hIcaVideoChannel;
  510. G_ConsoleShadowMouseChannel = m->hIcaMouseChannel;
  511. G_ConsoleShadowKeyboardChannel = m->hIcaKeyboardChannel;
  512. G_ConsoleShadowBeepChannel = m->hIcaBeepChannel;
  513. G_ConsoleShadowCommandChannel = m->hIcaCommandChannel;
  514. G_ConsoleShadowThinwireChannel = m->hIcaThinwireChannel;
  515. G_fCursorShadow = FALSE;
  516. SystemParametersInfo(SPI_GETCURSORSHADOW, 0, &G_fCursorShadow, 0);
  517. if (G_fCursorShadow) {
  518. SystemParametersInfo(SPI_SETCURSORSHADOW, 0, FALSE, 0);
  519. }
  520. hDisplayChangeEvent = m->hDisplayChangeEvent;
  521. Status = NtDuplicateObject( NtCurrentProcess(),
  522. G_ConsoleShadowVideoChannel,
  523. NtCurrentProcess(),
  524. &G_DupConsoleShadowVideoChannel,
  525. 0,
  526. 0,
  527. DUPLICATE_SAME_ACCESS );
  528. if (!NT_SUCCESS(Status)) {
  529. RIPMSG1(RIP_WARNING, "NtDuplicateObject failed with Status %lx", Status);
  530. goto Exit;
  531. }
  532. Status = NtDuplicateObject( NtCurrentProcess(),
  533. G_ConsoleShadowCommandChannel,
  534. NtCurrentProcess(),
  535. &G_DupConsoleShadowCommandChannel,
  536. 0,
  537. 0,
  538. DUPLICATE_SAME_ACCESS );
  539. if (!NT_SUCCESS(Status)) {
  540. RIPMSG1(RIP_WARNING, "NtDuplicateObject failed with Status %lx", Status);
  541. NtClose(G_DupConsoleShadowVideoChannel);
  542. G_DupConsoleShadowVideoChannel = NULL;
  543. goto Exit;
  544. }
  545. }
  546. /*
  547. * This must be 8 unicode characters (file name) plus two zero wide characters.
  548. */
  549. RtlZeroMemory(DisplayDriverName, sizeof(DisplayDriverName));
  550. memcpy(DisplayDriverName, m->DisplayDriverName, sizeof(DisplayDriverName) - 2);
  551. /*
  552. * Give the information to the WIN32 driver.
  553. */
  554. RtlZeroMemory(&DoConnectData, sizeof(DoConnectData));
  555. DoConnectData.fMouse = m->fMouse;
  556. DoConnectData.IcaBeepChannel = m->hIcaBeepChannel;
  557. DoConnectData.IcaVideoChannel = m->hIcaVideoChannel;
  558. DoConnectData.IcaMouseChannel = m->hIcaMouseChannel;
  559. DoConnectData.fEnableWindowsKey = m->fEnableWindowsKey;
  560. DoConnectData.IcaKeyboardChannel = m->hIcaKeyboardChannel;
  561. DoConnectData.IcaThinwireChannel = m->hIcaThinwireChannel;
  562. DoConnectData.fClientDoubleClickSupport = m->fClientDoubleClickSupport;
  563. DoConnectData.DisplayChangeEvent = hDisplayChangeEvent;
  564. /*
  565. * Give the information to the keyboard type/subtype/number of functions.
  566. */
  567. DoConnectData.ClientKeyboardType.Type = m->KeyboardType;
  568. DoConnectData.ClientKeyboardType.SubType = m->KeyboardSubType;
  569. DoConnectData.ClientKeyboardType.FunctionKey = m->KeyboardFunctionKey;
  570. memcpy(DoConnectData.WinStationName, G_WinStationName,
  571. min(sizeof(G_WinStationName), sizeof(DoConnectData.WinStationName)));
  572. DoConnectData.drProtocolType = m->ProtocolType;
  573. DoConnectData.drPelsHeight = m->VRes;
  574. DoConnectData.drPelsWidth = m->HRes;
  575. DoConnectData.drBitsPerPel = m->ColorDepth;
  576. mDoReconnect.ProtocolType = m->ProtocolType;
  577. mDoReconnect.HRes = m->HRes;
  578. mDoReconnect.VRes = m->VRes;
  579. mDoReconnect.ColorDepth = m->ColorDepth;
  580. W32WinStationDumpReconnectInfo(&mDoReconnect, FALSE);
  581. /* Give winstation protocol name */
  582. RtlZeroMemory(DoConnectData.ProtocolName, sizeof(DoConnectData.ProtocolName));
  583. memcpy(DoConnectData.ProtocolName, m->ProtocolName, sizeof(DoConnectData.ProtocolName) - 2);
  584. /* Give winstation audio drver name */
  585. RtlZeroMemory(DoConnectData.AudioDriverName, sizeof(DoConnectData.AudioDriverName));
  586. memcpy(DoConnectData.AudioDriverName, m->AudioDriverName, sizeof(DoConnectData.AudioDriverName) - 2);
  587. DoConnectData.fConsoleShadowFlag = (BOOL) m->ConsoleShadowFlag;
  588. Status = NtUserRemoteConnect(&DoConnectData,
  589. ARRAY_SIZE(DisplayDriverName),
  590. DisplayDriverName);
  591. if (Status != STATUS_SUCCESS) {
  592. RIPMSG1(RIP_WARNING, "NtUserRemoteConnect failed with Status %lx", Status);
  593. goto Exit;
  594. }
  595. Status = RtlCreateUserThread(NtCurrentProcess(),
  596. NULL,
  597. TRUE,
  598. 0L,
  599. 0L,
  600. 0L,
  601. Win32CommandChannelThread,
  602. (PVOID)m->ConsoleShadowFlag,
  603. &ThreadHandle,
  604. &ClientId);
  605. if (Status != STATUS_SUCCESS) {
  606. RIPMSG1(RIP_WARNING, "RtlCreateUserThread failed with Status %lx", Status);
  607. if (G_DupIcaVideoChannel) {
  608. NtClose(G_DupIcaVideoChannel);
  609. G_DupIcaVideoChannel = NULL;
  610. }
  611. if (G_DupIcaCommandChannel) {
  612. NtClose(G_DupIcaCommandChannel);
  613. G_DupIcaCommandChannel = NULL;
  614. }
  615. if (G_DupConsoleShadowVideoChannel) {
  616. NtClose(G_DupConsoleShadowVideoChannel);
  617. G_DupConsoleShadowVideoChannel = NULL;
  618. }
  619. if (G_DupConsoleShadowCommandChannel) {
  620. NtClose(G_DupConsoleShadowCommandChannel);
  621. G_DupConsoleShadowCommandChannel = NULL;
  622. }
  623. goto Exit;
  624. }
  625. /*
  626. * Add thread to server thread pool only if we are in regular sessions.
  627. * In console shadow, we don't do this as it will leak the handle --
  628. * CSRSS doesn't close these handles.
  629. */
  630. if (!m->ConsoleShadowFlag && CsrAddStaticServerThread(ThreadHandle, &ClientId, 0) == NULL) {
  631. RIPMSG0(RIP_WARNING, "CsrAddStaticServerThread failed");
  632. /*
  633. * Close the handle as the above function does not have a reference
  634. * to us in its list.
  635. */
  636. CloseHandle(ThreadHandle);
  637. goto Exit;
  638. }
  639. /*
  640. * Boost priority of thread
  641. */
  642. Priority = THREAD_BASE_PRIORITY_MAX;
  643. Status = NtSetInformationThread(ThreadHandle, ThreadBasePriority,
  644. &Priority, sizeof(Priority));
  645. UserAssert(NT_SUCCESS(Status));
  646. if (Status != STATUS_SUCCESS) {
  647. RIPMSG1(RIP_WARNING, "NtSetInformationThread failed with Status %lx", Status);
  648. Status = STATUS_NO_MEMORY;
  649. goto Exit;
  650. }
  651. /*
  652. * Resume the thread now that we've initialized things.
  653. */
  654. NtResumeThread(ThreadHandle, NULL);
  655. if (!m->ConsoleShadowFlag) {
  656. if (CsrConnectToUser() == NULL) {
  657. RIPMSG0(RIP_WARNING, "CsrConnectToUser failed");
  658. Status = STATUS_NO_MEMORY;
  659. goto Exit;
  660. }
  661. if (!CtxInitUser32()) {
  662. RIPMSG0(RIP_WARNING, "CtxInitUser32 failed");
  663. Status = STATUS_NO_MEMORY;
  664. goto Exit;
  665. }
  666. /*
  667. * Create the Spooler service thread
  668. */
  669. if (gSessionId != 0) {
  670. Status = MultiUserSpoolerInit();
  671. }
  672. /*
  673. * Save the resolution
  674. */
  675. gHRes = mDoReconnect.HRes;
  676. gVRes = mDoReconnect.VRes;
  677. gColorDepth = mDoReconnect.ColorDepth;
  678. } else {
  679. /*
  680. * By now, the object has been referenced in kernel mode.
  681. */
  682. CloseHandle(hDisplayChangeEvent);
  683. }
  684. Exit:
  685. #if DBG
  686. if (!m->ConsoleShadowFlag) {
  687. if (Status == STATUS_SUCCESS) {
  688. gulConnectCount++;
  689. }
  690. }
  691. #endif // DBG
  692. /*
  693. * Close the thread handle now if we are in console shadow
  694. */
  695. if (m->ConsoleShadowFlag && NULL != ThreadHandle) {
  696. CloseHandle(ThreadHandle);
  697. }
  698. return Status;
  699. }
  700. NTSTATUS
  701. W32WinStationDoDisconnect(
  702. PWINSTATION_APIMSG pMsg)
  703. {
  704. NTSTATUS Status = STATUS_SUCCESS;
  705. WINSTATIONDODISCONNECTMSG *m = &pMsg->u.DoDisconnect;
  706. IO_STATUS_BLOCK IoStatus;
  707. if (!m->ConsoleShadowFlag) {
  708. RtlZeroMemory(G_WinStationName, sizeof(G_WinStationName));
  709. Status = (NTSTATUS)NtUserCallNoParam(SFI_XXXREMOTEDISCONNECT);
  710. } else {
  711. Status = (NTSTATUS)NtUserCallNoParam(SFI_XXXREMOTECONSOLESHADOWSTOP);
  712. if (G_ConsoleShadowMouseChannel) {
  713. CloseHandle(G_ConsoleShadowMouseChannel);
  714. G_ConsoleShadowMouseChannel = NULL;
  715. }
  716. if (G_ConsoleShadowKeyboardChannel) {
  717. CloseHandle(G_ConsoleShadowKeyboardChannel);
  718. G_ConsoleShadowKeyboardChannel = NULL;
  719. }
  720. // Instead send a IOCTL to termdd
  721. if (G_ConsoleShadowCommandChannel) {
  722. Status = NtDeviceIoControlFile(
  723. G_ConsoleShadowCommandChannel,
  724. NULL,
  725. NULL,
  726. NULL,
  727. &IoStatus,
  728. IOCTL_ICA_CHANNEL_CLOSE_COMMAND_CHANNEL,
  729. NULL,
  730. 0,
  731. NULL,
  732. 0);
  733. CloseHandle(G_ConsoleShadowCommandChannel);
  734. G_ConsoleShadowCommandChannel = NULL;
  735. }
  736. if (G_ConsoleShadowVideoChannel) {
  737. Status = NtDeviceIoControlFile(
  738. G_ConsoleShadowVideoChannel,
  739. NULL,
  740. NULL,
  741. NULL,
  742. &IoStatus,
  743. IOCTL_ICA_CHANNEL_CLOSE_COMMAND_CHANNEL,
  744. NULL,
  745. 0,
  746. NULL,
  747. 0);
  748. CloseHandle(G_ConsoleShadowVideoChannel);
  749. G_ConsoleShadowVideoChannel = NULL;
  750. }
  751. if (G_ConsoleShadowBeepChannel) {
  752. CloseHandle(G_ConsoleShadowBeepChannel);
  753. G_ConsoleShadowBeepChannel = NULL;
  754. }
  755. if (G_ConsoleShadowThinwireChannel) {
  756. CloseHandle(G_ConsoleShadowThinwireChannel);
  757. G_ConsoleShadowThinwireChannel = NULL;
  758. }
  759. if (G_fCursorShadow) {
  760. SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (LPVOID)TRUE, 0);
  761. }
  762. }
  763. if (Status != STATUS_SUCCESS) {
  764. RIPMSG1(RIP_WARNING, "xxxRemoteDisconnect failed with Status %lx", Status);
  765. }
  766. #if DBG
  767. if (!m->ConsoleShadowFlag && Status == STATUS_SUCCESS) {
  768. gulConnectCount--;
  769. }
  770. #endif // DBG
  771. return Status;
  772. }
  773. NTSTATUS
  774. W32WinStationDoReconnect(
  775. PWINSTATION_APIMSG pMsg)
  776. {
  777. NTSTATUS Status = STATUS_SUCCESS;
  778. DORECONNECTDATA DoReconnectData;
  779. WINSTATIONDORECONNECTMSG* m = &pMsg->u.DoReconnect;
  780. UserAssert(gulConnectCount == 0);
  781. RtlZeroMemory(&DoReconnectData, sizeof(DoReconnectData));
  782. DoReconnectData.fMouse = m->fMouse;
  783. DoReconnectData.fEnableWindowsKey = m->fEnableWindowsKey;
  784. DoReconnectData.fClientDoubleClickSupport = m->fClientDoubleClickSupport;
  785. memcpy(G_WinStationName, m->WinStationName,
  786. min(sizeof(G_WinStationName), sizeof(m->WinStationName)));
  787. memcpy(DoReconnectData.WinStationName, G_WinStationName,
  788. min(sizeof(G_WinStationName), sizeof(DoReconnectData.WinStationName)));
  789. DoReconnectData.drProtocolType = m->ProtocolType;
  790. DoReconnectData.drPelsHeight = m->VRes;
  791. DoReconnectData.drPelsWidth = m->HRes;
  792. DoReconnectData.drBitsPerPel = m->ColorDepth;
  793. if (m->fDynamicReconnect) {
  794. DoReconnectData.fChangeDisplaySettings = TRUE;
  795. } else {
  796. DoReconnectData.fChangeDisplaySettings = FALSE;
  797. }
  798. // DoReconnectData.drDisplayFrequency is no yet setup
  799. DoReconnectData.drDisplayFrequency = 0;
  800. /*
  801. * Give the information to the keyboard type/subtype/number of functions.
  802. */
  803. DoReconnectData.ClientKeyboardType.Type = m->KeyboardType;
  804. DoReconnectData.ClientKeyboardType.SubType = m->KeyboardSubType;
  805. DoReconnectData.ClientKeyboardType.FunctionKey = m->KeyboardFunctionKey;
  806. RtlZeroMemory(DoReconnectData.DisplayDriverName, sizeof(DoReconnectData.DisplayDriverName));
  807. UserAssert(sizeof(m->DisplayDriverName) <= sizeof(WCHAR) * DR_DISPLAY_DRIVER_NAME_LENGTH);
  808. memcpy(DoReconnectData.DisplayDriverName, m->DisplayDriverName, sizeof(m->DisplayDriverName) - 2);
  809. RtlZeroMemory(DoReconnectData.ProtocolName, sizeof(DoReconnectData.ProtocolName));
  810. UserAssert(sizeof(m->DisplayDriverName) <= sizeof(WCHAR) * WPROTOCOLNAME_LENGTH);
  811. memcpy(DoReconnectData.ProtocolName, m->ProtocolName, sizeof(m->ProtocolName) - 2);
  812. RtlZeroMemory(DoReconnectData.AudioDriverName, sizeof(DoReconnectData.AudioDriverName));
  813. memcpy(DoReconnectData.AudioDriverName, m->AudioDriverName, sizeof(m->AudioDriverName) - 2);
  814. W32WinStationDumpReconnectInfo(m, TRUE);
  815. /*
  816. * Give the information to the WIN32 driver.
  817. */
  818. Status = (NTSTATUS)NtUserCallOneParam((ULONG_PTR)&DoReconnectData,
  819. SFI_XXXREMOTERECONNECT);
  820. if (Status != STATUS_SUCCESS) {
  821. RIPMSG1(RIP_WARNING, "xxxRemoteReconnect failed with Status %lx", Status);
  822. } else {
  823. /*
  824. * Save the resolution
  825. */
  826. gHRes = m->HRes;
  827. gVRes = m->VRes;
  828. gColorDepth = m->ColorDepth;
  829. #if DBG
  830. gulConnectCount++;
  831. #endif // DBG
  832. }
  833. return Status;
  834. }
  835. NTSTATUS
  836. W32WinStationDoNotify(
  837. PWINSTATION_APIMSG pMsg)
  838. {
  839. NTSTATUS Status = STATUS_SUCCESS;
  840. DONOTIFYDATA DoNotifyData;
  841. WINSTATIONDONOTIFYMSG* m = &pMsg->u.DoNotify;
  842. switch (m->NotifyEvent) {
  843. case WinStation_Notify_DisableScrnSaver:
  844. DoNotifyData.NotifyEvent = Notify_DisableScrnSaver;
  845. break;
  846. case WinStation_Notify_EnableScrnSaver:
  847. DoNotifyData.NotifyEvent = Notify_EnableScrnSaver;
  848. break;
  849. case WinStation_Notify_Disconnect:
  850. DoNotifyData.NotifyEvent = Notify_Disconnect;
  851. break;
  852. case WinStation_Notify_SyncDisconnect:
  853. DoNotifyData.NotifyEvent = Notify_SyncDisconnect;
  854. break;
  855. case WinStation_Notify_Reconnect:
  856. DoNotifyData.NotifyEvent = Notify_Reconnect;
  857. break;
  858. case WinStation_Notify_PreReconnect:
  859. DoNotifyData.NotifyEvent = Notify_PreReconnect;
  860. break;
  861. case WinStation_Notify_PreReconnectDesktopSwitch:
  862. DoNotifyData.NotifyEvent = Notify_PreReconnectDesktopSwitch;
  863. break;
  864. case WinStation_Notify_HelpAssistantShadowStart:
  865. DoNotifyData.NotifyEvent = Notify_HelpAssistantShadowStart;
  866. break;
  867. case WinStation_Notify_HelpAssistantShadowFinish:
  868. DoNotifyData.NotifyEvent = Notify_HelpAssistantShadowFinish;
  869. break;
  870. case WinStation_Notify_DisconnectPipe:
  871. DoNotifyData.NotifyEvent = Notify_DisconnectPipe;
  872. break;
  873. default:
  874. RIPMSGF1(RIP_ERROR, "Unknown NotifyEvent 0x%x", m->NotifyEvent);
  875. return STATUS_INVALID_PARAMETER;
  876. }
  877. /*
  878. * Give the information to the WIN32 driver.
  879. */
  880. Status = (NTSTATUS)NtUserCallOneParam((ULONG_PTR)&DoNotifyData,
  881. SFI_XXXREMOTENOTIFY);
  882. if (!NT_SUCCESS(Status)) {
  883. RIPMSG1(RIP_WARNING, "xxxRemoteNotify failed with Status %lx", Status);
  884. }
  885. return Status;
  886. }
  887. NTSTATUS
  888. W32WinStationExitWindows(
  889. PWINSTATION_APIMSG pMsg)
  890. {
  891. NTSTATUS Status = STATUS_SUCCESS;
  892. WINSTATIONEXITWINDOWSMSG* m = &pMsg->u.ExitWindows;
  893. UserAssert(gulConnectCount <= 1);
  894. /*
  895. * Cancel any existing ExitWindows call so that we can force logoff the user
  896. */
  897. CancelExitWindows();
  898. /*
  899. * Tell winlogon to logoff
  900. */
  901. Status = (NTSTATUS)NtUserCallNoParam(SFI_REMOTELOGOFF);
  902. if (!NT_SUCCESS(Status)) {
  903. RIPMSG1(RIP_WARNING, "RemoteLogoff failed with Status %lx", Status);
  904. }
  905. return Status;
  906. }
  907. NTSTATUS
  908. W32WinStationTerminate(
  909. PWINSTATION_APIMSG pMsg)
  910. {
  911. NTSTATUS Status = STATUS_SUCCESS;
  912. HANDLE hevtRitExited, hevtRitStuck, hevtShutDown;
  913. DONOTIFYDATA DoNotifyData;
  914. IO_STATUS_BLOCK IoStatus;
  915. UNREFERENCED_PARAMETER(pMsg);
  916. gbExitInProgress = TRUE;
  917. /*
  918. * Get rid of hard error thread.
  919. */
  920. if (gdwHardErrorThreadId != 0) {
  921. BoostHardError(-1, BHE_FORCE);
  922. /*
  923. * Poll (!!?) for hard error thread completion. The thread does
  924. * not exit.
  925. */
  926. while (gdwHardErrorThreadId != 0) {
  927. RIPMSG0(RIP_WARNING, "Waiting for hard error thread to stop...");
  928. Sleep(3 * 1000);
  929. }
  930. RIPMSG0(RIP_WARNING, "Stopped hard error thread");
  931. }
  932. if (g_hDoMessageEvent) {
  933. NtSetEvent(g_hDoMessageEvent, NULL);
  934. }
  935. /*
  936. * Give the information that we want to stop reading to the WIN32 driver.
  937. */
  938. DoNotifyData.NotifyEvent = Notify_StopReadInput;
  939. Status = (NTSTATUS)NtUserCallOneParam((ULONG_PTR)&DoNotifyData,
  940. SFI_XXXREMOTENOTIFY);
  941. if (!NT_SUCCESS(Status)) {
  942. RIPMSG1(RIP_WARNING, "W32WinStationTerminate : xxxRemoteNotify failed with Status %lx", Status);
  943. }
  944. if (G_IcaMouseChannel) {
  945. CloseHandle(G_IcaMouseChannel);
  946. G_IcaMouseChannel = NULL;
  947. }
  948. if (G_IcaKeyboardChannel) {
  949. CloseHandle(G_IcaKeyboardChannel);
  950. G_IcaKeyboardChannel = NULL;
  951. }
  952. // Instead send a IOCTL to termdd
  953. if (G_IcaCommandChannel) {
  954. Status = NtDeviceIoControlFile(
  955. G_IcaCommandChannel,
  956. NULL,
  957. NULL,
  958. NULL,
  959. &IoStatus,
  960. IOCTL_ICA_CHANNEL_CLOSE_COMMAND_CHANNEL,
  961. NULL,
  962. 0,
  963. NULL,
  964. 0);
  965. CloseHandle(G_IcaCommandChannel);
  966. G_IcaCommandChannel = NULL;
  967. }
  968. if (G_IcaVideoChannel) {
  969. Status = NtDeviceIoControlFile(
  970. G_IcaVideoChannel,
  971. NULL,
  972. NULL,
  973. NULL,
  974. &IoStatus,
  975. IOCTL_ICA_CHANNEL_CLOSE_COMMAND_CHANNEL,
  976. NULL,
  977. 0,
  978. NULL,
  979. 0);
  980. CloseHandle(G_IcaVideoChannel);
  981. G_IcaVideoChannel = NULL;
  982. }
  983. if (G_IcaBeepChannel) {
  984. CloseHandle(G_IcaBeepChannel);
  985. G_IcaBeepChannel = NULL;
  986. }
  987. if (G_IcaThinwireChannel) {
  988. CloseHandle(G_IcaThinwireChannel);
  989. G_IcaThinwireChannel = NULL;
  990. }
  991. hevtShutDown = OpenEvent(EVENT_ALL_ACCESS,
  992. FALSE,
  993. L"EventShutDownCSRSS");
  994. if (hevtShutDown == NULL) {
  995. /*
  996. * This case is for cached sessions where RIT and Destiop thread have
  997. * not been created.
  998. */
  999. RIPMSG0(RIP_WARNING, "W32WinStationTerminate terminating CSRSS ...");
  1000. if (gLUIDDeviceMapsEnabled == 0) {
  1001. Status = CleanupSessionObjectDirectories();
  1002. }
  1003. return 0;
  1004. }
  1005. hevtRitExited = CreateEvent(NULL,
  1006. FALSE,
  1007. FALSE,
  1008. L"EventRitExited");
  1009. UserAssert(hevtRitExited != NULL);
  1010. hevtRitStuck = CreateEvent(NULL,
  1011. FALSE,
  1012. FALSE,
  1013. L"EventRitStuck");
  1014. UserAssert(hevtRitStuck != NULL);
  1015. /*
  1016. * RIT is created. Signal this event that starts the
  1017. * cleanup in win32k.
  1018. */
  1019. SetEvent(hevtShutDown);
  1020. TAGMSG0(DBGTAG_TermSrv, "EventShutDownCSRSS set in CSRSS ...");
  1021. while (1) {
  1022. HANDLE arHandles[2] = {hevtRitExited, hevtRitStuck};
  1023. DWORD result;
  1024. result = WaitForMultipleObjects(2, arHandles, FALSE, INFINITE);
  1025. switch (result) {
  1026. case WAIT_OBJECT_0:
  1027. goto RITExited;
  1028. case WAIT_OBJECT_0 + 1:
  1029. /*
  1030. * The RIT is stuck because there are still GUI threads
  1031. * assigned to desktops. One reason for this is that winlogon
  1032. * died w/o calling ExitWindowsEx.
  1033. */
  1034. break;
  1035. default:
  1036. FRE_RIPMSG1(RIP_ERROR,
  1037. "WFMO returned unexpected value 0x%x",
  1038. result);
  1039. break;
  1040. }
  1041. }
  1042. RITExited:
  1043. TAGMSG0(DBGTAG_TermSrv, "EventRitExited set in CSRSS ...");
  1044. CloseHandle(hevtRitExited);
  1045. CloseHandle(hevtRitStuck);
  1046. CloseHandle(hevtShutDown);
  1047. Status = CleanupSessionObjectDirectories();
  1048. return Status;
  1049. }
  1050. NTSTATUS
  1051. W32WinStationNtSecurity(
  1052. PWINSTATION_APIMSG pMsg)
  1053. {
  1054. NTSTATUS Status;
  1055. UNREFERENCED_PARAMETER(pMsg);
  1056. Status = (NTSTATUS)NtUserCallNoParam(SFI_REMOTENTSECURITY);
  1057. if (!NT_SUCCESS(Status)) {
  1058. RIPMSG1(RIP_WARNING, "RemoteNtSecurity failed with Status %lx", Status);
  1059. }
  1060. return Status;
  1061. }
  1062. NTSTATUS
  1063. W32WinStationDoMessage(
  1064. PWINSTATION_APIMSG pMsg)
  1065. {
  1066. NTSTATUS Status = STATUS_SUCCESS;
  1067. Status = RemoteDoMessage(pMsg);
  1068. if (!NT_SUCCESS(Status)) {
  1069. RIPMSG1(RIP_WARNING, "RemoteDoMessage failed with Status %lx", Status);
  1070. }
  1071. return Status;
  1072. }
  1073. // This is different from W32WinStationDoMessage in that it loads the string and displays the message.
  1074. NTSTATUS
  1075. W32WinStationDoLoadStringNMessage(
  1076. PWINSTATION_APIMSG pMsg)
  1077. {
  1078. NTSTATUS Status;
  1079. Status = RemoteDoLoadStringNMessage(pMsg);
  1080. if (!NT_SUCCESS(Status)) {
  1081. RIPMSG1(RIP_WARNING, "RemoteDoLoadStringNMessage failed with Status %lx", Status);
  1082. }
  1083. return Status;
  1084. }
  1085. // This is the counter part to SMWinStationBroadcastSystemMessage
  1086. NTSTATUS
  1087. W32WinStationBroadcastSystemMessage(
  1088. PWINSTATION_APIMSG pMsg )
  1089. {
  1090. NTSTATUS Status;
  1091. Status = RemoteDoBroadcastSystemMessage(pMsg);
  1092. if (!NT_SUCCESS(Status)) {
  1093. RIPMSG1(RIP_WARNING, "RemoteDoBroadcastSystemMessage(): failed with status 0x%lx", Status);
  1094. }
  1095. return Status;
  1096. }
  1097. // This is the counter part to SMWinStationSendWindowMessage
  1098. NTSTATUS
  1099. W32WinStationSendWindowMessage(
  1100. PWINSTATION_APIMSG pMsg)
  1101. {
  1102. NTSTATUS Status;
  1103. Status = RemoteDoSendWindowMessage(pMsg);
  1104. if (!NT_SUCCESS(Status)) {
  1105. RIPMSG1(RIP_WARNING, "RemoteDoSendWindowMessage failed with Status 0x%lx", Status);
  1106. }
  1107. return Status;
  1108. }
  1109. NTSTATUS
  1110. W32WinStationThinwireStats(
  1111. PWINSTATION_APIMSG pMsg)
  1112. {
  1113. NTSTATUS Status;
  1114. WINSTATIONTHINWIRESTATSMSG* m = &pMsg->u.ThinwireStats;
  1115. Status = (NTSTATUS)NtUserCallOneParam((ULONG_PTR)&m->Stats,
  1116. SFI_REMOTETHINWIRESTATS);
  1117. if (!NT_SUCCESS(Status)) {
  1118. RIPMSG1(RIP_WARNING, "RemoteThinwireStats failed with Status %lx", Status);
  1119. }
  1120. return Status;
  1121. }
  1122. NTSTATUS
  1123. W32WinStationShadowSetup(
  1124. PWINSTATION_APIMSG pMsg)
  1125. {
  1126. NTSTATUS Status;
  1127. WINSTATIONSHADOWSETUPMSG* m = &pMsg->u.ShadowSetup;
  1128. Status = (NTSTATUS)NtUserCallNoParam(SFI_XXXREMOTESHADOWSETUP);
  1129. if (!NT_SUCCESS(Status)) {
  1130. RIPMSG1(RIP_WARNING, "xxxRemoteShadowSetup failed with Status %lx", Status);
  1131. }
  1132. return Status;
  1133. }
  1134. NTSTATUS
  1135. W32WinStationShadowStart(
  1136. PWINSTATION_APIMSG pMsg)
  1137. {
  1138. NTSTATUS Status;
  1139. WINSTATIONSHADOWSTARTMSG* m = &pMsg->u.ShadowStart;
  1140. Status = (NTSTATUS)NtUserCallTwoParam((ULONG_PTR)m->pThinwireData,
  1141. (ULONG_PTR)m->ThinwireDataLength,
  1142. SFI_REMOTESHADOWSTART);
  1143. if (!NT_SUCCESS(Status)) {
  1144. RIPMSG1(RIP_WARNING, "RemoteShadowStart failed with Status %lx", Status);
  1145. }
  1146. return Status;
  1147. }
  1148. NTSTATUS
  1149. W32WinStationShadowStop(
  1150. PWINSTATION_APIMSG pMsg)
  1151. {
  1152. NTSTATUS Status;
  1153. WINSTATIONSHADOWSTOPMSG* m = &pMsg->u.ShadowStop;
  1154. Status = (NTSTATUS)NtUserCallNoParam(SFI_XXXREMOTESHADOWSTOP);
  1155. if (!NT_SUCCESS(Status)) {
  1156. RIPMSG1(RIP_WARNING, "xxxRemoteShadowStop failed with Status %lx", Status);
  1157. }
  1158. return Status;
  1159. }
  1160. NTSTATUS
  1161. W32WinStationShadowCleanup(
  1162. PWINSTATION_APIMSG pMsg)
  1163. {
  1164. NTSTATUS Status;
  1165. WINSTATIONSHADOWCLEANUPMSG* m = &pMsg->u.ShadowCleanup;
  1166. Status = (NTSTATUS)NtUserCallTwoParam((ULONG_PTR)m->pThinwireData,
  1167. (ULONG_PTR)m->ThinwireDataLength,
  1168. SFI_REMOTESHADOWCLEANUP);
  1169. if (!NT_SUCCESS(Status)) {
  1170. RIPMSG1(RIP_WARNING, "RemoteShadowCleanup failed with Status %lx", Status);
  1171. }
  1172. return Status;
  1173. }
  1174. NTSTATUS
  1175. W32WinStationPassthruEnable(
  1176. PWINSTATION_APIMSG pMsg)
  1177. {
  1178. NTSTATUS Status;
  1179. UNREFERENCED_PARAMETER(pMsg);
  1180. Status = (NTSTATUS)NtUserCallNoParam(SFI_XXXREMOTEPASSTHRUENABLE);
  1181. if (!NT_SUCCESS(Status)) {
  1182. RIPMSG1(RIP_WARNING, "xxxRemotePassthruEnable failed with Status %lx", Status);
  1183. }
  1184. return Status;
  1185. }
  1186. NTSTATUS
  1187. W32WinStationPassthruDisable(
  1188. PWINSTATION_APIMSG pMsg)
  1189. {
  1190. NTSTATUS Status;
  1191. UNREFERENCED_PARAMETER(pMsg);
  1192. Status = (NTSTATUS)NtUserCallNoParam(SFI_REMOTEPASSTHRUDISABLE);
  1193. if (!NT_SUCCESS(Status)) {
  1194. RIPMSG1(RIP_WARNING, "RemotePassthruDisable failed with Status %lx", Status);
  1195. }
  1196. return Status;
  1197. }
  1198. NTSTATUS
  1199. CleanupSessionObjectDirectories(
  1200. VOID)
  1201. {
  1202. NTSTATUS Status;
  1203. OBJECT_ATTRIBUTES Attributes;
  1204. UNICODE_STRING UnicodeString;
  1205. HANDLE LinkHandle;
  1206. POBJECT_DIRECTORY_INFORMATION DirInfo;
  1207. BOOLEAN RestartScan;
  1208. UCHAR DirInfoBuffer[ 4096 ];
  1209. WCHAR szSessionString [ MAX_SESSION_PATH ];
  1210. ULONG Context = 0;
  1211. ULONG ReturnedLength;
  1212. HANDLE DosDevicesDirectory;
  1213. HANDLE *HandleArray;
  1214. ULONG Size = 100;
  1215. ULONG i, Count = 0;
  1216. swprintf(szSessionString,L"%ws\\%ld\\DosDevices",SESSION_ROOT,NtCurrentPeb()->SessionId);
  1217. RtlInitUnicodeString(&UnicodeString, szSessionString);
  1218. InitializeObjectAttributes(&Attributes,
  1219. &UnicodeString,
  1220. OBJ_CASE_INSENSITIVE,
  1221. NULL,
  1222. NULL);
  1223. Status = NtOpenDirectoryObject(&DosDevicesDirectory,
  1224. DIRECTORY_ALL_ACCESS,
  1225. &Attributes);
  1226. if (!NT_SUCCESS(Status)) {
  1227. RIPMSG1(RIP_WARNING, "NtOpenDirectoryObject failed with Status %lx", Status);
  1228. return Status;
  1229. }
  1230. Restart:
  1231. HandleArray = (HANDLE *)LocalAlloc(LPTR, Size * sizeof(HANDLE));
  1232. if (HandleArray == NULL) {
  1233. NtClose(DosDevicesDirectory);
  1234. return STATUS_NO_MEMORY;
  1235. }
  1236. RestartScan = TRUE;
  1237. DirInfo = (POBJECT_DIRECTORY_INFORMATION)DirInfoBuffer;
  1238. while (TRUE) {
  1239. Status = NtQueryDirectoryObject(DosDevicesDirectory,
  1240. (PVOID)DirInfo,
  1241. sizeof(DirInfoBuffer),
  1242. TRUE,
  1243. RestartScan,
  1244. &Context,
  1245. &ReturnedLength);
  1246. if (!NT_SUCCESS(Status)) {
  1247. if (Status == STATUS_NO_MORE_ENTRIES) {
  1248. Status = STATUS_SUCCESS;
  1249. }
  1250. break;
  1251. }
  1252. if (!wcscmp(DirInfo->TypeName.Buffer, L"SymbolicLink")) {
  1253. if (Count >= Size) {
  1254. for (i = 0; i < Count; i++) {
  1255. NtClose(HandleArray[i]);
  1256. }
  1257. Size += 20;
  1258. Count = 0;
  1259. LocalFree(HandleArray);
  1260. goto Restart;
  1261. }
  1262. InitializeObjectAttributes(&Attributes,
  1263. &DirInfo->Name,
  1264. OBJ_CASE_INSENSITIVE,
  1265. DosDevicesDirectory,
  1266. NULL);
  1267. Status = NtOpenSymbolicLinkObject(&LinkHandle,
  1268. SYMBOLIC_LINK_ALL_ACCESS,
  1269. &Attributes);
  1270. if (NT_SUCCESS(Status)) {
  1271. Status = NtMakeTemporaryObject(LinkHandle);
  1272. if (NT_SUCCESS(Status)) {
  1273. HandleArray[Count] = LinkHandle;
  1274. Count++;
  1275. }
  1276. }
  1277. }
  1278. RestartScan = FALSE;
  1279. }
  1280. for (i = 0; i < Count; i++) {
  1281. NtClose (HandleArray[i]);
  1282. }
  1283. LocalFree(HandleArray);
  1284. NtClose(DosDevicesDirectory);
  1285. return Status;
  1286. }
  1287. NTSTATUS
  1288. W32WinStationSetTimezone(
  1289. PWINSTATION_APIMSG pMsg)
  1290. {
  1291. /*++
  1292. Routine Description:
  1293. This function sets Time Zone Information as global shared data
  1294. Arguments:
  1295. NONE
  1296. Return Value:
  1297. NONE
  1298. --*/
  1299. TIME_ZONE_INFORMATION tzi;
  1300. tzi.Bias = pMsg->u.SetTimeZone.TimeZone.Bias;
  1301. tzi.StandardBias = pMsg->u.SetTimeZone.TimeZone.StandardBias;
  1302. tzi.DaylightBias = pMsg->u.SetTimeZone.TimeZone.DaylightBias;
  1303. memcpy(&tzi.StandardName,&(pMsg->u.SetTimeZone.TimeZone.StandardName),sizeof(tzi.StandardName));
  1304. memcpy(&tzi.DaylightName,&(pMsg->u.SetTimeZone.TimeZone.DaylightName),sizeof(tzi.DaylightName));
  1305. tzi.StandardDate.wYear = pMsg->u.SetTimeZone.TimeZone.StandardDate.wYear;
  1306. tzi.StandardDate.wMonth = pMsg->u.SetTimeZone.TimeZone.StandardDate.wMonth;
  1307. tzi.StandardDate.wDayOfWeek = pMsg->u.SetTimeZone.TimeZone.StandardDate.wDayOfWeek;
  1308. tzi.StandardDate.wDay = pMsg->u.SetTimeZone.TimeZone.StandardDate.wDay;
  1309. tzi.StandardDate.wHour = pMsg->u.SetTimeZone.TimeZone.StandardDate.wHour;
  1310. tzi.StandardDate.wMinute = pMsg->u.SetTimeZone.TimeZone.StandardDate.wMinute;
  1311. tzi.StandardDate.wSecond = pMsg->u.SetTimeZone.TimeZone.StandardDate.wSecond;
  1312. tzi.StandardDate.wMilliseconds = pMsg->u.SetTimeZone.TimeZone.StandardDate.wMilliseconds;
  1313. tzi.DaylightDate.wYear = pMsg->u.SetTimeZone.TimeZone.DaylightDate.wYear;
  1314. tzi.DaylightDate.wMonth = pMsg->u.SetTimeZone.TimeZone.DaylightDate.wMonth;
  1315. tzi.DaylightDate.wDayOfWeek = pMsg->u.SetTimeZone.TimeZone.DaylightDate.wDayOfWeek;
  1316. tzi.DaylightDate.wDay = pMsg->u.SetTimeZone.TimeZone.DaylightDate.wDay;
  1317. tzi.DaylightDate.wHour = pMsg->u.SetTimeZone.TimeZone.DaylightDate.wHour;
  1318. tzi.DaylightDate.wMinute = pMsg->u.SetTimeZone.TimeZone.DaylightDate.wMinute;
  1319. tzi.DaylightDate.wSecond = pMsg->u.SetTimeZone.TimeZone.DaylightDate.wSecond;
  1320. tzi.DaylightDate.wMilliseconds = pMsg->u.SetTimeZone.TimeZone.DaylightDate.wMilliseconds;
  1321. //call to kernel32
  1322. SetClientTimeZoneInformation(&tzi);
  1323. return STATUS_SUCCESS;
  1324. }
  1325. //
  1326. // Create \\Globals\TermSrvReady event with security descriptor, where only system can
  1327. // set/reset it's state and others can wait on it. Create this event only in session 0.
  1328. //
  1329. HANDLE CreateTermSrvReadyEvent()
  1330. {
  1331. NTSTATUS Status;
  1332. SID_IDENTIFIER_AUTHORITY SystemAuth = SECURITY_NT_AUTHORITY;
  1333. SID_IDENTIFIER_AUTHORITY WorldAuth = SECURITY_WORLD_SID_AUTHORITY;
  1334. SECURITY_ATTRIBUTES SecurityAttributes;
  1335. PSID pSystemSid = NULL;
  1336. PSID pWorldSid = NULL;
  1337. PSECURITY_DESCRIPTOR pSd = NULL;
  1338. PACL pEventDacl;
  1339. HANDLE hTermSrvReady = NULL;
  1340. ULONG AclLength;
  1341. // Allocate and Initialize the "System" Sid.
  1342. Status = RtlAllocateAndInitializeSid( &SystemAuth,
  1343. 1,
  1344. SECURITY_LOCAL_SYSTEM_RID,
  1345. 0, 0, 0, 0, 0, 0, 0,
  1346. &pSystemSid );
  1347. if (!NT_SUCCESS(Status)) {
  1348. goto TermSrvReadyErr;
  1349. }
  1350. // Allocate and Initialize the "World" Sid.
  1351. Status = RtlAllocateAndInitializeSid( &WorldAuth,
  1352. 1,
  1353. SECURITY_WORLD_RID,
  1354. 0, 0, 0, 0, 0, 0, 0,
  1355. &pWorldSid );
  1356. if (!NT_SUCCESS(Status)) {
  1357. goto TermSrvReadyErr;
  1358. }
  1359. // Allocate space for the security descriptor.
  1360. AclLength = (ULONG)sizeof(ACL) +
  1361. (2*((ULONG)sizeof(ACCESS_ALLOWED_ACE))) +
  1362. RtlLengthSid( pSystemSid ) +
  1363. RtlLengthSid( pWorldSid ) +
  1364. 8;
  1365. pSd = (PSECURITY_DESCRIPTOR) LocalAlloc(0, SECURITY_DESCRIPTOR_MIN_LENGTH + AclLength);
  1366. if (pSd == NULL) {
  1367. goto TermSrvReadyErr;
  1368. }
  1369. pEventDacl = (PACL) ((BYTE*)(pSd) + SECURITY_DESCRIPTOR_MIN_LENGTH);
  1370. // Set up a new ACL with no ACE.
  1371. Status = RtlCreateAcl(pEventDacl, AclLength, ACL_REVISION2);
  1372. if (!NT_SUCCESS(Status)) {
  1373. goto TermSrvReadyErr;
  1374. }
  1375. // WORLD access
  1376. Status = RtlAddAccessAllowedAce( pEventDacl,
  1377. ACL_REVISION2,
  1378. SYNCHRONIZE,
  1379. pWorldSid
  1380. );
  1381. if (!NT_SUCCESS(Status)) {
  1382. goto TermSrvReadyErr;
  1383. }
  1384. // SYSTEM access
  1385. Status = RtlAddAccessAllowedAce( pEventDacl,
  1386. ACL_REVISION2,
  1387. EVENT_MODIFY_STATE,
  1388. pSystemSid
  1389. );
  1390. if (!NT_SUCCESS(Status)) {
  1391. goto TermSrvReadyErr;
  1392. }
  1393. // Now initialize security descriptors that export this protection
  1394. Status = RtlCreateSecurityDescriptor(pSd, SECURITY_DESCRIPTOR_REVISION1);
  1395. if (!NT_SUCCESS(Status)) {
  1396. goto TermSrvReadyErr;
  1397. }
  1398. Status = RtlSetDaclSecurityDescriptor(pSd, TRUE, pEventDacl, FALSE);
  1399. if (!NT_SUCCESS(Status)) {
  1400. goto TermSrvReadyErr;
  1401. }
  1402. // Fill the Security Attributes
  1403. ZeroMemory(&SecurityAttributes, sizeof(SecurityAttributes));
  1404. SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  1405. SecurityAttributes.lpSecurityDescriptor = pSd;
  1406. SecurityAttributes.bInheritHandle = FALSE;
  1407. // Now create TermSrvReady event with this security attributes.
  1408. hTermSrvReady = CreateEventW(&SecurityAttributes, TRUE, FALSE, L"Global\\TermSrvReadyEvent");
  1409. if (hTermSrvReady == NULL) {
  1410. goto TermSrvReadyErr;
  1411. }
  1412. // Check if someone bad has already created this event for ill-purpose.
  1413. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  1414. NtClose(hTermSrvReady);
  1415. hTermSrvReady = NULL;
  1416. }
  1417. TermSrvReadyErr:
  1418. if (pSystemSid) {
  1419. RtlFreeSid(pSystemSid);
  1420. }
  1421. if (pWorldSid) {
  1422. RtlFreeSid(pWorldSid);
  1423. }
  1424. if (pSd) {
  1425. LocalFree(pSd);
  1426. }
  1427. return hTermSrvReady;
  1428. }