00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
#include "precomp.h"
00014
#pragma hdrstop
00015
00016 #define BEGIN_LPC_RECV(API) \
00017
P##API##MSG a = (P##API##MSG)&m->u.ApiMessageData; \
00018
PCSR_THREAD pcsrt; \
00019
PTEB Teb = NtCurrentTeb(); \
00020
NTSTATUS Status = STATUS_SUCCESS; \
00021
UNREFERENCED_PARAMETER(ReplyStatus); \
00022
\
00023
Teb->LastErrorValue = 0; \
00024
pcsrt = CSR_SERVER_QUERYCLIENTTHREAD();
00025
00026 #define END_LPC_RECV() \
00027
a->dwLastError = Teb->LastErrorValue; \
00028
return Status;
00029
00030 #define CCHMSGMAX 256
00031 #define CCHBODYMAX 512
00032
00033 #define CSR_THREAD_SHUTDOWNSKIP 0x00000008
00034
00035
BOOL WowExitTask(PCSR_THREAD pcsrt);
00036
NTSTATUS UserClientShutdown(PCSR_PROCESS pcsrp, ULONG dwFlags, BOOLEAN fFirstPass);
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 NTSTATUS _ExitWindowsEx(
00051 PCSR_THREAD pcsrt,
00052 UINT dwFlags,
00053 DWORD dwReserved)
00054 {
00055 LUID luidCaller;
00056
NTSTATUS Status = STATUS_SUCCESS;
00057
00058 UNREFERENCED_PARAMETER(dwReserved);
00059
00060
if ((
dwFlags & EWX_REBOOT) || (
dwFlags & EWX_POWEROFF)) {
00061
dwFlags |= EWX_SHUTDOWN;
00062 }
00063
00064
00065
00066
00067
00068
if ( (
dwFlags & ( ~ ( EWX_VALID ) ) ) != 0 )
00069 {
00070
if ( HandleToUlong(pcsrt->ClientId.UniqueProcess) !=
gIdLogon )
00071 {
00072 KdPrint((
"Process %x tried to call ExitWindowsEx with flags %x\n",
00073 pcsrt->ClientId.UniqueProcess,
dwFlags ));
00074
00075
return STATUS_ACCESS_DENIED ;
00076 }
00077 }
00078
00079
00080
00081
00082
00083
if (!CsrImpersonateClient(
NULL)) {
00084
return STATUS_BAD_IMPERSONATION_LEVEL;
00085 }
00086
00087
Status = CsrGetProcessLuid(
NULL, &luidCaller);
00088
if (!
NT_SUCCESS(
Status)) {
00089 CsrRevertToSelf();
00090
return Status;
00091 }
00092
00093
00094
00095
00096
00097
while (
TRUE) {
00098
00099 LARGE_INTEGER li;
00100
00101
Status =
NtUserSetInformationThread(pcsrt->ThreadHandle,
00102 UserThreadInitiateShutdown,
00103 &
dwFlags,
sizeof(
dwFlags));
00104
00105
switch (
Status) {
00106
case STATUS_PENDING:
00107
00108
00109
00110
00111
goto fastexit;
00112
00113
case STATUS_RETRY:
00114
00115
00116
00117
00118
00119
00120
EnterCrit();
00121 li.QuadPart = 0;
00122
if (
NtWaitForSingleObject(
gheventCancel,
FALSE, &li) == WAIT_OBJECT_0) {
00123
Status = STATUS_PENDING;
00124
LeaveCrit();
00125
goto fastexit;
00126 }
00127
00128
00129
00130
if (
gdwThreadEndSession == 0) {
00131
LeaveCrit();
00132
continue;
00133 }
00134
00135
NtClearEvent(
gheventCancelled);
00136
NtSetEvent(
gheventCancel,
NULL);
00137
LeaveCrit();
00138
00139
00140
00141
NtWaitForSingleObject(
gheventCancelled,
FALSE,
NULL);
00142
00143
EnterCrit();
00144
00145
00146
00147
00148
NtClearEvent(
gheventCancel);
00149
00150
00151
00152
00153
if (
gdwThreadEndSession != 0) {
00154 UserAssert(
gdwThreadEndSession == 0);
00155
Status = STATUS_PENDING;
00156
LeaveCrit();
00157
goto fastexit;
00158 }
00159
LeaveCrit();
00160
continue;
00161
00162
case STATUS_CANT_WAIT:
00163
00164
00165
00166
00167
00168
00169
00170
goto fastexit;
00171
00172
default:
00173
if (!
NT_SUCCESS(
Status)) {
00174 SetLastError(
RtlNtStatusToDosError(
Status));
00175
goto fastexit;
00176 }
00177 }
00178
break;
00179 }
00180
00181
00182
00183
00184
EnterCrit();
00185 UserAssert(
gdwThreadEndSession == 0);
00186
gdwThreadEndSession = HandleToUlong(pcsrt->ClientId.UniqueThread);
00187
LeaveCrit();
00188
00189
00190
00191
00192
Status = CsrShutdownProcesses(&luidCaller,
dwFlags);
00193
00194
00195
00196
NtUserSetInformationThread(pcsrt->ThreadHandle, UserThreadEndShutdown, &
Status,
sizeof(
Status));
00197
00198
EnterCrit();
00199
gdwThreadEndSession = 0;
00200
NtSetEvent(
gheventCancelled,
NULL);
00201
LeaveCrit();
00202
00203 fastexit:
00204 CsrRevertToSelf();
00205
00206
return Status;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 NTSTATUS UserClientShutdown(
00220 PCSR_PROCESS pcsrp,
00221 ULONG dwFlags,
00222 BOOLEAN fFirstPass)
00223 {
00224 PLIST_ENTRY ListHead, ListNext;
00225 PCSR_PROCESS Process;
00226 PCSR_THREAD Thread;
00227 USERTHREAD_SHUTDOWN_INFORMATION ShutdownInfo;
00228
BOOL fNoMsgs;
00229
BOOL fNoMsgsEver =
TRUE;
00230
BOOL Forced =
FALSE;
00231
BOOL bDoBlock;
00232
BOOL fNoRetry;
00233
DWORD cmd = 0, dwClientFlags;
00234
NTSTATUS Status;
00235
NTSTATUS TerminateStatus = STATUS_ACCESS_DENIED;
00236
UINT cThreads;
00237
BOOL fSendEndSession =
FALSE;
00238
00239
#if DBG
00240
DWORD dwLocalThreadEndSession =
gdwThreadEndSession;
00241
#endif
00242
00243
00244
00245
00246
00247
00248
00249
if (!(
dwFlags & EWX_SHUTDOWN) && (pcsrp->ShutdownFlags & SHUTDOWN_OTHERCONTEXT)) {
00250
Status =
SHUTDOWN_UNKNOWN_PROCESS;
00251
goto CleanupAndExit;
00252 }
00253
00254
00255
00256
00257
00258 fNoRetry = (pcsrp->ShutdownFlags & SHUTDOWN_NORETRY) ||
00259 (
dwFlags & EWX_FORCE);
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 dwClientFlags =
WMCS_EXIT | (fNoRetry ?
WMCS_NORETRY : 0);
00270
00271
00272
00273
00274
00275
00276
if (!(
dwFlags & (EWX_WINLOGON_OLD_REBOOT | EWX_WINLOGON_OLD_SHUTDOWN))) {
00277 dwClientFlags |=
WMCS_LOGOFF;
00278 }
00279
00280
if (
dwFlags & EWX_FORCEIFHUNG) {
00281 dwClientFlags |=
WMCS_NODLGIFHUNG;
00282 }
00283
if (!(pcsrp->ShutdownFlags & (SHUTDOWN_SYSTEMCONTEXT | SHUTDOWN_OTHERCONTEXT))) {
00284 dwClientFlags |=
WMCS_CONTEXTLOGOFF;
00285 }
00286
00287
00288
00289
00290
00291
00292
00293 CsrLockProcessByClientId(pcsrp->ClientId.UniqueProcess, &Process);
00294
00295 ShutdownInfo.StatusShutdown =
SHUTDOWN_UNKNOWN_PROCESS;
00296
00297
00298
00299
00300
00301 ListHead = &pcsrp->ThreadList;
00302 ListNext = ListHead->Flink;
00303
while (ListNext != ListHead) {
00304 Thread = CONTAINING_RECORD( ListNext, CSR_THREAD, Link );
00305 Thread->Flags &= ~
CSR_THREAD_SHUTDOWNSKIP;
00306 ListNext = ListNext->Flink;
00307 }
00308
00309
00310
00311
00312
00313 cThreads = 0;
00314 ShutdownInfo.drdRestore.pdeskRestore =
NULL;
00315 ShutdownInfo.drdRestore.hdeskNew =
NULL;
00316
while (
TRUE) {
00317 ListNext = ListHead->Flink;
00318
while (ListNext != ListHead) {
00319 Thread = CONTAINING_RECORD( ListNext, CSR_THREAD, Link );
00320
00321
00322
00323
00324
00325
00326 UserAssert(
gdwThreadEndSession == dwLocalThreadEndSession);
00327
if (HandleToUlong(Thread->ClientId.UniqueThread) ==
gdwThreadEndSession) {
00328 Thread->Flags |=
CSR_THREAD_SHUTDOWNSKIP;
00329 }
00330
00331
if (!(Thread->Flags &
00332 (CSR_THREAD_DESTROYED |
CSR_THREAD_SHUTDOWNSKIP))) {
00333
break;
00334 }
00335 ListNext = ListNext->Flink;
00336 }
00337
if (ListNext == ListHead)
00338
break;
00339
00340 Thread->Flags |=
CSR_THREAD_SHUTDOWNSKIP;
00341 ShutdownInfo.dwFlags = dwClientFlags;
00342
00343
Status =
NtUserQueryInformationThread(Thread->ThreadHandle,
00344 UserThreadShutdownInformation, &ShutdownInfo,
sizeof(ShutdownInfo),
NULL);
00345
00346
if (!
NT_SUCCESS(
Status))
00347
continue;
00348
if (ShutdownInfo.StatusShutdown ==
SHUTDOWN_UNKNOWN_PROCESS)
00349
continue;
00350
if (ShutdownInfo.StatusShutdown ==
SHUTDOWN_KNOWN_PROCESS) {
00351 CsrUnlockProcess(Process);
00352
Status =
SHUTDOWN_KNOWN_PROCESS;
00353
goto RestoreDesktop;
00354 }
00355
00356
00357
00358
00359
00360
00361
if (!(dwClientFlags &
WMCS_CONTEXTLOGOFF) && (ShutdownInfo.hwndDesktop ==
NULL)) {
00362
00363
00364
00365
00366 ShutdownInfo.StatusShutdown =
SHUTDOWN_UNKNOWN_PROCESS;
00367
continue;
00368 }
00369
00370
00371
00372
00373 cThreads++;
00374
00375
if (
ISTS()) {
00376 Forced = (
dwFlags & EWX_FORCE);
00377 fNoMsgs = (pcsrp->ShutdownFlags & SHUTDOWN_NORETRY) ||
00378 !(ShutdownInfo.dwFlags & USER_THREAD_GUI);
00379 fNoMsgsEver &= fNoMsgs;
00380
if (Forced && (!(
dwFlags & EWX_NONOTIFY) || (
gSessionId != 0))) {
00381 dwClientFlags &= ~
WMCS_LOGOFF;
00382 }
00383
00384
if (fNoMsgs || Forced) {
00385
BoostHardError((ULONG_PTR)Thread->ClientId.UniqueProcess,
BHE_FORCE);
00386 }
00387 bDoBlock = (fNoMsgs ==
FALSE);
00388
00389 }
else {
00390
if (fNoRetry || !(ShutdownInfo.dwFlags & USER_THREAD_GUI)) {
00391
00392
00393
00394
00395
BoostHardError((ULONG_PTR)Thread->ClientId.UniqueProcess,
BHE_FORCE);
00396 bDoBlock =
FALSE;
00397 }
else {
00398 bDoBlock =
TRUE;
00399 }
00400 }
00401
00402
if (bDoBlock) {
00403 CsrReferenceThread(Thread);
00404 CsrUnlockProcess(Process);
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 cmd =
ThreadShutdownNotify(dwClientFlags |
WMCS_QUERYEND, (ULONG_PTR)Thread, 0);
00423
00424 CsrLockProcessByClientId(pcsrp->ClientId.UniqueProcess, &Process);
00425 CsrDereferenceThread(Thread);
00426
00427
00428
00429
00430
switch (cmd) {
00431
case TSN_USERSAYSCANCEL:
00432
case TSN_APPSAYSNOTOK:
00433
if (!Forced) {
00434 dwClientFlags &= ~
WMCS_EXIT;
00435 }
00436
00437
00438
00439
00440
case TSN_APPSAYSOK:
00441 fSendEndSession =
TRUE;
00442
break;
00443
00444
case TSN_USERSAYSKILL:
00445
00446
00447
00448
00449
00450
00451 dwClientFlags |=
WMCS_EXIT;
00452
goto KillIt;
00453
00454
case TSN_NOWINDOW:
00455
00456
00457
00458
00459
00460
00461
00462
00463
if (fFirstPass) {
00464 cThreads--;
00465 }
00466
break;
00467 }
00468 }
00469 }
00470
00471
00472
00473
00474
if (fSendEndSession) {
00475
00476
00477
00478
00479
00480 ListNext = ListHead->Flink;
00481
while (ListNext != ListHead) {
00482 Thread = CONTAINING_RECORD( ListNext, CSR_THREAD, Link );
00483 Thread->Flags &= ~
CSR_THREAD_SHUTDOWNSKIP;
00484 ListNext = ListNext->Flink;
00485 }
00486
00487
00488
00489
00490
while (
TRUE) {
00491 ListHead = &pcsrp->ThreadList;
00492 ListNext = ListHead->Flink;
00493
while (ListNext != ListHead) {
00494 Thread = CONTAINING_RECORD( ListNext, CSR_THREAD, Link );
00495
if (!(Thread->Flags &
00496 (CSR_THREAD_DESTROYED |
CSR_THREAD_SHUTDOWNSKIP))) {
00497
break;
00498 }
00499 ListNext = ListNext->Flink;
00500 }
00501
if (ListNext == ListHead)
00502
break;
00503
00504 Thread->Flags |=
CSR_THREAD_SHUTDOWNSKIP;
00505 ShutdownInfo.dwFlags = dwClientFlags;
00506
00507
Status =
NtUserQueryInformationThread(Thread->ThreadHandle,
00508 UserThreadShutdownInformation, &ShutdownInfo,
sizeof(ShutdownInfo),
NULL);
00509
00510
if (!
NT_SUCCESS(
Status))
00511
continue;
00512
00513
if (ShutdownInfo.StatusShutdown ==
SHUTDOWN_UNKNOWN_PROCESS ||
00514 !(ShutdownInfo.dwFlags & USER_THREAD_GUI))
00515
continue;
00516
00517
00518
00519
00520 CsrReferenceThread(Thread);
00521 CsrUnlockProcess(Process);
00522
00523
00524
00525
00526
00527
00528
ThreadShutdownNotify(dwClientFlags, (ULONG_PTR)Thread, 0);
00529
00530 CsrLockProcessByClientId(pcsrp->ClientId.UniqueProcess, &Process);
00531 CsrDereferenceThread(Thread);
00532 }
00533 }
00534
00535 KillIt:
00536 CsrUnlockProcess(Process);
00537
00538
if (
ISTS()) {
00539 bDoBlock = (!fNoMsgsEver && !(dwClientFlags &
WMCS_EXIT));
00540 }
else {
00541 bDoBlock = (!fNoRetry && !(dwClientFlags &
WMCS_EXIT));
00542 }
00543
00544
if (bDoBlock) {
00545
Status =
SHUTDOWN_CANCEL;
00546
goto RestoreDesktop;
00547 }
00548
00549
00550
00551
00552
00553
if (cThreads == 0)
00554 ShutdownInfo.StatusShutdown =
SHUTDOWN_UNKNOWN_PROCESS;
00555
else
00556 ShutdownInfo.StatusShutdown =
SHUTDOWN_KNOWN_PROCESS;
00557
00558
if (ShutdownInfo.StatusShutdown ==
SHUTDOWN_UNKNOWN_PROCESS ||
00559 !(dwClientFlags &
WMCS_CONTEXTLOGOFF)) {
00560
00561
00562
00563
00564
00565
Status =
SHUTDOWN_UNKNOWN_PROCESS;
00566
00567
if (ShutdownInfo.drdRestore.hdeskNew) {
00568
goto RestoreDesktop;
00569 }
00570
goto CleanupAndExit;
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
if (
ISTS()) {
00585
NTSTATUS ExitStatus;
00586 HANDLE
DebugPort;
00587
00588 ExitStatus = DBG_TERMINATE_PROCESS;
00589
if (
NT_SUCCESS(
NtQueryInformationProcess(NtCurrentProcess(),
00590 ProcessDebugPort,
00591 &
DebugPort,
00592
sizeof(HANDLE),
00593
NULL)) &&
00594 (
DebugPort !=
NULL)) {
00595
00596 ExitStatus = 0;
00597 }
00598 TerminateStatus =
NtTerminateProcess(pcsrp->ProcessHandle, ExitStatus);
00599 }
else {
00600 TerminateStatus =
NtTerminateProcess(pcsrp->ProcessHandle, DBG_TERMINATE_PROCESS);
00601 }
00602
00603 pcsrp->Flags |= CSR_PROCESS_TERMINATED;
00604
00605
00606
00607
00608
00609
00610
Status =
SHUTDOWN_KNOWN_PROCESS;
00611
00612 RestoreDesktop:
00613
00614
00615
00616
00617 {
00618 USERTHREAD_USEDESKTOPINFO utudi;
00619 utudi.hThread =
NULL;
00620 RtlCopyMemory(&(utudi.drdRestore), &(ShutdownInfo.drdRestore),
sizeof(DESKRESTOREDATA));
00621
00622
NtUserSetInformationThread(NtCurrentThread(), UserThreadUseDesktop,
00623 &utudi,
sizeof(utudi));
00624 }
00625
00626
00627
00628
00629
00630
if (
Status !=
SHUTDOWN_UNKNOWN_PROCESS) {
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
if (TerminateStatus != STATUS_ACCESS_DENIED) {
00644 LARGE_INTEGER li;
00645
00646 li.QuadPart = (LONGLONG)-10000 *
gdwProcessTerminateTimeout;
00647 TerminateStatus =
NtWaitForSingleObject(pcsrp->ProcessHandle,
00648
FALSE,
00649 &li);
00650
if (TerminateStatus != STATUS_WAIT_0) {
00651 RIPMSG2(RIP_WARNING,
00652
"UserClientShutdown: wait for process %x failed with status %x",
00653 pcsrp->ClientId.UniqueProcess, TerminateStatus);
00654 }
00655 }
00656
00657 CsrDereferenceProcess(pcsrp);
00658 }
00659
00660
00661 CleanupAndExit:
00662
00663
return Status;
00664 }
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676 VOID CALLBACK
WMCSCallback(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult)
00677 {
00678
PWMCSDATA pwmcsd = (
PWMCSDATA)dwData;
00679
if (pwmcsd->
dwFlags &
WMCSD_IGNORE) {
00680 LocalFree(pwmcsd);
00681
return;
00682 }
00683
00684 pwmcsd->
dwFlags |=
WMCSD_REPLY;
00685 pwmcsd->
dwRet = (
DWORD)lResult;
00686
00687 UNREFERENCED_PARAMETER(hwnd);
00688 UNREFERENCED_PARAMETER(uMsg);
00689 }
00690
00691
00692
00693
00694
00695
00696
00697
00698 HWND
GetInputWindow (PCSR_THREAD pcsrt, HWND hwnd)
00699 {
00700
DWORD dwTimeout;
00701 HWND hwndPopup;
00702
00703
00704
00705 dwTimeout =
gCmsHungAppTimeout;
00706
NtUserQueryInformationThread(pcsrt->ThreadHandle,
00707 UserThreadHungStatus, &dwTimeout,
sizeof(dwTimeout),
NULL);
00708
00709
00710
00711
00712
if (!dwTimeout && !
IsWindowEnabled(hwnd)) {
00713 hwndPopup =
GetWindow(hwnd, GW_ENABLEDPOPUP);
00714
if ((hwndPopup !=
NULL) && (hwndPopup != hwnd)) {
00715
return hwndPopup;
00716 }
00717 }
00718
00719
return NULL;
00720 }
00721
00722
00723
00724
00725
00726
00727
00728 void GetApplicationText (HWND hwnd, HANDLE hThread, WCHAR *pwcText, UINT uLen)
00729 {
00730
00731
00732
00733
00734
GetWindowText(hwnd, pwcText, uLen);
00735
if (*pwcText == 0) {
00736
00737
00738
00739
NtUserQueryInformationThread(hThread, UserThreadTaskName,
00740 pwcText, uLen *
sizeof(WCHAR),
NULL);
00741 }
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 DWORD ThreadShutdownNotify(DWORD dwClientFlags, ULONG_PTR dwThread, LPARAM lParam)
00758 {
00759 HWND hwnd, hwndOwner;
00760
PWMCSDATA pwmcsd =
NULL;
00761 HWND hwndDlg;
00762
ENDDLGPARAMS edp;
00763
DWORD dwRet, dwRealTimeout, dwTimeout, dwStartTiming, dwCmd;
00764 MSG
msg;
00765 PCSR_THREAD pcsrt;
00766 HANDLE hThread;
00767
BOOL fEndTaskNow =
FALSE;
00768
00769
#define ESMH_CANCELEVENT 0
00770
#define ESMH_THREAD 1
00771
#define ESMH_HANDLECOUNT 2
00772
HANDLE ahandles[
ESMH_HANDLECOUNT];
00773
00774
00775
00776
00777
00778
00779
if (dwClientFlags &
WMCS_CONSOLE) {
00780 hThread = (HANDLE)dwThread;
00781 dwRealTimeout = 0;
00782
goto SetupWaitLoop;
00783 }
else {
00784 pcsrt = (PCSR_THREAD)dwThread;
00785 hThread = pcsrt->ThreadHandle;
00786 hwnd = (HWND)lParam;
00787 }
00788
00789
00790
00791
00792
00793
if (hwnd ==
NULL) {
00794
EnumThreadWindows(HandleToUlong(pcsrt->ClientId.UniqueThread),
00795 &
FindWindowFromThread, (LPARAM)&hwnd);
00796 }
00797
if (hwnd ==
NULL) {
00798
return TSN_NOWINDOW;
00799 }
00800
00801
00802
00803
while ((hwndOwner =
GetWindow(hwnd, GW_OWNER)) !=
NULL) {
00804 hwnd = hwndOwner;
00805 }
00806
00807
#if defined(FE_IME)
00808
00809
00810
00811
00812
00813
00814
if (!(dwClientFlags &
WMCS_ENDTASK)) {
00815
if ((HANDLE)
GetWindowLongPtr(hwnd, GWLP_HINSTANCE) ==
ghModuleWin) {
00816
return TSN_APPSAYSOK;
00817 }
00818 }
00819
#endif
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
if ((dwClientFlags &
WMCS_ENDTASK)) {
00838
00839 dwTimeout =
gCmsHungAppTimeout;
00840
NtUserQueryInformationThread(pcsrt->ThreadHandle, UserThreadHungStatus, &dwTimeout,
sizeof(dwTimeout),
NULL);
00841
00842
if (!
IsWindowEnabled(hwnd) || dwTimeout){
00843 dwRealTimeout = 0;
00844 fEndTaskNow =
TRUE;
00845 }
00846
00847
00848 }
00849
00850
if (!fEndTaskNow) {
00851
00852
SetForegroundWindow(hwnd);
00853 dwRealTimeout =
gCmsHungAppTimeout;
00854
if (dwClientFlags &
WMCS_ENDTASK) {
00855
PostMessage(hwnd, WM_CLOSE, 0, 0);
00856 }
else {
00857
00858
00859
00860
00861
if (!(dwClientFlags & (
WMCS_QUERYEND |
WMCS_EXIT))) {
00862
SendNotifyMessage(hwnd, WM_CLIENTSHUTDOWN, dwClientFlags, 0);
00863
return TSN_APPSAYSOK;
00864 }
00865
00866
00867
00868 pwmcsd = (
PWMCSDATA)LocalAlloc(LPTR,
sizeof(
WMCSDATA));
00869
if (pwmcsd ==
NULL) {
00870
return TSN_USERSAYSKILL;
00871 }
00872
00873
SendMessageCallback(hwnd, WM_CLIENTSHUTDOWN, dwClientFlags, 0,
00874
WMCSCallback, (ULONG_PTR)pwmcsd);
00875 }
00876 }
00877
00878 SetupWaitLoop:
00879
00880
00881
00882
00883 ZeroMemory(&edp,
sizeof(edp));
00884 edp.dwFlags =
EDPF_NODLG;
00885
00886
00887
00888
00889
00890 *(ahandles +
ESMH_CANCELEVENT) =
gheventCancel;
00891 *(ahandles +
ESMH_THREAD) = hThread;
00892 dwStartTiming = GetTickCount();
00893 dwCmd = 0;
00894
while (dwCmd == 0) {
00895
00896
00897
00898 dwTimeout = dwRealTimeout;
00899
if ((dwTimeout != 0) && (dwTimeout != INFINITE)) {
00900 dwTimeout -= (GetTickCount() - dwStartTiming);
00901
if ((
int)dwTimeout < 0) {
00902 dwTimeout = 0;
00903 }
00904 }
00905
00906 dwRet =
MsgWaitForMultipleObjects(
ESMH_HANDLECOUNT, ahandles,
FALSE, dwTimeout, QS_ALLINPUT);
00907
00908
switch (dwRet) {
00909
case WAIT_OBJECT_0 +
ESMH_CANCELEVENT:
00910
00911
00912
00913 dwCmd =
TSN_USERSAYSCANCEL;
00914
break;
00915
00916
case WAIT_OBJECT_0 +
ESMH_THREAD:
00917
00918
00919
00920 dwCmd =
TSN_APPSAYSOK;
00921
break;
00922
00923
case WAIT_OBJECT_0 +
ESMH_HANDLECOUNT:
00924
00925
00926
00927
while (
PeekMessage(&
msg,
NULL, 0, 0, PM_REMOVE)) {
00928
if ((edp.dwFlags &
EDPF_NODLG)
00929 || !
IsDialogMessage(hwndDlg, &
msg)) {
00930
00931
TranslateMessage(&
msg);
00932
DispatchMessage(&
msg);
00933 }
00934 }
00935
00936
00937
00938
if ((pwmcsd !=
NULL) && (pwmcsd->
dwFlags &
WMCSD_REPLY)) {
00939
00940
switch (pwmcsd->
dwRet) {
00941
default:
00942
00943
00944
00945
00946
00947
00948
case WMCSR_ALLOWSHUTDOWN:
00949
00950
00951
00952
00953
BoostHardError((ULONG_PTR)pcsrt->ClientId.UniqueProcess,
BHE_FORCE);
00954
00955
00956
00957
case WMCSR_DONE:
00958 dwCmd =
TSN_APPSAYSOK;
00959
break;
00960
00961
case WMCSR_CANCEL:
00962 dwCmd =
TSN_APPSAYSNOTOK;
00963
break;
00964 }
00965 }
00966
00967
00968
00969
00970
else if (!(edp.dwFlags &
EDPF_NODLG)) {
00971
break;
00972 }
00973
00974
00975
00976
else if (edp.dwFlags &
EDPF_RESPONSE) {
00977
switch(edp.dwRet) {
00978
case IDC_ENDNOW:
00979
00980
00981
00982 dwCmd =
TSN_USERSAYSKILL;
00983
break;
00984
00985
00986
default:
00987 dwCmd =
TSN_USERSAYSCANCEL;
00988
break;
00989 }
00990 }
00991
break;
00992
00993
case WAIT_TIMEOUT:
00994
00995
if (dwClientFlags &
WMCS_NORETRY) {
00996
00997
00998
00999
01000
01001 UserAssert(
ISTS());
01002
01003 dwCmd =
TSN_APPSAYSOK;
01004
break;
01005 }
01006
01007
01008
01009
01010
01011
01012 dwRealTimeout = INFINITE;
01013
01014
01015
01016
01017
01018
01019
01020
if (!(dwClientFlags &
WMCS_CONSOLE)) {
01021
if (
BoostHardError((ULONG_PTR)pcsrt->ClientId.UniqueProcess,
BHE_TEST)
01022 || (
GetInputWindow(pcsrt, hwnd) !=
NULL)) {
01023
01024 edp.dwFlags |=
EDPF_INPUT;
01025 }
else {
01026
01027
01028
01029
01030
01031
01032
if ((dwClientFlags &
WMCS_NODLGIFHUNG)
01033 || (!(dwClientFlags &
WMCS_ENDTASK)
01034 && !(dwClientFlags &
WMCS_CONTEXTLOGOFF))) {
01035
01036 dwCmd =
TSN_USERSAYSKILL;
01037
break;
01038 }
01039
01040
01041
01042
if (dwClientFlags &
WMCS_ENDTASK) {
01043 edp.dwFlags |=
EDPF_HUNG;
01044 }
else {
01045 edp.dwFlags |=
EDPF_WAIT;
01046 }
01047 }
01048 }
01049
01050
01051
01052
01053
01054
if (
gfAutoEndTask) {
01055 dwCmd =
TSN_USERSAYSKILL;
01056
break;
01057 }
01058
01059
01060
01061 edp.dwRet = 0;
01062 edp.dwClientFlags = dwClientFlags;
01063
if (dwClientFlags &
WMCS_CONSOLE) {
01064 edp.pcsrt =
NULL;
01065 edp.lParam = lParam;
01066 }
else {
01067 edp.pcsrt = pcsrt;
01068 edp.lParam = (LPARAM)hwnd;
01069 }
01070
01071 hwndDlg = CreateDialogParam (
ghModuleWin, MAKEINTRESOURCE(
IDD_ENDTASK),
01072
NULL,
EndTaskDlgProc, (LPARAM)(&edp));
01073
01074
01075
01076
if (hwndDlg ==
NULL) {
01077 edp.dwFlags |=
EDPF_NODLG;
01078 dwCmd =
TSN_USERSAYSKILL;
01079
break;
01080 }
01081
break;
01082
01083
default:
01084
01085
01086
01087 UserAssert(dwRet != dwRet);
01088 dwCmd =
TSN_USERSAYSKILL;
01089
break;
01090 }
01091 }
01092
01093
01094
01095
01096
01097
if (!(edp.dwFlags &
EDPF_NODLG)) {
01098
DestroyWindow(hwndDlg);
01099 }
01100
01101
01102
01103
01104
if (pwmcsd !=
NULL) {
01105
if (pwmcsd->
dwFlags &
WMCSD_REPLY) {
01106 LocalFree(pwmcsd);
01107 }
else {
01108 pwmcsd->
dwFlags |=
WMCSD_IGNORE;
01109 }
01110 }
01111
#if DBG
01112
01113
01114
01115
if ((dwClientFlags &
WMCS_EXIT) && (dwCmd ==
TSN_APPSAYSNOTOK)) {
01116 WCHAR achTitle[
CCHBODYMAX];
01117 WCHAR *pwcText;
01118 UserAssert(!(dwClientFlags &
WMCS_CONSOLE));
01119 pwcText = achTitle;
01120 *(achTitle +
CCHBODYMAX - 1) = (WCHAR)0;
01121
GetApplicationText(hwnd, hThread, pwcText,
CCHBODYMAX - 1);
01122 KdPrint((
"Log off canceled by pid:%#lx tid:%#lx - '%ws'.\n",
01123 HandleToUlong(pcsrt->ClientId.UniqueProcess),
01124 HandleToUlong(pcsrt->ClientId.UniqueThread),
01125 pwcText));
01126 }
01127
#endif
01128
01129
01130
01131
01132
if ((dwCmd ==
TSN_USERSAYSKILL) && !(dwClientFlags &
WMCS_CONSOLE)) {
01133
01134
BoostHardError((ULONG_PTR)pcsrt->ClientId.UniqueProcess,
BHE_FORCE);
01135
01136
if (!(pcsrt->Flags & CSR_THREAD_DESTROYED) &&
WowExitTask(pcsrt)) {
01137 dwCmd =
TSN_APPSAYSOK;
01138 }
01139 }
01140
01141
return dwCmd;
01142 }
01143
01144
01145
01146
01147
01148
01149
01150
01151 void SetEndTaskDlgStatus(
ENDDLGPARAMS *pedp, HWND hwndDlg, UINT uStrId, BOOL fInit)
01152 {
01153
BOOL f, fIsWaiting, fWasWaiting;
01154 WCHAR *pwcText;
01155
01156 fWasWaiting = (pedp->
uStrId == STR_ENDTASK_WAIT);
01157 fIsWaiting = (pedp->
dwFlags &
EDPF_WAIT);
01158
01159
01160
01161 pedp->
uStrId = uStrId;
01162 pwcText =
ServerLoadString(
ghModuleWin, uStrId,
NULL, &f);
01163
if (pwcText !=
NULL) {
01164
SetDlgItemText(hwndDlg,
IDC_STATUSMSG, pwcText);
01165 LocalFree(pwcText);
01166 }
01167
01168
01169
01170
01171
if (!(pedp->
dwFlags &
EDPF_HUNG) && !(pedp->
dwClientFlags &
WMCS_CONSOLE)) {
01172
SetTimer(hwndDlg,
IDT_CHECKAPPSTATE,
gCmsHungAppTimeout,
NULL);
01173 }
01174
01175
01176
01177
01178
01179
01180
if (fInit || (fIsWaiting ^ fWasWaiting)) {
01181 RECT rc;
01182 HWND hwndStatusCancel =
GetDlgItem(hwndDlg,
IDC_STATUSCANCEL);
01183 HWND hwndCancelButton =
GetDlgItem(hwndDlg, IDCANCEL);
01184 HWND hwndEndButton =
GetDlgItem(hwndDlg,
IDC_ENDNOW);
01185
DWORD dwSwpFlags;
01186
01187
01188
01189
01190
01191 dwSwpFlags = ((fIsWaiting ? SWP_HIDEWINDOW : SWP_SHOWWINDOW)
01192 | SWP_NOREDRAW | SWP_NOSIZE | SWP_NOMOVE
01193 | SWP_NOZORDER | SWP_NOSENDCHANGING
01194 | SWP_NOACTIVATE);
01195
01196
01197
01198
01199
01200
01201
if (fIsWaiting) {
01202
SendMessage(hwndDlg, DM_SETDEFID,
IDC_ENDNOW, 0);
01203
SetFocus(hwndEndButton);
01204 }
01205
SetWindowPos(hwndStatusCancel,
NULL, 0, 0, 0, 0, dwSwpFlags);
01206
SetWindowPos(hwndCancelButton,
NULL, 0, 0, 0, 0, dwSwpFlags);
01207
01208
01209
01210
if (!fIsWaiting) {
01211
SendMessage(hwndDlg, DM_SETDEFID, IDCANCEL, 0);
01212
SetFocus(hwndCancelButton);
01213 }
01214
01215
01216
01217
if (fIsWaiting && (pedp->
hbrProgress ==
NULL)) {
01218
int iMagic;
01219
01220
01221
01222
01223
01224
01225
01226
GetClientRect(hwndStatusCancel, &pedp->
rcBar);
01227 iMagic = (pedp->
rcBar.bottom - pedp->
rcBar.top) / 4;
01228
InflateRect(&pedp->
rcBar, 0, -iMagic +
GetSystemMetrics(SM_CYEDGE));
01229 pedp->
rcBar.right -= (5 * iMagic);
01230
OffsetRect(&pedp->
rcBar, 0, -iMagic);
01231
MapWindowPoints(hwndStatusCancel, hwndDlg, (LPPOINT)&pedp->
rcBar, 2);
01232
01233
01234
01235
01236 pedp->
rcProgress = pedp->
rcBar;
01237
InflateRect(&pedp->
rcProgress, -
GetSystemMetrics(SM_CXEDGE), -
GetSystemMetrics(SM_CYEDGE));
01238 pedp->
iProgressStop = pedp->
rcProgress.right;
01239 pedp->
iProgressWidth = ((2 * (pedp->
rcProgress.bottom - pedp->
rcProgress.top)) / 3);
01240
01241 pedp->
rcProgress.right = pedp->
rcProgress.left + pedp->
iProgressWidth - 1;
01242
01243 pedp->
hbrProgress = CreateSolidBrush(
GetSysColor(COLOR_ACTIVECAPTION));
01244
01245
01246
01247
GetWindowRect(hwndEndButton, &pedp->
rcEndButton);
01248
MapWindowPoints(
NULL, hwndDlg, (LPPOINT)&pedp->
rcEndButton, 2);
01249 }
01250
01251
01252
01253
if (fIsWaiting) {
01254 RECT rcEndButton;
01255
UINT uTimeout = (
gdwHungToKillCount *
gCmsHungAppTimeout)
01256 / ((pedp->
iProgressStop - pedp->
rcProgress.left) / pedp->
iProgressWidth);
01257
SetTimer(hwndDlg,
IDT_PROGRESS, uTimeout,
NULL);
01258
01259
01260
01261
01262
01263
GetWindowRect(hwndCancelButton, &rc);
01264
GetWindowRect(hwndEndButton, &rcEndButton);
01265 rc.left = rc.right - (rcEndButton.right - rcEndButton.left);
01266
MapWindowPoints(
NULL, hwndDlg, (LPPOINT)&rc, 2);
01267 }
else if (fWasWaiting) {
01268 KillTimer(hwndDlg,
IDT_PROGRESS);
01269 rc = pedp->
rcEndButton;
01270 }
01271
01272
01273
01274
if (fIsWaiting || fWasWaiting) {
01275
SetWindowPos(hwndEndButton,
NULL, rc.left, rc.top, 0, 0,
01276 SWP_NOREDRAW | SWP_NOSIZE | SWP_NOACTIVATE
01277 | SWP_NOZORDER | SWP_NOSENDCHANGING);
01278 }
01279
01280
01281
01282
if (!fInit) {
01283 InvalidateRect(hwndDlg,
NULL,
TRUE);
01284 }
01285 }
01286
01287
01288
01289
01290
01291
if (fInit || (pedp->
dwFlags &
EDPF_HUNG)) {
01292
SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0,
01293 SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW
01294 | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
01295
01296
if (fInit) {
01297
SetForegroundWindow(hwndDlg);
01298 }
01299 }
01300 }
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312 INT_PTR
APIENTRY EndTaskDlgProc(
01313 HWND hwndDlg,
01314 UINT msg,
01315 WPARAM wParam,
01316 LPARAM lParam)
01317 {
01318
ENDDLGPARAMS* pedp;
01319 WCHAR achTitle[
CCHBODYMAX];
01320 WCHAR *pwcText, *pwcTemp;
01321
UINT uLen;
01322
UINT uStrId;
01323 PAINTSTRUCT ps;
01324 HDC hdc, hdcMem;
01325
BOOL fIsInput, fWasInput;
01326
#ifdef USE_MIRRORING
01327
int iOldLayout;
01328
#endif
01329
01330
switch (
msg) {
01331
case WM_INITDIALOG:
01332
01333
01334
01335 pedp = (
ENDDLGPARAMS*)lParam;
01336
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (ULONG_PTR)pedp);
01337
01338
01339
01340 pedp->dwFlags &= ~
EDPF_NODLG;
01341
01342
01343
01344
01345 *(achTitle +
CCHBODYMAX - 1) = (WCHAR)0;
01346 uLen =
GetWindowText(hwndDlg, achTitle,
CCHBODYMAX - 1);
01347 pwcText = achTitle + uLen;
01348 uLen =
CCHBODYMAX - 1 - uLen;
01349
01350
01351
01352
if (pedp->dwClientFlags &
WMCS_CONSOLE) {
01353 pwcTemp = (WCHAR *)pedp->lParam;
01354
while (uLen-- && (*pwcText++ = *pwcTemp++));
01355 }
else {
01356
GetApplicationText((HWND)pedp->lParam, pedp->pcsrt->ThreadHandle, pwcText, uLen);
01357 }
01358
01359
SetWindowText(hwndDlg, achTitle);
01360
01361
01362
01363
01364
01365 pedp->hIcon = (HICON)
GetProp((HWND)pedp->lParam,
ICON_PROP_NAME);
01366
01367
if (pedp->hIcon ==
NULL) {
01368
01369 pedp->hIcon = (HICON)
GetClassLongPtr((HWND)pedp->lParam, GCLP_HICON);
01370
01371
if (pedp->hIcon ==
NULL) {
01372
01373
if (pedp->dwClientFlags &
WMCS_CONSOLE) {
01374 pedp->hIcon = LoadIcon(
ghModuleWin, MAKEINTRESOURCE(
IDI_CONSOLE));
01375 }
01376
else {
01377 pedp->hIcon = LoadIcon(
NULL, IDI_APPLICATION);
01378 }
01379 }
01380 }
01381
01382
01383
01384
01385
if (pedp->dwClientFlags &
WMCS_CONSOLE) {
01386 uStrId = STR_ENDTASK_CONSOLE;
01387 }
else if (pedp->dwFlags &
EDPF_INPUT) {
01388 uStrId = STR_ENDTASK_INPUT;
01389 }
else if (pedp->dwFlags &
EDPF_WAIT) {
01390 uStrId = STR_ENDTASK_WAIT;
01391 }
else {
01392 uStrId = STR_ENDTASK_HUNG;
01393 }
01394
01395
01396
01397
SetEndTaskDlgStatus(pedp, hwndDlg, uStrId,
TRUE);
01398
return FALSE;
01399
01400
01401
case WM_PAINT:
01402 pedp = (
ENDDLGPARAMS*)
GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
01403
if ((pedp ==
NULL) || (pedp->hIcon ==
NULL)) {
01404
break;
01405 }
01406
01407
01408
01409 hdc =
BeginPaint(hwndDlg, &ps);
01410
#ifdef USE_MIRRORING
01411
iOldLayout = GetLayout(hdc);
01412
if (iOldLayout != GDI_ERROR) {
01413 SetLayout(hdc, iOldLayout|LAYOUT_BITMAPORIENTATIONPRESERVED);
01414 }
01415
#endif
01416
DrawIcon(hdc,
ETD_XICON,
ETD_YICON, pedp->hIcon);
01417
#ifdef USE_MIRRORING
01418
if (iOldLayout != GDI_ERROR) {
01419 SetLayout(hdc, iOldLayout);
01420 }
01421
#endif
01422
01423
01424
01425
01426
if (pedp->dwFlags &
EDPF_WAIT) {
01427 RECT rc;
01428
01429
01430
01431 rc = pedp->rcBar;
01432
DrawEdge(hdc, &rc, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
01433
InflateRect(&rc, -1, -1);
01434
01435
01436
01437 rc.right = rc.left + pedp->iProgressWidth - 1;
01438
while (rc.left < pedp->rcProgress.left) {
01439
if (rc.right > pedp->iProgressStop) {
01440 rc.right = pedp->iProgressStop;
01441
if (rc.left >= rc.right) {
01442
break;
01443 }
01444 }
01445
FillRect(hdc, &rc, pedp->hbrProgress);
01446 rc.left += pedp->iProgressWidth;
01447 rc.right += pedp->iProgressWidth;
01448 }
01449 }
else {
01450
01451
01452
01453
01454
if (pedp->hbmpWarning ==
NULL) {
01455 BITMAP bmp;
01456 pedp->hbmpWarning = LoadBitmap(
ghModuleWin, MAKEINTRESOURCE(
IDB_WARNING));
01457
if (GetObject(pedp->hbmpWarning,
sizeof(bmp), &bmp)) {
01458 pedp->rcWarning.left =
ETD_XICON;
01459 pedp->rcWarning.top =
ETD_XICON + 32 - bmp.bmHeight;
01460 pedp->rcWarning.right = bmp.bmWidth;
01461 pedp->rcWarning.bottom = bmp.bmHeight;
01462 }
01463 }
01464
01465
01466
01467 hdcMem = CreateCompatibleDC(hdc);
01468 SelectObject(hdcMem, pedp->hbmpWarning);
01469 GdiTransparentBlt(hdc, pedp->rcWarning.left, pedp->rcWarning.top,
01470 pedp->rcWarning.right, pedp->rcWarning.bottom,
01471 hdcMem, 0, 0, pedp->rcWarning.right, pedp->rcWarning.bottom, RGB(255, 0, 255));
01472 DeleteDC(hdcMem);
01473 }
01474
01475 EndPaint(hwndDlg, &ps);
01476
return TRUE;
01477
01478
case WM_TIMER:
01479 pedp = (
ENDDLGPARAMS*)
GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
01480
if (pedp ==
NULL) {
01481
return TRUE;
01482 }
01483
switch (wParam) {
01484
case IDT_CHECKAPPSTATE:
01485 pedp->dwCheckTimerCount++;
01486
01487
01488
01489
01490 fIsInput = (
BoostHardError((ULONG_PTR)pedp->pcsrt->ClientId.UniqueProcess,
BHE_TEST)
01491 || (
GetInputWindow(pedp->pcsrt, (HWND)pedp->lParam) !=
NULL));
01492 fWasInput = (pedp->dwFlags &
EDPF_INPUT);
01493
if (fIsInput ^ fWasInput) {
01494
UINT uProgress;
01495 pedp->dwFlags &= ~(
EDPF_INPUT |
EDPF_WAIT);
01496 pedp->dwFlags |= (fIsInput ?
EDPF_INPUT :
EDPF_WAIT);
01497
SetEndTaskDlgStatus(pedp, hwndDlg,
01498 (fIsInput ? STR_ENDTASK_INPUT : STR_ENDTASK_WAIT),
01499
FALSE);
01500 pedp->dwCheckTimerCount /= 2;
01501 uProgress = pedp->rcProgress.left - pedp->rcBar.left -
GetSystemMetrics(SM_CXEDGE);
01502 uProgress /= 2;
01503 pedp->rcProgress.left -= uProgress;
01504 pedp->rcProgress.right -= uProgress;
01505 }
01506
01507
01508
01509
if (pedp->dwCheckTimerCount >=
gdwHungToKillCount) {
01510 KillTimer(hwndDlg,
IDT_CHECKAPPSTATE);
01511 pedp->dwFlags &= ~(
EDPF_INPUT |
EDPF_WAIT);
01512 pedp->dwFlags |=
EDPF_HUNG;
01513
SetEndTaskDlgStatus(pedp, hwndDlg, STR_ENDTASK_HUNG,
FALSE);
01514 }
01515
break;
01516
01517
case IDT_PROGRESS:
01518
01519
01520
01521
if (pedp->rcProgress.right >= pedp->iProgressStop) {
01522 pedp->rcProgress.right = pedp->iProgressStop;
01523
if (pedp->rcProgress.left >= pedp->rcProgress.right) {
01524
break;
01525 }
01526 }
01527 hdc =
GetDC(hwndDlg);
01528
FillRect(hdc, &pedp->rcProgress, pedp->hbrProgress);
01529
ReleaseDC(hwndDlg, hdc);
01530 pedp->rcProgress.left += pedp->iProgressWidth;
01531 pedp->rcProgress.right += pedp->iProgressWidth;
01532
break;
01533 }
01534
return TRUE;
01535
01536
01537
case WM_NCACTIVATE:
01538
01539
01540
01541
01542 pedp = (
ENDDLGPARAMS*)
GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
01543
if (pedp !=
NULL) {
01544 HWND hwnd;
01545
if (wParam) {
01546 hwnd = HWND_TOPMOST;
01547 }
else if (pedp->dwClientFlags &
WMCS_CONSOLE) {
01548 hwnd = HWND_TOP;
01549 }
else {
01550 hwnd = (HWND)pedp->lParam;
01551 }
01552
SetWindowPos(hwndDlg, hwnd,
01553 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
01554 }
01555
break;
01556
01557
01558
case WM_COMMAND:
01559
01560
01561
01562 pedp = (
ENDDLGPARAMS*)
GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
01563
if (pedp !=
NULL) {
01564 pedp->dwRet = (
DWORD)wParam;
01565 }
01566
DestroyWindow(hwndDlg);
01567
break;
01568
01569
01570
case WM_DESTROY:
01571
01572
01573
01574 pedp = (
ENDDLGPARAMS*)
GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
01575
if (pedp !=
NULL) {
01576 pedp->dwFlags |= (
EDPF_NODLG |
EDPF_RESPONSE);
01577
if (pedp->hbmpWarning !=
NULL) {
01578 DeleteObject(pedp->hbmpWarning);
01579 }
01580
if (pedp->hbrProgress !=
NULL) {
01581 DeleteObject(pedp->hbrProgress);
01582 }
01583 }
01584
break;
01585 }
01586
01587
return FALSE;
01588 }
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601 BOOL _EndTask(
01602 HWND hwnd,
01603 BOOL fShutdown,
01604 BOOL fMeanKill)
01605 {
01606
BOOL fRet =
TRUE;
01607 PCSR_THREAD pcsrt = CSR_SERVER_QUERYCLIENTTHREAD();
01608 PCSR_THREAD pcsrtKill;
01609
DWORD dwThreadId;
01610
DWORD dwProcessId;
01611 LPWSTR lpszMsg;
01612
BOOL fAllocated;
01613
DWORD dwCmd;
01614 USERTHREAD_USEDESKTOPINFO utudi;
01615
NTSTATUS Status;
01616
01617
01618
01619
01620
01621
01622 UNREFERENCED_PARAMETER(fShutdown);
01623
01624
01625
01626
01627
01628 utudi.hThread = pcsrt->ThreadHandle;
01629 utudi.drdRestore.pdeskRestore =
NULL;
01630
01631
Status =
NtUserSetInformationThread(NtCurrentThread(),
01632 UserThreadUseDesktop, &utudi,
sizeof(utudi));
01633
if (!
NT_SUCCESS(
Status)) {
01634
01635
01636
01637
return TRUE;
01638 }
01639
01640
01641
01642
01643
01644 dwThreadId =
GetWindowThreadProcessId(hwnd, &dwProcessId);
01645
if (dwThreadId == 0) {
01646
goto RestoreDesktop;
01647 }
01648
01649
01650
01651
01652
if (dwProcessId ==
gIdLogon) {
01653
goto RestoreDesktop;
01654 }
01655
01656
01657
01658
01659
01660
if ((HANDLE)
GetWindowLongPtr(hwnd, GWLP_HINSTANCE) ==
ghModuleWin) {
01661
PostMessage(hwnd, WM_CLOSE, 0, 0);
01662
goto RestoreDesktop;
01663 }
01664
01665
01666
01667
01668 CsrLockThreadByClientId((HANDLE)LongToHandle( dwThreadId ), &pcsrtKill);
01669
if (pcsrtKill ==
NULL) {
01670
goto RestoreDesktop;
01671 }
01672 CsrReferenceThread(pcsrtKill);
01673 CsrUnlockThread(pcsrtKill);
01674
01675
01676
01677
01678
if (!fMeanKill) {
01679
01680
01681
01682
01683
01684 dwCmd =
ThreadShutdownNotify(
WMCS_ENDTASK, (ULONG_PTR)pcsrtKill, (LPARAM)hwnd);
01685
01686
switch (dwCmd) {
01687
case TSN_APPSAYSNOTOK:
01688
01689
01690
01691
01692 CsrDereferenceThread(pcsrtKill);
01693 fRet =
FALSE;
01694
goto RestoreDesktop;
01695
01696
case TSN_USERSAYSCANCEL:
01697
01698
01699
01700
01701 CsrDereferenceThread(pcsrtKill);
01702
goto RestoreDesktop;
01703 }
01704 }
01705
01706
01707
01708
01709
01710
01711
if (!(pcsrtKill->Flags & CSR_THREAD_DESTROYED) && !
WowExitTask(pcsrtKill)) {
01712
01713
BOOL bDoBlock;
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
if (
ISTS()) {
01726
NTSTATUS ExitStatus;
01727 HANDLE
DebugPort;
01728
01729 ExitStatus = DBG_TERMINATE_PROCESS;
01730
if (
NT_SUCCESS(
NtQueryInformationProcess(NtCurrentProcess(),
01731 ProcessDebugPort,
01732 &
DebugPort,
01733
sizeof(HANDLE),
01734
NULL)) &&
01735 (
DebugPort !=
NULL)) {
01736
01737 ExitStatus = 0;
01738 }
01739
if (!
NT_SUCCESS(
NtTerminateProcess(pcsrtKill->Process->ProcessHandle,
01740 ExitStatus))) {
01741
01742 bDoBlock =
TRUE;
01743 }
else {
01744 bDoBlock =
FALSE;
01745 }
01746 }
else {
01747
if (!
NT_SUCCESS(
NtTerminateProcess(pcsrtKill->Process->ProcessHandle,
01748 DBG_TERMINATE_PROCESS))) {
01749 bDoBlock =
TRUE;
01750 }
else {
01751 bDoBlock =
FALSE;
01752 }
01753 }
01754
01755
if (bDoBlock) {
01756
01757
01758
01759
01760
01761 lpszMsg =
ServerLoadString(
ghModuleWin, STR_APPDEBUGGED,
01762
NULL, &fAllocated);
01763
if (lpszMsg) {
01764 MessageBoxEx(
NULL, lpszMsg,
NULL, MB_OK | MB_SETFOREGROUND, 0);
01765 LocalFree(lpszMsg);
01766 }
01767 }
else {
01768 pcsrtKill->Process->Flags |= CSR_PROCESS_TERMINATED;
01769 }
01770 }
01771 CsrDereferenceThread(pcsrtKill);
01772
01773 RestoreDesktop:
01774 utudi.hThread =
NULL;
01775
Status =
NtUserSetInformationThread(NtCurrentThread(),
01776 UserThreadUseDesktop, &utudi,
sizeof(utudi));
01777 UserAssert(
NT_SUCCESS(
Status));
01778
01779
return fRet;
01780 }
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791 BOOL WowExitTask(
01792 PCSR_THREAD pcsrt)
01793 {
01794 HANDLE ahandle[2];
01795 USERTHREAD_WOW_INFORMATION WowInfo;
01796
NTSTATUS Status;
01797
01798 ahandle[1] =
gheventCancel;
01799
01800
01801
01802
01803
Status =
NtUserQueryInformationThread(pcsrt->ThreadHandle,
01804 UserThreadWOWInformation, &WowInfo,
sizeof(WowInfo),
NULL);
01805
if (!
NT_SUCCESS(
Status))
01806
return FALSE;
01807
01808
01809
01810
01811
if (WowInfo.hTaskWow == 0)
01812
return FALSE;
01813
01814
01815
01816
01817
01818 ahandle[0] =
InternalCreateCallbackThread(pcsrt->Process->ProcessHandle,
01819 (ULONG_PTR)WowInfo.lpfnWowExitTask,
01820 (ULONG_PTR)WowInfo.hTaskWow);
01821
if (ahandle[0] ==
NULL) {
01822
NtTerminateProcess(pcsrt->Process->ProcessHandle, 0);
01823 pcsrt->Process->Flags |= CSR_PROCESS_TERMINATED;
01824
goto Exit;
01825 }
01826
01827 WaitForMultipleObjects(2, ahandle,
FALSE, INFINITE);
01828
NtClose(ahandle[0]);
01829
01830 Exit:
01831
return TRUE;
01832 }
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842 DWORD InternalWaitCancel(
01843 HANDLE handle,
01844 DWORD dwMilliseconds)
01845 {
01846 HANDLE ahandle[2];
01847
01848 ahandle[0] = handle;
01849 ahandle[1] =
gheventCancel;
01850
01851
return WaitForMultipleObjects(2, ahandle,
FALSE, dwMilliseconds);
01852 }
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865 HANDLE
InternalCreateCallbackThread(
01866 HANDLE hProcess,
01867 ULONG_PTR lpfn,
01868 ULONG_PTR dwData)
01869 {
01870 LONG BasePriority;
01871 HANDLE hThread, hToken;
01872 PTOKEN_DEFAULT_DACL lpDaclDefault;
01873 TOKEN_DEFAULT_DACL daclDefault;
01874 ULONG cbDacl;
01875 SECURITY_ATTRIBUTES attrThread;
01876 SECURITY_DESCRIPTOR sd;
01877
DWORD idThread;
01878
NTSTATUS Status;
01879
01880 hThread =
NULL;
01881
01882
Status =
NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
01883
if (!
NT_SUCCESS(
Status)) {
01884 KdPrint((
"NtOpenProcessToken failed, status = %x\n",
Status));
01885
return NULL;
01886 }
01887
01888 cbDacl = 0;
01889
NtQueryInformationToken(hToken,
01890 TokenDefaultDacl,
01891 &daclDefault,
01892
sizeof(daclDefault),
01893 &cbDacl);
01894
01895 lpDaclDefault = (PTOKEN_DEFAULT_DACL)LocalAlloc(LMEM_FIXED, cbDacl);
01896
if (lpDaclDefault ==
NULL) {
01897 KdPrint((
"LocalAlloc failed for lpDaclDefault"));
01898
goto closeexit;
01899 }
01900
01901
Status =
NtQueryInformationToken(hToken,
01902 TokenDefaultDacl,
01903 lpDaclDefault,
01904 cbDacl,
01905 &cbDacl);
01906
if (!
NT_SUCCESS(
Status)) {
01907 KdPrint((
"NtQueryInformationToken failed, status = %x\n",
Status));
01908
goto freeexit;
01909 }
01910
01911
if (!
NT_SUCCESS(
RtlCreateSecurityDescriptor(&sd,
01912 SECURITY_DESCRIPTOR_REVISION1))) {
01913 UserAssert(
FALSE);
01914
goto freeexit;
01915 }
01916
01917
RtlSetDaclSecurityDescriptor(&sd,
TRUE, lpDaclDefault->DefaultDacl,
TRUE);
01918
01919 attrThread.nLength =
sizeof(attrThread);
01920 attrThread.lpSecurityDescriptor = &sd;
01921 attrThread.bInheritHandle =
FALSE;
01922
01923 GetLastError();
01924 hThread = CreateRemoteThread(hProcess,
01925 &attrThread,
01926 0
L,
01927 (LPTHREAD_START_ROUTINE)lpfn,
01928 (
LPVOID)dwData,
01929 0,
01930 &idThread);
01931
01932
if (hThread !=
NULL) {
01933 BasePriority = THREAD_PRIORITY_HIGHEST;
01934
NtSetInformationThread(hThread,
01935 ThreadBasePriority,
01936 &BasePriority,
01937
sizeof(LONG));
01938 }
01939
01940 freeexit:
01941 LocalFree((HANDLE)lpDaclDefault);
01942
01943 closeexit:
01944
NtClose(hToken);
01945
01946
return hThread;
01947 }
01948
01949 ULONG
01950 SrvExitWindowsEx(
01951 IN OUT PCSR_API_MSG m,
01952 IN OUT PCSR_REPLY_STATUS ReplyStatus)
01953 {
01954
BEGIN_LPC_RECV(EXITWINDOWSEX);
01955
01956
Status =
_ExitWindowsEx(pcsrt, a->uFlags, a->dwReserved);
01957 a->fSuccess =
NT_SUCCESS(
Status);
01958
01959
END_LPC_RECV();
01960 }
01961
01962 ULONG
01963 SrvEndTask(
01964 IN OUT PCSR_API_MSG m,
01965 IN OUT PCSR_REPLY_STATUS ReplyStatus)
01966 {
01967
PENDTASKMSG petm = (
PENDTASKMSG)&m->u.ApiMessageData;
01968 PCSR_THREAD pcsrt;
01969 PTEB Teb = NtCurrentTeb();
01970
01971 Teb->LastErrorValue = 0;
01972 pcsrt = CSR_SERVER_QUERYCLIENTTHREAD();
01973
01974
01975
01976
01977
01978
if (pcsrt->Process->ClientPort !=
NULL) {
01979 m->ReturnValue = STATUS_SUCCESS;
01980 petm->
dwLastError = 0;
01981 petm->
fSuccess =
TRUE;
01982
NtReplyPort(pcsrt->Process->ClientPort, (PPORT_MESSAGE)m);
01983 *ReplyStatus = CsrServerReplied;
01984 }
01985
01986 petm->
fSuccess =
_EndTask(petm->
hwnd, petm->
fShutdown, petm->
fForce);
01987
01988 petm->
dwLastError = Teb->LastErrorValue;
01989
return STATUS_SUCCESS;
01990 }
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001 BOOL IsPrivileged(
02002 PPRIVILEGE_SET ppSet)
02003 {
02004 HANDLE hToken;
02005
NTSTATUS Status;
02006 BOOLEAN bResult =
FALSE;
02007 UNICODE_STRING strSubSystem;
02008
02009
02010
02011
02012
if (!CsrImpersonateClient(
NULL))
02013
return FALSE;
02014
02015
02016
02017
02018
RtlInitUnicodeString(&strSubSystem,
L"USER32");
02019
if (
NT_SUCCESS(
Status =
NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY,
02020 (BOOLEAN)
TRUE, &hToken))) {
02021
02022
02023
02024
02025
Status =
NtPrivilegeCheck(hToken, ppSet, &bResult);
02026
NtPrivilegeObjectAuditAlarm(&strSubSystem,
NULL, hToken,
02027 0, ppSet, bResult);
02028
NtClose(hToken);
02029
if (!bResult) {
02030 SetLastError(ERROR_ACCESS_DENIED);
02031 }
02032 }
02033 CsrRevertToSelf();
02034
if (!
NT_SUCCESS(
Status))
02035 SetLastError(
RtlNtStatusToDosError(
Status));
02036
02037
02038
02039
02040
return (
BOOL)(bResult &&
NT_SUCCESS(
Status));
02041 }
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052 ULONG
02053 SrvRegisterServicesProcess(
02054 IN OUT PCSR_API_MSG m,
02055 IN OUT PCSR_REPLY_STATUS ReplyStatus)
02056 {
02057 PRIVILEGE_SET
psTcb = { 1, PRIVILEGE_SET_ALL_NECESSARY,
02058 { SE_TCB_PRIVILEGE, 0 }
02059 };
02060
02061
BEGIN_LPC_RECV(REGISTERSERVICESPROCESS);
02062
02063
02064
02065
02066
02067
EnterCrit();
02068
if ((
gdwServicesProcessId != 0) || !
IsPrivileged(&
psTcb)) {
02069 SetLastError(ERROR_ACCESS_DENIED);
02070 a->fSuccess =
FALSE;
02071 }
else {
02072
gdwServicesProcessId = a->dwProcessId;
02073 a->fSuccess =
TRUE;
02074 }
02075
LeaveCrit();
02076
02077
END_LPC_RECV();
02078 }
02079
02080
#if defined(FE_IME)
02081
02082
02083
02084
02085
02086
02087
02088
02089
BOOL
02090 IsImeWindow(
02091 HWND hwnd
02092 )
02093 {
02094
int num;
02095 WCHAR ClassName[16];
02096
DWORD ClassStyle;
02097
02098 num = GetClassName(hwnd, ClassName,
sizeof(ClassName)/
sizeof(WCHAR)-1);
02099
if (num == 0)
02100
return FALSE;
02101
02102 ClassName[num] =
L'\0';
02103
if (wcsncmp(ClassName, L
"IME", 3) == 0)
02104
return TRUE;
02105
02106 ClassStyle = GetClassLong(hwnd, GCL_STYLE);
02107
if (ClassStyle & CS_IME)
02108
return TRUE;
02109
else
02110
return FALSE;
02111 }
02112
#endif