source: trunk/src/kernel32/conodin32.cpp@ 22018

Last change on this file since 22018 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 10.4 KB
Line 
1/* $Id: conodin32.cpp,v 1.1 2002-06-26 07:13:30 sandervl Exp $
2 *
3 * Part of consol which require Odin32 headers not compatible with os2wrap.h.
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#include <odin.h>
12#include <odinwrap.h>
13#include <os2sel.h>
14
15#include <os2win.h>
16#include <winnt.h>
17#include <winnls.h>
18#include <wincon.h>
19#include <winprocess.h>
20
21#include <stdlib.h>
22#include <string.h>
23
24#include <misc.h>
25#include <wprocess.h>
26
27#include "console.h"
28
29#define DBG_LOCALLOG DBG_conodin32
30#include "dbglocal.h"
31
32
33
34
35
36
37/**
38 * Internal worker for generating console control events.
39 * This worker doesn't validate the event.
40 *
41 * @returns TRUE/FALSE.
42 * @param dwCtrlEvent The event number to generate.
43 * CTRL_C_EVENT or CTRL_BREAK_EVENT.
44 * @param dwProcessGroupId The target process group
45 * Odin32: Currently only supports our selfs.
46 * @status partially implemented and tested.
47 * @author knut st. osmundsen (bird@anduin.net)
48 * @remark NT is doing this asynchronus.
49 * @remark We don't handle all removal/add situation too well..
50 */
51BOOL InternalGenerateConsoleCtrlEvent(DWORD dwCtrlEvent, DWORD dwProcessGroupId)
52{
53 ENVDB * pEDB;
54 BOOL fHandled = FALSE;
55 PDB * pdb;
56 PCONCTRL pCur;
57 PCONCTRLDATA pData;
58
59 /*
60 * Get process data.
61 */
62 pdb = PROCESS_IdToPDB(0);
63 if (pdb == NULL || pdb->env_db == NULL)
64 {
65 dprintf(("KERNEL32:CONSOLE: GenerateConsoleCtrlEvent(%08x,%08x) - pdb == NULL || pdb->env_db == NULL. To early?\n",
66 dwCtrlEvent, dwProcessGroupId));
67 DebugInt3();
68 return FALSE;
69 }
70 pEDB = pdb->env_db;
71
72
73 /*
74 * Do the work.
75 * I'm lazy, so I'm using critical section for this.
76 * (Should perhaps use the break_sem.. But NT doesn't use that apparently.)
77 */
78 EnterCriticalSection(&pEDB->section);
79 pData = ((PCONCTRLDATA)pEDB->break_handlers);
80 pCur = pData->pHead;
81 while (pCur)
82 {
83 void *pvFree = NULL;
84 pCur->flFlags |= ODIN32_CONCTRL_FLAGS_USED;
85 fHandled = ((PHANDLER_ROUTINE)pCur->pfnHandler)(dwCtrlEvent);
86 pCur->flFlags &= ~ODIN32_CONCTRL_FLAGS_USED;
87
88 if (pCur->flFlags & ODIN32_CONCTRL_FLAGS_USED)
89 {
90 pvFree = pCur;
91 if (pCur->pNext)
92 pCur->pNext->pPrev = pCur->pPrev;
93 else
94 pData->pTail = pCur->pPrev;
95 if (pCur->pPrev)
96 pCur->pPrev->pNext = pCur->pNext;
97 else
98 pData->pHead = pCur->pNext;
99 }
100
101 /* next */
102 pCur = pCur->pNext;
103 free(pvFree);
104 if (fHandled)
105 break;
106 }
107 LeaveCriticalSection(&pEDB->section);
108 return fHandled;
109}
110
111
112/**
113 * Generatea Ctrl event to for a console. Ie. Ctrl-C or Ctrl-Break.
114 * @returns Success indicator.
115 * @param dwCtrlEvent The event number to generate.
116 * CTRL_C_EVENT or CTRL_BREAK_EVENT.
117 * @param dwProcessGroupId The target process group
118 * Odin32: Currently only supports our selfs.
119 * @status partially implemented and tested.
120 * @author knut st. osmundsen (bird@anduin.net)
121 * @todo Respect the fIgnoreCtrlC flag.
122 */
123BOOL WIN32API GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
124 DWORD dwProcessGroupId)
125{
126 ENVDB * pEDB;
127 BOOL fHandled = FALSE;
128
129 dprintf(("KERNEL32:CONSOLE: GenerateConsoleCtrlEvent(%08x,%08x) - partially implemented(?).\n",
130 dwCtrlEvent, dwProcessGroupId));
131
132 /*
133 * Get process data.
134 */
135 //PDB *pdb = PROCESS_IdToPDB(0);
136 struct _PDB *pdb = PROCESS_IdToPDB(0);
137 if (pdb == NULL || pdb->env_db == NULL)
138 {
139 dprintf(("KERNEL32:CONSOLE: GenerateConsoleCtrlEvent(%08x,%08x) - pdb == NULL || pdb->env_db == NULL. To early?\n",
140 dwCtrlEvent, dwProcessGroupId));
141 DebugInt3();
142 return FALSE;
143 }
144
145 /*
146 * Validate input.
147 */
148 if ( dwCtrlEvent != CTRL_C_EVENT
149 && dwCtrlEvent != CTRL_BREAK_EVENT)
150 { /* bad event */
151 SetLastError(ERROR_MR_MID_NOT_FOUND);
152 dprintf(("KERNEL32:CONSOLE: GenerateConsoleCtrlEvent(%08x,%08x) - Event. Returns FALSE.\n",
153 dwCtrlEvent, dwProcessGroupId));
154 return FALSE;
155 }
156
157 if ( dwProcessGroupId != 0
158 && ( dwProcessGroupId != (DWORD)pdb->server_pid
159 && (pdb->group == NULL || dwProcessGroupId != (DWORD)pdb->group->server_pid))
160 )
161 { /* bad pid group */
162 dprintf(("KERNEL32:CONSOLE: GenerateConsoleCtrlEvent(%08x,%08x) - Unsupported PID no action taken. Returns TRUE.\n",
163 dwCtrlEvent, dwProcessGroupId));
164 return TRUE;
165 }
166
167
168 /*
169 * Do the work.
170 */
171 return InternalGenerateConsoleCtrlEvent(dwCtrlEvent, dwProcessGroupId);
172}
173
174
175/**
176 * Default ctrl handler.
177 *
178 * @returns TRUE if handled (allway).
179 * FALSE if not.
180 * @param dwEvent The event which is to be handled.
181 * @status partially implemented and tested
182 * @author knut st. osmundsen (bird@anduin.net)
183 * @todo Make sure the exit code is right.
184 * Needs *working* testcases!
185 */
186BOOL WIN32API DefaultConsoleCtrlHandler(DWORD dwEvent)
187{
188 dprintf(("KERNEL32:CONSOLE: DefaultConsoleCtrlHandler(%08x)\n", dwEvent));
189 ExitProcess(0); /* TODO: Make sure this is the right exit value */
190 return TRUE;
191}
192
193
194/**
195 * Adds or removes a control handler of a certain type.
196 *
197 * @returns Success indicator.
198 * @param pfnHandler Pointer to the handler routine.
199 * NULL is allowed.
200 * @param fAdd TRUE: Add handler.
201 * FALSE: Removed handler.
202 * If pfnHandler is NULL the call will
203 * disable / enable handling of the Ctrl-C event.
204 * (Not completely implemented, see todo on GenerateConsoleCtrlEvent.)
205 * @status partially implemented tested.
206 * @author knut st. osmundsen (bird@anduin.net)
207 * @todo Testcase 24 doesn't work. NT does restart a few times apparently.
208 * Must check Win2k and WinXP!
209 */
210BOOL WIN32API SetConsoleCtrlHandler(PHANDLER_ROUTINE pfnHandler, BOOL fAdd)
211{
212 BOOL fRc = FALSE;
213 PDB * pdb;
214 dprintf(("KERNEL32:CONSOLE: SetConsoleCtrlHandler(%08x,%08x)\n", pfnHandler, fAdd));
215
216 pdb = PROCESS_Current();
217 if (pdb)
218 {
219 if (pdb->env_db)
220 {
221 ENVDB * pEDB = pdb->env_db;
222 PCONCTRLDATA pData = (PCONCTRLDATA)pEDB->break_handlers;
223
224 /*
225 * Do the work.
226 * I'm lazy, so I'm using critical section for this.
227 * I probably should use the break_sem...
228 */
229 if (pfnHandler)
230 {
231 if (fAdd)
232 {
233 /*
234 * Add operation.
235 */
236 PCONCTRL pNew = (PCONCTRL)malloc(sizeof(CONCTRL));
237 if (pNew)
238 {
239 pNew->pfnHandler = (void *)pfnHandler;
240 pNew->pPrev = NULL;
241
242 EnterCriticalSection(&pEDB->section);
243 pNew->pNext = pData->pHead;
244 if (pData->pHead)
245 {
246 pData->pHead->pPrev = pNew;
247 pData->pHead = pNew;
248 }
249 else
250 pData->pTail = pData->pHead = pNew;
251 LeaveCriticalSection(&pEDB->section);
252
253 fRc = TRUE;
254 }
255 else
256 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
257 }
258 else
259 {
260 PCONCTRL pCur;
261
262 /*
263 * Removal of a routine is requested.
264 * Walk the list looking for it.
265 */
266 EnterCriticalSection(&pEDB->section);
267 for (pCur = pData->pTail;
268 pCur;
269 pCur = pCur->pPrev)
270 {
271 if (pCur->pfnHandler == pfnHandler)
272 {
273 /*
274 * Found it.
275 * Unlink it if not marked as active.
276 * Else mark it for deleletion.
277 */
278 if (pCur->flFlags & ODIN32_CONCTRL_FLAGS_USED)
279 pCur->flFlags = ODIN32_CONCTRL_FLAGS_REMOVED;
280 else
281 {
282 if (pCur->pNext)
283 pCur->pNext->pPrev = pCur->pPrev;
284 else
285 pData->pTail = pCur->pPrev;
286 if (pCur->pPrev)
287 pCur->pPrev->pNext = pCur->pNext;
288 else
289 pData->pHead = pCur->pNext;
290 free(pCur);
291 }
292
293 fRc = TRUE;
294 break;
295 }
296 }
297 LeaveCriticalSection(&pEDB->section);
298
299 if (!fRc)
300 SetLastError(ERROR_INVALID_PARAMETER);
301 }
302 }
303 else
304 { /*
305 * No handler routine - which means setting some flag.
306 */
307 dprintf(("KERNEL32:CONSOLE: SetConsoleCtrlHandler(0,%d) Turning on and off Ctrl-C isn't implemented yet\n",
308 fAdd));
309 EnterCriticalSection(&pEDB->section);
310 pData->fIgnoreCtrlC = fAdd != 0; /* Just make this a 1 or 0 for convenience. */
311 LeaveCriticalSection(&pEDB->section);
312 fRc = TRUE;
313
314 }
315 }
316 else
317 {
318 dprintf(("KERNEL32:CONSOLE: SetConsoleCtrlHandler - pdb->env_db is NULL. This is really bad!\n"));
319 DebugInt3();
320 }
321 }
322 else
323 {
324 dprintf(("KERNEL32:CONSOLE: SetConsoleCtrlHandler - PROCESS_Current(): failed! \n"));
325 DebugInt3();
326 }
327
328 return fRc;
329}
Note: See TracBrowser for help on using the repository browser.