Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

api.c

Go to the documentation of this file.
00001 00002 /************************************************************************* 00003 * 00004 * api.c 00005 * 00006 * WinStation Control API's for WIN32 subsystem. 00007 * 00008 * Copyright (c) 1985 - 1999, Microsoft Corporation 00009 * 00010 *************************************************************************/ 00011 00012 /* 00013 * Includes 00014 */ 00015 #include "precomp.h" 00016 #pragma hdrstop 00017 00018 #include "ntuser.h" 00019 00020 #include <winsta.h> 00021 #include <wstmsg.h> 00022 00023 #define SESSION_ROOT L"\\Sessions" 00024 #define MAX_SESSION_PATH 256 00025 00026 extern NTSTATUS CsrPopulateDosDevices(void); 00027 00028 NTSTATUS 00029 CleanupSessionObjectDirectories(void); 00030 00031 HANDLE CsrQueryApiPort(void); 00032 extern BOOL CtxInitUser32(VOID); 00033 00034 extern DrChangeDisplaySettings(WINSTATIONDORECONNECTMSG*); 00035 00036 USHORT gHRes = 0; 00037 USHORT gVRes = 0; 00038 USHORT gColorDepth = 0; 00039 00040 HANDLE ghportLPC = NULL; 00041 00042 BOOLEAN gbExitInProgress = FALSE; 00043 00044 #if DBG 00045 ULONG gulConnectCount = 0; 00046 #endif // DBG 00047 00048 /* 00049 * The following are gotten from ICASRV. 00050 * 00051 */ 00052 00053 HANDLE G_IcaVideoChannel = NULL; 00054 HANDLE G_IcaMouseChannel = NULL; 00055 HANDLE G_IcaKeyboardChannel = NULL; 00056 HANDLE G_IcaBeepChannel = NULL; 00057 HANDLE G_IcaCommandChannel = NULL; 00058 HANDLE G_IcaThinwireChannel = NULL; 00059 WCHAR G_WinStationName[WINSTATIONNAME_LENGTH]; 00060 00061 00062 /* 00063 * Definition for the WinStation control API's dispatch table 00064 */ 00065 typedef NTSTATUS (*PWIN32WINSTATION_API)(IN OUT PWINSTATION_APIMSG ApiMsg); 00066 00067 typedef struct _WIN32WINSTATION_DISPATCH { 00068 PWIN32WINSTATION_API pWin32ApiProc; 00069 } WIN32WINSTATION_DISPATCH, *PWIN32WINSTATION_DISPATCH; 00070 00071 NTSTATUS W32WinStationDoConnect( IN OUT PWINSTATION_APIMSG ); 00072 00073 NTSTATUS W32WinStationDoDisconnect( IN OUT PWINSTATION_APIMSG ); 00074 00075 NTSTATUS W32WinStationDoReconnect( IN OUT PWINSTATION_APIMSG ); 00076 00077 NTSTATUS W32WinStationExitWindows( IN OUT PWINSTATION_APIMSG ); 00078 00079 NTSTATUS W32WinStationTerminate( IN OUT PWINSTATION_APIMSG ); 00080 00081 NTSTATUS W32WinStationNtSecurity( IN OUT PWINSTATION_APIMSG ); 00082 00083 NTSTATUS W32WinStationDoMessage( IN OUT PWINSTATION_APIMSG ); 00084 00085 NTSTATUS W32WinStationThinwireStats( IN OUT PWINSTATION_APIMSG ); 00086 00087 NTSTATUS W32WinStationShadowSetup( IN OUT PWINSTATION_APIMSG ); 00088 00089 NTSTATUS W32WinStationShadowStart( IN OUT PWINSTATION_APIMSG ); 00090 00091 NTSTATUS W32WinStationShadowStop( IN OUT PWINSTATION_APIMSG ); 00092 00093 NTSTATUS W32WinStationShadowCleanup( IN OUT PWINSTATION_APIMSG ); 00094 00095 NTSTATUS W32WinStationPassthruEnable( IN OUT PWINSTATION_APIMSG ); 00096 00097 NTSTATUS W32WinStationPassthruDisable( IN OUT PWINSTATION_APIMSG ); 00098 00099 // This is the counter part to SMWinStationBroadcastSystemMessage 00100 NTSTATUS W32WinStationBroadcastSystemMessage( IN OUT PWINSTATION_APIMSG ); 00101 // This is the counter part to SMWinStationSendWindowMessage 00102 NTSTATUS W32WinStationSendWindowMessage( IN OUT PWINSTATION_APIMSG ); 00103 00104 /* 00105 * WinStation API Dispatch Table 00106 * 00107 * Only the API's that WIN32 implements as opposed to ICASRV 00108 * are entered here. The rest are NULL so that the same WinStation API 00109 * numbers may be used by ICASRV and WIN32. If this table is 00110 * changed, the table below must be modified too, as well as the API 00111 * dispatch table in the ICASRV. 00112 */ 00113 00114 /* 00115 * If you ever change the index of the function pointers in this array 00116 * make sure API_W32WINSTATIONTERMINATE has the right index 00117 * for W32WinStationTerminate 00118 */ 00119 00120 #define API_W32WINSTATIONTERMINATE 12 // includes -- W32WinStationSendWindowMessage 00121 00122 WIN32WINSTATION_DISPATCH Win32WinStationDispatch[SMWinStationMaxApiNumber] = { 00123 NULL, // create 00124 NULL, // reset 00125 NULL, // disconnect 00126 NULL, // WCharLog 00127 NULL, // ApiWinStationGetSMCommand, 00128 NULL, // ApiWinStationBrokenConnection, 00129 NULL, // ApiWinStationIcaReplyMessage, 00130 NULL, // ApiWinStationIcaShadowHotkey, 00131 W32WinStationDoConnect, 00132 W32WinStationDoDisconnect, 00133 W32WinStationDoReconnect, 00134 W32WinStationExitWindows, 00135 W32WinStationTerminate, 00136 W32WinStationNtSecurity, 00137 W32WinStationDoMessage, 00138 NULL, 00139 W32WinStationThinwireStats, 00140 W32WinStationShadowSetup, 00141 W32WinStationShadowStart, 00142 W32WinStationShadowStop, 00143 W32WinStationShadowCleanup, 00144 W32WinStationPassthruEnable, 00145 W32WinStationPassthruDisable, 00146 NULL, // [AraBern] this was missing: SMWinStationInitialProgram 00147 NULL, // [AraBern] this was missing: SMWinStationNtsdDebug 00148 W32WinStationBroadcastSystemMessage, 00149 W32WinStationSendWindowMessage, 00150 }; 00151 00152 #if DBG 00153 PSZ Win32WinStationAPIName[SMWinStationMaxApiNumber] = { 00154 "SmWinStationCreate", 00155 "SmWinStationReset", 00156 "SmWinStationDisconnect", 00157 "SmWinStationWCharLog", 00158 "SmWinStationGetSMCommand", 00159 "SmWinStationBrokenConnection", 00160 "SmWinStationIcaReplyMessage", 00161 "SmWinStationIcaShadowHotkey", 00162 "SmWinStationDoConnect", 00163 "SmWinStationDoDisconnect", 00164 "SmWinStationDoReconnect", 00165 "SmWinStationExitWindows", 00166 "SmWinStationTerminate", 00167 "SmWinStationNtSecurity", 00168 "SmWinStationDoMessage", 00169 "SmWinstationDoBreakPoint", 00170 "SmWinStationThinwireStats", 00171 "SmWinStationShadowSetup", 00172 "SmWinStationShadowStart", 00173 "SmWinStationShadowStop", 00174 "SmWinStationShadowCleanup", 00175 "SmWinStationPassthruEnable", 00176 "SmWinStationPassthruDisable", 00177 "SMWinStationInitialProgram", 00178 "SMWinStationNtsdDebug", 00179 "W32WinStationBroadcastSystemMessage", 00180 "W32WinStationSendWindowMessage", 00181 }; 00182 #endif 00183 00184 NTSTATUS TerminalServerRequestThread( PVOID ); 00185 00186 extern NTSTATUS Win32CommandChannelThread( PVOID ); 00187 extern NTSTATUS RemoteDoMessage( PWINSTATION_APIMSG pMsg ); 00188 extern NTSTATUS MultiUserSpoolerInit(); 00189 //extern BOOL CtxGetCrossWinStationDebug( VOID ); 00190 00191 extern HANDLE g_hDoMessageEvent; 00192 00193 extern NTSTATUS RemoteDoBroadcastSystemMessage( PWINSTATION_APIMSG pMsg ); 00194 extern NTSTATUS RemoteDoSendWindowMessage( PWINSTATION_APIMSG pMsg); 00195 00196 00197 /***************************************************************************** 00198 * 00199 * WinStationAPIInit 00200 * 00201 * Creates and initializes the WinStation API port and thread. 00202 * 00203 * ENTRY: 00204 * No Parameters 00205 * 00206 * EXIT: 00207 * STATUS_SUCCESS - no error 00208 * 00209 ****************************************************************************/ 00210 00211 NTSTATUS 00212 WinStationAPIInit( 00213 VOID) 00214 { 00215 NTSTATUS Status; 00216 CLIENT_ID ClientId; 00217 HANDLE ThreadHandle; 00218 KPRIORITY Priority; 00219 00220 #if DBG 00221 static BOOL Inited = FALSE; 00222 #endif 00223 00224 UserAssert(Inited == FALSE); 00225 00226 gSessionId = NtCurrentPeb()->SessionId; 00227 00228 #if DBG 00229 if (Inited) 00230 DBGHYD(("WinStationAPIInit called twice !!!\n")); 00231 00232 Inited = TRUE; 00233 #endif 00234 00235 Status = RtlCreateUserThread(NtCurrentProcess(), 00236 NULL, 00237 TRUE, 00238 0L, 00239 0L, 00240 0L, 00241 TerminalServerRequestThread, 00242 NULL, 00243 &ThreadHandle, 00244 &ClientId); 00245 00246 if (!NT_SUCCESS(Status)) { 00247 DBGHYD(("WinStationAPIInit: failed to create TerminalServerRequestThread\n")); 00248 goto Exit; 00249 } 00250 /* 00251 * Add thread to server thread pool 00252 */ 00253 CsrAddStaticServerThread(ThreadHandle, &ClientId, 0); 00254 00255 /* 00256 * Boost priority of ICA SRV Request thread 00257 */ 00258 Priority = THREAD_BASE_PRIORITY_MAX; 00259 00260 Status = NtSetInformationThread(ThreadHandle, ThreadBasePriority, 00261 &Priority, sizeof(Priority)); 00262 00263 if (!NT_SUCCESS(Status)) { 00264 DBGHYD(("WinStationAPIInit: failed to set thread priority\n")); 00265 goto Exit; 00266 } 00267 00268 /* 00269 * Resume the thread now that we've initialized things. 00270 */ 00271 NtResumeThread(ThreadHandle, NULL); 00272 00273 00274 Exit: 00275 return Status; 00276 } 00277 00278 NTSTATUS 00279 TerminalServerRequestThread( 00280 IN PVOID ThreadParameter) 00281 { 00282 PTEB Teb; 00283 UNICODE_STRING PortName; 00284 SECURITY_QUALITY_OF_SERVICE DynamicQos; 00285 WINSTATIONAPI_CONNECT_INFO info; 00286 ULONG ConnectInfoLength; 00287 WINSTATION_APIMSG ApiMsg; 00288 PWIN32WINSTATION_DISPATCH pDispatch; 00289 NTSTATUS Status; 00290 REMOTE_PORT_VIEW ServerView; 00291 HANDLE CsrStartHandle, hevtTermSrvInit; 00292 00293 /* 00294 * Initialize GDI accelerators. Identify this thread as a server thread. 00295 */ 00296 Teb = NtCurrentTeb(); 00297 Teb->GdiClientPID = 4; // PID_SERVERLPC 00298 Teb->GdiClientTID = HandleToUlong(Teb->ClientId.UniqueThread); 00299 00300 /* 00301 * Connect to user 00302 */ 00303 00304 hevtTermSrvInit = CreateEvent(NULL, TRUE, FALSE, 00305 L"Global\\TermSrvReadyEvent"); 00306 00307 UserAssert(hevtTermSrvInit != NULL); 00308 #if DBG 00309 if (hevtTermSrvInit == NULL) { 00310 DBGHYD(("ERROR: could not create TermSrvReadyEvent !!!\n")); 00311 } 00312 #endif 00313 00314 Status = NtWaitForSingleObject(hevtTermSrvInit, FALSE, NULL); 00315 00316 NtClose(hevtTermSrvInit); 00317 00318 /* 00319 * Connect to terminal server API port 00320 */ 00321 DynamicQos.ImpersonationLevel = SecurityImpersonation; 00322 DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; 00323 DynamicQos.EffectiveOnly = TRUE; 00324 00325 RtlInitUnicodeString(&PortName, L"\\SmSsWinStationApiPort"); 00326 00327 /* 00328 * Init the REMOTE_VIEW structure 00329 */ 00330 ServerView.Length = sizeof(ServerView); 00331 ServerView.ViewSize = 0; 00332 ServerView.ViewBase = 0; 00333 00334 /* 00335 * Fill in the ConnectInfo structure with our access request mask 00336 */ 00337 info.Version = CITRIX_WINSTATIONAPI_VERSION; 00338 info.RequestedAccess = 0; // BUGBUG should ask for ALL access 00339 ConnectInfoLength = sizeof(WINSTATIONAPI_CONNECT_INFO); 00340 00341 Status = NtConnectPort( &ghportLPC, 00342 &PortName, 00343 &DynamicQos, 00344 NULL, // ClientView 00345 &ServerView, 00346 NULL, // Max message length [select default] 00347 (PVOID)&info, 00348 &ConnectInfoLength); 00349 00350 if (!NT_SUCCESS(Status)) { 00351 RIPMSG0(RIP_WARNING, "TerminalServerRequestThread: Failed to connect to LPC port"); 00352 return Status; 00353 } 00354 00355 RtlZeroMemory(&ApiMsg, sizeof(ApiMsg)); 00356 00357 // 00358 // Terminal Server calls into Session Manager to create a new Hydra session. 00359 // The session manager creates and resume a new session and returns to Terminal 00360 // server the session id of the new session. There is a race condition where 00361 // CSR can resume and call into terminal server before terminal server can 00362 // store the session id in its internal structure. To prevent this CSR will 00363 // wait here on a named event which will be set by Terminal server once it 00364 // gets the sessionid for the newly created session 00365 // 00366 00367 if (NtCurrentPeb()->SessionId != 0) { 00368 00369 CsrStartHandle = CreateEvent(NULL, TRUE, FALSE, L"CsrStartEvent"); 00370 00371 if (!CsrStartHandle) { 00372 00373 RIPMSG1(RIP_WARNING, "TerminalServerRequestThread: Failed to create 'CsrStartEvent' with Status 0x%x", 00374 Status); 00375 00376 return Status; 00377 00378 } else { 00379 00380 Status = NtWaitForSingleObject(CsrStartHandle, FALSE, NULL); 00381 00382 NtClose(CsrStartHandle); 00383 if (!NT_SUCCESS(Status)) { 00384 DBGHYD(("TerminalServerRequestThread: Wait for object 'CsrStartEvent' failed Status=0x%x\n", 00385 Status)); 00386 } 00387 } 00388 } 00389 00390 for (;;) { 00391 00392 /* 00393 * Initialize LPC message fields 00394 */ 00395 ApiMsg.h.u1.s1.DataLength = sizeof(ApiMsg) - sizeof(PORT_MESSAGE); 00396 ApiMsg.h.u1.s1.TotalLength = sizeof(ApiMsg); 00397 ApiMsg.h.u2.s2.Type = 0; // Kernel will fill in message type 00398 ApiMsg.h.u2.s2.DataInfoOffset = 0; 00399 ApiMsg.ApiNumber = SMWinStationGetSMCommand; 00400 00401 Status = NtRequestWaitReplyPort(ghportLPC, 00402 (PPORT_MESSAGE)&ApiMsg, 00403 (PPORT_MESSAGE)&ApiMsg); 00404 00405 if (!NT_SUCCESS(Status)) { 00406 DBGHYD(("TerminalServerRequestThread wait failed with Status %lx\n", 00407 Status)); 00408 break; 00409 } 00410 00411 if (ApiMsg.ApiNumber >= SMWinStationMaxApiNumber ) { 00412 00413 DBGHYD(("TerminalServerRequestThread Bad API number %d\n", 00414 ApiMsg.ApiNumber)); 00415 00416 ApiMsg.ReturnedStatus = STATUS_NOT_IMPLEMENTED; 00417 00418 } else { 00419 00420 /* 00421 * We must VALIDATE which ones are implemented here 00422 */ 00423 pDispatch = &Win32WinStationDispatch[ApiMsg.ApiNumber]; 00424 00425 if (pDispatch->pWin32ApiProc) { 00426 00427 BOOL bRestoreDesktop = FALSE; 00428 NTSTATUS Status; 00429 USERTHREAD_USEDESKTOPINFO utudi; 00430 00431 /* 00432 * For all the win32k callouts with the exception of 00433 * terminate set this thread to the current desktop 00434 */ 00435 if (ApiMsg.ApiNumber != API_W32WINSTATIONTERMINATE) { 00436 utudi.hThread = NULL; 00437 utudi.drdRestore.pdeskRestore = NULL; 00438 Status = NtUserSetInformationThread(NtCurrentThread(), 00439 UserThreadUseActiveDesktop, 00440 &utudi, sizeof(utudi)); 00441 00442 if (NT_SUCCESS(Status)) { 00443 bRestoreDesktop = TRUE; 00444 } 00445 } 00446 00447 /* 00448 * Call the API 00449 */ 00450 ApiMsg.ReturnedStatus = (pDispatch->pWin32ApiProc)(&ApiMsg); 00451 00452 if (bRestoreDesktop) { 00453 NtUserSetInformationThread(NtCurrentThread(), 00454 UserThreadUseDesktop, 00455 &utudi, 00456 sizeof(utudi)); 00457 } 00458 00459 } else { 00460 // This control API is not implemented in WIN32 00461 ApiMsg.ReturnedStatus = STATUS_NOT_IMPLEMENTED; 00462 } 00463 } 00464 } 00465 00466 ExitThread(0); 00467 00468 return STATUS_UNSUCCESSFUL; 00469 00470 UNREFERENCED_PARAMETER(ThreadParameter); 00471 } 00472 00473 #if DBG 00474 VOID 00475 W32WinStationDumpReconnectInfo( 00476 WINSTATIONDORECONNECTMSG *pDoReconnect, 00477 BOOLEAN bReconnect) 00478 { 00479 PSTR pCallerName; 00480 00481 if (bReconnect) { 00482 pCallerName = "W32WinStationDoReconnect"; 00483 } else { 00484 pCallerName = "W32WinStationDoConnect"; 00485 } 00486 00487 DbgPrint(pCallerName); 00488 DbgPrint(" - Display resolution information for session %d :\n", gSessionId); 00489 00490 DbgPrint("\tProtocolType : %04d\n", pDoReconnect->ProtocolType); 00491 DbgPrint("\tHRes : %04d\n", pDoReconnect->HRes); 00492 DbgPrint("\tVRes : %04d\n", pDoReconnect->VRes); 00493 DbgPrint("\tColorDepth : %04d\n", pDoReconnect->ColorDepth); 00494 00495 DbgPrint("\tKeyboardType : %d\n", pDoReconnect->KeyboardType); 00496 DbgPrint("\tKeyboardSubType : %d\n", pDoReconnect->KeyboardSubType); 00497 DbgPrint("\tKeyboardFunctionKey : %d\n", pDoReconnect->KeyboardFunctionKey); 00498 } 00499 #else 00500 #define W32WinStationDumpReconnectInfo(p, b) 00501 #endif // DBG 00502 00503 NTSTATUS 00504 W32WinStationDoConnect( 00505 PWINSTATION_APIMSG pMsg) 00506 { 00507 NTSTATUS Status = STATUS_SUCCESS; 00508 WINSTATIONDOCONNECTMSG* m = &pMsg->u.DoConnect; 00509 WCHAR DisplayDriverName[10]; 00510 CLIENT_ID ClientId; 00511 HANDLE ThreadHandle; 00512 KPRIORITY Priority; 00513 DOCONNECTDATA DoConnectData; 00514 WINSTATIONDORECONNECTMSG mDoReconnect; 00515 00516 UserAssert(gulConnectCount == 0); 00517 00518 /* 00519 * Populate the sessions \DosDevices from 00520 * the current consoles settings 00521 */ 00522 Status = CsrPopulateDosDevices(); 00523 if( !NT_SUCCESS(Status) ) { 00524 DBGHYD(("CsrPopulateDosDevices failed with Status %lx\n", Status)); 00525 goto Exit; 00526 } 00527 00528 00529 G_IcaVideoChannel = m->hIcaVideoChannel; 00530 G_IcaMouseChannel = m->hIcaMouseChannel; 00531 G_IcaKeyboardChannel = m->hIcaKeyboardChannel; 00532 G_IcaBeepChannel = m->hIcaBeepChannel; 00533 G_IcaCommandChannel = m->hIcaCommandChannel; 00534 G_IcaThinwireChannel = m->hIcaThinwireChannel; 00535 00536 memset(G_WinStationName, 0, sizeof(G_WinStationName)); 00537 memcpy(G_WinStationName, m->WinStationName, 00538 min(sizeof(G_WinStationName), sizeof(m->WinStationName))); 00539 00540 /* 00541 * This must be 8 unicode characters (file name) plus two zero wide characters. 00542 */ 00543 memset(DisplayDriverName, 0, sizeof(DisplayDriverName)); 00544 memcpy(DisplayDriverName, m->DisplayDriverName, sizeof(DisplayDriverName) - 2); 00545 00546 /* 00547 * Give the information to the WIN32 driver. 00548 */ 00549 memset(&DoConnectData, 0, sizeof(DoConnectData)); 00550 00551 DoConnectData.fMouse = m->fMouse; 00552 DoConnectData.IcaBeepChannel = G_IcaBeepChannel; 00553 DoConnectData.IcaVideoChannel = G_IcaVideoChannel; 00554 DoConnectData.IcaMouseChannel = G_IcaMouseChannel; 00555 DoConnectData.fEnableWindowsKey = m->fEnableWindowsKey;; 00556 00557 DoConnectData.IcaKeyboardChannel = G_IcaKeyboardChannel; 00558 DoConnectData.IcaThinwireChannel = G_IcaThinwireChannel; 00559 DoConnectData.fClientDoubleClickSupport = m->fClientDoubleClickSupport; 00560 00561 /* 00562 * Give the information to the keyboard type/subtype/number of functions. 00563 */ 00564 DoConnectData.ClientKeyboardType.Type = m->KeyboardType; 00565 DoConnectData.ClientKeyboardType.SubType = m->KeyboardSubType; 00566 DoConnectData.ClientKeyboardType.FunctionKey = m->KeyboardFunctionKey; 00567 00568 memcpy(DoConnectData.WinStationName, G_WinStationName, 00569 min(sizeof(G_WinStationName), sizeof(DoConnectData.WinStationName))); 00570 00571 DoConnectData.drProtocolType = m->ProtocolType; 00572 DoConnectData.drPelsHeight = m->VRes; 00573 DoConnectData.drPelsWidth = m->HRes; 00574 DoConnectData.drBitsPerPel = m->ColorDepth; 00575 //BUGBUG DoConnectData.drDisplayFrequency is no yet setup 00576 00577 // We set here the WINSTATIONDORECONNECTMSG that we will be using latter 00578 // In the call to DrChangeDisplaySettings(), because we want to trace the display 00579 // resolution information, prior to call NtUserRemoteConnect(). 00580 00581 mDoReconnect.ProtocolType = m->ProtocolType; 00582 mDoReconnect.HRes = m->HRes; 00583 mDoReconnect.VRes = m->VRes; 00584 mDoReconnect.ColorDepth = m->ColorDepth; 00585 00586 W32WinStationDumpReconnectInfo(&mDoReconnect, FALSE); 00587 00588 /* Give winstation protocol name */ 00589 memset(DoConnectData.ProtocolName, 0, sizeof(DoConnectData.ProtocolName)); 00590 memcpy(DoConnectData.ProtocolName, m->ProtocolName, sizeof(DoConnectData.ProtocolName) - 2); 00591 00592 /* Give winstation audio drver name */ 00593 memset(DoConnectData.AudioDriverName, 0, sizeof(DoConnectData.AudioDriverName)); 00594 memcpy(DoConnectData.AudioDriverName, m->AudioDriverName, sizeof(DoConnectData.AudioDriverName) - 2); 00595 00596 Status = NtUserRemoteConnect(&DoConnectData, 00597 sizeof(DisplayDriverName), 00598 DisplayDriverName); 00599 00600 if (!NT_SUCCESS(Status)) { 00601 DBGHYD(("NtUserRemoteConnect failed with Status %lx\n", Status)); 00602 goto Exit; 00603 } 00604 00605 Status = RtlCreateUserThread( NtCurrentProcess(), 00606 NULL, 00607 TRUE, 00608 0L, 00609 0L, 00610 0L, 00611 Win32CommandChannelThread, 00612 NULL, 00613 &ThreadHandle, 00614 &ClientId ); 00615 00616 UserAssert(NT_SUCCESS(Status)); 00617 00618 if (!NT_SUCCESS(Status)) { 00619 DBGHYD(("RtlCreateUserThread failed with Status %lx\n", Status)); 00620 goto Exit; 00621 } 00622 00623 /* 00624 * Add thread to server thread pool 00625 */ 00626 if (CsrAddStaticServerThread(ThreadHandle, &ClientId, 0) == NULL) { 00627 DBGHYD(("CsrAddStaticServerThread failed\n")); 00628 goto Exit; 00629 } 00630 00631 /* 00632 * Boost priority of thread 00633 */ 00634 Priority = THREAD_BASE_PRIORITY_MAX; 00635 00636 Status = NtSetInformationThread(ThreadHandle, ThreadBasePriority, 00637 &Priority, sizeof(Priority)); 00638 00639 UserAssert(NT_SUCCESS(Status)); 00640 00641 if (!NT_SUCCESS(Status)) { 00642 DBGHYD(("NtSetInformationThread failed with Status %lx\n", Status)); 00643 Status = STATUS_NO_MEMORY; 00644 goto Exit; 00645 } 00646 00647 /* 00648 * Resume the thread now that we've initialized things. 00649 */ 00650 NtResumeThread(ThreadHandle, NULL); 00651 00652 if (CsrConnectToUser() == NULL) { 00653 DBGHYD(("CsrConnectToUser failed\n")); 00654 Status = STATUS_NO_MEMORY; 00655 goto Exit; 00656 } 00657 00658 if (!CtxInitUser32()) { 00659 DBGHYD(("CtxInitUser32 failed\n")); 00660 Status = STATUS_NO_MEMORY; 00661 goto Exit; 00662 } 00663 00664 /* 00665 * Create the Spooler service thread 00666 */ 00667 if (gSessionId != 0) { 00668 Status = MultiUserSpoolerInit(); 00669 } 00670 00671 /* 00672 * Save the resolution 00673 */ 00674 gHRes = mDoReconnect.HRes; 00675 gVRes = mDoReconnect.VRes; 00676 gColorDepth = mDoReconnect.ColorDepth; 00677 00678 00679 Exit: 00680 00681 #if DBG 00682 if (NT_SUCCESS(Status)) { 00683 gulConnectCount++; 00684 } 00685 #endif // DBG 00686 00687 return Status; 00688 } 00689 00690 00691 NTSTATUS 00692 W32WinStationDoDisconnect( 00693 PWINSTATION_APIMSG pMsg) 00694 { 00695 NTSTATUS Status = STATUS_SUCCESS; 00696 00697 memset(G_WinStationName, 0, sizeof(G_WinStationName)); 00698 00699 Status = (NTSTATUS)NtUserCallNoParam(SFI_XXXREMOTEDISCONNECT); 00700 00701 if (!NT_SUCCESS(Status)) { 00702 DBGHYD(("xxxRemoteDisconnect failed with Status %lx\n", Status)); 00703 } 00704 00705 #if DBG 00706 else { 00707 gulConnectCount--; 00708 } 00709 #endif // DBG 00710 00711 return Status; 00712 00713 UNREFERENCED_PARAMETER(pMsg); 00714 } 00715 00716 00717 NTSTATUS 00718 W32WinStationDoReconnect( 00719 PWINSTATION_APIMSG pMsg) 00720 { 00721 NTSTATUS Status = STATUS_SUCCESS; 00722 DORECONNECTDATA DoReconnectData; 00723 WINSTATIONDORECONNECTMSG* m = &pMsg->u.DoReconnect; 00724 00725 UserAssert(gulConnectCount == 0); 00726 00727 00728 memset(&DoReconnectData, 0, sizeof(DoReconnectData)); 00729 00730 DoReconnectData.fMouse = m->fMouse; 00731 DoReconnectData.fEnableWindowsKey = m->fEnableWindowsKey; 00732 DoReconnectData.fClientDoubleClickSupport = m->fClientDoubleClickSupport; 00733 00734 memcpy(G_WinStationName, m->WinStationName, 00735 min(sizeof(G_WinStationName), sizeof(m->WinStationName))); 00736 00737 memcpy(DoReconnectData.WinStationName, G_WinStationName, 00738 min(sizeof(G_WinStationName), sizeof(DoReconnectData.WinStationName))); 00739 00740 DoReconnectData.drProtocolType = m->ProtocolType; 00741 DoReconnectData.drPelsHeight = m->VRes; 00742 DoReconnectData.drPelsWidth = m->HRes; 00743 DoReconnectData.drBitsPerPel = m->ColorDepth; 00744 if ((m->fDynamicReconnect) && (gHRes != m->HRes || gVRes != m->VRes || gColorDepth != m->ColorDepth ) ) { 00745 DoReconnectData.fChangeDisplaySettings = TRUE; 00746 }else{ 00747 DoReconnectData.fChangeDisplaySettings = FALSE; 00748 } 00749 //BUGBUG DoReconnectData.drDisplayFrequency is no yet setup 00750 DoReconnectData.drDisplayFrequency = 0; 00751 00752 /* 00753 * Give the information to the keyboard type/subtype/number of functions. 00754 */ 00755 DoReconnectData.ClientKeyboardType.Type = m->KeyboardType; 00756 DoReconnectData.ClientKeyboardType.SubType = m->KeyboardSubType; 00757 DoReconnectData.ClientKeyboardType.FunctionKey = m->KeyboardFunctionKey; 00758 00759 W32WinStationDumpReconnectInfo( m, TRUE); 00760 00761 /* 00762 * Give the information to the WIN32 driver. 00763 */ 00764 00765 Status = (NTSTATUS)NtUserCallOneParam((ULONG_PTR)&DoReconnectData, 00766 SFI_XXXREMOTERECONNECT); 00767 00768 if (!NT_SUCCESS(Status)) { 00769 DBGHYD(("xxxRemoteReconnect failed with Status %lx\n", Status)); 00770 }else{ 00771 00772 /* 00773 * Save the resolution 00774 */ 00775 gHRes = m->HRes; 00776 gVRes = m->VRes; 00777 gColorDepth = m->ColorDepth; 00778 00779 #if DBG 00780 gulConnectCount++; 00781 #endif // DBG 00782 } 00783 00784 00785 return Status; 00786 } 00787 00788 00789 NTSTATUS 00790 W32WinStationExitWindows( 00791 PWINSTATION_APIMSG pMsg) 00792 { 00793 NTSTATUS Status = STATUS_SUCCESS; 00794 WINSTATIONEXITWINDOWSMSG* m = &pMsg->u.ExitWindows; 00795 00796 if (gSessionId == 0) { 00797 //BUGBUG v-nicbd: I am just wondering why it would be meaningless for the console. (?) 00798 DBGHYD(("W32WinStationExitWindows meaningless for main session\n")); 00799 return STATUS_INVALID_PARAMETER; 00800 } 00801 00802 UserAssert(gulConnectCount <= 1); 00803 00804 /* 00805 * Tell winlogon to logoff 00806 */ 00807 Status = (NTSTATUS)NtUserCallNoParam(SFI_REMOTELOGOFF); 00808 00809 if (!NT_SUCCESS(Status)) { 00810 DBGHYD(("RemoteLogoff failed with Status %lx\n", Status)); 00811 } 00812 00813 return Status; 00814 } 00815 00816 00817 NTSTATUS 00818 W32WinStationTerminate( 00819 PWINSTATION_APIMSG pMsg) 00820 { 00821 NTSTATUS Status = STATUS_SUCCESS; 00822 HANDLE hevtShutDown; 00823 HANDLE hevtRitExited, hevtRitStuck; 00824 00825 extern HANDLE WinStationIcaApiPort; 00826 00827 gbExitInProgress = TRUE; 00828 00829 /* 00830 * Get rid of hard error thread 00831 */ 00832 00833 00834 if (gdwHardErrorThreadId != 0) { 00835 00836 BoostHardError(-1, BHE_FORCE); 00837 00838 /* 00839 * Poll (!!?) for hard error thread completion. The thread does 00840 * not exit. 00841 */ 00842 while (gdwHardErrorThreadId != 0) { 00843 DBGHYD(("Waiting for hard error thread to stop...\n")); 00844 00845 Sleep(3 * 1000); 00846 } 00847 00848 DBGHYD(("Stopped hard error thread\n")); 00849 } 00850 00851 if (g_hDoMessageEvent) 00852 NtSetEvent(g_hDoMessageEvent, NULL); 00853 00854 if (G_IcaMouseChannel) { 00855 CloseHandle(G_IcaMouseChannel); 00856 G_IcaMouseChannel = NULL; 00857 } 00858 00859 if (G_IcaKeyboardChannel) { 00860 CloseHandle(G_IcaKeyboardChannel); 00861 G_IcaKeyboardChannel = NULL; 00862 } 00863 00864 if (G_IcaCommandChannel) { 00865 CloseHandle(G_IcaCommandChannel); 00866 G_IcaCommandChannel = NULL; 00867 } 00868 00869 if (G_IcaVideoChannel) { 00870 CloseHandle(G_IcaVideoChannel); 00871 G_IcaVideoChannel = NULL; 00872 } 00873 if (G_IcaBeepChannel) { 00874 CloseHandle(G_IcaBeepChannel); 00875 G_IcaBeepChannel = NULL; 00876 } 00877 if (G_IcaThinwireChannel) { 00878 CloseHandle(G_IcaThinwireChannel); 00879 G_IcaThinwireChannel = NULL; 00880 } 00881 00882 hevtShutDown = OpenEvent(EVENT_ALL_ACCESS, 00883 FALSE, 00884 L"EventShutDownCSRSS"); 00885 00886 if (hevtShutDown == NULL) { 00887 /* 00888 * This case is for cached sessions where RIT and Destiop thread have 00889 * not been created. 00890 */ 00891 DBGHYD(("W32WinStationTerminate terminating CSRSS ...\n")); 00892 00893 Status = CleanupSessionObjectDirectories(); 00894 00895 if (ghportLPC) { 00896 NtClose(ghportLPC); 00897 ghportLPC = NULL; 00898 } 00899 00900 return 0; 00901 } 00902 00903 hevtRitExited = CreateEvent(NULL, 00904 FALSE, 00905 FALSE, 00906 L"EventRitExited"); 00907 00908 UserAssert(hevtRitExited != NULL); 00909 00910 hevtRitStuck = CreateEvent(NULL, 00911 FALSE, 00912 FALSE, 00913 L"EventRitStuck"); 00914 00915 UserAssert(hevtRitStuck != NULL); 00916 00917 /* 00918 * RIT is created. Signal this event that starts the 00919 * cleanup in win32k 00920 */ 00921 SetEvent(hevtShutDown); 00922 00923 DBGHYD(("EventShutDownCSRSS set in CSRSS ...\n")); 00924 00925 00926 while (1) { 00927 00928 HANDLE arHandles[2] = {hevtRitExited, hevtRitStuck}; 00929 DWORD result; 00930 00931 result = WaitForMultipleObjects(2, arHandles, FALSE, INFINITE); 00932 00933 switch (result) { 00934 case WAIT_OBJECT_0: 00935 goto RITExited; 00936 00937 case WAIT_OBJECT_0 + 1: 00938 00939 /* 00940 * The RIT is stucked because there are still GUI threads 00941 * assigned to desktops. One reason for this is that winlogon 00942 * died w/o calling ExitWindowsEx. 00943 */ 00944 UserAssert(ghportLPC != NULL); 00945 00946 if (ghportLPC) { 00947 NtClose(ghportLPC); 00948 ghportLPC = NULL; 00949 } 00950 break; 00951 default: 00952 UserAssert(0); 00953 break; 00954 } 00955 } 00956 00957 RITExited: 00958 00959 DBGHYD(("EventRitExited set in CSRSS ...\n")); 00960 00961 CloseHandle(hevtRitExited); 00962 CloseHandle(hevtRitStuck); 00963 00964 CloseHandle(hevtShutDown); 00965 00966 Status = CleanupSessionObjectDirectories(); 00967 00968 if (ghportLPC) { 00969 NtClose(ghportLPC); 00970 ghportLPC = NULL; 00971 } 00972 00973 return Status; 00974 UNREFERENCED_PARAMETER(pMsg); 00975 } 00976 00977 00978 NTSTATUS 00979 W32WinStationNtSecurity( 00980 PWINSTATION_APIMSG pMsg) 00981 { 00982 NTSTATUS Status = STATUS_SUCCESS; 00983 00984 Status = (NTSTATUS)NtUserCallNoParam(SFI_REMOTENTSECURITY); 00985 00986 if (!NT_SUCCESS(Status)) { 00987 DBGHYD(("RemoteNtSecurity failed with Status %lx\n", Status)); 00988 } 00989 00990 return Status; 00991 UNREFERENCED_PARAMETER(pMsg); 00992 } 00993 00994 00995 NTSTATUS 00996 W32WinStationDoMessage( 00997 PWINSTATION_APIMSG pMsg) 00998 { 00999 NTSTATUS Status = STATUS_SUCCESS; 01000 01001 Status = RemoteDoMessage(pMsg); 01002 01003 if (!NT_SUCCESS(Status)) { 01004 DBGHYD(("RemoteDoMessage failed with Status %lx\n", Status)); 01005 } 01006 01007 return Status; 01008 } 01009 01010 // This is the counter part to SMWinStationBroadcastSystemMessage 01011 NTSTATUS 01012 W32WinStationBroadcastSystemMessage( 01013 PWINSTATION_APIMSG pMsg ) 01014 { 01015 01016 NTSTATUS Status = STATUS_SUCCESS; 01017 01018 Status = RemoteDoBroadcastSystemMessage(pMsg); 01019 01020 if (!NT_SUCCESS(Status)) { 01021 DBGHYD(("RemoteDoBroadcastSystemMessage(): failed with status 0x%lx\n", Status)); 01022 } 01023 01024 return Status; 01025 } 01026 // This is the counter part to SMWinStationSendWindowMessage 01027 NTSTATUS 01028 W32WinStationSendWindowMessage( 01029 PWINSTATION_APIMSG pMsg) 01030 { 01031 01032 NTSTATUS Status = STATUS_SUCCESS; 01033 01034 Status = RemoteDoSendWindowMessage(pMsg); 01035 01036 if (!NT_SUCCESS(Status)) { 01037 DBGHYD(("RemoteDoSendWindowMessage failed with Status 0x%lx\n", Status)); 01038 } 01039 01040 return Status; 01041 } 01042 01043 01044 NTSTATUS 01045 W32WinStationThinwireStats( 01046 PWINSTATION_APIMSG pMsg) 01047 { 01048 NTSTATUS Status = STATUS_SUCCESS; 01049 WINSTATIONTHINWIRESTATSMSG* m = &pMsg->u.ThinwireStats; 01050 01051 Status = (NTSTATUS)NtUserCallOneParam((ULONG_PTR)&m->Stats, 01052 SFI_REMOTETHINWIRESTATS); 01053 01054 if (!NT_SUCCESS(Status)) { 01055 DBGHYD(("RemoteThinwireStats failed with Status %lx\n", Status)); 01056 } 01057 01058 return Status; 01059 } 01060 01061 01062 NTSTATUS 01063 W32WinStationShadowSetup( 01064 PWINSTATION_APIMSG pMsg) 01065 { 01066 NTSTATUS Status = STATUS_SUCCESS; 01067 WINSTATIONSHADOWSETUPMSG* m = &pMsg->u.ShadowSetup; 01068 01069 Status = (NTSTATUS)NtUserCallNoParam(SFI_XXXREMOTESHADOWSETUP); 01070 01071 if (!NT_SUCCESS(Status)) { 01072 DBGHYD(("xxxRemoteShadowSetup failed with Status %lx\n", Status)); 01073 } 01074 01075 return Status; 01076 } 01077 01078 01079 NTSTATUS 01080 W32WinStationShadowStart( 01081 PWINSTATION_APIMSG pMsg) 01082 { 01083 NTSTATUS Status = STATUS_SUCCESS; 01084 WINSTATIONSHADOWSTARTMSG* m = &pMsg->u.ShadowStart; 01085 01086 Status = (NTSTATUS)NtUserCallTwoParam((ULONG_PTR)m->pThinwireData, 01087 (ULONG_PTR)m->ThinwireDataLength, 01088 SFI_REMOTESHADOWSTART); 01089 01090 if (!NT_SUCCESS(Status)) { 01091 DBGHYD(("RemoteShadowStart failed with Status %lx\n", Status)); 01092 } 01093 01094 return Status; 01095 } 01096 01097 01098 NTSTATUS 01099 W32WinStationShadowStop( 01100 PWINSTATION_APIMSG pMsg) 01101 { 01102 NTSTATUS Status = STATUS_SUCCESS; 01103 WINSTATIONSHADOWSTOPMSG* m = &pMsg->u.ShadowStop; 01104 01105 Status = (NTSTATUS)NtUserCallNoParam(SFI_XXXREMOTESHADOWSTOP); 01106 01107 if (!NT_SUCCESS(Status)) { 01108 DBGHYD(("xxxRemoteShadowStop failed with Status %lx\n", Status)); 01109 } 01110 01111 return Status; 01112 } 01113 01114 01115 NTSTATUS 01116 W32WinStationShadowCleanup( 01117 PWINSTATION_APIMSG pMsg) 01118 { 01119 NTSTATUS Status = STATUS_SUCCESS; 01120 WINSTATIONSHADOWCLEANUPMSG* m = &pMsg->u.ShadowCleanup; 01121 01122 Status = (NTSTATUS)NtUserCallTwoParam((ULONG_PTR)m->pThinwireData, 01123 (ULONG_PTR)m->ThinwireDataLength, 01124 SFI_REMOTESHADOWCLEANUP); 01125 01126 if (!NT_SUCCESS(Status)) { 01127 DBGHYD(("RemoteShadowCleanup failed with Status %lx\n", Status)); 01128 } 01129 01130 return Status; 01131 } 01132 01133 01134 NTSTATUS 01135 W32WinStationPassthruEnable( 01136 PWINSTATION_APIMSG pMsg) 01137 { 01138 NTSTATUS Status = STATUS_SUCCESS; 01139 01140 Status = (NTSTATUS)NtUserCallNoParam(SFI_XXXREMOTEPASSTHRUENABLE); 01141 01142 if (!NT_SUCCESS(Status)) { 01143 DBGHYD(("xxxRemotePassthruEnable failed with Status %lx\n", Status)); 01144 } 01145 01146 return Status; 01147 UNREFERENCED_PARAMETER(pMsg); 01148 } 01149 01150 01151 NTSTATUS 01152 W32WinStationPassthruDisable( 01153 PWINSTATION_APIMSG pMsg) 01154 { 01155 NTSTATUS Status = STATUS_SUCCESS; 01156 01157 Status = (NTSTATUS)NtUserCallNoParam(SFI_REMOTEPASSTHRUDISABLE); 01158 01159 if (!NT_SUCCESS(Status)) { 01160 DBGHYD(("RemotePassthruDisable failed with Status %lx\n", Status)); 01161 } 01162 01163 return Status; 01164 UNREFERENCED_PARAMETER(pMsg); 01165 } 01166 01167 01168 NTSTATUS 01169 CleanupSessionObjectDirectories( 01170 VOID) 01171 { 01172 NTSTATUS Status; 01173 OBJECT_ATTRIBUTES Attributes; 01174 UNICODE_STRING UnicodeString; 01175 HANDLE LinkHandle; 01176 POBJECT_DIRECTORY_INFORMATION DirInfo; 01177 BOOLEAN RestartScan; 01178 UCHAR DirInfoBuffer[ 4096 ]; 01179 WCHAR szSessionString [ MAX_SESSION_PATH ]; 01180 ULONG Context = 0; 01181 ULONG ReturnedLength; 01182 HANDLE DosDevicesDirectory; 01183 HANDLE *HandleArray; 01184 ULONG Size = 100; 01185 ULONG i, Count = 0; 01186 01187 swprintf(szSessionString,L"%ws\\%ld\\DosDevices",SESSION_ROOT,NtCurrentPeb()->SessionId); 01188 01189 RtlInitUnicodeString(&UnicodeString, szSessionString); 01190 01191 InitializeObjectAttributes(&Attributes, 01192 &UnicodeString, 01193 OBJ_CASE_INSENSITIVE, 01194 NULL, 01195 NULL); 01196 01197 Status = NtOpenDirectoryObject(&DosDevicesDirectory, 01198 DIRECTORY_ALL_ACCESS, 01199 &Attributes); 01200 01201 if (!NT_SUCCESS(Status)) { 01202 DBGHYD(("NtOpenDirectoryObject failed with Status %lx\n", Status)); 01203 return Status; 01204 } 01205 01206 Restart: 01207 HandleArray = (HANDLE *)LocalAlloc(LPTR, Size * sizeof(HANDLE)); 01208 01209 if (HandleArray == NULL) { 01210 01211 NtClose(DosDevicesDirectory); 01212 return STATUS_NO_MEMORY; 01213 } 01214 01215 RestartScan = TRUE; 01216 DirInfo = (POBJECT_DIRECTORY_INFORMATION)&DirInfoBuffer; 01217 01218 while (TRUE) { 01219 Status = NtQueryDirectoryObject( DosDevicesDirectory, 01220 (PVOID)DirInfo, 01221 sizeof(DirInfoBuffer), 01222 TRUE, 01223 RestartScan, 01224 &Context, 01225 &ReturnedLength); 01226 01227 /* 01228 * Check the status of the operation. 01229 */ 01230 if (!NT_SUCCESS(Status)) { 01231 01232 if (Status == STATUS_NO_MORE_ENTRIES) { 01233 Status = STATUS_SUCCESS; 01234 } 01235 break; 01236 } 01237 01238 if (!wcscmp(DirInfo->TypeName.Buffer, L"SymbolicLink")) { 01239 01240 if ( Count >= Size ) { 01241 01242 for (i = 0; i < Count ; i++) { 01243 NtClose (HandleArray[i]); 01244 } 01245 Size += 20; 01246 Count = 0; 01247 LocalFree(HandleArray); 01248 goto Restart; 01249 01250 } 01251 01252 InitializeObjectAttributes( &Attributes, 01253 &DirInfo->Name, 01254 OBJ_CASE_INSENSITIVE, 01255 DosDevicesDirectory, 01256 NULL); 01257 01258 Status = NtOpenSymbolicLinkObject( &LinkHandle, 01259 SYMBOLIC_LINK_ALL_ACCESS, 01260 &Attributes); 01261 01262 if (NT_SUCCESS(Status)) { 01263 01264 Status = NtMakeTemporaryObject( LinkHandle ); 01265 01266 if (NT_SUCCESS( Status )) { 01267 HandleArray[Count] = LinkHandle; 01268 Count++; 01269 } 01270 } 01271 01272 } 01273 RestartScan = FALSE; 01274 } 01275 01276 for (i = 0; i < Count ; i++) { 01277 01278 NtClose (HandleArray[i]); 01279 01280 } 01281 01282 LocalFree(HandleArray); 01283 01284 NtClose(DosDevicesDirectory); 01285 01286 return Status; 01287 }

Generated on Sat May 15 19:39:15 2004 for test by doxygen 1.3.7