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

power.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: power.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains the code to implement power management. 00007 * 00008 * History: 00009 * 02-Dec-1996 JerrySh Created. 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 #include <ntcsrmsg.h> 00016 #include "csrmsg.h" 00017 #include "ntddvdeo.h" 00018 00019 #pragma alloc_text(INIT, InitializePowerRequestList) 00020 00021 extern BOOL gbUserInitialized; 00022 extern BOOL fGdiEnabled; 00023 00024 LIST_ENTRY gPowerRequestList; 00025 PFAST_MUTEX gpPowerRequestMutex; 00026 PKEVENT gpEventPowerRequest; 00027 BOOL gbHibernate = FALSE; 00028 00029 typedef struct tagPOWERREQUEST { 00030 LIST_ENTRY PowerRequestLink; 00031 KEVENT Event; 00032 NTSTATUS Status; 00033 PKWIN32_POWEREVENT_PARAMETERS Parms; 00034 } POWERREQUEST, *PPOWERREQUEST; 00035 00036 PPOWERREQUEST gpPowerRequestCurrent; 00037 00038 __inline VOID EnterPowerCrit() { 00039 KeEnterCriticalRegion(); 00040 ExAcquireFastMutexUnsafe(gpPowerRequestMutex); 00041 } 00042 00043 __inline VOID LeavePowerCrit() { 00044 ExReleaseFastMutexUnsafe(gpPowerRequestMutex); 00045 KeLeaveCriticalRegion(); 00046 } 00047 00048 /***************************************************************************\ 00049 * CancelPowerRequest 00050 * 00051 * The power request can't be satisfied because the worker thread is gone. 00052 * 00053 * History: 00054 * 20-Oct-1998 JerrySh Created. 00055 \***************************************************************************/ 00056 00057 VOID 00058 CancelPowerRequest( 00059 PPOWERREQUEST pPowerRequest) 00060 { 00061 UserAssert(pPowerRequest != gpPowerRequestCurrent); 00062 pPowerRequest->Status = STATUS_UNSUCCESSFUL; 00063 KeSetEvent(&pPowerRequest->Event, EVENT_INCREMENT, FALSE); 00064 } 00065 00066 /***************************************************************************\ 00067 * QueuePowerRequest 00068 * 00069 * Insert a power request into the list and wakeup CSRSS to process it. 00070 * 00071 * History: 00072 * 20-Oct-1998 JerrySh Created. 00073 \***************************************************************************/ 00074 00075 NTSTATUS 00076 QueuePowerRequest( 00077 PKWIN32_POWEREVENT_PARAMETERS Parms) 00078 { 00079 NTSTATUS Status = STATUS_SUCCESS; 00080 PPOWERREQUEST pPowerRequest; 00081 TL tlPool; 00082 00083 UserAssert(gpEventPowerRequest != NULL); 00084 UserAssert(gpPowerRequestMutex != NULL); 00085 00086 /* 00087 * Allocate and initialize the power request. 00088 */ 00089 pPowerRequest = UserAllocPoolNonPaged(sizeof(POWERREQUEST), TAG_POWER); 00090 if (pPowerRequest == NULL) { 00091 return STATUS_NO_MEMORY; 00092 } 00093 KeInitializeEvent(&pPowerRequest->Event, SynchronizationEvent, FALSE); 00094 pPowerRequest->Parms = Parms; 00095 00096 /* 00097 * Insert the power request into the list. 00098 */ 00099 EnterPowerCrit(); 00100 if (gbNoMorePowerCallouts) { 00101 Status = STATUS_UNSUCCESSFUL; 00102 } else { 00103 InsertHeadList(&gPowerRequestList, &pPowerRequest->PowerRequestLink); 00104 } 00105 LeavePowerCrit(); 00106 00107 /* 00108 * If this is a system thread or a non-GUI thread, tell CSRSS to do the 00109 * work and wait for it to finish. Otherwise, we'll do the work ourselves. 00110 */ 00111 if (NT_SUCCESS(Status)) { 00112 if (IS_SYSTEM_THREAD(PsGetCurrentThread()) || 00113 W32GetCurrentThread() == NULL) { 00114 KeSetEvent(gpEventPowerRequest, EVENT_INCREMENT, FALSE); 00115 } else { 00116 EnterCrit(); 00117 ThreadLockPool(PtiCurrent(), pPowerRequest, &tlPool); 00118 xxxUserPowerCalloutWorker(); 00119 ThreadUnlockPool(PtiCurrent(), &tlPool); 00120 LeaveCrit(); 00121 } 00122 Status = KeWaitForSingleObject(&pPowerRequest->Event, 00123 WrUserRequest, 00124 KernelMode, 00125 FALSE, 00126 NULL); 00127 00128 if (NT_SUCCESS(Status)) { 00129 Status = pPowerRequest->Status; 00130 } 00131 } 00132 00133 /* 00134 * Free the power request. 00135 */ 00136 UserAssert(pPowerRequest != gpPowerRequestCurrent); 00137 UserFreePool(pPowerRequest); 00138 00139 return Status; 00140 } 00141 00142 /***************************************************************************\ 00143 * UnqueuePowerRequest 00144 * 00145 * Remove a power request from the list. 00146 * 00147 * History: 00148 * 20-Oct-1998 JerrySh Created. 00149 \***************************************************************************/ 00150 00151 PPOWERREQUEST 00152 UnqueuePowerRequest(VOID) 00153 { 00154 PLIST_ENTRY pEntry; 00155 PPOWERREQUEST pPowerRequest = NULL; 00156 00157 /* 00158 * Remove a power request from the list. 00159 */ 00160 EnterPowerCrit(); 00161 if (!IsListEmpty(&gPowerRequestList)) { 00162 pEntry = RemoveTailList(&gPowerRequestList); 00163 pPowerRequest = CONTAINING_RECORD(pEntry, POWERREQUEST, PowerRequestLink); 00164 } 00165 LeavePowerCrit(); 00166 00167 return pPowerRequest; 00168 } 00169 00170 /***************************************************************************\ 00171 * InitializePowerRequestList 00172 * 00173 * Initialize global power request list state. 00174 * 00175 * History: 00176 * 20-Oct-1998 JerrySh Created. 00177 \***************************************************************************/ 00178 00179 NTSTATUS 00180 InitializePowerRequestList( 00181 HANDLE hPowerRequestEvent) 00182 { 00183 NTSTATUS Status; 00184 00185 InitializeListHead(&gPowerRequestList); 00186 00187 Status = ObReferenceObjectByHandle(hPowerRequestEvent, 00188 EVENT_ALL_ACCESS, 00189 *ExEventObjectType, 00190 KernelMode, 00191 &gpEventPowerRequest, 00192 NULL); 00193 if (!NT_SUCCESS(Status)) { 00194 return Status; 00195 } 00196 00197 gpPowerRequestMutex = UserAllocPoolNonPaged(sizeof(FAST_MUTEX), TAG_POWER); 00198 if (gpPowerRequestMutex == NULL) { 00199 return STATUS_NO_MEMORY; 00200 } 00201 ExInitializeFastMutex(gpPowerRequestMutex); 00202 00203 return STATUS_SUCCESS; 00204 } 00205 00206 /***************************************************************************\ 00207 * CleanupPowerRequestList 00208 * 00209 * Cancel any pending power requests. 00210 * 00211 * History: 00212 * 20-Oct-1998 JerrySh Created. 00213 \***************************************************************************/ 00214 00215 VOID 00216 CleanupPowerRequestList(VOID) 00217 { 00218 PPOWERREQUEST pPowerRequest; 00219 00220 /* 00221 * Make sure no new power requests come in. 00222 */ 00223 gbNoMorePowerCallouts = TRUE; 00224 00225 /* 00226 * If we never allocated anything, there's nothing to clean up. 00227 */ 00228 if (gpPowerRequestMutex == NULL) { 00229 return; 00230 } 00231 00232 /* 00233 * Mark any pending power requests as cacelled. 00234 */ 00235 while ((pPowerRequest = UnqueuePowerRequest()) != NULL) { 00236 CancelPowerRequest(pPowerRequest); 00237 } 00238 } 00239 00240 /***************************************************************************\ 00241 * DeletePowerRequestList 00242 * 00243 * Clean up any global power request state. 00244 * 00245 * History: 00246 * 20-Oct-1998 JerrySh Created. 00247 \***************************************************************************/ 00248 00249 VOID 00250 DeletePowerRequestList(VOID) 00251 { 00252 if (gpPowerRequestMutex) { 00253 00254 /* 00255 * Make sure there are no pending power requests. 00256 */ 00257 UserAssert(IsListEmpty(&gPowerRequestList)); 00258 00259 /* 00260 * Free the power request structures. 00261 */ 00262 UserFreePool(gpPowerRequestMutex); 00263 gpPowerRequestMutex = NULL; 00264 } 00265 } 00266 00267 /***************************************************************************\ 00268 * UserPowerEventCalloutWorker 00269 * 00270 * History: 00271 * 02-Dec-1996 JerrySh Created. 00272 \***************************************************************************/ 00273 00274 NTSTATUS xxxUserPowerEventCalloutWorker( 00275 PKWIN32_POWEREVENT_PARAMETERS Parms) 00276 { 00277 BROADCASTSYSTEMMSGPARAMS bsmParams; 00278 NTSTATUS Status = STATUS_SUCCESS; 00279 PSPOWEREVENTTYPE EventNumber = Parms->EventNumber; 00280 ULONG_PTR Code = Parms->Code; 00281 BOOL bCurrentPowerOn; 00282 00283 /* 00284 * Make sure CSRSS is still running. 00285 */ 00286 if (gbNoMorePowerCallouts) { 00287 return STATUS_UNSUCCESSFUL; 00288 } 00289 00290 switch (EventNumber) { 00291 case PsW32FullWake: 00292 /* 00293 * Let all the applications know that they can resume operation. 00294 */ 00295 bsmParams.dwRecipients = BSM_ALLDESKTOPS; 00296 bsmParams.dwFlags = BSF_QUEUENOTIFYMESSAGE; 00297 xxxSendMessageBSM(NULL, 00298 WM_POWERBROADCAST, 00299 PBT_APMRESUMESUSPEND, 00300 0, 00301 &bsmParams); 00302 break; 00303 00304 case PsW32EventCode: 00305 /* 00306 * Post a message to winlogon, and let them put up a message box 00307 * or play a sound. 00308 */ 00309 00310 if (gspwndLogonNotify) { 00311 _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY, LOGON_PLAYPOWERSOUND, (ULONG)Code); 00312 Status = STATUS_SUCCESS; 00313 } else { 00314 Status = STATUS_UNSUCCESSFUL; 00315 } 00316 00317 break; 00318 00319 case PsW32PowerPolicyChanged: 00320 /* 00321 * Set video timeout value. 00322 */ 00323 xxxSystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, (ULONG)Code, 0, 0); 00324 xxxSystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, (ULONG)Code, 0, 0); 00325 break; 00326 00327 case PsW32SystemPowerState: 00328 /* 00329 * Let all the applications know that the power status has changed. 00330 */ 00331 bsmParams.dwRecipients = BSM_ALLDESKTOPS; 00332 bsmParams.dwFlags = BSF_POSTMESSAGE; 00333 xxxSendMessageBSM(NULL, 00334 WM_POWERBROADCAST, 00335 PBT_APMPOWERSTATUSCHANGE, 00336 0, 00337 &bsmParams); 00338 break; 00339 00340 case PsW32SystemTime: 00341 /* 00342 * Let all the applications know that the system time has changed. 00343 */ 00344 bsmParams.dwRecipients = BSM_ALLDESKTOPS; 00345 bsmParams.dwFlags = BSF_POSTMESSAGE; 00346 xxxSendMessageBSM(NULL, 00347 WM_TIMECHANGE, 00348 0, 00349 0, 00350 &bsmParams); 00351 break; 00352 00353 case PsW32DisplayState: 00354 /* 00355 * Set video timeout active status. 00356 */ 00357 xxxSystemParametersInfo(SPI_SETLOWPOWERACTIVE, !Code, 0, 0); 00358 xxxSystemParametersInfo(SPI_SETPOWEROFFACTIVE, !Code, 0, 0); 00359 break; 00360 00361 case PsW32GdiOff: 00362 /* 00363 * At this point we will disable the display device 00364 */ 00365 00366 DrvSetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD3); 00367 00368 bCurrentPowerOn = DrvQueryMDEVPowerState(gpDispInfo->pmdev); 00369 if (bCurrentPowerOn) { 00370 DrvDisableMDEV(gpDispInfo->pmdev, TRUE); 00371 } 00372 DrvSetMDEVPowerState(gpDispInfo->pmdev, FALSE); 00373 00374 break; 00375 00376 case PsW32GdiOn: 00377 /* 00378 * Call video driver to turn the display back on. 00379 */ 00380 bCurrentPowerOn = DrvQueryMDEVPowerState(gpDispInfo->pmdev); 00381 if (!bCurrentPowerOn) { 00382 DrvEnableMDEV(gpDispInfo->pmdev, TRUE); 00383 } 00384 DrvSetMDEVPowerState(gpDispInfo->pmdev, TRUE); 00385 DrvSetMonitorPowerState(gpDispInfo->pmdev, PowerDeviceD0); 00386 00387 /* 00388 * Repaint the whole screen 00389 */ 00390 xxxUserResetDisplayDevice(); 00391 00392 if (gbHibernate) 00393 { 00394 HANDLE pdo; 00395 00396 PVOID PhysDisp = DrvWakeupHandler(&pdo); 00397 00398 if (PhysDisp) 00399 { 00400 UNICODE_STRING strDeviceName; 00401 DEVMODEW NewMode; 00402 ULONG bPrune; 00403 00404 if (DrvDisplaySwitchHandler(PhysDisp, &strDeviceName, &NewMode, &bPrune)) 00405 { 00406 /* 00407 * CSRSS is not the only process to diliver power callout 00408 */ 00409 if (!ISCSRSS()) { 00410 xxxUserChangeDisplaySettings(NULL, NULL, NULL, grpdeskRitInput, 00411 ((bPrune) ? 0 : CDS_RAWMODE) | CDS_TRYCLOSEST | CDS_RESET, 0, KernelMode); 00412 } 00413 else 00414 { 00415 DESKRESTOREDATA drdRestore; 00416 00417 drdRestore.pdeskRestore = NULL; 00418 if (NT_SUCCESS (xxxSetCsrssThreadDesktop(grpdeskRitInput, &drdRestore)) ) 00419 { 00420 xxxUserChangeDisplaySettings(NULL, NULL, NULL, NULL, 00421 ((bPrune) ? 0 : CDS_RAWMODE) | CDS_TRYCLOSEST | CDS_RESET, 0, KernelMode); 00422 xxxRestoreCsrssThreadDesktop(&drdRestore); 00423 } 00424 } 00425 } 00426 00427 // 00428 // If there is a requirement to reenumerate sub-devices 00429 // 00430 if (pdo) 00431 { 00432 IoInvalidateDeviceRelations((PDEVICE_OBJECT)pdo, BusRelations); 00433 } 00434 } 00435 } 00436 gbHibernate = FALSE; 00437 00438 break; 00439 00440 default: 00441 Status = STATUS_NOT_IMPLEMENTED; 00442 break; 00443 } 00444 00445 return Status; 00446 } 00447 00448 /***************************************************************************\ 00449 * UserPowerEventCallout 00450 * 00451 * History: 00452 * 02-Dec-1996 JerrySh Created. 00453 \***************************************************************************/ 00454 00455 NTSTATUS UserPowerEventCallout( 00456 PKWIN32_POWEREVENT_PARAMETERS Parms) 00457 { 00458 00459 /* 00460 * Make sure CSRSS is running. 00461 */ 00462 if (!gbVideoInitialized || gbNoMorePowerCallouts) { 00463 return STATUS_UNSUCCESSFUL; 00464 } 00465 00466 UserAssert(gpepCSRSS != NULL); 00467 00468 /* 00469 * Process the power request. 00470 */ 00471 return QueuePowerRequest(Parms); 00472 } 00473 00474 /***************************************************************************\ 00475 * UserPowerStateCalloutWorker 00476 * 00477 * History: 00478 * 02-Dec-1996 JerrySh Created. 00479 \***************************************************************************/ 00480 00481 NTSTATUS xxxUserPowerStateCalloutWorker(VOID) 00482 { 00483 BOOL fContinue; 00484 BROADCASTSYSTEMMSGPARAMS bsmParams; 00485 NTSTATUS Status = STATUS_SUCCESS; 00486 TL tlpwnd; 00487 00488 /* 00489 * Make sure CSRSS is still running. 00490 */ 00491 if (gbNoMorePowerCallouts) { 00492 return STATUS_UNSUCCESSFUL; 00493 } 00494 00495 /* 00496 * Store the event so this thread can be promoted later. 00497 */ 00498 EnterPowerCrit(); 00499 gPowerState.pEvent = PtiCurrent()->pEventQueueServer; 00500 LeavePowerCrit(); 00501 00502 if (!gPowerState.fCritical) { 00503 /* 00504 * Ask the applications if we can suspend operation. 00505 */ 00506 if (gPowerState.fQueryAllowed) { 00507 gPowerState.bsmParams.dwRecipients = BSM_ALLDESKTOPS; 00508 gPowerState.bsmParams.dwFlags = BSF_NOHANG | BSF_FORCEIFHUNG; 00509 if (gPowerState.fUIAllowed) { 00510 gPowerState.bsmParams.dwFlags |= BSF_ALLOWSFW; 00511 } 00512 if (gPowerState.fOverrideApps == FALSE) { 00513 gPowerState.bsmParams.dwFlags |= (BSF_QUERY | BSF_NOTIMEOUTIFNOTHUNG); 00514 } 00515 fContinue = xxxSendMessageBSM(NULL, 00516 WM_POWERBROADCAST, 00517 PBT_APMQUERYSUSPEND, 00518 gPowerState.fUIAllowed, 00519 &gPowerState.bsmParams); 00520 00521 /* 00522 * If an app says to abort and we're not in override apps or 00523 * critical mode, send out the suspend failed message and bail. 00524 */ 00525 if (!(fContinue || gPowerState.fOverrideApps || gPowerState.fCritical)) { 00526 gPowerState.bsmParams.dwRecipients = BSM_ALLDESKTOPS; 00527 gPowerState.bsmParams.dwFlags = BSF_QUEUENOTIFYMESSAGE; 00528 xxxSendMessageBSM(NULL, 00529 WM_POWERBROADCAST, 00530 PBT_APMQUERYSUSPENDFAILED, 00531 0, 00532 &gPowerState.bsmParams); 00533 EnterPowerCrit(); 00534 gPowerState.pEvent = NULL; 00535 gPowerState.fInProgress = FALSE; 00536 LeavePowerCrit(); 00537 return STATUS_CANCELLED; 00538 } 00539 } 00540 00541 /* 00542 * Let all the applications know they should suspend operation. 00543 */ 00544 if (!gPowerState.fCritical) { 00545 gPowerState.bsmParams.dwRecipients = BSM_ALLDESKTOPS; 00546 gPowerState.bsmParams.dwFlags = BSF_NOHANG | BSF_FORCEIFHUNG; 00547 xxxSendMessageBSM(NULL, 00548 WM_POWERBROADCAST, 00549 PBT_APMSUSPEND, 00550 0, 00551 &gPowerState.bsmParams); 00552 } 00553 } 00554 00555 /* 00556 * Clear the event so the thread won't wake up prematurely. 00557 */ 00558 EnterPowerCrit(); 00559 gPowerState.pEvent = NULL; 00560 LeavePowerCrit(); 00561 00562 /* 00563 * Look for a Winlogon window to notify. 00564 */ 00565 if (gspwndLogonNotify != NULL) { 00566 gPowerState.psParams.FullScreenMode = !fGdiEnabled; 00567 ThreadLockAlways(gspwndLogonNotify, &tlpwnd); 00568 Status = (NTSTATUS)xxxSendMessage(gspwndLogonNotify, 00569 WM_LOGONNOTIFY, 00570 LOGON_POWERSTATE, 00571 (LPARAM)&gPowerState.psParams); 00572 ThreadUnlock(&tlpwnd); 00573 } 00574 00575 /* 00576 * The power state broadcast is over. 00577 */ 00578 EnterPowerCrit(); 00579 gPowerState.fInProgress = FALSE; 00580 LeavePowerCrit(); 00581 00582 /* 00583 * Tickle the input time so we don't fire up a screen saver right away. 00584 */ 00585 glinp.timeLastInputMessage = NtGetTickCount(); 00586 00587 /* 00588 * Let all the applications know that we're waking up. 00589 */ 00590 bsmParams.dwRecipients = BSM_ALLDESKTOPS; 00591 bsmParams.dwFlags = BSF_QUEUENOTIFYMESSAGE; 00592 xxxSendMessageBSM(NULL, 00593 WM_POWERBROADCAST, 00594 PBT_APMRESUMEAUTOMATIC, 00595 0, 00596 &bsmParams); 00597 00598 return Status; 00599 } 00600 00601 /***************************************************************************\ 00602 * UserPowerStateCallout 00603 * 00604 * History: 00605 * 02-Dec-1996 JerrySh Created. 00606 \***************************************************************************/ 00607 00608 NTSTATUS UserPowerStateCallout( 00609 PKWIN32_POWERSTATE_PARAMETERS Parms) 00610 { 00611 BOOLEAN Promotion = Parms->Promotion; 00612 POWER_ACTION SystemAction = Parms->SystemAction; 00613 SYSTEM_POWER_STATE MinSystemState = Parms->MinSystemState; 00614 ULONG Flags = Parms->Flags; 00615 00616 /* 00617 * Make sure CSRSS is running. 00618 */ 00619 if (!gbVideoInitialized || gbNoMorePowerCallouts || !gspwndLogonNotify) { 00620 return STATUS_UNSUCCESSFUL; 00621 } 00622 00623 UserAssert(gpepCSRSS != NULL); 00624 00625 EnterPowerCrit(); 00626 00627 /* 00628 * Make sure we're not trying to promote a non-existent request 00629 * or start a new one when we're already doing it. 00630 */ 00631 if ((Promotion && !gPowerState.fInProgress) || 00632 (!Promotion && gPowerState.fInProgress)) { 00633 LeavePowerCrit(); 00634 return STATUS_INVALID_PARAMETER; 00635 } 00636 00637 /* 00638 * Save our state. 00639 */ 00640 gPowerState.fInProgress = TRUE; 00641 gPowerState.fOverrideApps = (Flags & POWER_ACTION_OVERRIDE_APPS) != 0; 00642 gPowerState.fCritical = (Flags & POWER_ACTION_CRITICAL) != 0; 00643 gPowerState.fQueryAllowed = (Flags & POWER_ACTION_QUERY_ALLOWED) != 0; 00644 gPowerState.fUIAllowed = (Flags & POWER_ACTION_UI_ALLOWED) != 0; 00645 gPowerState.psParams.SystemAction = SystemAction; 00646 gPowerState.psParams.MinSystemState = MinSystemState; 00647 gPowerState.psParams.Flags = Flags; 00648 if (gPowerState.fOverrideApps) { 00649 gPowerState.bsmParams.dwFlags = BSF_NOHANG | BSF_FORCEIFHUNG; 00650 } 00651 if (gPowerState.fCritical) { 00652 gPowerState.bsmParams.dwFlags = BSF_NOHANG | BSF_QUERY; 00653 } 00654 if (gPowerState.pEvent) { 00655 KeSetEvent(gPowerState.pEvent, EVENT_INCREMENT, FALSE); 00656 } 00657 00658 LeavePowerCrit(); 00659 00660 /* 00661 * If this is a promotion, we're done. 00662 */ 00663 if (Promotion) { 00664 return STATUS_SUCCESS; 00665 } 00666 00667 /* 00668 * Process the power request. 00669 */ 00670 return QueuePowerRequest(NULL); 00671 } 00672 00673 /***************************************************************************\ 00674 * UserPowerCalloutWorker 00675 * 00676 * Pull any pending power requests off the list and call the appropriate 00677 * power callout function. 00678 * 00679 * History: 00680 * 02-Dec-1996 JerrySh Created. 00681 \***************************************************************************/ 00682 00683 VOID 00684 xxxUserPowerCalloutWorker(VOID) 00685 { 00686 PPOWERREQUEST pPowerRequest; 00687 TL tlPool; 00688 00689 while ((pPowerRequest = UnqueuePowerRequest()) != NULL) { 00690 /* 00691 * Make sure the event gets signalled even if the thread dies in a 00692 * callback or the waiting thread might get stuck. 00693 */ 00694 ThreadLockPoolCleanup(PtiCurrent(), pPowerRequest, &tlPool, CancelPowerRequest); 00695 00696 /* 00697 * Call the appropriate power worker function. 00698 */ 00699 gpPowerRequestCurrent = pPowerRequest; 00700 if (pPowerRequest->Parms) { 00701 pPowerRequest->Status = xxxUserPowerEventCalloutWorker(pPowerRequest->Parms); 00702 } else { 00703 pPowerRequest->Status = xxxUserPowerStateCalloutWorker(); 00704 } 00705 gpPowerRequestCurrent = NULL; 00706 00707 /* 00708 * Tell the waiting thread to proceed. 00709 */ 00710 ThreadUnlockPoolCleanup(PtiCurrent(), &tlPool); 00711 KeSetEvent(&pPowerRequest->Event, EVENT_INCREMENT, FALSE); 00712 } 00713 } 00714 00715 00716 00717 /***************************************************************************\ 00718 * VideoPortCalloutThread 00719 * 00720 * Call the appropriate power callout function and return. 00721 * 00722 * History: 00723 * 02-Dec-1996 JerrySh Created. 00724 \***************************************************************************/ 00725 00726 VOID 00727 VideoPortCalloutThread( 00728 PVIDEO_WIN32K_CALLBACKS_PARAMS Params 00729 ) 00730 { 00731 00732 /* 00733 * Convert this thread to GUI if it's not already converted 00734 */ 00735 UserAssert(W32GetCurrentThread() == NULL); 00736 00737 Params->Status = InitSystemThread(NULL); 00738 00739 if (!NT_SUCCESS(Params->Status)) { 00740 return; 00741 } 00742 00743 // DbgPrint("video --- Before CritSect\n"); 00744 EnterCrit(); 00745 // DbgPrint("video --- After CritSect\n"); 00746 00747 00748 switch (Params->CalloutType) { 00749 00750 case VideoWakeupCallout: 00751 gbHibernate = TRUE; 00752 break; 00753 00754 case VideoDisplaySwitchCallout: 00755 { 00756 UNICODE_STRING strDeviceName; 00757 DEVMODEW NewMode; 00758 ULONG bPrune; 00759 00760 if (Params->PhysDisp != NULL) 00761 { 00762 if (DrvDisplaySwitchHandler(Params->PhysDisp, &strDeviceName, &NewMode, &bPrune)) 00763 { 00764 DESKRESTOREDATA drdRestore; 00765 00766 drdRestore.pdeskRestore = NULL; 00767 00768 /* 00769 * CSRSS is not the only process to diliver power callout 00770 */ 00771 00772 if (!ISCSRSS() || 00773 NT_SUCCESS (xxxSetCsrssThreadDesktop(grpdeskRitInput, &drdRestore)) ) 00774 { 00775 if (!DrvQueryMDEVPowerState(gpDispInfo->pmdev)) { 00776 00777 DrvEnableMDEV(gpDispInfo->pmdev, TRUE); 00778 DrvSetMDEVPowerState(gpDispInfo->pmdev, TRUE); 00779 } 00780 00781 xxxUserChangeDisplaySettings(NULL, NULL, NULL, grpdeskRitInput, 00782 ((bPrune) ? 0 : CDS_RAWMODE) | CDS_TRYCLOSEST | CDS_RESET, 0, KernelMode); 00783 00784 if (ISCSRSS()) 00785 { 00786 xxxRestoreCsrssThreadDesktop(&drdRestore); 00787 } 00788 } 00789 } 00790 } 00791 } 00792 00793 // 00794 // If there is a requirement to reenumerate sub-devices 00795 // 00796 if (Params->Param) 00797 { 00798 IoInvalidateDeviceRelations((PDEVICE_OBJECT)Params->Param, BusRelations); 00799 } 00800 00801 Params->Status = STATUS_SUCCESS; 00802 break; 00803 00804 case VideoFindAdapterCallout: 00805 00806 if (Params->Param) { 00807 00808 DrvEnableMDEV(gpDispInfo->pmdev, TRUE); 00809 xxxUserResetDisplayDevice(); 00810 00811 } else { 00812 00813 DrvDisableMDEV(gpDispInfo->pmdev, TRUE); 00814 } 00815 00816 Params->Status = STATUS_SUCCESS; 00817 break; 00818 00819 default: 00820 00821 UserAssert(FALSE); 00822 00823 Params->Status = STATUS_UNSUCCESSFUL; 00824 00825 } 00826 00827 00828 // DbgPrint("video --- Before Leave CritSect\n"); 00829 LeaveCrit(); 00830 // DbgPrint("video --- After Leave CritSect\n"); 00831 00832 00833 return; 00834 } 00835 00836 00837 /***************************************************************************\ 00838 * VideoPortCallout 00839 * 00840 * History: 00841 * 26-Jul-1998 AndreVa Created. 00842 \***************************************************************************/ 00843 00844 VOID 00845 VideoPortCallout( 00846 IN PVOID Params 00847 ) 00848 { 00849 00850 /* 00851 * To make sure this is a system thread, we create a new thread. 00852 */ 00853 00854 HANDLE hThread; 00855 NTSTATUS Status; 00856 00857 // DbgPrint("Callout --- Enter !!!\n"); 00858 00859 Status = CreateSystemThread(VideoPortCalloutThread, Params, &hThread); 00860 if (NT_SUCCESS(Status)) { 00861 Status = NtWaitForSingleObject(hThread, FALSE, NULL); 00862 if (NT_SUCCESS(Status)) { 00863 Status = ((PVIDEO_WIN32K_CALLBACKS_PARAMS)(Params))->Status; 00864 } 00865 ZwClose(hThread); 00866 } 00867 00868 // DbgPrint("Callout --- Leave !!!\n"); 00869 00870 ((PVIDEO_WIN32K_CALLBACKS_PARAMS)(Params))->Status = Status; 00871 }

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