Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

ctrlc.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1985 - 1999, Microsoft Corporation 00004 00005 Module Name: 00006 00007 ctrlc.c 00008 00009 Abstract: 00010 00011 This module implements ctrl-c handling 00012 00013 Author: 00014 00015 Therese Stowell (thereses) 1-Mar-1991 00016 00017 Revision History: 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]; // initial handler list 00030 ULONG HandlerListLength; // used length of handler list 00031 ULONG AllocatedHandlerListLength; // allocated length of handler list 00032 PHANDLER_ROUTINE *HandlerList; // pointer to handler list 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 This is the default ctrl handler. 00050 00051 Parameters: 00052 00053 CtrlType - type of ctrl event (ctrl-c, ctrl-break). 00054 00055 Return Value: 00056 00057 none. 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 This routine initializes ctrl handling. It is called by AllocConsole 00073 and the dll initialization code. 00074 00075 Parameters: 00076 00077 none. 00078 00079 Return Value: 00080 00081 none. 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 Routine Description: 00100 00101 This thread is created when ctrl-c or ctrl-break is entered, 00102 or when close is selected. it calls the appropriate handlers. 00103 00104 Arguments: 00105 00106 lpThreadParameter - what type of event happened. 00107 00108 Return Value: 00109 00110 STATUS_SUCCESS 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 // If this bit is set, it means we don't want to cause this process 00126 // to exit itself if it is a logoff or shutdown event. 00127 // 00128 fNoExit = 0x80000000 & EventNumber; 00129 EventNumber &= ~0x80000000; 00130 00131 // 00132 // the ctrl_close event is set when the user selects the window 00133 // close option from the system menu, or EndTask, or Settings-Terminate. 00134 // the system close event is used when another ctrl-thread times out. 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 // If the process is being debugged, give the debugger 00148 // a shot. If the debugger handles the exception, then 00149 // go back and wait. 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 //if (LastConsoleEventActive) 00199 //EventNumber = SYSTEM_ROOT_CONSOLE_EVENT; 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 // Don't call the last handler (the default one which calls 00212 // ExitProcess() if this process isn't supposed to exit (system 00213 // process are not supposed to exit because of shutdown or 00214 // logoff event notification). 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 Routine Description: 00255 00256 Sends a ConsolepNotifyLastClose command to the server. 00257 00258 Arguments: 00259 00260 none. 00261 00262 Return Value: 00263 00264 None. 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 // private api 00290 { 00291 00292 LastConsoleEventActive = TRUE; 00293 SetLastConsoleEventActiveInternal(); 00294 } 00295 00296 BOOL 00297 SetCtrlHandler( 00298 IN PHANDLER_ROUTINE HandlerRoutine 00299 ) 00300 00301 /*++ 00302 00303 Routine Description: 00304 00305 This routine adds a ctrl handler to the process's list. 00306 00307 Arguments: 00308 00309 HandlerRoutine - pointer to ctrl handler. 00310 00311 Return Value: 00312 00313 TRUE - success. 00314 00315 --*/ 00316 00317 { 00318 PHANDLER_ROUTINE *NewHandlerList; 00319 00320 // 00321 // NULL handler routine is not stored in table. It is 00322 // used to temporarily inhibit ^C event handling 00323 // 00324 00325 if ( !HandlerRoutine ) { 00326 NtCurrentPeb()->ProcessParameters->ConsoleFlags = IGNORE_CTRL_C; 00327 return TRUE; 00328 } 00329 00330 if (HandlerListLength == AllocatedHandlerListLength) { 00331 00332 // 00333 // grow list 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 // copy list 00345 // 00346 00347 RtlCopyMemory(NewHandlerList,HandlerList,sizeof(PHANDLER_ROUTINE) * HandlerListLength); 00348 00349 if (HandlerList != SingleHandler) { 00350 00351 // 00352 // free old list 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 Routine Description: 00375 00376 This routine removes a ctrl handler from the process's list. 00377 00378 Arguments: 00379 00380 HandlerRoutine - pointer to ctrl handler. 00381 00382 Return Value: 00383 00384 TRUE - success. 00385 00386 --*/ 00387 00388 { 00389 ULONG i; 00390 00391 // 00392 // NULL handler routine is not stored in table. It is 00393 // used to temporarily inhibit ^C event handling. Removing 00394 // this handler allows normal processing to occur 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 // add or delete 00420 ) 00421 00422 /*++ 00423 00424 Routine Description: 00425 00426 This routine adds or removes a ctrl handler from the process's list. 00427 00428 Arguments: 00429 00430 HandlerRoutine - pointer to ctrl handler. 00431 00432 Add - if TRUE, add handler. else remove. 00433 00434 Return Value: 00435 00436 TRUE - success. 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

Generated on Sat May 15 19:39:37 2004 for test by doxygen 1.3.7