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

server.c

Go to the documentation of this file.
00001 /**************************************************************************\ 00002 * Module Name: server.c 00003 * 00004 * Server support routines for the CSR stuff. 00005 * 00006 * Copyright (c) 1985 - 1999, Microsoft Corporation 00007 * 00008 * Created: 10-Dec-90 00009 * 00010 * History: 00011 * 10-Dec-90 created by sMeans 00012 * 00013 \**************************************************************************/ 00014 00015 00016 #include "precomp.h" 00017 #pragma hdrstop 00018 00019 #include "dbt.h" 00020 #include "ntdddisk.h" 00021 #include "ntuser.h" 00022 #include <regstr.h> 00023 00024 00025 HANDLE hThreadNotification; 00026 HANDLE hKeyPriority; 00027 UNICODE_STRING PriorityValueName; 00028 IO_STATUS_BLOCK IoStatusRegChange; 00029 ULONG RegChangeBuffer; 00030 HANDLE ghNlsEvent; 00031 BOOL gfLogon; 00032 FARPROC gpfnAttachRoutine; 00033 HANDLE ghPowerRequestEvent; 00034 HANDLE ghMediaRequestEvent; 00035 00036 #define ID_NLS 0 00037 #define ID_POWER 1 00038 #define ID_MEDIACHANGE 2 00039 #define ID_NETDEVCHANGE 3 00040 00041 #define ID_NUM_EVENTS 4 00042 00043 // 00044 // Name of event to pulse to request a device-arrival broadcast, 00045 // 00046 #define SC_BSM_EVENT_NAME L"ScNetDrvMsg" 00047 00048 // 00049 // What the net drive bitmask was when we last broadcast (initially 0) 00050 // 00051 DWORD LastNetDrives; 00052 00053 00054 HANDLE CsrApiPort; 00055 HANDLE CsrQueryApiPort(VOID); 00056 00057 ULONG 00058 SrvExitWindowsEx( 00059 IN OUT PCSR_API_MSG m, 00060 IN OUT PCSR_REPLY_STATUS ReplyStatus); 00061 00062 ULONG 00063 SrvEndTask( 00064 IN OUT PCSR_API_MSG m, 00065 IN OUT PCSR_REPLY_STATUS ReplyStatus); 00066 00067 ULONG 00068 SrvLogon( 00069 IN OUT PCSR_API_MSG m, 00070 IN OUT PCSR_REPLY_STATUS ReplyStatus); 00071 00072 ULONG 00073 SrvRegisterServicesProcess( 00074 IN OUT PCSR_API_MSG m, 00075 IN OUT PCSR_REPLY_STATUS ReplyStatus); 00076 00077 ULONG 00078 SrvActivateDebugger( 00079 IN OUT PCSR_API_MSG m, 00080 IN OUT PCSR_REPLY_STATUS ReplyStatus); 00081 00082 ULONG 00083 SrvGetThreadConsoleDesktop( 00084 IN OUT PCSR_API_MSG m, 00085 IN OUT PCSR_REPLY_STATUS ReplyStatus); 00086 00087 ULONG 00088 SrvDeviceEvent( 00089 IN OUT PCSR_API_MSG m, 00090 IN OUT PCSR_REPLY_STATUS ReplyStatus); 00091 00092 ULONG 00093 SrvRegisterLogonProcess( 00094 IN OUT PCSR_API_MSG m, 00095 IN OUT PCSR_REPLY_STATUS ReplyStatus); 00096 00097 ULONG 00098 SrvWin32HeapFail( 00099 IN OUT PCSR_API_MSG m, 00100 IN OUT PCSR_REPLY_STATUS ReplyStatus); 00101 00102 ULONG 00103 SrvWin32HeapStat( 00104 IN OUT PCSR_API_MSG m, 00105 IN OUT PCSR_REPLY_STATUS ReplyStatus); 00106 00107 PCSR_API_ROUTINE UserServerApiDispatchTable[ UserpMaxApiNumber - UserpExitWindowsEx ] = { 00108 (PCSR_API_ROUTINE)SrvExitWindowsEx, 00109 (PCSR_API_ROUTINE)SrvEndTask, 00110 (PCSR_API_ROUTINE)SrvLogon, 00111 (PCSR_API_ROUTINE)SrvRegisterServicesProcess, 00112 (PCSR_API_ROUTINE)SrvActivateDebugger, 00113 (PCSR_API_ROUTINE)SrvGetThreadConsoleDesktop, 00114 (PCSR_API_ROUTINE)SrvDeviceEvent, 00115 (PCSR_API_ROUTINE)SrvRegisterLogonProcess, 00116 (PCSR_API_ROUTINE)SrvWin32HeapFail, 00117 (PCSR_API_ROUTINE)SrvWin32HeapStat, 00118 }; 00119 00120 BOOLEAN UserServerApiServerValidTable[ UserpMaxApiNumber - UserpExitWindowsEx ] = { 00121 FALSE, // ExitWindowsEx 00122 FALSE, // EndTask 00123 FALSE, // Logon 00124 FALSE, // RegisterServicesProcess 00125 FALSE, // ActivateDebugger 00126 TRUE, // GetThreadConsoleDesktop 00127 FALSE, // DeviceEvent 00128 FALSE, // RegisterLogonProcess 00129 FALSE, // Win32HeapFail 00130 FALSE, // Win32HeapStat 00131 }; 00132 00133 #if DBG 00134 PSZ UserServerApiNameTable[ UserpMaxApiNumber - UserpExitWindowsEx ] = { 00135 "SrvExitWindowsEx", 00136 "SrvEndTask", 00137 "SrvLogon", 00138 "SrvRegisterServicesProcess", 00139 "SrvActivateDebugger", 00140 "SrvGetThreadConsoleDesktop", 00141 "SrvDeviceEvent", 00142 "SrvRegisterLogonProcess", 00143 "SrvWin32HeapFail", 00144 "SrvWin32HeapStat" 00145 }; 00146 #endif // DBG 00147 00148 NTSTATUS 00149 UserServerDllInitialization( 00150 PCSR_SERVER_DLL psrvdll 00151 ); 00152 00153 NTSTATUS UserClientConnect(PCSR_PROCESS Process, PVOID ConnectionInformation, 00154 PULONG pulConnectionLen); 00155 VOID UserHardError(PCSR_THREAD pcsrt, PHARDERROR_MSG pmsg); 00156 NTSTATUS UserClientShutdown(PCSR_PROCESS Process, ULONG dwFlags, BOOLEAN fFirstPass); 00157 00158 VOID GetTimeouts(VOID); 00159 VOID StartRegReadRead(VOID); 00160 VOID RegReadApcProcedure(PVOID RegReadApcContext, PIO_STATUS_BLOCK IoStatus); 00161 VOID NotificationThread(PVOID); 00162 typedef BOOL (*PFNPROCESSCREATE)(DWORD, DWORD, ULONG_PTR, DWORD); 00163 00164 VOID InitializeConsoleAttributes(VOID); 00165 NTSTATUS GetThreadConsoleDesktop(DWORD dwThreadId, HDESK *phdesk); 00166 NTSTATUS MyRegOpenKey(IN HANDLE hKey, IN LPWSTR lpSubKey, OUT PHANDLE phResult); 00167 00168 BOOL BaseSetProcessCreateNotify(PFNPROCESSCREATE pfn); 00169 VOID BaseSrvNlsUpdateRegistryCache(PVOID ApcContext, 00170 PIO_STATUS_BLOCK pIoStatusBlock); 00171 NTSTATUS BaseSrvNlsLogon(BOOL); 00172 NTSTATUS WinStationAPIInit(VOID); 00173 00174 /***************************************************************************\ 00175 * UserServerDllInitialization 00176 * 00177 * Called by the CSR stuff to allow a server DLL to initialize itself and 00178 * provide information about the APIs it provides. 00179 * 00180 * Several operations are performed during this initialization: 00181 * 00182 * - The shared heap (client read-only) handle is initialized. 00183 * - The Raw Input Thread (RIT) is launched. 00184 * - GDI is initialized. 00185 * 00186 * History: 00187 * 10-19-92 DarrinM Integrated xxxUserServerDllInitialize into this rtn. 00188 * 11-08-91 patrickh move GDI init here from DLL init routine. 00189 * 12-10-90 sMeans Created. 00190 \***************************************************************************/ 00191 00192 NTSTATUS UserServerDllInitialization( 00193 PCSR_SERVER_DLL psrvdll) 00194 { 00195 CLIENT_ID ClientId; 00196 BOOL bAllocated; 00197 NTSTATUS Status; 00198 00199 /* 00200 * Initialize the RIP flags to default 00201 */ 00202 gdwRIPFlags = RIPF_DEFAULT; 00203 00204 #if DBG 00205 if (RtlGetNtGlobalFlags() & FLG_SHOW_LDR_SNAPS) { 00206 RIPMSG0(RIP_WARNING, 00207 "UserServerDllInitialization: entered"); 00208 } 00209 #endif 00210 00211 /* 00212 * Initialize a critical section structure that will be used to protect 00213 * all of the User Server's critical sections (except a few special 00214 * cases like the RIT -- see below). 00215 */ 00216 00217 Status = RtlInitializeCriticalSection(&gcsUserSrv); 00218 if (!NT_SUCCESS(Status)) 00219 { 00220 RIPMSG1(RIP_WARNING, 00221 "UserServerDllInitialization: InitializeCriticalSection failed with Status %x", 00222 Status); 00223 return Status; 00224 } 00225 EnterCrit(); 00226 00227 /* 00228 * Remember WINSRV.DLL's hmodule so we can grab resources from it later. 00229 */ 00230 ghModuleWin = psrvdll->ModuleHandle; 00231 00232 psrvdll->ApiNumberBase = USERSRV_FIRST_API_NUMBER; 00233 psrvdll->MaxApiNumber = UserpMaxApiNumber; 00234 psrvdll->ApiDispatchTable = UserServerApiDispatchTable; 00235 00236 if (ISTS()) { 00237 UserServerApiServerValidTable[0] = TRUE; // for ExitWindowsEx 00238 } 00239 00240 psrvdll->ApiServerValidTable = UserServerApiServerValidTable; 00241 #if DBG 00242 psrvdll->ApiNameTable = UserServerApiNameTable; 00243 #else 00244 psrvdll->ApiNameTable = NULL; 00245 #endif 00246 psrvdll->ConnectRoutine = UserClientConnect; 00247 psrvdll->HardErrorRoutine = UserHardError; 00248 psrvdll->ShutdownProcessRoutine = UserClientShutdown; 00249 00250 /* 00251 * Create these events used by shutdown 00252 */ 00253 //BUGBUG we should test the return code of NtCreateEvent 00254 NtCreateEvent(&gheventCancel, EVENT_ALL_ACCESS, NULL, 00255 NotificationEvent, FALSE); 00256 NtCreateEvent(&gheventCancelled, EVENT_ALL_ACCESS, NULL, 00257 NotificationEvent, FALSE); 00258 00259 /* 00260 * Create the event used by the power request code. 00261 */ 00262 NtCreateEvent(&ghPowerRequestEvent, EVENT_ALL_ACCESS, NULL, 00263 SynchronizationEvent, FALSE); 00264 00265 /* 00266 * Create the event used by the media change code. 00267 */ 00268 NtCreateEvent(&ghMediaRequestEvent, EVENT_ALL_ACCESS, NULL, 00269 SynchronizationEvent, FALSE); 00270 00271 /* 00272 * Tell the base what user address to call when it is creating a process 00273 * (but before the process starts running). 00274 */ 00275 BaseSetProcessCreateNotify(NtUserNotifyProcessCreate); 00276 00277 /* 00278 * Load some strings. 00279 */ 00280 gpwszaSUCCESS = (PWSTR)RtlLoadStringOrError(ghModuleWin, 00281 STR_SUCCESS, NULL, &bAllocated, FALSE); 00282 gpwszaSYSTEM_INFORMATION = (PWSTR)RtlLoadStringOrError(ghModuleWin, 00283 STR_SYSTEM_INFORMATION, NULL, &bAllocated, FALSE); 00284 gpwszaSYSTEM_WARNING = (PWSTR)RtlLoadStringOrError(ghModuleWin, 00285 STR_SYSTEM_WARNING, NULL, &bAllocated, FALSE); 00286 gpwszaSYSTEM_ERROR = (PWSTR)RtlLoadStringOrError(ghModuleWin, 00287 STR_SYSTEM_ERROR, NULL, &bAllocated, FALSE); 00288 /* 00289 * Initialize USER 00290 */ 00291 00292 { 00293 HANDLE hModBase; 00294 00295 hModBase = GetModuleHandle(TEXT("kernel32")); 00296 UserAssert(hModBase); 00297 gpfnAttachRoutine = GetProcAddress(hModBase,"BaseAttachCompleteThunk"); 00298 UserAssert(gpfnAttachRoutine); 00299 00300 Status = NtUserInitialize(USERCURRENTVERSION, ghPowerRequestEvent, ghMediaRequestEvent); 00301 if (!NT_SUCCESS(Status)) { 00302 RIPMSG1(RIP_WARNING, 00303 "UserServerDllInitialization: NtUserInitialize failed with Status %x", 00304 Status); 00305 goto ExitUserInit; 00306 } 00307 } 00308 00309 if (ISTS()) { 00310 00311 Status = WinStationAPIInit(); 00312 if (!NT_SUCCESS(Status)) { 00313 RIPMSG1(RIP_WARNING, 00314 "UserServerDllInitialization: WinStationAPIInit failed with Status %x", 00315 Status); 00316 goto ExitUserInit; 00317 } 00318 } 00319 00320 /* 00321 * Start registry notification thread 00322 */ 00323 Status = RtlCreateUserThread(NtCurrentProcess(), NULL, FALSE, 0, 0, 4*0x1000, 00324 (PUSER_THREAD_START_ROUTINE)NotificationThread, NULL, &hThreadNotification, 00325 &ClientId); 00326 if (!NT_SUCCESS(Status)) { 00327 RIPMSG1(RIP_WARNING, 00328 "UserServerDllInitialization: RtlCreateUserThread failed with Status %x", 00329 Status); 00330 } 00331 CsrAddStaticServerThread(hThreadNotification, &ClientId, 0); 00332 00333 ExitUserInit: 00334 LeaveCrit(); 00335 return Status; 00336 } 00337 00338 /**************************************************************************\ 00339 * UserClientConnect 00340 * 00341 * This function is called once for each client process that connects to the 00342 * User server. When the client dynlinks to USER.DLL, USER.DLL's init code 00343 * is executed and calls CsrClientConnectToServer to establish the connection. 00344 * The server portion of ConnectToServer calls out this entrypoint. 00345 * 00346 * UserClientConnect first verifies version numbers to make sure the client 00347 * is compatible with this server and then completes all process-specific 00348 * initialization. 00349 * 00350 * History: 00351 * 02-??-91 SMeans Created. 00352 * 04-02-91 DarrinM Added User intialization code. 00353 \**************************************************************************/ 00354 00355 extern WORD gDispatchTableValues; 00356 00357 NTSTATUS UserClientConnect( 00358 PCSR_PROCESS Process, 00359 PVOID ConnectionInformation, 00360 PULONG pulConnectionLen) 00361 { 00362 /* 00363 * Pass the api port to the kernel. Do this early so the kernel 00364 * can send a datagram to CSR to activate a debugger. 00365 */ 00366 if (CsrApiPort == NULL) { 00367 CsrApiPort = CsrQueryApiPort(); 00368 NtUserSetInformationThread( 00369 NtCurrentThread(), 00370 UserThreadCsrApiPort, 00371 &CsrApiPort, 00372 sizeof(HANDLE)); 00373 } 00374 00375 UserAssert(*pulConnectionLen == sizeof(USERCONNECT)); 00376 if (*pulConnectionLen != sizeof(USERCONNECT)) { 00377 return STATUS_INVALID_PARAMETER; 00378 } 00379 00380 ((PUSERCONNECT)ConnectionInformation)->dwDispatchCount = gDispatchTableValues; 00381 return NtUserProcessConnect(Process->ProcessHandle, 00382 (PUSERCONNECT)ConnectionInformation, *pulConnectionLen); 00383 } 00384 00385 00386 VOID 00387 RegReadApcProcedure( 00388 PVOID RegReadApcContext, 00389 PIO_STATUS_BLOCK IoStatus 00390 ) 00391 { 00392 UNICODE_STRING ValueString; 00393 LONG Status; 00394 BYTE Buf[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)]; 00395 DWORD cbSize; 00396 ULONG l; 00397 00398 UNREFERENCED_PARAMETER(RegReadApcContext); 00399 UNREFERENCED_PARAMETER(IoStatus); 00400 00401 RtlInitUnicodeString(&ValueString, L"Win32PrioritySeparation"); 00402 Status = NtQueryValueKey(hKeyPriority, 00403 &ValueString, 00404 KeyValuePartialInformation, 00405 (PKEY_VALUE_PARTIAL_INFORMATION)Buf, 00406 sizeof(Buf), 00407 &cbSize); 00408 if (NT_SUCCESS(Status)) { 00409 l = *((PDWORD)((PKEY_VALUE_PARTIAL_INFORMATION)Buf)->Data); 00410 } else { 00411 l = PROCESS_PRIORITY_SEPARATION_MAX; // last resort default 00412 } 00413 00414 NtSetSystemInformation(SystemPrioritySeperation,&l,sizeof(ULONG)); 00415 00416 NtNotifyChangeKey( 00417 hKeyPriority, 00418 NULL, 00419 (PIO_APC_ROUTINE)RegReadApcProcedure, 00420 NULL, 00421 &IoStatusRegChange, 00422 REG_NOTIFY_CHANGE_LAST_SET, 00423 FALSE, 00424 &RegChangeBuffer, 00425 sizeof(RegChangeBuffer), 00426 TRUE 00427 ); 00428 } 00429 00430 VOID 00431 StartRegReadRead(VOID) 00432 { 00433 UNICODE_STRING UnicodeString; 00434 OBJECT_ATTRIBUTES OA; 00435 00436 RtlInitUnicodeString(&UnicodeString, 00437 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\PriorityControl"); 00438 InitializeObjectAttributes(&OA, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); 00439 00440 if (!NT_SUCCESS(NtOpenKey(&hKeyPriority, KEY_READ | KEY_NOTIFY, &OA))) 00441 UserAssert(FALSE); 00442 00443 RegReadApcProcedure(NULL, NULL); 00444 } 00445 00446 00447 /***************************************************************************\ 00448 * HandleMediaChangeEvent 00449 * 00450 * This routine is responsible for broadcasting the WM_DEVICECHANGE message 00451 * when media arrives or is removed from a CD-ROM device. 00452 * 00453 * History: 00454 * 23-Feb-96 BradG Modified to handle event per CD-ROM device 00455 * 23-April-96 Salimc Some CD-ROM drives notify us that media has 00456 * arrived before the drive has recognized that it had 00457 * new media. The call to DeviceIoctl() will fail in 00458 * this case. To fix this we made the following changes 00459 * 00460 * aDriveState is an array of tri-state global variable 00461 * for each drive.Each variable starts off in an UNKNOWN 00462 * state and on the first event with any drive we do the 00463 * full MAX_TRIES or less CHECK_VERIFY's which then gets 00464 * us into either a INSERTED or EJECTED state. From then 00465 * on we know that each new event is going to be the 00466 * opposite of what we currently have. 00467 * 00468 * UNKNOWN => do upto MAX_TRIES CHECK_VERIFY's with 00469 * delay to get into EJECTED or INSERTED state. 00470 * 00471 * INSERTED => do 1 CHECK_VERIFY to get into 00472 * EJECTED state 00473 * 00474 * EJECTED => do upto MAX_TRIES CHECK_VERIFY's with 00475 * delay to get into INSERTED state 00476 * 00477 \***************************************************************************/ 00478 00479 VOID HandleMediaChangeEvent(VOID) 00480 { 00481 /* 00482 * Local variables 00483 */ 00484 00485 DWORD dwRecipients; 00486 BOOL bResult; 00487 NTSTATUS Status; 00488 DEV_BROADCAST_VOLUME dbcvInfo; 00489 USERTHREAD_USEDESKTOPINFO utudi; 00490 00491 ULONG cDrive; 00492 00493 while (cDrive = (ULONG)NtUserCallNoParam(SFI_GETDEVICECHANGEINFO)) { 00494 00495 /* 00496 * Determine if it's an arrival or removal 00497 */ 00498 bResult = (cDrive & 0x80000000); 00499 00500 /* 00501 * Initialize the structures used for BroadcastSystemMessage 00502 */ 00503 dbcvInfo.dbcv_size = sizeof(dbcvInfo); 00504 dbcvInfo.dbcv_devicetype = DBT_DEVTYP_VOLUME; 00505 dbcvInfo.dbcv_reserved = 0; 00506 dbcvInfo.dbcv_flags = DBTF_MEDIA; 00507 dbcvInfo.dbcv_unitmask = cDrive; 00508 00509 dwRecipients = BSM_ALLCOMPONENTS | BSM_ALLDESKTOPS; 00510 00511 /* 00512 * Temporarily we must assign this thread to a desktop so we can 00513 * call USER's BroascastSystemMessage() routine. We call the 00514 * private SetThreadDesktopToDefault() to assign ourselves to the 00515 * desktop that is currently receiving input. 00516 */ 00517 utudi.hThread = NULL; 00518 utudi.drdRestore.pdeskRestore = NULL; 00519 Status = NtUserSetInformationThread(NtCurrentThread(), 00520 UserThreadUseActiveDesktop, 00521 &utudi, sizeof(utudi)); 00522 if (NT_SUCCESS(Status)) { 00523 /* 00524 * Broadcast the message 00525 */ 00526 BroadcastSystemMessage(BSF_FORCEIFHUNG | ((bResult) ? BSF_ALLOWSFW : 0), 00527 &dwRecipients, 00528 WM_DEVICECHANGE, 00529 // HACK: need to or 0x8000 in wParam 00530 // because this is a flag to let 00531 // BSM know that lParam is a pointer 00532 // to a data structure. 00533 0x8000 | ((bResult) ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE), 00534 (LPARAM)&dbcvInfo); 00535 00536 /* 00537 * Set our thread's desktop back to NULL. This will decrement 00538 * the desktop's reference count. 00539 */ 00540 NtUserSetInformationThread(NtCurrentThread(), 00541 UserThreadUseDesktop, 00542 &utudi, 00543 sizeof(utudi)); 00544 } 00545 } 00546 } 00547 00548 DWORD 00549 GetNetworkDrives( 00550 ) 00551 /*++ 00552 00553 Routine Description: 00554 00555 Returns a drive bitmask similar to GetLogicalDrives, but including 00556 only the network drives. 00557 00558 Arguments: 00559 00560 Return Value: 00561 00562 00563 --*/ 00564 { 00565 DWORD Mask = 0; 00566 DWORD DriveNumber; 00567 PROCESS_DEVICEMAP_INFORMATION ProcessDeviceMapInfo; 00568 00569 if (NT_SUCCESS(NtQueryInformationProcess( NtCurrentProcess(), 00570 ProcessDeviceMap, 00571 &ProcessDeviceMapInfo.Query, 00572 sizeof( ProcessDeviceMapInfo.Query ), 00573 NULL 00574 ))) { 00575 // For all the drives from C to Z 00576 for (DriveNumber = 2; DriveNumber < 26; DriveNumber++) 00577 { 00578 if (ProcessDeviceMapInfo.Query.DriveType[DriveNumber] == DOSDEVICE_DRIVE_REMOTE) 00579 { 00580 Mask |= (1 << DriveNumber); 00581 } 00582 } 00583 } 00584 00585 return Mask; 00586 } 00587 00588 VOID 00589 HandleRemoteNetDeviceChangeEvent( 00590 ) 00591 /*++ 00592 00593 Routine Description: 00594 00595 00596 Arguments: 00597 00598 Return Value: 00599 00600 --*/ 00601 { 00602 DWORD NetDrives; 00603 DEV_BROADCAST_VOLUME dbv; 00604 LONG status; 00605 USERTHREAD_USEDESKTOPINFO utudi; 00606 00607 00608 00609 /* 00610 * Temporarily we must assign this thread to a desktop so we can 00611 * call USER's BroascastSystemMessage() routine. We call the 00612 * private SetThreadDesktopToDefault() to assign ourselves to the 00613 * desktop that is currently receiving input. 00614 */ 00615 utudi.hThread = NULL; 00616 utudi.drdRestore.pdeskRestore = NULL; 00617 status = NtUserSetInformationThread(NtCurrentThread(), 00618 UserThreadUseActiveDesktop, 00619 &utudi, sizeof(utudi)); 00620 if (!NT_SUCCESS(status)) { 00621 return; 00622 } 00623 00624 // 00625 // Keep broadcasting until the set of net drives stops changing 00626 // 00627 for (;;) 00628 { 00629 00630 // 00631 // Get the current net drive bitmask and compare against the net 00632 // drive bitmask when we last broadcast 00633 // 00634 NetDrives = GetNetworkDrives(); 00635 00636 if (NetDrives == LastNetDrives) 00637 { 00638 break; 00639 } 00640 00641 // 00642 // Broadcast about deleted volumes 00643 // 00644 dbv.dbcv_size = sizeof(dbv); 00645 dbv.dbcv_devicetype = DBT_DEVTYP_VOLUME; 00646 dbv.dbcv_reserved = 0; 00647 dbv.dbcv_unitmask = LastNetDrives & ~NetDrives; 00648 dbv.dbcv_flags = DBTF_NET; 00649 if (dbv.dbcv_unitmask != 0) 00650 { 00651 DWORD dwRec = BSM_APPLICATIONS | BSM_ALLDESKTOPS; 00652 status = BroadcastSystemMessage( 00653 BSF_FORCEIFHUNG | BSF_NOHANG | BSF_NOTIMEOUTIFNOTHUNG, 00654 &dwRec, 00655 WM_DEVICECHANGE, 00656 (WPARAM) DBT_DEVICEREMOVECOMPLETE, 00657 (LPARAM)(DEV_BROADCAST_HDR*)(&dbv) 00658 ); 00659 00660 } 00661 00662 // 00663 // Broadcast about added volumes 00664 // 00665 dbv.dbcv_unitmask = NetDrives & ~LastNetDrives; 00666 if (dbv.dbcv_unitmask != 0) 00667 { 00668 DWORD dwRec = BSM_APPLICATIONS | BSM_ALLDESKTOPS; 00669 00670 status = BroadcastSystemMessage( 00671 BSF_FORCEIFHUNG | BSF_NOHANG | BSF_NOTIMEOUTIFNOTHUNG, 00672 &dwRec, 00673 WM_DEVICECHANGE, 00674 (WPARAM) DBT_DEVICEARRIVAL, 00675 (LPARAM)(DEV_BROADCAST_HDR*)(&dbv) 00676 ); 00677 00678 00679 } 00680 00681 // 00682 // Remember the drive set that we last broadcast about 00683 // 00684 LastNetDrives = NetDrives; 00685 00686 // 00687 // Go around the loop again to detect changes that may have occurred 00688 // while we were broadcasting 00689 // 00690 } 00691 00692 /* 00693 * Set our thread's desktop back to NULL. This will decrement 00694 * the desktop's reference count. 00695 */ 00696 NtUserSetInformationThread(NtCurrentThread(), 00697 UserThreadUseDesktop, 00698 &utudi, 00699 sizeof(utudi)); 00700 00701 return; 00702 } 00703 00704 BOOL 00705 CreateBSMEventSD( 00706 PSECURITY_DESCRIPTOR * SecurityDescriptor 00707 ) 00708 /*++ 00709 00710 Routine Description: 00711 00712 This function creates a security descriptor for the BSM request event. 00713 It grants EVENT_ALL_ACCESS to local system and EVENT_MODIFY_STATE access 00714 to the rest of the world. This prevents principals other than local 00715 system from waiting for the event. 00716 00717 Arguments: 00718 00719 SecurityDescriptor - Receives a pointer to the new security descriptor. 00720 Should be freed with LocalFree. 00721 00722 Return Value: 00723 00724 TRUE - success 00725 00726 FALSE - failure, use GetLastError 00727 00728 00729 --*/ 00730 { 00731 NTSTATUS Status; 00732 ULONG AclLength; 00733 PACL EventDacl; 00734 PSID WorldSid = NULL; 00735 PSID SystemSid = NULL; 00736 SID_IDENTIFIER_AUTHORITY NtSidAuthority = SECURITY_NT_AUTHORITY; 00737 SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; 00738 BOOL retval = TRUE; 00739 00740 *SecurityDescriptor = NULL; 00741 00742 Status = RtlAllocateAndInitializeSid( &NtSidAuthority, 00743 1, 00744 SECURITY_LOCAL_SYSTEM_RID, 00745 0, 0, 0, 0, 0, 0, 0, 00746 &SystemSid ); 00747 00748 if (!NT_SUCCESS(Status)) { 00749 retval = FALSE; 00750 goto Cleanup; 00751 } 00752 00753 Status = RtlAllocateAndInitializeSid( &WorldSidAuthority, 00754 1, 00755 SECURITY_WORLD_RID, 00756 0, 0, 0, 0, 0, 0, 0, 00757 &WorldSid ); 00758 00759 if (!NT_SUCCESS(Status)) { 00760 retval = FALSE; 00761 goto Cleanup; 00762 } 00763 00764 00765 // 00766 // Allocate a buffer to contain the SD followed by the DACL 00767 // Note, the well-known SIDs are expected to have been created 00768 // by this time 00769 // 00770 00771 AclLength = (ULONG)sizeof(ACL) + 00772 (2*((ULONG)sizeof(ACCESS_ALLOWED_ACE))) + 00773 RtlLengthSid( SystemSid ) + 00774 RtlLengthSid( WorldSid ) + 00775 8; // 8 is for good measure 00776 00777 *SecurityDescriptor = (PSECURITY_DESCRIPTOR) 00778 LocalAlloc( 0, SECURITY_DESCRIPTOR_MIN_LENGTH + AclLength ); 00779 00780 if (*SecurityDescriptor == NULL) { 00781 retval = FALSE; 00782 goto Cleanup; 00783 } 00784 00785 EventDacl = (PACL) ((BYTE*)(*SecurityDescriptor) + SECURITY_DESCRIPTOR_MIN_LENGTH); 00786 00787 00788 // 00789 // Set up a default ACL 00790 // 00791 // Public: WORLD:EVENT_MODIFY_STATE, SYSTEM:all 00792 00793 Status = RtlCreateAcl( EventDacl, AclLength, ACL_REVISION2); 00794 if (!NT_SUCCESS(Status)) { 00795 retval = FALSE; 00796 goto Cleanup; 00797 } 00798 00799 00800 // 00801 // WORLD access 00802 // 00803 00804 Status = RtlAddAccessAllowedAce ( 00805 EventDacl, 00806 ACL_REVISION2, 00807 EVENT_MODIFY_STATE, 00808 WorldSid 00809 ); 00810 if (!NT_SUCCESS(Status)) { 00811 retval = FALSE; 00812 goto Cleanup; 00813 } 00814 00815 00816 // 00817 // SYSTEM access 00818 // 00819 00820 Status = RtlAddAccessAllowedAce ( 00821 EventDacl, 00822 ACL_REVISION2, 00823 EVENT_ALL_ACCESS, 00824 SystemSid 00825 ); 00826 if (!NT_SUCCESS(Status)) { 00827 retval = FALSE; 00828 goto Cleanup; 00829 } 00830 00831 00832 00833 // 00834 // Now initialize security descriptors 00835 // that export this protection 00836 // 00837 00838 Status = RtlCreateSecurityDescriptor( 00839 *SecurityDescriptor, 00840 SECURITY_DESCRIPTOR_REVISION1 00841 ); 00842 if (!NT_SUCCESS(Status)) { 00843 retval = FALSE; 00844 goto Cleanup; 00845 } 00846 00847 Status = RtlSetDaclSecurityDescriptor( 00848 *SecurityDescriptor, 00849 TRUE, // DaclPresent 00850 EventDacl, 00851 FALSE // DaclDefaulted 00852 ); 00853 00854 if (!NT_SUCCESS(Status)) { 00855 retval = FALSE; 00856 goto Cleanup; 00857 } 00858 00859 Cleanup: 00860 00861 if (WorldSid) { 00862 RtlFreeSid(WorldSid); 00863 } 00864 00865 if (SystemSid) { 00866 RtlFreeSid(SystemSid); 00867 } 00868 00869 if ((retval == FALSE) && (*SecurityDescriptor != NULL)) { 00870 LocalFree(*SecurityDescriptor); 00871 *SecurityDescriptor = NULL; 00872 } 00873 00874 00875 return retval; 00876 } 00877 00878 00879 00880 00881 VOID NotificationThread( 00882 PVOID pJunk) 00883 { 00884 KPRIORITY Priority; 00885 NTSTATUS Status; 00886 HANDLE hEvent[ID_NUM_EVENTS]; 00887 WCHAR szObjectStr[MAX_SESSION_PATH]; 00888 OBJECT_ATTRIBUTES Attributes; 00889 UNICODE_STRING UnicodeString; 00890 PSECURITY_DESCRIPTOR pSD = NULL; 00891 ULONG NumEvents = ID_NUM_EVENTS; 00892 00893 UNREFERENCED_PARAMETER(pJunk); 00894 00895 try { 00896 00897 /* 00898 * Set the priority of the RIT to 3. 00899 */ 00900 Priority = LOW_PRIORITY + 3; 00901 NtSetInformationThread(hThreadNotification, ThreadPriority, &Priority, 00902 sizeof(KPRIORITY)); 00903 00904 /* 00905 * Setup the NLS event 00906 */ 00907 NtCreateEvent(&ghNlsEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); 00908 UserAssert( ghNlsEvent != NULL ); 00909 hEvent[ID_NLS] = ghNlsEvent; 00910 00911 /* 00912 * Setup the power request event 00913 */ 00914 hEvent[ID_POWER] = ghPowerRequestEvent; 00915 00916 /* 00917 * Setup the MediaChangeEvent 00918 */ 00919 hEvent[ID_MEDIACHANGE] = ghMediaRequestEvent; 00920 00921 00922 /* 00923 * Setup the NetDeviceChange Event 00924 */ 00925 00926 if (gSessionId != 0) { 00927 // 00928 // Only on remote Session 00929 // 00930 00931 00932 swprintf(szObjectStr,L"%ws\\%ld\\BaseNamedObjects\\%ws", 00933 SESSION_ROOT,gSessionId,SC_BSM_EVENT_NAME); 00934 00935 RtlInitUnicodeString(&UnicodeString, szObjectStr); 00936 00937 if (CreateBSMEventSD(&pSD) ) { 00938 00939 InitializeObjectAttributes(&Attributes, 00940 &UnicodeString, 00941 OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 00942 NULL, 00943 pSD); 00944 00945 if (!NT_SUCCESS(NtCreateEvent(&hEvent[ID_NETDEVCHANGE], EVENT_ALL_ACCESS, &Attributes, SynchronizationEvent, FALSE))) { 00946 00947 NumEvents--; 00948 00949 } 00950 00951 LocalFree(pSD); 00952 } else { 00953 00954 NumEvents--; 00955 } 00956 00957 } else { 00958 // 00959 // On Console we don't wait for NetDeviceEvent 00960 // 00961 NumEvents--; 00962 } 00963 00964 /* 00965 * Only want media change events on the console. 00966 */ 00967 if (gSessionId == 0) { 00968 } 00969 00970 StartRegReadRead(); 00971 00972 /* 00973 * Sit and wait forever. 00974 */ 00975 while (TRUE) { 00976 Status = NtWaitForMultipleObjects(NumEvents, 00977 hEvent, 00978 WaitAny, 00979 TRUE, 00980 NULL); 00981 00982 00983 if (Status == ID_NLS + WAIT_OBJECT_0) { 00984 00985 /* 00986 * Handle the NLS event 00987 */ 00988 if (gfLogon) { 00989 gfLogon = FALSE; 00990 BaseSrvNlsUpdateRegistryCache(NULL, NULL); 00991 } 00992 00993 } 00994 else if (Status == ID_POWER + WAIT_OBJECT_0) { 00995 00996 /* 00997 * Handle the power request event 00998 */ 00999 NtUserCallNoParam(SFI_XXXUSERPOWERCALLOUTWORKER); 01000 01001 } 01002 else if (Status == ID_MEDIACHANGE + WAIT_OBJECT_0) { 01003 01004 /* 01005 * Handle the media change event 01006 */ 01007 HandleMediaChangeEvent(); 01008 01009 NtResetEvent(hEvent[ID_MEDIACHANGE], NULL); 01010 } 01011 else if (Status == ID_NETDEVCHANGE + WAIT_OBJECT_0) { 01012 01013 /* 01014 * Handle the NetDevice change event for remote sessions 01015 */ 01016 HandleRemoteNetDeviceChangeEvent(); 01017 01018 } 01019 01020 01021 } // While (TRUE) 01022 01023 } except (CsrUnhandledExceptionFilter(GetExceptionInformation())) { 01024 KdPrint(("Registry notification thread is dead, sorry.\n")); 01025 } 01026 } 01027 01028 01029 UINT GetRegIntFromID( 01030 HKEY hKey, 01031 int KeyID, 01032 UINT nDefault) 01033 { 01034 LPWSTR lpszValue; 01035 BOOL fAllocated; 01036 UNICODE_STRING Value; 01037 DWORD cbSize; 01038 BYTE Buf[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 20 * sizeof(WCHAR)]; 01039 NTSTATUS Status; 01040 UINT ReturnValue; 01041 01042 lpszValue = (LPWSTR)RtlLoadStringOrError(ghModuleWin, 01043 KeyID, NULL, &fAllocated, FALSE); 01044 01045 RtlInitUnicodeString(&Value, lpszValue); 01046 Status = NtQueryValueKey(hKey, 01047 &Value, 01048 KeyValuePartialInformation, 01049 (PKEY_VALUE_PARTIAL_INFORMATION)Buf, 01050 sizeof(Buf), 01051 &cbSize); 01052 if (NT_SUCCESS(Status)) { 01053 01054 /* 01055 * Convert string to int. 01056 */ 01057 RtlInitUnicodeString(&Value, (LPWSTR)((PKEY_VALUE_PARTIAL_INFORMATION)Buf)->Data); 01058 RtlUnicodeStringToInteger(&Value, 10, &ReturnValue); 01059 } else { 01060 ReturnValue = nDefault; 01061 } 01062 01063 LocalFree(lpszValue); 01064 01065 return(ReturnValue); 01066 } 01067 01068 VOID GetTimeouts(VOID) 01069 { 01070 HANDLE hCurrentUserKey; 01071 HANDLE hKey; 01072 NTSTATUS Status; 01073 01074 Status = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &hCurrentUserKey); 01075 if (NT_SUCCESS(Status)) { 01076 Status = MyRegOpenKey(hCurrentUserKey, 01077 L"Control Panel\\Desktop", 01078 &hKey); 01079 if (NT_SUCCESS(Status)) { 01080 gCmsHungAppTimeout = GetRegIntFromID( 01081 hKey, 01082 STR_CMSHUNGAPPTIMEOUT, 01083 gCmsHungAppTimeout); 01084 gCmsWaitToKillTimeout = GetRegIntFromID( 01085 hKey, 01086 STR_CMSWAITTOKILLTIMEOUT, 01087 gCmsWaitToKillTimeout); 01088 01089 gdwHungToKillCount = gCmsWaitToKillTimeout / gCmsHungAppTimeout; 01090 01091 gfAutoEndTask = GetRegIntFromID( 01092 hKey, 01093 STR_AUTOENDTASK, 01094 gfAutoEndTask); 01095 NtClose(hKey); 01096 } 01097 NtClose(hCurrentUserKey); 01098 } 01099 01100 Status = MyRegOpenKey(NULL, 01101 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control", 01102 &hKey); 01103 if (NT_SUCCESS(Status)) { 01104 gdwServicesWaitToKillTimeout = GetRegIntFromID( 01105 hKey, 01106 STR_WAITTOKILLSERVICETIMEOUT, 01107 gCmsWaitToKillTimeout); 01108 gdwProcessTerminateTimeout = GetRegIntFromID( 01109 hKey, 01110 STR_PROCESSTERMINATETIMEOUT, 01111 PROCESSTERMINATETIMEOUT); 01112 if (gdwProcessTerminateTimeout < CMSHUNGAPPTIMEOUT) { 01113 gdwProcessTerminateTimeout = CMSHUNGAPPTIMEOUT; 01114 } 01115 01116 NtClose(hKey); 01117 } 01118 } 01119 01120 ULONG 01121 SrvLogon( 01122 IN OUT PCSR_API_MSG m, 01123 IN OUT PCSR_REPLY_STATUS ReplyStatus) 01124 { 01125 PLOGONMSG a = (PLOGONMSG)&m->u.ApiMessageData; 01126 NTSTATUS Status; 01127 01128 UNREFERENCED_PARAMETER(ReplyStatus); 01129 01130 if (!CsrImpersonateClient(NULL)) 01131 return (ULONG)STATUS_UNSUCCESSFUL; 01132 01133 if (a->fLogon) { 01134 01135 /* 01136 * Flush the MultiLingual UI (MUI) alternate 01137 * resource modules from within NTDLL, so that the 01138 * new user logging-on gets his chance to 01139 * load his own. 01140 */ 01141 LdrFlushAlternateResourceModules(); 01142 01143 /* 01144 * Take care of NLS cache for LogON. 01145 */ 01146 BaseSrvNlsLogon(TRUE); 01147 01148 /* 01149 * Set the cleanup event so that the RIT can handle the NLS 01150 * registry notification. 01151 */ 01152 gfLogon = TRUE; 01153 Status = NtSetEvent( ghNlsEvent, NULL ); 01154 ASSERT(NT_SUCCESS(Status)); 01155 } else { 01156 01157 /* 01158 * Take care of NLS cache for LogOFF. 01159 */ 01160 BaseSrvNlsLogon(FALSE); 01161 } 01162 01163 /* 01164 * Get timeout values from registry 01165 */ 01166 GetTimeouts(); 01167 01168 CsrRevertToSelf(); 01169 01170 /* 01171 * Initialize console attributes 01172 */ 01173 InitializeConsoleAttributes(); 01174 01175 return (ULONG)STATUS_SUCCESS; 01176 } 01177 01178 ULONG 01179 SrvRegisterLogonProcess( 01180 IN OUT PCSR_API_MSG m, 01181 IN OUT PCSR_REPLY_STATUS ReplyStatus) 01182 { 01183 /* 01184 * Fail if this is not the first call. 01185 */ 01186 if (gIdLogon != 0) { 01187 return (ULONG)STATUS_UNSUCCESSFUL; 01188 } 01189 01190 gIdLogon = *(DWORD*)m->u.ApiMessageData; 01191 01192 UNREFERENCED_PARAMETER(ReplyStatus); 01193 01194 return (ULONG)STATUS_SUCCESS; 01195 } 01196 01197 ULONG 01198 SrvWin32HeapFail( 01199 IN OUT PCSR_API_MSG m, 01200 IN OUT PCSR_REPLY_STATUS ReplyStatus) 01201 { 01202 #if DBG 01203 PWIN32HEAPFAILMSG a = (PWIN32HEAPFAILMSG)&m->u.ApiMessageData; 01204 01205 Win32HeapFailAllocations(a->bFail); 01206 01207 #endif 01208 return (ULONG)STATUS_SUCCESS; 01209 UNREFERENCED_PARAMETER(m); 01210 UNREFERENCED_PARAMETER(ReplyStatus); 01211 } 01212 01213 ULONG 01214 SrvWin32HeapStat( 01215 IN OUT PCSR_API_MSG m, 01216 IN OUT PCSR_REPLY_STATUS ReplyStatus) 01217 { 01218 #if DBG 01219 extern DWORD Win32HeapStat(PDBGHEAPSTAT phs, DWORD dwLen, BOOL bNeedTagShift); 01220 01221 PWIN32HEAPSTATMSG a = (PWIN32HEAPSTATMSG)&m->u.ApiMessageData; 01222 01223 if (!CsrValidateMessageBuffer(m, &a->phs, a->dwLen, sizeof(BYTE))) { 01224 return STATUS_INVALID_PARAMETER; 01225 } 01226 a->dwMaxTag = Win32HeapStat(a->phs, a->dwLen, TRUE); 01227 01228 #endif 01229 return (ULONG)STATUS_SUCCESS; 01230 UNREFERENCED_PARAMETER(m); 01231 UNREFERENCED_PARAMETER(ReplyStatus); 01232 } 01233 01234 ULONG 01235 SrvGetThreadConsoleDesktop( 01236 IN OUT PCSR_API_MSG m, 01237 IN OUT PCSR_REPLY_STATUS ReplyStatus) 01238 { 01239 PGETTHREADCONSOLEDESKTOPMSG a = (PGETTHREADCONSOLEDESKTOPMSG)&m->u.ApiMessageData; 01240 01241 UNREFERENCED_PARAMETER(ReplyStatus); 01242 01243 return GetThreadConsoleDesktop(a->dwThreadId, &a->hdeskConsole); 01244 } 01245 01246 /***************************************************************************\ 01247 * FindWindowFromThread 01248 * 01249 * This is a callback function passed to EnumThreadWindows by 01250 * to find a top level window owned by a given thread; 01251 * ideally, we want to find a top level owner. 01252 * 01253 * 07/18/96 GerardoB Created 01254 \***************************************************************************/ 01255 BOOL CALLBACK FindWindowFromThread (HWND hwnd, LPARAM lParam) 01256 { 01257 BOOL fTopLevelOwner; 01258 #ifdef FE_IME 01259 if ( IsImeWindow(hwnd) ) { 01260 return TRUE; 01261 } 01262 #endif 01263 01264 fTopLevelOwner = (GetWindow(hwnd, GW_OWNER) == NULL); 01265 if ((*((HWND *)lParam) == NULL) || fTopLevelOwner) { 01266 *((HWND *)lParam) = hwnd; 01267 } 01268 return !fTopLevelOwner; 01269 } 01270 01271 DWORD GetRipComponent(VOID) { return RIP_USERSRV; } 01272 01273 DWORD GetDbgTagFlags(int tag) 01274 { 01275 return 0; 01276 UNREFERENCED_PARAMETER(tag); 01277 } 01278 01279 DWORD GetRipPID(VOID) { return 0; } 01280 DWORD GetRipFlags(VOID) { return gdwRIPFlags; } 01281 01282 VOID SetRipFlags(DWORD dwRipFlags, DWORD dwRipPID) 01283 { 01284 if ((dwRipFlags != (DWORD)-1) && !(dwRipFlags & ~RIPF_VALIDUSERFLAGS)) { 01285 gdwRIPFlags = (WORD)((gdwRIPFlags & ~RIPF_VALIDUSERFLAGS) | dwRipFlags); 01286 } 01287 UNREFERENCED_PARAMETER(dwRipPID); 01288 } 01289 01290 VOID SetDbgTag(int tag, DWORD dwBitFlags) 01291 { 01292 UNREFERENCED_PARAMETER(tag); 01293 UNREFERENCED_PARAMETER(dwBitFlags); 01294 } 01295 01296 VOID UserRtlRaiseStatus(NTSTATUS Status) 01297 { 01298 RtlRaiseStatus(Status); 01299 } 01300 01301 /* 01302 * We get this warning if we don't explicitly initalize gZero: 01303 * 01304 * C4132: 'gZero' : const object should be initialized 01305 * 01306 * But we can't explicitly initialize it since it is a union. So 01307 * we turn the warning off. 01308 */ 01309 #pragma warning(disable:4132) 01310 CONST ALWAYSZERO gZero; 01311 #pragma warning(default:4132)

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