test: power.c Source File

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 }