00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
#include "precomp.h"
00014 
#pragma hdrstop
00015 
00016 #define OPTIONMASK (EWX_SHUTDOWN | EWX_REBOOT | EWX_FORCE)
00017 
00018 
00019 
00020 
00021 PWINDOWSTATION  gpwinstaLogoff;
00022 DWORD           gdwLocks;
00023 DWORD           gdwShutdownFlags;
00024 HANDLE          
gpidEndSession;
00025 
00026 extern PSECURITY_DESCRIPTOR 
gpsdInitWinSta;
00027 
00028 
00029 
00030 
00031 
00032 
00033 BOOL PrepareForLogoff(
00034     UINT uFlags)
00035 {
00036     
PTHREADINFO ptiCurrent = 
PtiCurrent();
00037 
00038     
CheckCritIn();
00039 
00040     
if (ptiCurrent->
TIF_flags & 
TIF_RESTRICTED) {
00041         
PW32JOB pW32Job;
00042 
00043         pW32Job = ptiCurrent->
ppi->
pW32Job;
00044 
00045         UserAssert(pW32Job != 
NULL);
00046 
00047         
if (pW32Job->
restrictions & JOB_OBJECT_UILIMIT_EXITWINDOWS) {
00048             
00049             
return FALSE;
00050         }
00051     }
00052 
00053     
00054 
00055 
00056 
00057 
00058     
if (ptiCurrent->pEThread->Cid.UniqueProcess == 
gpidLogon) {
00059         
00060 
00061 
00062         
TL tlName;
00063         PUNICODE_STRING pProfileUserName = 
CreateProfileUserName(&tlName);
00064         
RegisterPerUserKeyboardIndicators(pProfileUserName);
00065         
FreeProfileUserName(pProfileUserName, &tlName);
00066     }
00067 
00068     
return TRUE;
00069     UNREFERENCED_PARAMETER(uFlags);
00070 }
00071 
00072 
00073 
00074 
00075 
00076 
00077 BOOL NotifyLogon(
00078     
PWINDOWSTATION pwinsta,
00079     PLUID pluidCaller,
00080     DWORD dwFlags,
00081     NTSTATUS StatusCode)
00082 {
00083     
BOOL fNotified = 
FALSE;
00084     
DWORD dwllParam;
00085     
DWORD dwStatus;
00086 
00087     
if (!(
dwFlags & EWX_NONOTIFY)) {
00088 
00089         
if (
dwFlags & EWX_CANCELED) {
00090             dwllParam = LOGON_LOGOFFCANCELED;
00091             dwStatus = StatusCode;
00092         } 
else {
00093             dwllParam = LOGON_LOGOFF;
00094             dwStatus = 
dwFlags;
00095         }
00096 
00097         
if (
dwFlags & EWX_SHUTDOWN) {
00098             
00099 
00100 
00101             
if (
gspwndLogonNotify != 
NULL) {
00102                 
_PostMessage(
gspwndLogonNotify, WM_LOGONNOTIFY,
00103                              dwllParam, (LONG)dwStatus);
00104                 fNotified = 
TRUE;
00105             }
00106         } 
else {
00107             
if (
gspwndLogonNotify != 
NULL &&
00108                     (
RtlEqualLuid(&pwinsta->
luidUser, pluidCaller) ||
00109                      
RtlEqualLuid(&
luidSystem, pluidCaller))) {
00110                 
_PostMessage(
gspwndLogonNotify, WM_LOGONNOTIFY, dwllParam,
00111                         (LONG)dwStatus);
00112                 fNotified = 
TRUE;
00113             }
00114         }
00115     }
00116     
return fNotified;
00117 }
00118 
00119 NTSTATUS InitiateShutdown(
00120     
PETHREAD Thread,
00121     PULONG lpdwFlags)
00122 {
00123     
static PRIVILEGE_SET psShutdown = {
00124         1, PRIVILEGE_SET_ALL_NECESSARY, { SE_SHUTDOWN_PRIVILEGE, 0 }
00125     };
00126     
PEPROCESS Process;
00127     LUID luidCaller;
00128     
PPROCESSINFO ppi;
00129     
PWINDOWSTATION pwinsta;
00130     HWINSTA hwinsta;
00131     
PTHREADINFO ptiClient;
00132     
NTSTATUS Status;
00133     
DWORD dwFlags;
00134 
00135     
00136 
00137 
00138 
00139     Process = 
THREAD_TO_PROCESS(Thread);
00140     ptiClient = 
PtiFromThread(Thread);
00141     
Status = 
GetProcessLuid(Thread, &luidCaller);
00142 
00143     
if (!
NT_SUCCESS(
Status)) {
00144         
return Status;
00145     }
00146 
00147     
00148 
00149 
00150 
00151 
00152     
dwFlags = *lpdwFlags;
00153     
if (
RtlEqualLuid(&luidCaller, &
luidSystem)) {
00154         
dwFlags |= EWX_SYSTEM_CALLER;
00155     } 
else {
00156         
dwFlags &= ~EWX_SYSTEM_CALLER;
00157     }
00158 
00159     
00160 
00161 
00162 
00163     ppi = 
PpiFromProcess(Process);
00164     
if (ppi == 
NULL) {
00165         
00166 
00167 
00168 
00169         
return STATUS_INVALID_HANDLE;
00170     }
00171     pwinsta = ppi->
rpwinsta;
00172     hwinsta = ppi->
hwinsta;
00173     
00174 
00175 
00176 
00177     
if (Thread->
Cid.UniqueProcess != 
gpidLogon) {
00178         
dwFlags &= ~EWX_WINLOGON_CALLER;
00179         *lpdwFlags = 
dwFlags;
00180 
00181         
if (pwinsta == 
NULL) {
00182 
#ifndef LATER
00183 
            return STATUS_INVALID_HANDLE;
00184 
#else
00185 
            hwinsta = ppi->pOpenObjectTable[HI_WINDOWSTATION].h;
00186             
if (hwinsta == 
NULL) {
00187                 
return STATUS_INVALID_HANDLE;
00188             }
00189             pwinsta = (
PWINDOWSTATION)ppi->pOpenObjectTable[HI_WINDOWSTATION].phead;
00190 
#endif
00191 
        }
00192 
00193         
00194 
00195 
00196         
if (!
RtlAreAllAccessesGranted(ppi->
amwinsta, WINSTA_EXITWINDOWS)) {
00197             
return STATUS_ACCESS_DENIED;
00198         }
00199 
00200         
00201 
00202 
00203 
00204         
if (
dwFlags & EWX_SHUTDOWN) {
00205             
if (!
IsPrivileged(&psShutdown) ) {
00206                 
return STATUS_PRIVILEGE_NOT_HELD;
00207             }
00208         } 
else {
00209 
00210             
00211 
00212 
00213 
00214             
if (pwinsta->
dwWSF_Flags & 
WSF_NOIO) {
00215                 
return STATUS_INVALID_DEVICE_REQUEST;
00216             }
00217         }
00218     }
00219 
00220     
00221 
00222 
00223     
if (
gdwThreadEndSession != 0) {
00224         
DWORD dwNew;
00225 
00226         
00227 
00228 
00229 
00230         
if (!
RtlEqualLuid(&luidCaller, &
gpwinstaLogoff->
luidEndSession) &&
00231                 (
gpidEndSession != 
gpidLogon)) {
00232             
return STATUS_RETRY;
00233         }
00234 
00235         
00236 
00237 
00238         dwNew = 
dwFlags & 
OPTIONMASK & (~
gdwShutdownFlags);
00239 
00240         
00241 
00242 
00243 
00244         
if (dwNew && HandleToUlong(
PsGetCurrentThread()->Cid.UniqueThread) !=
00245                 
gdwThreadEndSession) {
00246             
00247 
00248 
00249             
if (!(
dwFlags & EWX_SHUTDOWN) &&
00250                     pwinsta != 
gpwinstaLogoff) {
00251                 
return STATUS_DEVICE_BUSY;
00252             }
00253 
00254             
00255 
00256 
00257             
gdwShutdownFlags = 
dwFlags;
00258 
00259             
if (dwNew & EWX_FORCE) {
00260                 
return STATUS_RETRY;
00261             } 
else {
00262                 
return STATUS_PENDING;
00263             }
00264         } 
else {
00265             
00266 
00267 
00268             
return STATUS_PENDING;
00269         }
00270     }
00271 
00272     
00273 
00274 
00275 
00276     
if (Thread->
Cid.UniqueProcess != 
gpidLogon) {
00277         
if (
dwFlags & EWX_NOTIFY) {
00278             
if (ptiClient && ptiClient->
TIF_flags & 
TIF_16BIT)
00279                 
gptiShutdownNotify = ptiClient;
00280             
dwFlags &= ~EWX_NOTIFY;
00281             *lpdwFlags = 
dwFlags;
00282         }
00283 
00284         
if (
NotifyLogon(pwinsta, &luidCaller, 
dwFlags, STATUS_SUCCESS))
00285             
return STATUS_PENDING;
00286         
else if (ptiClient && ptiClient->
cWindows)
00287             
return STATUS_CANT_WAIT;
00288     }
00289 
00290     
00291 
00292 
00293 
00294     
dwFlags |= EWX_WINLOGON_CALLER;
00295     *lpdwFlags = 
dwFlags;
00296     
gdwShutdownFlags = 
dwFlags;
00297 
00298     
gdwThreadEndSession = HandleToUlong(
PsGetCurrentThread()->Cid.UniqueThread);
00299     
gpidEndSession = 
PsGetCurrentThread()->Cid.UniqueProcess;
00300     
gpwinstaLogoff = pwinsta;
00301     pwinsta->
luidEndSession = luidCaller;
00302 
00303     
00304 
00305 
00306 
00307     
gdwLocks = pwinsta->dwWSF_Flags & (
WSF_SWITCHLOCK | 
WSF_OPENLOCK);
00308     pwinsta->dwWSF_Flags |= (
WSF_OPENLOCK | 
WSF_SHUTDOWN);
00309 
00310     
00311 
00312 
00313 
00314     
if (
dwFlags &
00315         (EWX_WINLOGON_OLD_SHUTDOWN | EWX_WINLOGON_OLD_REBOOT |
00316          EWX_SHUTDOWN | EWX_REBOOT)) {
00317 
00318         pwinsta->dwWSF_Flags |= 
WSF_REALSHUTDOWN;
00319     }
00320 
00321     
return STATUS_SUCCESS;
00322 }
00323 
00324 NTSTATUS EndShutdown(
00325     
PETHREAD Thread,
00326     NTSTATUS StatusShutdown)
00327 {
00328     
PWINDOWSTATION pwinsta = 
gpwinstaLogoff;
00329     
PDESKTOP pdesk;
00330     LUID luidCaller;
00331     UserAssert(
gpwinstaLogoff);
00332 
00333     
gpwinstaLogoff = 
NULL;
00334     
gpidEndSession = 
NULL;
00335     
gdwThreadEndSession = 0;
00336     pwinsta->
dwWSF_Flags &= ~
WSF_SHUTDOWN;
00337 
00338     
if (!
NT_SUCCESS(
GetProcessLuid(Thread, &luidCaller))) {
00339         luidCaller = RtlConvertUlongToLuid(0);     
00340     }
00341 
00342     
if (!
NT_SUCCESS(StatusShutdown)) {
00343 
00344         
00345 
00346 
00347 
00348         
if (
gptiShutdownNotify) {
00349             
_PostThreadMessage(
gptiShutdownNotify, WM_ENDSESSION, 
FALSE, 0);
00350             
gptiShutdownNotify = 
NULL;
00351         }
00352 
00353         
00354 
00355 
00356 
00357         pwinsta->
dwWSF_Flags =
00358                 (pwinsta->
dwWSF_Flags & ~
WSF_OPENLOCK) |
00359                 
gdwLocks;
00360 
00361         
00362 
00363 
00364 
00365         
NotifyLogon(pwinsta, &luidCaller, 
gdwShutdownFlags | EWX_CANCELED, StatusShutdown);
00366 
00367         
return STATUS_SUCCESS;
00368     }
00369 
00370     
gptiShutdownNotify = 
NULL;
00371 
00372     
00373 
00374 
00375 
00376 
00377     
if (((pwinsta->
luidUser.LowPart != 0) || (pwinsta->
luidUser.HighPart != 0)) &&
00378             
RtlEqualLuid(&pwinsta->
luidUser, &luidCaller)) {
00379 
00380         
00381 
00382 
00383         
for (pdesk = pwinsta->
rpdeskList; pdesk != 
NULL; pdesk = pdesk->
rpdeskNext) {
00384             
RtlZeroHeap(Win32HeapGetHandle(pdesk->
pheapDesktop), 0);
00385         }
00386 
00387         
00388 
00389 
00390 
00391 
00392         
ForceEmptyClipboard(pwinsta);
00393 
00394         
00395 
00396 
00397 
00398         
RtlEmptyAtomTable(pwinsta->
pGlobalAtomTable, 
FALSE);
00399 
00400         
00401         
00402         
00403 
00404         
if (
TEST_PUDF(
PUDF_FONTSARELOADED)) {
00405             
LeaveCrit();
00406             GreRemoveAllButPermanentFonts();
00407             
EnterCrit();
00408             
CLEAR_PUDF(
PUDF_FONTSARELOADED);
00409         }
00410     } 
else {
00411         pwinsta->
dwWSF_Flags &= ~
WSF_OPENLOCK;
00412     }
00413 
00414     
00415 
00416 
00417     
NotifyLogon(pwinsta, &luidCaller, 
gdwShutdownFlags, STATUS_SUCCESS);
00418 
00419     
return STATUS_SUCCESS;
00420 }
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 LONG 
xxxClientShutdown2(
00429     
PBWL pbwl,
00430     UINT msg,
00431     WPARAM wParam)
00432 {
00433     HWND *phwnd;
00434     
PWND pwnd;
00435     
TL tlpwnd;
00436     
BOOL fEnd;
00437     
PTHREADINFO ptiCurrent = 
PtiCurrent();
00438     
BOOL fDestroyTimers;
00439     LPARAM lParam;
00440 
00441     
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455      fDestroyTimers = (wParam & 
WMCS_EXIT) && (wParam & 
WMCS_CONTEXTLOGOFF);
00456 
00457      
00458 
00459 
00460      lParam = wParam & ENDSESSION_LOGOFF;
00461      wParam &= 
WMCS_EXIT;
00462 
00463     
00464 
00465 
00466 
00467     
for (phwnd = pbwl->
rghwnd; *phwnd != (HWND)1; phwnd++) {
00468         
if ((pwnd = 
RevalidateHwnd(*phwnd)) == 
NULL)
00469             
continue;
00470 
00471         
ThreadLockAlways(pwnd, &tlpwnd);
00472 
00473         
00474 
00475 
00476         
switch (
msg) {
00477         
case WM_QUERYENDSESSION:
00478 
00479             
00480 
00481 
00482 
00483             
if (ptiCurrent == 
gptiShutdownNotify) {
00484                 fEnd = 
TRUE;
00485             } 
else {
00486                 fEnd = (
xxxSendMessage(pwnd, WM_QUERYENDSESSION, 
FALSE, lParam) != 0);
00487                 
if (!fEnd) {
00488                     RIPMSG2(RIP_WARNING, 
"xxxClientShutdown2: pwnd:%p canceled shutdown. lParam:%p",
00489                             pwnd, lParam);
00490                 }
00491             }
00492             
break;
00493 
00494         
case WM_ENDSESSION:
00495             
xxxSendMessage(pwnd, WM_ENDSESSION, wParam, lParam);
00496             fEnd = 
TRUE;
00497 
00498             
if (fDestroyTimers) {
00499                 
DestroyWindowsTimers(pwnd);
00500             }
00501 
00502             
break;
00503         }
00504 
00505         
ThreadUnlock(&tlpwnd);
00506 
00507         
if (!fEnd)
00508             
return WMCSR_CANCEL;
00509     }
00510 
00511     
return WMCSR_ALLOWSHUTDOWN;
00512 }
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520 
00521 LONG 
xxxClientShutdown(
00522     
PWND pwnd,
00523     WPARAM wParam)
00524 {
00525     
PBWL pbwl;
00526     
PTHREADINFO ptiT;
00527     LONG lRet;
00528 
00529     
00530 
00531 
00532     ptiT = 
GETPTI(pwnd);
00533 
00534     
if ((pbwl = 
BuildHwndList(ptiT->
rpdesk->
pDeskInfo->
spwnd->
spwndChild,
00535             
BWL_ENUMLIST, ptiT)) == 
NULL) {
00536         
00537 
00538 
00539 
00540         
return WMCSR_ALLOWSHUTDOWN;
00541     }
00542 
00543     
if (wParam & 
WMCS_QUERYEND) {
00544         lRet = 
xxxClientShutdown2(pbwl, WM_QUERYENDSESSION, wParam);
00545     } 
else {
00546         
xxxClientShutdown2(pbwl, WM_ENDSESSION, wParam);
00547         lRet = 
WMCSR_DONE;
00548     }
00549 
00550     
FreeHwndList(pbwl);
00551     
return lRet;
00552 }
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 BOOL xxxRegisterUserHungAppHandlers(
00566     PFNW32ET pfnW32EndTask,
00567     HANDLE   hEventWowExec)
00568 {
00569     
BOOL   bRetVal;
00570     
PPROCESSINFO    ppi;
00571     
PWOWPROCESSINFO pwpi;
00572 
00573     
00574     
00575     
00576     
00577     pwpi = (
PWOWPROCESSINFO) UserAllocPoolWithQuotaZInit(
00578             
sizeof(
WOWPROCESSINFO), TAG_WOWPROCESSINFO);
00579 
00580     
if (!pwpi)
00581         
return FALSE;
00582 
00583     
00584     
00585     
00586     bRetVal = 
NT_SUCCESS(
ObReferenceObjectByHandle(
00587                  hEventWowExec,
00588                  EVENT_ALL_ACCESS,
00589                  *
ExEventObjectType,
00590                  
UserMode,
00591                  &pwpi->
pEventWowExec,
00592                  
NULL
00593                  ));
00594 
00595     
00596     
00597     
00598     
00599     
if (bRetVal) {
00600         pwpi->
hEventWowExecClient = hEventWowExec;
00601         pwpi->
lpfnWowExitTask = pfnW32EndTask;
00602         ppi = 
PpiCurrent();
00603         ppi->
pwpi = pwpi;
00604 
00605         
00606         pwpi->
pwpiNext = 
gpwpiFirstWow;
00607         
gpwpiFirstWow  = pwpi;
00608 
00609         }
00610     
else {
00611         UserFreePool(pwpi);
00612         }
00613 
00614    
return bRetVal;
00615 }