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 }