00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "precomp.h"
00022
#pragma hdrstop
00023
00024
#if !defined(BUILD_WOW64)
00025
00026 #define LIST_INCREMENT 2 // amount to grow handler list
00027 #define INITIAL_LIST_SIZE 1 // initial length of handler list
00028
00029 PHANDLER_ROUTINE
SingleHandler[
INITIAL_LIST_SIZE];
00030 ULONG
HandlerListLength;
00031 ULONG
AllocatedHandlerListLength;
00032 PHANDLER_ROUTINE *
HandlerList;
00033
00034 #define NUMBER_OF_CTRL_EVENTS 7 // number of ctrl events
00035 #define SYSTEM_CLOSE_EVENT 4
00036
00037 #define IGNORE_CTRL_C 0x01
00038
00039 BOOL LastConsoleEventActive;
00040
00041
00042
BOOL
00043 DefaultHandler(
00044 IN ULONG CtrlType
00045 )
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 {
00062 ExitProcess((
DWORD)CONTROL_C_EXIT);
00063
return TRUE;
00064 UNREFERENCED_PARAMETER(CtrlType);
00065 }
00066
00067
NTSTATUS
00068 InitializeCtrlHandling( VOID )
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 {
00086
AllocatedHandlerListLength =
HandlerListLength =
INITIAL_LIST_SIZE;
00087
HandlerList =
SingleHandler;
00088
SingleHandler[0] =
DefaultHandler;
00089
return STATUS_SUCCESS;
00090 }
00091
00092
DWORD
00093 CtrlRoutine(
00094 IN LPVOID lpThreadParameter
00095 )
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 {
00115 ULONG i;
00116 ULONG EventNumber,OriginalEventNumber;
00117
DWORD fNoExit;
00118
DWORD dwExitCode;
00119 EXCEPTION_RECORD ExceptionRecord;
00120
00121 SetThreadPriority(NtCurrentThread(), THREAD_PRIORITY_HIGHEST);
00122 OriginalEventNumber = EventNumber = PtrToUlong(lpThreadParameter);
00123
00124
00125
00126
00127
00128 fNoExit = 0x80000000 & EventNumber;
00129 EventNumber &= ~0x80000000;
00130
00131
00132
00133
00134
00135
00136
00137
switch (EventNumber) {
00138
default:
00139
ASSERT (EventNumber <
NUMBER_OF_CTRL_EVENTS);
00140
if (EventNumber >=
NUMBER_OF_CTRL_EVENTS)
00141
return (
DWORD)STATUS_UNSUCCESSFUL;
00142
break;
00143
00144
case CTRL_C_EVENT:
00145
case CTRL_BREAK_EVENT:
00146
00147
00148
00149
00150
00151
00152
if (!IsDebuggerPresent())
00153
break;
00154
00155
if ( EventNumber == CTRL_C_EVENT ) {
00156 ExceptionRecord.ExceptionCode = DBG_CONTROL_C;
00157 }
00158
else {
00159 ExceptionRecord.ExceptionCode = DBG_CONTROL_BREAK;
00160 }
00161 ExceptionRecord.ExceptionFlags = 0;
00162 ExceptionRecord.ExceptionRecord =
NULL;
00163 ExceptionRecord.ExceptionAddress = (PVOID)
DefaultHandler;
00164 ExceptionRecord.NumberParameters = 0;
00165
00166
try {
00167
RtlRaiseException(&ExceptionRecord);
00168 } except (
EXCEPTION_EXECUTE_HANDLER) {
00169
LockDll();
00170
try {
00171
if (EventNumber != CTRL_C_EVENT ||
00172 NtCurrentPeb()->ProcessParameters->ConsoleFlags !=
IGNORE_CTRL_C) {
00173
for (i=
HandlerListLength;i>0;i--) {
00174
if ((
HandlerList[i-1])(EventNumber)) {
00175
break;
00176 }
00177 }
00178 }
00179 } finally {
00180
UnlockDll();
00181 }
00182 }
00183 ExitThread(0);
00184
break;
00185
00186
case SYSTEM_CLOSE_EVENT:
00187 ExitProcess((
DWORD)CONTROL_C_EXIT);
00188
break;
00189
00190
case SYSTEM_ROOT_CONSOLE_EVENT:
00191
if (!
LastConsoleEventActive)
00192 ExitThread(0);
00193
break;
00194
00195
case CTRL_CLOSE_EVENT:
00196
case CTRL_LOGOFF_EVENT:
00197
case CTRL_SHUTDOWN_EVENT:
00198
00199
00200
break;
00201 }
00202
00203
LockDll();
00204 dwExitCode = 0;
00205
try {
00206
if (EventNumber != CTRL_C_EVENT ||
00207 NtCurrentPeb()->ProcessParameters->ConsoleFlags !=
IGNORE_CTRL_C) {
00208
for (i=
HandlerListLength;i>0;i--) {
00209
00210
00211
00212
00213
00214
00215
00216
00217
if ((i-1) == 0 && fNoExit) {
00218
if (EventNumber == CTRL_LOGOFF_EVENT ||
00219 EventNumber == CTRL_SHUTDOWN_EVENT) {
00220
break;
00221 }
00222 }
00223
00224
if ((
HandlerList[i-1])(EventNumber)) {
00225
switch (EventNumber) {
00226
case CTRL_CLOSE_EVENT:
00227
case CTRL_LOGOFF_EVENT:
00228
case CTRL_SHUTDOWN_EVENT:
00229
case SYSTEM_ROOT_CONSOLE_EVENT:
00230 dwExitCode = OriginalEventNumber;
00231
break;
00232 }
00233
break;
00234 }
00235 }
00236 }
00237 } finally {
00238
UnlockDll();
00239 }
00240 ExitThread(dwExitCode);
00241
return STATUS_SUCCESS;
00242 }
00243
00244
#endif
00245
00246
#if !defined(BUILD_WOW6432)
00247
00248
VOID
00249
APIENTRY
00250 SetLastConsoleEventActiveInternal( VOID )
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 {
00269
CONSOLE_API_MSG m;
00270
PCONSOLE_NOTIFYLASTCLOSE_MSG a = &m.
u.SetLastConsoleEventActive;
00271
00272 a->
ConsoleHandle =
GET_CONSOLE_HANDLE;
00273
CsrClientCallServer( (PCSR_API_MSG)&m,
00274
NULL,
00275 CSR_MAKE_API_NUMBER( CONSRV_SERVERDLL_INDEX,
00276
ConsolepNotifyLastClose
00277 ),
00278
sizeof( *a )
00279 );
00280 }
00281
00282
#endif
00283
00284
#if !defined(BUILD_WOW64)
00285
00286
VOID
00287
APIENTRY
00288 SetLastConsoleEventActive( VOID )
00289
00290 {
00291
00292
LastConsoleEventActive =
TRUE;
00293
SetLastConsoleEventActiveInternal();
00294 }
00295
00296
BOOL
00297 SetCtrlHandler(
00298 IN PHANDLER_ROUTINE HandlerRoutine
00299 )
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 {
00318 PHANDLER_ROUTINE *NewHandlerList;
00319
00320
00321
00322
00323
00324
00325
if ( !HandlerRoutine ) {
00326 NtCurrentPeb()->ProcessParameters->ConsoleFlags =
IGNORE_CTRL_C;
00327
return TRUE;
00328 }
00329
00330
if (
HandlerListLength ==
AllocatedHandlerListLength) {
00331
00332
00333
00334
00335
00336 NewHandlerList = (PHANDLER_ROUTINE *)
RtlAllocateHeap( RtlProcessHeap(), 0,
00337
sizeof(PHANDLER_ROUTINE) * (
HandlerListLength +
LIST_INCREMENT));
00338
if (!NewHandlerList) {
00339
SET_LAST_ERROR(ERROR_NOT_ENOUGH_MEMORY);
00340
return FALSE;
00341 }
00342
00343
00344
00345
00346
00347 RtlCopyMemory(NewHandlerList,
HandlerList,
sizeof(PHANDLER_ROUTINE) *
HandlerListLength);
00348
00349
if (
HandlerList !=
SingleHandler) {
00350
00351
00352
00353
00354
00355
RtlFreeHeap(RtlProcessHeap(), 0,
HandlerList);
00356 }
00357
HandlerList = NewHandlerList;
00358
AllocatedHandlerListLength +=
LIST_INCREMENT;
00359 }
00360
ASSERT (
HandlerListLength <
AllocatedHandlerListLength);
00361
00362
HandlerList[
HandlerListLength] = HandlerRoutine;
00363
HandlerListLength++;
00364
return TRUE;
00365 }
00366
00367
BOOL
00368 RemoveCtrlHandler(
00369 IN PHANDLER_ROUTINE HandlerRoutine
00370 )
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 {
00389 ULONG i;
00390
00391
00392
00393
00394
00395
00396
00397
if ( !HandlerRoutine ) {
00398 NtCurrentPeb()->ProcessParameters->ConsoleFlags = 0;
00399
return TRUE;
00400 }
00401
00402
for (i=0;i<
HandlerListLength;i++) {
00403
if (*(
HandlerList+i) == HandlerRoutine) {
00404
if (i < (
HandlerListLength-1)) {
00405 memmove(&
HandlerList[i],&
HandlerList[i+1],
sizeof(PHANDLER_ROUTINE) * (
HandlerListLength - i - 1));
00406 }
00407
HandlerListLength -= 1;
00408
return TRUE;
00409 }
00410 }
00411
SET_LAST_ERROR(ERROR_INVALID_PARAMETER);
00412
return FALSE;
00413 }
00414
00415
BOOL
00416
APIENTRY
00417 SetConsoleCtrlHandler(
00418 IN PHANDLER_ROUTINE HandlerRoutine,
00419 IN BOOL Add
00420 )
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 {
00441
BOOL Success;
00442
00443
LockDll();
00444
if (Add) {
00445 Success =
SetCtrlHandler(HandlerRoutine);
00446 }
00447
else {
00448 Success =
RemoveCtrlHandler(HandlerRoutine);
00449 }
00450
UnlockDll();
00451
return Success;
00452 }
00453
00454
#endif