source: trunk/src/kernel32/testcase/ConsoleCtrlHandler.c

Last change on this file was 8772, checked in by sandervl, 23 years ago

KSO: added testcases for SetConsoleCtrlHandler, GenerateConsoleCtrlEvent & MultiByteToWideChar

File size: 20.7 KB
Line 
1/* $Id: ConsoleCtrlHandler.c,v 1.1 2002-06-26 07:11:02 sandervl Exp $
2 *
3 * Test of SetConsoleCtrlHandler and GenerateConsoleCtrlEvent.
4 *
5 * Copyright (c) 2002 knut st. osmundsen (bird@anduin.net)
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11
12/*******************************************************************************
13* Defined Constants And Macros *
14*******************************************************************************/
15//#define HACKING
16
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#include <windows.h>
22#include <wincon.h>
23#define _WPROCESS_H__ /* a hack to exclude some odin specific stuff. */
24#include <winprocess.h>
25#include <thread.h>
26
27#include <process.h>
28#include <string.h>
29#include <stdio.h>
30
31
32/*******************************************************************************
33* Global Variables *
34*******************************************************************************/
35char aRHOrder[20];
36int iRHOrder = 0;
37int fRemoveAdd = FALSE; /* Flag which enables removal/add within
38 * the RemovalHandler#(). I.e. makes them
39 * really ugly. */
40
41
42/*******************************************************************************
43* Internal Functions *
44*******************************************************************************/
45BOOL WIN32API RemovalHandler0(DWORD dwEvent);
46BOOL WIN32API RemovalHandler1(DWORD dwEvent);
47BOOL WIN32API RemovalHandler2(DWORD dwEvent);
48BOOL WIN32API RemovalHandler3(DWORD dwEvent);
49BOOL WIN32API RemovalHandler4(DWORD dwEvent);
50BOOL WIN32API RemovalHandler5(DWORD dwEvent);
51
52
53/**
54 * Display syntax
55 */
56int syntax(const char * arg0)
57{
58 const char *psz = strrchr(arg0, '\\');
59 if (!psz)
60 psz = strrchr(arg0, '/');
61 else if (strrchr(psz, '/'))
62 psz = strrchr(psz, '/');
63 if (!psz)
64 psz = strrchr(arg0, ':');
65 if (!psz)
66 psz = arg0;
67 else
68 psz++;
69
70 printf("Syntax: %s <testcase#>\n"
71 "\n"
72 "Testcases: (1-9 is non-interactive; 10-19 is interactive)\n"
73 " 1 - Watch default action.\n"
74 " 2 - Register two handlers and rais Ctrl-C condition.\n"
75 " 3 - Register two handlers and rais Ctrl-Break condition.\n"
76 , psz);
77 return -1;
78}
79
80
81/**
82 * Print internal structures.
83 */
84#ifdef WIN32
85 #ifdef __WATCOMC__
86 #undef NtCurrentTeb
87 __declspec(dllimport) TEB * __cdecl NtCurrentTeb(void);
88 #endif
89#endif
90
91
92/**
93 * Hacking function.
94 */
95#ifdef HACKING
96static void printflags(const char *psz)
97{
98 TEB * pTEB = NtCurrentTeb();
99
100 printf("printflags %s\n", psz);
101 if ((unsigned)pTEB->process >= 0x10000 && (unsigned)pTEB->process < 0xc0000000)
102 {
103 ENVDB *pEDB = pTEB->process->env_db;
104 if ((unsigned)pEDB >= 0x10000 && (unsigned)pEDB < 0xc0000000)
105 {
106 printf("pEDB->inherit_console= 0x%08x\n", pEDB->inherit_console);
107 printf("pEDB->break_type = 0x%08x\n", pEDB->break_type);
108 printf("pEDB->break_sem = 0x%08x\n", pEDB->break_sem);
109 printf("pEDB->break_event = 0x%08x\n", pEDB->break_event);
110 printf("pEDB->break_thread = 0x%08x\n", pEDB->break_thread);
111 printf("pEDB->break_handlers = 0x%08x\n", pEDB->break_handlers);
112 printf("pEDB->section = 0x%08x\n", pEDB->section);
113
114 fflush(stdout);
115#if 0
116 printf("pTEB=%x pTEB->process=%x\n", pTEB, pTEB->process);
117 printf("pEDB->break_type[0] = 0x%08x\n", ((PDWORD)pEDB->break_type)[0]); fflush(stdout);
118 printf("pEDB->break_type[1] = 0x%08x\n", ((PDWORD)pEDB->break_type)[1]); fflush(stdout);
119 printf("pEDB->break_type[2] = 0x%08x\n", ((PDWORD)pEDB->break_type)[2]); fflush(stdout);
120 printf("pEDB->break_type[3] = 0x%08x\n", ((PDWORD)pEDB->break_type)[3]); fflush(stdout);
121 printf("pEDB->break_type[4] = 0x%08x\n", ((PDWORD)pEDB->break_type)[4]); fflush(stdout);
122 printf("pEDB->break_type[5] = 0x%08x\n", ((PDWORD)pEDB->break_type)[5]); fflush(stdout);
123 printf("pEDB->break_type[6] = 0x%08x\n", ((PDWORD)pEDB->break_type)[6]); fflush(stdout);
124 printf("pEDB->break_type[7] = 0x%08x\n", ((PDWORD)pEDB->break_type)[7]); fflush(stdout);
125 printf("pEDB->break_type[8] = 0x%08x\n", ((PDWORD)pEDB->break_type)[8]); fflush(stdout);
126 printf("pEDB->break_type[9] = 0x%08x\n", ((PDWORD)pEDB->break_type)[9]); fflush(stdout);
127#endif
128 }
129 else
130 printf("pTEB->process->env_db = %x\n", pEDB);
131 }
132 else
133 printf("pTEB->process = %x\n", pTEB->process);
134}
135#else
136static void printflags(const char *psz)
137{
138 psz = psz;
139 return;
140}
141#endif
142
143
144/**
145 * Test handler
146 */
147BOOL WIN32API MyHandler(DWORD dwCtrlType)
148{
149 printflags("MyHandler");
150 switch (dwCtrlType)
151 {
152 case CTRL_C_EVENT:
153 printf("dwCtrlType=%d CTRL_C_EVENT\n", dwCtrlType);
154 break;
155 case CTRL_BREAK_EVENT:
156 printf("dwCtrlType=%d CTRL_BREAK_EVENT\n", dwCtrlType);
157 break;
158 case CTRL_CLOSE_EVENT:
159 printf("dwCtrlType=%d CTRL_CLOSE_EVENT\n", dwCtrlType);
160 break;
161 case CTRL_LOGOFF_EVENT:
162 printf("dwCtrlType=%d CTRL_LOGOFF_EVENT\n", dwCtrlType);
163 break;
164 case CTRL_SHUTDOWN_EVENT:
165 printf("dwCtrlType=%d CTRL_SHUTDOWN_EVENT\n", dwCtrlType);
166 break;
167
168 default:
169 printf("dwCtrlType=%d\n", dwCtrlType);
170 }
171 return TRUE;
172}
173
174
175/**
176 * Testing of linking and removal of entries while in the handler.
177 */
178BOOL WIN32API RemovalHandler0(DWORD dwEvent)
179{
180 printf("RemovalHandler0 ");
181 if (fRemoveAdd)
182 {
183 if (SetConsoleCtrlHandler(RemovalHandler0, FALSE))
184 printf("remove of 0 ok");
185 else
186 printf("remove of 0 nok! lasterr=%d", GetLastError());
187 }
188 printf("\n");
189 aRHOrder[iRHOrder++] = 0;
190 return FALSE;
191}
192BOOL WIN32API RemovalHandler1(DWORD dwEvent)
193{
194 printf("RemovalHandler1 ");
195 if (fRemoveAdd)
196 {
197 if (SetConsoleCtrlHandler(RemovalHandler3, TRUE))
198 {
199 if (SetConsoleCtrlHandler(RemovalHandler3, FALSE))
200 printf("add & remove of 3 ok");
201 else
202 printf("remove of 3 nok! lasterr=%d", GetLastError());
203 }
204 else
205 printf("add of 3 nok! lasterr=%d", GetLastError());
206 }
207 printf("\n");
208 aRHOrder[iRHOrder++] = 1;
209 return FALSE;
210}
211
212BOOL WIN32API RemovalHandler2(DWORD dwEvent)
213{
214 printf("RemovalHandler2 ");
215 if (fRemoveAdd)
216 {
217 if (SetConsoleCtrlHandler(RemovalHandler2, FALSE))
218 printf("remove of 2 ok");
219 else
220 printf("remove of 2nok! lasterr=%d", GetLastError());
221 }
222 printf("\n");
223 aRHOrder[iRHOrder++] = 2;
224 return FALSE;
225}
226
227BOOL WIN32API RemovalHandler3(DWORD dwEvent)
228{
229 printf("RemovalHandler3 ");
230 if (fRemoveAdd)
231 {
232 if (SetConsoleCtrlHandler(RemovalHandler3, FALSE))
233 printf("remove of 3 ok");
234 else
235 printf("remove of 3 nok! lasterr=%d", GetLastError());
236 }
237 printf("\n");
238 aRHOrder[iRHOrder++] = 3;
239 return TRUE;
240}
241
242BOOL WIN32API RemovalHandler4(DWORD dwEvent)
243{
244 printf("RemovalHandler4 ");
245 if (fRemoveAdd)
246 {
247 if (SetConsoleCtrlHandler(RemovalHandler4, TRUE))
248 printf("add of 4 ok");
249 else
250 printf("add of 4 nok! lasterr=%d", GetLastError());
251 }
252 printf("\n");
253 aRHOrder[iRHOrder++] = 4;
254 return FALSE;
255}
256
257BOOL WIN32API RemovalHandler5(DWORD dwEvent)
258{
259 printf("RemovalHandler5 ");
260 if (fRemoveAdd)
261 {
262 if ( SetConsoleCtrlHandler(RemovalHandler5, FALSE)
263 && SetConsoleCtrlHandler(RemovalHandler5, FALSE)
264 && SetConsoleCtrlHandler(RemovalHandler5, FALSE))
265 printf("remove of 5 three times ok\n");
266 else
267 printf("remove of 5 three times nok! lasterr=%d\n", GetLastError());
268 }
269 printf("\n");
270 aRHOrder[iRHOrder++] = 5;
271 return FALSE;
272}
273
274BOOL WIN32API RemovalHandler6(DWORD dwEvent)
275{
276 printf("RemovalHandler6 ");
277 if (fRemoveAdd)
278 {
279 if (SetConsoleCtrlHandler(RemovalHandler6, FALSE))
280 printf("remove of 6 ok\n");
281 else
282 printf("remove of 6 nok! lasterr=%d\n", GetLastError());
283 }
284 printf("\n");
285 aRHOrder[iRHOrder++] = 6;
286 return TRUE;
287}
288
289
290
291
292/**
293 *
294 * @returns 0 on success.
295 * non-zero on failure.
296 * @param argv A
297 * @status completely implemented.
298 * @author knut st. osmundsen (bird@anduin.net)
299 * @remark
300 */
301int main(int argc, char **argv)
302{
303 int iCase; /* testcase number. */
304 int argi;
305 int rc = 0;
306 char szCmd[512];
307
308 /*
309 * Check for syntax request.
310 */
311 if (argc != 2 || atol(argv[1]) == 0)
312 return syntax(argv[0]);
313
314 for (argi = 1; argi < argc; argi++)
315 if ( (argv[argi][0] == '-' || argv[argi][0] == '/')
316 && (argv[argi][1] == '-' || argv[argi][1] == 'h' || argv[argi][1] == 'H')
317 )
318 return syntax(argv[0]);
319
320 iCase = atol(argv[1]);
321 switch (iCase)
322 {
323 case 1:
324 case 2:
325 case 3:
326 {
327 int pid;
328 sprintf(szCmd, "%d", atol(argv[1])*100);
329 printflags("Initial");
330 if (SetConsoleCtrlHandler(NULL, TRUE))
331 printflags("After Set(NULL,TRUE) -> ok");
332 else
333 printflags("After Set(NULL,TRUE) -> nok");
334 pid = spawnl(P_WAIT, argv[0], argv[0], szCmd, NULL);
335 if (SetConsoleCtrlHandler(NULL, TRUE))
336 printflags("After Set(NULL,TRUE) -> ok");
337 else
338 printflags("After Set(NULL,TRUE) -> nok");
339 rc = wait(&pid);
340 printf("exit rc=%d\n", rc);
341 break;
342 }
343
344 case 1*100:
345 printf("GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0) rc=%d\n",
346 GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0));
347 break;
348
349 case 2*100:
350 printflags("Initial");
351 if (SetConsoleCtrlHandler(MyHandler, TRUE))
352 printflags("After Set(MyHandler,FALSE) -> ok");
353 else
354 printflags("After Set(MyHandler,FALSE) -> nok");
355 //printf("GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0) rc=%d\n",
356 // GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0));
357 Sleep(10000);
358 printflags("end");
359 break;
360
361 case 3*100:
362 printf("GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0) rc=%d\n",
363 GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0));
364 printf("fatal error: Invalid testcase number (%d).\n", atol(argv[1]));
365 break;
366
367 /*
368 * Negative testing of GenerateConsoleCtrlEvent().
369 */
370 case 20:
371 {
372 int i;
373 struct _NegEvent
374 {
375 DWORD dwEvent;
376 DWORD dwPidGroup;
377 DWORD dwLastError;
378 } aEvents[] =
379 {
380 {CTRL_CLOSE_EVENT/*2*/, 0, ERROR_MR_MID_NOT_FOUND},
381 {CTRL_LOGOFF_EVENT/*5*/, 0, ERROR_MR_MID_NOT_FOUND},
382 {CTRL_SHUTDOWN_EVENT/*6*/, 0, ERROR_MR_MID_NOT_FOUND},
383 {3, 0, ERROR_MR_MID_NOT_FOUND},
384 {4, 0, ERROR_MR_MID_NOT_FOUND},
385 {7, 0, ERROR_MR_MID_NOT_FOUND},
386 {-1, 0, ERROR_MR_MID_NOT_FOUND},
387 {-2, 0, ERROR_MR_MID_NOT_FOUND},
388 {CTRL_C_EVENT, 0xdeadbeef, -1}, /* this is weird! */
389 {CTRL_BREAK_EVENT, 0xdeadbeef, -1}, /* this is weird! */
390 {CTRL_LOGOFF_EVENT/*5*/, -1, ERROR_MR_MID_NOT_FOUND},
391 {CTRL_SHUTDOWN_EVENT/*6*/, -1, ERROR_MR_MID_NOT_FOUND},
392 {CTRL_SHUTDOWN_EVENT/*6*/, -1, ERROR_MR_MID_NOT_FOUND},
393 {3, -1, ERROR_MR_MID_NOT_FOUND},
394 {4, -1, ERROR_MR_MID_NOT_FOUND},
395 {7, -1, ERROR_MR_MID_NOT_FOUND},
396 {-1, -1, ERROR_MR_MID_NOT_FOUND},
397 {-2, -1, ERROR_MR_MID_NOT_FOUND}
398 };
399
400 for (i = 0; i < sizeof(aEvents) / sizeof(aEvents[0]); i++)
401 {
402 BOOL fRc;
403 DWORD dwLastError;
404 SetLastError(-1);
405 fRc = GenerateConsoleCtrlEvent(aEvents[i].dwEvent, aEvents[i].dwPidGroup);
406 if (fRc != 0 && fRc != 1)
407 printf("Warning: GenerateConsoleCtrlEvent(%d, %d) returned %d\n", aEvents[i].dwEvent, aEvents[i].dwPidGroup, fRc);
408 if (aEvents[i].dwLastError == -1 ? !fRc : fRc)
409 {
410 printf("error: GenerateConsoleCtrlEvent(%d, %d) returned %d\n", aEvents[i].dwEvent, aEvents[i].dwPidGroup, fRc);
411 rc++;
412 }
413
414 dwLastError = GetLastError();
415 if (dwLastError != aEvents[i].dwLastError)
416 {
417 printf("error: GenerateConsoleCtrlEvent(%d, %d) LastError=%d expected=%d\n",
418 aEvents[i].dwEvent, aEvents[i].dwPidGroup, dwLastError, aEvents[i].dwLastError);
419 rc++;
420 }
421 }
422 break;
423 }
424
425
426 /*
427 * Negative testing of SetConsoleCtrlHandler().
428 */
429 case 21:
430 {
431 int i;
432 struct _NegHandler
433 {
434 DWORD dwHandler;
435 DWORD dwAdd;
436 DWORD dwLastError;
437 } aHandlers[] =
438 {
439 {0, 0, -1}, /* 0 */
440 {0, 0, -1}, /* 1 */
441 {(DWORD)&main, 0, ERROR_INVALID_PARAMETER}, /* 2 */
442 {0xffffffff, 0, ERROR_INVALID_PARAMETER}, /* 3 */
443 {0, 1, -1}, /* 4 */
444 {0, 1, -1}, /* 5 */
445 {0xffffffff, 1, -1}, /* 6 */
446 {(DWORD)&main, 1, -1}, /* 7 */
447 {(DWORD)&main, 0, -1}, /* 8 */
448 {(DWORD)&main, 0xdeadbeef, -1}, /* 9 */
449 {(DWORD)&main, 1, -1}, /*11 */
450 {(DWORD)&main, 0, -1}, /*12 */
451 {(DWORD)&main, 0, -1}, /*13 */
452 {(DWORD)&main, 0, ERROR_INVALID_PARAMETER}, /*14 */
453 {0, 0xdeadbeef, -1}, /*15 */
454 };
455
456 for (i = 0; i < sizeof(aHandlers) / sizeof(aHandlers[0]); i++)
457 {
458 BOOL fRc;
459 DWORD dwLastError;
460
461 SetLastError(-1);
462 fRc = SetConsoleCtrlHandler((PHANDLER_ROUTINE)(void*)aHandlers[i].dwHandler, aHandlers[i].dwAdd);
463 if (fRc != 0 && fRc != 1)
464 printf("Warning-%d: SetConsoleCtrlHandler(%d, %d) returned %d\n", i, aHandlers[i].dwHandler, aHandlers[i].dwAdd, fRc);
465 if (aHandlers[i].dwLastError == -1 ? !fRc : fRc)
466 {
467 printf("error-%d: SetConsoleCtrlHandler(%d, %d) returned %d\n", i, aHandlers[i].dwHandler, aHandlers[i].dwAdd, fRc);
468 rc++;
469 }
470
471 dwLastError = GetLastError();
472 if (dwLastError != aHandlers[i].dwLastError)
473 {
474 printf("error-%d: SetConsoleCtrlHandler(%d, %d) LastError=%d expected=%d\n",
475 i, aHandlers[i].dwHandler, aHandlers[i].dwAdd, dwLastError, aHandlers[i].dwLastError);
476 rc++;
477 }
478 }
479
480 break;
481 }
482
483
484 /*
485 * Check how a removal of one self from inside a handler works.
486 */
487 case 24:
488 fRemoveAdd = TRUE;
489 case 23:
490 case 22:
491 {
492 if ( SetConsoleCtrlHandler(RemovalHandler6, TRUE)
493 && SetConsoleCtrlHandler(RemovalHandler0, TRUE)
494 && SetConsoleCtrlHandler(RemovalHandler2, TRUE)
495 && SetConsoleCtrlHandler(RemovalHandler4, TRUE)
496 && SetConsoleCtrlHandler(RemovalHandler5, TRUE)
497 && SetConsoleCtrlHandler(RemovalHandler5, TRUE)
498 && SetConsoleCtrlHandler(RemovalHandler5, TRUE)
499 && SetConsoleCtrlHandler(RemovalHandler0, TRUE)
500 && SetConsoleCtrlHandler(RemovalHandler1, TRUE)
501 && SetConsoleCtrlHandler(RemovalHandler0, TRUE)
502 )
503 {
504 if (iCase == 23)
505 {
506 if (!SetConsoleCtrlHandler(RemovalHandler0, FALSE))
507 {
508 printf("Failed to remove hanlder 0. lasterr=%d\n", GetLastError());
509 rc++;
510 }
511 }
512
513 if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0))
514 {
515 char aRHOrder22[20] = {0,1,0,5,5,5,4,2,0,6,-1,-1};
516 char aRHOrder23[20] = {0,1,0,5,5,5,4,2,6,-1,-1};
517 char aRHOrder24[20] = {0,0,0,1,5,1,1,4,2,6,-1,-1};
518
519 Sleep(1000); /* This is really asyncronus events apparently :/ */
520 if ( (iCase == 22 && iRHOrder == 10 && !memcmp(aRHOrder, aRHOrder22, iRHOrder))
521 || (iCase == 23 && iRHOrder == 9 && !memcmp(aRHOrder, aRHOrder23, iRHOrder))
522 || (iCase == 24 && iRHOrder == 10 && !memcmp(aRHOrder, aRHOrder24, iRHOrder))
523 )
524 {
525 rc = rc; /* nop */
526 }
527 else
528 {
529 int i;
530 char * paRHOrderExpected;
531 int cRHOrderExpected;
532
533 /*
534 * Failed - give details.
535 */
536 printf("error: all handlers wasn't called correctly.\n");
537 printf("actual - #=%-2d order=", iRHOrder);
538 for (i = 0; i < iRHOrder; i++)
539 printf("%d ", (int)aRHOrder[i]);
540 switch (iCase)
541 {
542 case 22: paRHOrderExpected = &aRHOrder22[0]; cRHOrderExpected = 10; break;
543 case 23: paRHOrderExpected = &aRHOrder23[0]; cRHOrderExpected = 9; break;
544 case 24: paRHOrderExpected = &aRHOrder24[0]; cRHOrderExpected = 10; break;
545 }
546 printf("\n"
547 "expected - #=%-2d order=", cRHOrderExpected);
548 for (i = 0; i < cRHOrderExpected; i++)
549 printf("%d ", (int)paRHOrderExpected[i]);
550 printf("\n");
551 rc++;
552 }
553 }
554 else
555 {
556 printf("error: GenerateConsoleCtrlEvent failed. lasterr=%d\n", GetLastError());
557 rc++;
558 }
559 }
560 else
561 {
562 printf("error: Adding of RemovalHandler failed. lasterr=%d\n", GetLastError());
563 rc++;
564 }
565 break;
566 }
567
568
569
570 default:
571 printf("fatal error: Invalid testcase number (%d).\n", atol(argv[1]));
572 rc = 16;
573 }
574
575 printf(" . %d Errors .\n", rc);
576 fflush(stdout); /* odin32 bug! */
577 return rc;
578}
Note: See TracBrowser for help on using the repository browser.