source: trunk/src/kernel32/conin.cpp

Last change on this file was 22052, checked in by dmik, 13 years ago

kernel32: Properly handle backspace and tab characters in console input/output mode.

File size: 39.1 KB
RevLine 
[10471]1/* $Id: conin.cpp,v 1.18 2004-02-19 13:03:05 sandervl Exp $ */
[111]2
3/*
4 * Win32 Console API Translation for OS/2
5 * 1998/02/10 Patrick Haller (haller@zebra.fh-weingarten.de)
6 * Project Odin Software License can be found in LICENSE.TXT
7 */
8
9
10#ifdef DEBUG
11#define DEBUG_LOCAL
[1484]12#define DEBUG_LOCAL2
[111]13#endif
14
15
16/*****************************************************************************
17 * Remark *
18 *****************************************************************************
19*/
20
21
22/*****************************************************************************
23 * Includes *
24 *****************************************************************************/
25
26#define INCL_WIN
27#define INCL_DOSMEMMGR
28#define INCL_DOSSEMAPHORES
29#define INCL_DOSERRORS
30#define INCL_DOSPROCESS
31#define INCL_DOSMODULEMGR
32#define INCL_VIO
33#define INCL_AVIO
[4502]34#include <os2wrap.h> //Odin32 OS/2 api wrappers
[111]35
[2984]36#include <win32api.h>
[111]37#include <misc.h>
38#include <string.h>
[4525]39#include <stdlib.h>
[111]40
41#include "conwin.h" // Windows Header for console only
42#include "HandleManager.h"
43#include "HMDevice.h"
44#include "Conin.H"
45#include "Console2.h"
[1484]46#include <heapstring.h>
[111]47
[4502]48#define DBG_LOCALLOG DBG_conin
[2802]49#include "dbglocal.h"
[111]50
51
52/*****************************************************************************
53 * Name : DWORD HMDeviceConsoleInClass::CreateFile
54 * Purpose : this is called from the handle manager if a CreateFile() is
55 * performed on a handle
56 * Parameters: LPCSTR lpFileName name of the file / device
57 * PHMHANDLEDATA pHMHandleData data of the NEW handle
58 * PVOID lpSecurityAttributes ignored
59 * PHMHANDLEDATA pHMHandleDataTemplate data of the template handle
60 * Variables :
61 * Result :
62 * Remark : @@@PH CONIN$ handles should be exclusive
63 * reject other requests to this device
64 * Status : NO_ERROR - API succeeded
65 * other - what is to be set in SetLastError
66 *
67 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
68 *****************************************************************************/
69
[7549]70DWORD HMDeviceConsoleInClass::CreateFile (LPCSTR lpFileName,
[111]71 PHMHANDLEDATA pHMHandleData,
72 PVOID lpSecurityAttributes,
73 PHMHANDLEDATA pHMHandleDataTemplate)
74{
75#ifdef DEBUG_LOCAL
76 WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleInClass::CreateFile %s(%s,%08x,%08x,%08x)\n",
77 lpHMDeviceName,
78 lpFileName,
[149]79 pHMHandleData->hHMHandle,
[111]80 lpSecurityAttributes,
81 pHMHandleDataTemplate);
82#endif
83
84 return(NO_ERROR);
85}
86
[7549]87/*****************************************************************************
88 * Name : DWORD HMDeviceConsoleInClass::GetFileType
89 * Purpose : determine the handle type
90 * Parameters: PHMHANDLEDATA pHMHandleData
91 * Variables :
92 * Result : API returncode
93 * Remark :
94 * Status :
95 *
96 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
97 *****************************************************************************/
[111]98
[7549]99DWORD HMDeviceConsoleInClass::GetFileType(PHMHANDLEDATA pHMHandleData)
100{
101 dprintf(("KERNEL32: HMDeviceConsoleInClass::GetFileType %s(%08x)\n",
102 lpHMDeviceName,
103 pHMHandleData));
104
105 return FILE_TYPE_CHAR;
106}
107
[111]108/*****************************************************************************
109 * Name :
110 * Purpose :
111 * Parameters:
112 * Variables :
113 * Result :
114 * Remark :
115 * Status :
116 *
117 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
118 *****************************************************************************/
119
[2050]120BOOL HMDeviceConsoleInClass::ReadFile(PHMHANDLEDATA pHMHandleData,
[7549]121 LPCVOID lpBuffer,
122 DWORD nNumberOfBytesToRead,
123 LPDWORD lpNumberOfBytesRead,
124 LPOVERLAPPED lpOverlapped,
125 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
[111]126{
127 ULONG ulCounter; /* character counter for the queue loop */
128 PSZ pszTarget; /* pointer to target buffer */
129 APIRET rc; /* API returncode */
130 INPUT_RECORD InputRecord; /* buffer for the event to be read */
131 ULONG ulPostCounter; /* semaphore post counter */
[1484]132 BOOL fLoop = TRUE; /* set to false if function may return to caller */
[111]133
134#ifdef DEBUG_LOCAL
135 WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleInClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)\n",
136 lpHMDeviceName,
[149]137 pHMHandleData->hHMHandle,
[111]138 lpBuffer,
139 nNumberOfBytesToRead,
140 lpNumberOfBytesRead,
141 lpOverlapped);
142#endif
143
[7550]144 if(lpCompletionRoutine) {
145 dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
146 }
147
[111]148 ulCounter = 0; /* read ascii chars from queue */
149 pszTarget = (PSZ)lpBuffer;
150
151 /* block if no key events are in the queue */
[1484]152 for (;fLoop;) /* until we got some characters */
[111]153 {
[4502]154 iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_WAIT); /* if queue is currently empty */
[111]155
156 do
157 {
158 rc = iConsoleInputEventPop(&InputRecord); /* get event from queue */
159 if (rc == NO_ERROR) /* if we've got a valid event in the queue */
160 {
[1484]161 //@@@PH other events are discarded!
162 if ( (InputRecord.EventType == KEY_EVENT) && /* check event type */
163 (InputRecord.Event.KeyEvent.bKeyDown == TRUE) )
[111]164 {
[1484]165 // console in line input mode ?
166 if (pConsoleInput->dwConsoleMode & ENABLE_LINE_INPUT)
167 {
168 // continue until buffer full or CR entered
[3976]169 // Note: CRLF is actually returned at the end of the buffer!
[1484]170 if (InputRecord.Event.KeyEvent.uChar.AsciiChar == 0x0d)
171 fLoop = FALSE;
172 }
173 else
[3976]174 // return on any single key in buffer :)
175 // fLoop = FALSE;
176 // @@@PH 2000/08/10 changed behaviour to return ALL input events
177 // recorded in the console.
[4502]178 fLoop = (iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_PEEK) != 0);
[1484]179
180 // record key stroke
181 if (pConsoleInput->dwConsoleMode & ENABLE_PROCESSED_INPUT)
182 {
183 // filter special characters first
184 switch (InputRecord.Event.KeyEvent.uChar.AsciiChar)
185 {
[3978]186 case 0x00:
187 // Ascii values of 0x00 are sent e.g. for SHIFT-DOWN
188 // key events, etc.
189 break;
[4502]190
[1484]191 case 0x03: // ctrl-c is filtered!
[3976]192 // @@@PH we're supposed to call a ctrl-c break handler here!
193 break;
[4502]194
[1484]195 case 0x0d: // CR
[3976]196 // CR is automatically expanded to CRLF if in line input mode!
197 if (pConsoleInput->dwConsoleMode & ENABLE_LINE_INPUT)
198 {
199 *pszTarget = 0x0d; // CR
200 pszTarget++;
201 ulCounter++;
202 if (ulCounter < nNumberOfBytesToRead) // check for room
203 {
204 *pszTarget = 0x0a; // LF
205 pszTarget++;
206 ulCounter++;
207 }
[4502]208
[3976]209 if (pConsoleInput->dwConsoleMode & ENABLE_ECHO_INPUT)
210 HMWriteFile(pConsoleGlobals->hConsoleBuffer,
211 pszTarget-2,
212 2,
213 &ulPostCounter, /* dummy result */
[7549]214 NULL, NULL);
[4502]215
[3976]216 }
[4502]217
[1484]218 break;
219
220 case 0x08: // backspace
221 if (ulCounter > 0)
222 {
223 ulCounter--;
224 pszTarget--;
[111]225 /* local echo enabled ? */
[1484]226 if (pConsoleInput->dwConsoleMode & ENABLE_ECHO_INPUT)
[22052]227 {
228 ULONG repeat = 1;
229 if (*pszTarget == 0x09) // tab
230 {
231 // detect the expanded width of the deleted tab
232 ULONG cnt = 0;
233 PSZ psz = (PSZ)lpBuffer;
234 ULONG p = 0, ulTabSize = pConsoleGlobals->Options.ulTabSize;
235 for (; cnt < ulCounter; cnt++, psz++)
236 {
237 if (*psz == 0x09)
238 p += ulTabSize - p % ulTabSize;
239 else
240 {
241 if (*psz == 0x0d && cnt < ulCounter && *(psz + 1) == 0x0a)
242 psz++;
243 p++;
244 }
245 }
246 // this will give us the expanded width
247 repeat = ulTabSize - p % ulTabSize;
248
249 }
250 while (repeat--)
251 HMWriteFile(pConsoleGlobals->hConsoleBuffer,
252 &InputRecord.Event.KeyEvent.uChar.AsciiChar,
253 1,
254 &ulPostCounter, /* dummy result */
255 NULL, NULL);
256 }
257 }
258 break;
259
260 case 0x09: // tab
261 /* local echo enabled ? */
262 if (pConsoleInput->dwConsoleMode & ENABLE_ECHO_INPUT)
263 {
264 // expand tabs (not rely on HMWriteFile since we calculate tabs from the
265 // beginning of the whole buffer, not the current line)
266 ULONG repeat = 1;
267 // detect the expanded width of the new tab
268 ULONG cnt = 0;
269 PSZ psz = (PSZ)lpBuffer;
270 ULONG p = 0, ulTabSize = pConsoleGlobals->Options.ulTabSize;
271 for (; cnt < ulCounter; cnt++, psz++)
272 {
273 if (*psz == 0x09)
274 p += ulTabSize - p % ulTabSize;
275 else
276 {
277 if (*psz == 0x0d && cnt < ulCounter && *(psz + 1) == 0x0a)
278 psz++;
279 p++;
280 }
281 }
282 // this will give us the expanded width
283 repeat = ulTabSize - p % ulTabSize;
284
285 while (repeat--)
[1484]286 HMWriteFile(pConsoleGlobals->hConsoleBuffer,
[22052]287 " ",
[111]288 1,
289 &ulPostCounter, /* dummy result */
[7549]290 NULL, NULL);
[1484]291 }
[22052]292
293 *pszTarget = InputRecord.Event.KeyEvent.uChar.AsciiChar;
294 pszTarget++;
295 ulCounter++;
[1484]296 break;
[111]297
[1484]298 default:
299 // OK, for the rest ...
300 *pszTarget = InputRecord.Event.KeyEvent.uChar.AsciiChar;
301 dprintf(("KERNEL32:CONIN$: Debug: recorded key (%c - %02xh)\n",
302 *pszTarget,
303 *pszTarget));
[670]304
[1484]305 pszTarget++;
306 ulCounter++;
307 /* local echo enabled ? */
308 if (pConsoleInput->dwConsoleMode & ENABLE_ECHO_INPUT)
309 HMWriteFile(pConsoleGlobals->hConsoleBuffer,
310 &InputRecord.Event.KeyEvent.uChar.AsciiChar,
311 1,
312 &ulPostCounter, /* dummy result */
[7549]313 NULL, NULL);
[1484]314 }
315 }
316 else
317 {
318 *pszTarget = InputRecord.Event.KeyEvent.uChar.AsciiChar;
319 dprintf(("KERNEL32:CONIN$: Debug: recorded key (%c - %02xh)\n",
320 *pszTarget,
321 *pszTarget));
322
323 pszTarget++;
324 ulCounter++;
325
326 /* local echo enabled ? */
327 if (pConsoleInput->dwConsoleMode & ENABLE_ECHO_INPUT)
328 HMWriteFile(pConsoleGlobals->hConsoleBuffer,
329 &InputRecord.Event.KeyEvent.uChar.AsciiChar,
330 1,
331 &ulPostCounter, /* dummy result */
[7549]332 NULL, NULL);
[1484]333 }
334
[670]335 // buffer filled?
[111]336 if (ulCounter >= nNumberOfBytesToRead) /* at buffer's end ? */
[1484]337 fLoop = FALSE;
[111]338 }
339 /* Note: other events are discarded */
340 }
341 }
342 while (rc == NO_ERROR);
343 }
344
345 *lpNumberOfBytesRead = ulCounter; /* write result */
346
347 return(TRUE); /* OK */
348}
349
350
351/*****************************************************************************
352 * Name :
353 * Purpose :
354 * Parameters:
355 * Variables :
356 * Result :
357 * Remark :
358 * Status :
359 *
360 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
361 *****************************************************************************/
362
[2050]363BOOL HMDeviceConsoleInClass::WriteFile(PHMHANDLEDATA pHMHandleData,
[111]364 LPCVOID lpBuffer,
365 DWORD nNumberOfBytesToWrite,
366 LPDWORD lpNumberOfBytesWritten,
[7549]367 LPOVERLAPPED lpOverlapped,
368 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
[111]369{
370
371#ifdef DEBUG_LOCAL
372 WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleInClass:WriteFile %s(%08x,%08x,%08x,%08x,%08x)\n",
373 lpHMDeviceName,
[149]374 pHMHandleData->hHMHandle,
[111]375 lpBuffer,
376 nNumberOfBytesToWrite,
377 lpNumberOfBytesWritten,
378 lpOverlapped);
379#endif
380
[2984]381 SetLastError(ERROR_ACCESS_DENIED_W);
[2050]382 return FALSE;
[111]383}
384
385
386/*****************************************************************************
387 * Name :
388 * Purpose :
389 * Parameters:
390 * Variables :
391 * Result :
392 * Remark :
393 * Status :
394 *
395 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
396 *****************************************************************************/
397
398DWORD HMDeviceConsoleInClass::_DeviceRequest (PHMHANDLEDATA pHMHandleData,
399 ULONG ulRequestCode,
400 ULONG arg1,
401 ULONG arg2,
402 ULONG arg3,
403 ULONG arg4)
404{
405 switch (ulRequestCode)
406 {
407 case DRQ_FLUSHCONSOLEINPUTBUFFER:
408 return (HMDeviceConsoleInClass::
409 FlushConsoleInputBuffer(pHMHandleData));
410
[296]411 case DRQ_GETCONSOLEMODE:
412 return (HMDeviceConsoleInClass
413 ::GetConsoleMode(pHMHandleData,
414 (LPDWORD)arg1));
415
[111]416 case DRQ_GETNUMBEROFCONSOLEINPUTEVENTS:
417 return (HMDeviceConsoleInClass::
418 GetNumberOfConsoleInputEvents(pHMHandleData,
419 (LPDWORD)arg1));
420
421 case DRQ_PEEKCONSOLEINPUTA:
422 return (HMDeviceConsoleInClass::
423 PeekConsoleInputA(pHMHandleData,
424 (PINPUT_RECORD)arg1,
425 (DWORD) arg2,
426 (LPDWORD) arg3));
427
428 case DRQ_PEEKCONSOLEINPUTW:
429 return (HMDeviceConsoleInClass::
430 PeekConsoleInputW(pHMHandleData,
431 (PINPUT_RECORD)arg1,
432 (DWORD) arg2,
433 (LPDWORD) arg3));
434
435
436 case DRQ_READCONSOLEA:
437 return (HMDeviceConsoleInClass::
438 ReadConsoleA(pHMHandleData,
439 (CONST VOID*) arg1,
440 (DWORD) arg2,
441 (LPDWORD) arg3,
442 (LPVOID) arg4));
443
444 case DRQ_READCONSOLEW:
445 return (HMDeviceConsoleInClass::
446 ReadConsoleW(pHMHandleData,
447 (CONST VOID*) arg1,
448 (DWORD) arg2,
449 (LPDWORD) arg3,
450 (LPVOID) arg4));
451
452 case DRQ_READCONSOLEINPUTA:
453 return (HMDeviceConsoleInClass::
454 ReadConsoleInputA(pHMHandleData,
455 (PINPUT_RECORD)arg1,
456 (DWORD)arg2,
457 (LPDWORD)arg3));
458
459 case DRQ_READCONSOLEINPUTW:
460 return (HMDeviceConsoleInClass::
461 ReadConsoleInputW(pHMHandleData,
462 (PINPUT_RECORD)arg1,
463 (DWORD)arg2,
464 (LPDWORD)arg3));
465
[296]466 case DRQ_SETCONSOLEMODE:
467 return (HMDeviceConsoleInClass
468 ::SetConsoleMode(pHMHandleData,
469 (DWORD)arg1));
470
[111]471 case DRQ_WRITECONSOLEINPUTA:
472 return (HMDeviceConsoleInClass::
473 WriteConsoleInputA(pHMHandleData,
474 (PINPUT_RECORD)arg1,
475 (DWORD)arg2,
476 (LPDWORD)arg3));
477
478 case DRQ_WRITECONSOLEINPUTW:
479 return (HMDeviceConsoleInClass::
480 WriteConsoleInputW(pHMHandleData,
481 (PINPUT_RECORD)arg1,
482 (DWORD)arg2,
483 (LPDWORD)arg3));
484
485 }
486
487#ifdef DEBUG_LOCAL
488 WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleInClass:_DeviceRequest %s(%08x,%08x,%08x,%08x,%08x,%08x) unknown request\n",
489 lpHMDeviceName,
[149]490 pHMHandleData->hHMHandle,
[111]491 ulRequestCode,
492 arg1,
493 arg2,
494 arg3,
495 arg4);
496#endif
497
[2984]498 SetLastError(ERROR_INVALID_FUNCTION_W); /* request not implemented */
[111]499 return(FALSE); /* we assume this indicates API call failed */
500}
501
502
503/*****************************************************************************
504 * Name : BOOL HMDeviceConsoleInClass::FlushConsoleInputBuffer
505 * Purpose : flushes all events from the input queue
506 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
507 * Variables :
508 * Result :
509 * Remark :
510 * Status : UNTESTED
511 *
512 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
513 *****************************************************************************/
514
515BOOL HMDeviceConsoleInClass::FlushConsoleInputBuffer(PHMHANDLEDATA pHMHandleData)
516{
517 ULONG ulCounter; /* loop counter */
518
519#ifdef DEBUG_LOCAL2
520 WriteLog("KERNEL32/CONSOLE: CONIN$::FlushConsoleInputBuffer(%08x).\n",
521 pHMHandleData);
522#endif
523
[4502]524 //get all pending events
525 iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_PEEK);
526
[111]527 pConsoleInput->ulIndexFree = 0;
528 pConsoleInput->ulIndexEvent = 0;
529 pConsoleInput->ulEvents = 0;
530
531 for (ulCounter = 0;
532 ulCounter < CONSOLE_INPUTQUEUESIZE;
533 ulCounter++)
534 pConsoleInput->arrInputRecord[ulCounter].EventType = 0x0000; /* free event */
535
536 return (TRUE);
537}
538
539
540/*****************************************************************************
541 * Name : DWORD HMDeviceConsoleInClass::GetConsoleMode
542 * Purpose : queries the current console mode
543 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
544 * LPDWORD lpMode
545 * Variables :
546 * Result :
547
548 * Remark :
549 * Status : UNTESTED
550 *
551 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
552 *****************************************************************************/
553
554DWORD HMDeviceConsoleInClass::GetConsoleMode(PHMHANDLEDATA pHMHandleData,
555 LPDWORD lpMode)
556{
557#ifdef DEBUG_LOCAL2
558 WriteLog("KERNEL32/CONSOLE: CONIN$::GetConsoleMode(%08x,%08x).\n",
559 pHMHandleData,
560 lpMode);
561#endif
562
563 *lpMode = pConsoleInput->dwConsoleMode; /* return current console mode */
564
565 return (TRUE);
566}
567
568
569/*****************************************************************************
570 * Name : DWORD HMDeviceConsoleInClass::GetNumberOfConsoleInputEvents
571 * Purpose : queries the current number of events in the input queue
572 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
573 * LPDWORD lpNumberOfEvents - return number of events
574 * Variables :
575 * Result :
576 * Remark :
577 * Status : UNTESTED
578 *
579 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
580 *****************************************************************************/
581
582BOOL HMDeviceConsoleInClass::GetNumberOfConsoleInputEvents(PHMHANDLEDATA pHMHandleData,
583 LPDWORD lpNumberOfEvents)
584{
585#ifdef DEBUG_LOCAL2
586 WriteLog("KERNEL32/CONSOLE: CONIN$::GetNumberOfConsoleInputEvents(%08x,%08x).\n",
587 pHMHandleData,
588 lpNumberOfEvents);
589#endif
590
[4502]591 //get all pending events and return number of events
592 *lpNumberOfEvents = iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_PEEK);
[111]593
594 return (TRUE);
595}
596
597
598/*****************************************************************************
599 * Name : DWORD HMDeviceConsoleInClass::PeekConsoleInputA
600 * Purpose : peeks events placed in the console input queue
601 * Parameters: PHMHANDLEDATA pHMHandleData - current handle data
602 * PINPUT_RECORD pirBuffer - target buffer for events
603 * DWORD cInRecords - number of input records
604 * LPDWORD lpcRead - returns number of events stored
605 * Variables :
606 * Result : TRUE if successful, FALSE otherwise
607 * Remark : if queue is completely filled and no event is free,
608 * loop will scan over queue multiple times, until target
609 * buffer is filled. It does not check ulCounter to stop
610 * when one scan of the queue is complete.
611 * Status : UNTESTED
612 *
613 * Author : Patrick Haller [Tue, 1998/02/10 01:55]
614 *****************************************************************************/
615
616DWORD HMDeviceConsoleInClass::PeekConsoleInputA(PHMHANDLEDATA pHMHandleData,
617 PINPUT_RECORD pirBuffer,
618 DWORD cInRecords,
619 LPDWORD lpcRead)
620{
621 ULONG ulCounter; /* loop counter */
622 ULONG ulCurrentEvent; /* index of current event in the queue */
623 PINPUT_RECORD pirEvent; /* pointer to current queue element */
624
625#ifdef DEBUG_LOCAL2
626 WriteLog("KERNEL32/CONSOLE: HMDeviceConsoleInClass::PeekConsoleInputA(%08x,%08x,%08x,%08x).\n",
627 pHMHandleData,
628 pirBuffer,
629 cInRecords,
630 lpcRead);
631#endif
632
[4502]633 if (iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_PEEK) == 0) /* if queue is currently empty */
[111]634 {
635 *lpcRead = 0; /* no events read from queue */
636 return (TRUE); /* OK, we're done */
637 }
638
639
640 for (ulCounter = 0,
641 ulCurrentEvent = pConsoleInput->ulIndexEvent,
642 pirEvent = &pConsoleInput->arrInputRecord[pConsoleInput->ulIndexEvent];
643
644 ulCounter < cInRecords;
645
646 ulCounter++,
647 ulCurrentEvent++,
648 pirEvent++,
649 pirBuffer++)
650 {
651 if (ulCurrentEvent > CONSOLE_INPUTQUEUESIZE) /* reaching after end of que*/
652 {
653 ulCurrentEvent = 0; /* then start over from beginning of queue */
654 pirEvent = pConsoleInput->arrInputRecord;
655 }
656
657 if (pirEvent->EventType == 0x0000) /* no more events ? */
658 break; /* leave loop then */
659
660 memcpy(pirEvent, /* copy event data */
661 pirBuffer,
662 sizeof(INPUT_RECORD));
663 }
664
665 *lpcRead = ulCounter; /* return number of events read */
666 return (TRUE); /* OK, we're done */
667}
668
669
670/*****************************************************************************
671 * Name : DWORD HMDeviceConsoleInClass::PeekConsoleInputW
672 * Purpose : peeks events placed in the console input queue
673 * Parameters: PHMHANDLEDATA pHMHandleData - current handle data
674 * PINPUT_RECORD pirBuffer - target buffer for events
675 * DWORD cInRecords - number of input records
676 * LPDWORD lpcRead - returns number of events stored
677 * Variables :
678 * Result : TRUE if successful, FALSE otherwise
679 * Remark : if queue is completely filled and no event is free,
680 * loop will scan over queue multiple times, until target
681 * buffer is filled. It does not check ulCounter to stop
682 * when one scan of the queue is complete.
683 * Status : UNTESTED
684 *
685 * Author : Patrick Haller [Tue, 1998/02/10 01:55]
686 *****************************************************************************/
687
688DWORD HMDeviceConsoleInClass::PeekConsoleInputW(PHMHANDLEDATA pHMHandleData,
689 PINPUT_RECORD pirBuffer,
690 DWORD cInRecords,
691 LPDWORD lpcRead)
692{
693 ULONG ulCounter; /* loop counter */
694 ULONG ulCurrentEvent; /* index of current event in the queue */
695 PINPUT_RECORD pirEvent; /* pointer to current queue element */
696
697#ifdef DEBUG_LOCAL2
698 WriteLog("KERNEL32/CONSOLE: HMDeviceConsoleInClass::PeekConsoleInputW(%08x,%08x,%08x,%08x).\n",
699 pHMHandleData,
700 pirBuffer,
701 cInRecords,
702 lpcRead);
703#endif
704
[4502]705 if (iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_PEEK) == 0) /* if queue is currently empty */
[111]706 {
707 *lpcRead = 0; /* no events read from queue */
708 return (TRUE); /* OK, we're done */
709 }
710
711
712 for (ulCounter = 0,
713 ulCurrentEvent = pConsoleInput->ulIndexEvent,
714 pirEvent = &pConsoleInput->arrInputRecord[pConsoleInput->ulIndexEvent];
715
716 ulCounter < cInRecords;
717
718 ulCounter++,
719 ulCurrentEvent++,
720 pirEvent++,
721 pirBuffer++)
722 {
723 if (ulCurrentEvent > CONSOLE_INPUTQUEUESIZE) /* reaching after end of que*/
724 {
725 ulCurrentEvent = 0; /* then start over from beginning of queue */
726 pirEvent = pConsoleInput->arrInputRecord;
727 }
728
729 if (pirEvent->EventType == 0x0000) /* no more events ? */
730 break; /* leave loop then */
731
732 memcpy(pirEvent, /* copy event data */
733 pirBuffer,
734 sizeof(INPUT_RECORD));
735 }
736
737 *lpcRead = ulCounter; /* return number of events read */
738 return (TRUE); /* OK, we're done */
739}
740
741
742/*****************************************************************************
743 * Name : DWORD HMDeviceConsoleInClass::ReadConsoleA
744 * Purpose : read a string from the console
745 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
746 * LPWORD lpwAttribute
747 * DWORD cWriteCells
748 * COORD dwWriteCoord
749 * LPDWORD lpcWritten
750 * Variables :
751 * Result :
752 * Remark :
753 * Status : UNTESTED
754 *
755 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
756 *****************************************************************************/
757
758DWORD HMDeviceConsoleInClass::ReadConsoleA(PHMHANDLEDATA pHMHandleData,
759 CONST VOID* lpvBuffer,
760 DWORD cchToRead,
761 LPDWORD lpcchRead,
762 LPVOID lpvReserved)
763{
764 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
765
766#ifdef DEBUG_LOCAL2
767 WriteLog("KERNEL32/CONSOLE: CONIN$::ReadConsoleA(%08x,%08x,%u,%08x,%08x).\n",
768 pHMHandleData,
769 lpvBuffer,
770 cchToRead,
771 lpcchRead,
772 lpvReserved);
773#endif
774
775 /* simply forward the request to that routine */
776 return (HMDeviceConsoleInClass::ReadFile(pHMHandleData,
777 lpvBuffer,
778 cchToRead,
779 lpcchRead,
[7549]780 NULL, NULL));
[111]781}
782
783/*****************************************************************************
784 * Name : DWORD HMDeviceConsoleInClass::ReadConsoleW
785 * Purpose : write a string to the console
786 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
787 * LPWORD lpwAttribute
788 * DWORD cWriteCells
789 * COORD dwWriteCoord
790 * LPDWORD lpcWritten
791 * Variables :
792 * Result :
793 * Remark :
794 * Status : UNTESTED
795 *
796 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
797 *****************************************************************************/
798
799DWORD HMDeviceConsoleInClass::ReadConsoleW(PHMHANDLEDATA pHMHandleData,
800 CONST VOID* lpvBuffer,
801 DWORD cchToRead,
802 LPDWORD lpcchRead,
803 LPVOID lpvReserved)
804{
805 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
806 DWORD dwResult;
[1484]807 LPSTR lpstrAscii;
[111]808
809#ifdef DEBUG_LOCAL2
810 WriteLog("KERNEL32/CONSOLE: CONIN$::ReadConsoleW(%08x,%08x,%u,%08x,%08x).\n",
811 pHMHandleData,
812 lpvBuffer,
813 cchToRead,
814 lpcchRead,
815 lpvReserved);
816#endif
817
[1484]818 // create ascii buffer
[10471]819 lpstrAscii = (LPSTR)HEAP_malloc(cchToRead * sizeof( WCHAR ));
[1484]820 if (lpstrAscii == NULL)
821 return ERROR_NOT_ENOUGH_MEMORY;
822
[111]823 /* simply forward the request to that routine */
[10471]824 // FIXME : if results of ReadFile() have MBCS string, some data might be lost on next call.
[111]825 dwResult = HMDeviceConsoleInClass::ReadFile(pHMHandleData,
[1484]826 lpstrAscii,
[10471]827 cchToRead * sizeof( WCHAR ),
[111]828 lpcchRead,
[7549]829 NULL, NULL);
830
[1484]831 /* Ascii -> unicode translation */
832 if (dwResult == TRUE)
[10471]833 *lpcchRead = MultiByteToWideChar( GetConsoleCP(), 0, lpstrAscii, *lpcchRead, ( LPWSTR )lpvBuffer, cchToRead );
[111]834
[1484]835 HEAP_free(lpstrAscii);
836
[111]837 return (dwResult); /* deliver return code */
838}
839
840
841/*****************************************************************************
842 * Name : DWORD HMDeviceConsoleInClass::ReadConsoleInputA
843 * Purpose : read events placed in the console input queue
844 * Parameters: PHMHANDLEDATA pHMHandleData - current handle data
845 * PINPUT_RECORD pirBuffer - target buffer for events
846 * DWORD cInRecords - number of input records
847 * LPDWORD lpcRead - returns number of events stored
848 * Variables :
849 * Result : TRUE if successful, FALSE otherwise
850 * Remark :
851 * Status : UNTESTED
852 *
853 * Author : Patrick Haller [Tue, 1998/02/10 01:55]
854 *****************************************************************************/
855
856DWORD HMDeviceConsoleInClass::ReadConsoleInputA(PHMHANDLEDATA pHMHandleData,
857 PINPUT_RECORD pirBuffer,
858 DWORD cInRecords,
859 LPDWORD lpcRead)
860{
861 ULONG ulPostCounter; /* semaphore post counter - ignored */
862 APIRET rc; /* API returncode */
863
864#ifdef DEBUG_LOCAL2
865 WriteLog("KERNEL32/CONSOLE: HMDeviceConsoleInClass::ReadConsoleInputA(%08x,%08x,%08x,%08x).\n",
866 pHMHandleData,
867 pirBuffer,
868 cInRecords,
869 lpcRead);
870#endif
871
[4502]872 iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_WAIT);
[111]873
874 /* now read events into target buffer */
875 for (ulPostCounter = 0;
876 ulPostCounter < cInRecords;
877 ulPostCounter++,
878 pirBuffer++)
879 {
880 rc = iConsoleInputEventPop(pirBuffer); /* get event from queue */
881 if (rc != NO_ERROR) /* if read error occurs, break look */
882 break;
883 }
884
885 *lpcRead = ulPostCounter; /* return number of records read */
886 return (TRUE); /* OK */
887}
888
889
890/*****************************************************************************
891 * Name : DWORD HMDeviceConsoleInClass::ReadConsoleInputW
892 * Purpose : read events placed in the console input queue
893 * Parameters: PHMHANDLEDATA pHMHandleData - current handle data
894 * PINPUT_RECORD pirBuffer - target buffer for events
895 * DWORD cInRecords - number of input records
896 * LPDWORD lpcRead - returns number of events stored
897 * Variables :
898 * Result : TRUE if successful, FALSE otherwise
899 * Remark :
900 * Status : UNTESTED
901 *
902 * Author : Patrick Haller [Tue, 1998/02/10 01:55]
903 *****************************************************************************/
904
905DWORD HMDeviceConsoleInClass::ReadConsoleInputW(PHMHANDLEDATA pHMHandleData,
906 PINPUT_RECORD pirBuffer,
907 DWORD cInRecords,
908 LPDWORD lpcRead)
909{
910 ULONG ulPostCounter; /* semaphore post counter - ignored */
911 APIRET rc; /* API returncode */
912
913#ifdef DEBUG_LOCAL2
914 WriteLog("KERNEL32/CONSOLE: HMDeviceConsoleInClass::ReadConsoleInputW(%08x,%08x,%08x,%08x).\n",
915 pHMHandleData,
916 pirBuffer,
917 cInRecords,
918 lpcRead);
919#endif
920
[4502]921 iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_WAIT);
[111]922
923 /* now read events into target buffer */
924 for (ulPostCounter = 0;
925 ulPostCounter < cInRecords;
926 ulPostCounter++,
927 pirBuffer++)
928 {
929 rc = iConsoleInputEventPop(pirBuffer); /* get event from queue */
930 if (rc != NO_ERROR) /* if read error occurs, break look */
931 break;
932 }
933
934 *lpcRead = ulPostCounter; /* return number of records read */
935 return (TRUE); /* OK */
936}
937
938
939/*****************************************************************************
940 * Name : DWORD HMDeviceConsoleInClass::SetConsoleMode
941 * Purpose : sets the current console mode
942 * Parameters: PHMHANDLEDATA pHMHandleData - handle specific data
943 * DWORD dwMode - console mode
944 * Variables :
945 * Result :
946 * Remark :
947 * Status : UNTESTED
948 *
949 * Author : Patrick Haller [Wed, 1998/02/16 11:46]
950 *****************************************************************************/
951
952DWORD HMDeviceConsoleInClass::SetConsoleMode(PHMHANDLEDATA pHMHandleData,
953 DWORD dwMode)
954{
955 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
956
957#ifdef DEBUG_LOCAL2
958 WriteLog("KERNEL32/CONSOLE: CONIN$::SetConsoleMode(%08x,%08x).\n",
959 pHMHandleData,
960 dwMode);
961#endif
962
963 pConsoleInput->dwConsoleMode = dwMode; /* set current console mode */
964
965 return (TRUE);
966}
967
968
969/*****************************************************************************
970 * Name : DWORD HMDeviceConsoleInClass::WriteConsoleInputA
971 * Purpose : this writes event records directly into the queue
972 * Parameters: PHMHANDLEDATA pHMHandleData
973 * PINPUT_RECORD pirBuffer
974 * DWORD cInRecords
975 * LPDWORD lpcWritten
976 * Variables :
977 * Result :
978 * Remark :
979 * Status : NO_ERROR - API succeeded
980 * other - what is to be set in SetLastError
981 *
982 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
983 *****************************************************************************/
984
985DWORD HMDeviceConsoleInClass::WriteConsoleInputA (PHMHANDLEDATA pHMHandleData,
986 PINPUT_RECORD pirBuffer,
987 DWORD cInRecords,
988 LPDWORD lpcWritten)
989{
990 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
991 APIRET rc; /* API returncode */
992 ULONG ulCounter; /* loop counter */
993
994#ifdef DEBUG_LOCAL2
995 WriteLog("KERNEL32/CONSOLE: CONIN$::WriteConsoleInputA(%08x,%08x,%u,%08x).\n",
996 pHMHandleData,
997 pirBuffer,
998 cInRecords,
999 lpcWritten);
1000#endif
1001
1002 for (ulCounter = 0;
1003 ulCounter < cInRecords;
1004 ulCounter++,
1005 pirBuffer++)
1006 {
1007 rc = iConsoleInputEventPush(pirBuffer); /* push current event */
1008 if (rc != NO_ERROR) /* oops ? queue full ? problem ? */
1009 break;
1010 }
1011
1012 *lpcWritten = ulCounter; /* return number of events written */
1013 return (TRUE); /* OK */
1014}
1015
1016
1017/*****************************************************************************
1018 * Name : DWORD HMDeviceConsoleInClass::WriteConsoleInputW
1019 * Purpose : this writes event records directly into the queue
1020 * Parameters: PHMHANDLEDATA pHMHandleData
1021 * PINPUT_RECORD pirBuffer
1022 * DWORD cInRecords
1023 * LPDWORD lpcWritten
1024 * Variables :
1025 * Result :
1026 * Remark :
1027 * Status : NO_ERROR - API succeeded
1028 * other - what is to be set in SetLastError
1029 *
1030 * Author : Patrick Haller [Wed, 1998/02/11 20:44]
1031 *****************************************************************************/
1032
1033DWORD HMDeviceConsoleInClass::WriteConsoleInputW (PHMHANDLEDATA pHMHandleData,
1034 PINPUT_RECORD pirBuffer,
1035 DWORD cInRecords,
1036 LPDWORD lpcWritten)
1037{
1038 PCONSOLEBUFFER pConsoleBuffer = (PCONSOLEBUFFER)pHMHandleData->lpHandlerData;
1039 APIRET rc; /* API returncode */
1040 ULONG ulCounter; /* loop counter */
1041
1042#ifdef DEBUG_LOCAL2
1043 WriteLog("KERNEL32/CONSOLE: CONIN$::WriteConsoleInputW(%08x,%08x,%u,%08x).\n",
1044 pHMHandleData,
1045 pirBuffer,
1046 cInRecords,
1047 lpcWritten);
1048#endif
1049
1050 for (ulCounter = 0;
1051 ulCounter < cInRecords;
1052 ulCounter++,
1053 pirBuffer++)
1054 {
1055 rc = iConsoleInputEventPush(pirBuffer); /* push current event */
1056 if (rc != NO_ERROR) /* oops ? queue full ? problem ? */
1057 break;
1058 }
1059
1060 *lpcWritten = ulCounter; /* return number of events written */
1061 return (TRUE); /* OK */
1062}
1063
1064
Note: See TracBrowser for help on using the repository browser.