source: trunk/src/kernel32/conin.cpp @ 22052

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

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

File size: 39.1 KB
Line 
1/* $Id: conin.cpp,v 1.18 2004-02-19 13:03:05 sandervl Exp $ */
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
12#define DEBUG_LOCAL2
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
34#include <os2wrap.h>    //Odin32 OS/2 api wrappers
35
36#include <win32api.h>
37#include <misc.h>
38#include <string.h>
39#include <stdlib.h>
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"
46#include <heapstring.h>
47
48#define DBG_LOCALLOG    DBG_conin
49#include "dbglocal.h"
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
70DWORD HMDeviceConsoleInClass::CreateFile (LPCSTR        lpFileName,
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,
79           pHMHandleData->hHMHandle,
80           lpSecurityAttributes,
81           pHMHandleDataTemplate);
82#endif
83
84  return(NO_ERROR);
85}
86
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 *****************************************************************************/
98
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
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
120BOOL HMDeviceConsoleInClass::ReadFile(PHMHANDLEDATA pHMHandleData,
121                                      LPCVOID       lpBuffer,
122                                      DWORD         nNumberOfBytesToRead,
123                                      LPDWORD       lpNumberOfBytesRead,
124                                      LPOVERLAPPED  lpOverlapped,
125                                      LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
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 */
132  BOOL   fLoop = TRUE;      /* set to false if function may return to caller */
133
134#ifdef DEBUG_LOCAL
135  WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleInClass::ReadFile %s(%08x,%08x,%08x,%08x,%08x)\n",
136           lpHMDeviceName,
137           pHMHandleData->hHMHandle,
138           lpBuffer,
139           nNumberOfBytesToRead,
140           lpNumberOfBytesRead,
141           lpOverlapped);
142#endif
143
144  if(lpCompletionRoutine) {
145      dprintf(("!WARNING!: lpCompletionRoutine not supported -> fall back to sync IO"));
146  }
147
148  ulCounter = 0;                              /* read ascii chars from queue */
149  pszTarget = (PSZ)lpBuffer;
150
151                                  /* block if no key events are in the queue */
152  for (;fLoop;)                       /* until we got some characters */
153  {
154    iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_WAIT);      /* if queue is currently empty */
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      {
161        //@@@PH other events are discarded!
162        if ( (InputRecord.EventType == KEY_EVENT) &&     /* check event type */
163             (InputRecord.Event.KeyEvent.bKeyDown == TRUE) )
164        {
165          // console in line input mode ?
166          if (pConsoleInput->dwConsoleMode & ENABLE_LINE_INPUT)
167          {
168            // continue until buffer full or CR entered
169            // Note: CRLF is actually returned at the end of the buffer!
170            if (InputRecord.Event.KeyEvent.uChar.AsciiChar == 0x0d)
171              fLoop = FALSE;
172          }
173          else
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.
178            fLoop = (iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_PEEK) != 0);
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            {
186              case 0x00:
187                // Ascii values of 0x00 are sent e.g. for SHIFT-DOWN
188                // key events, etc.
189                break;
190
191              case 0x03: // ctrl-c is filtered!
192                // @@@PH we're supposed to call a ctrl-c break handler here!
193                break;
194
195              case 0x0d: // CR
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                  }
208
209                  if (pConsoleInput->dwConsoleMode & ENABLE_ECHO_INPUT)
210                    HMWriteFile(pConsoleGlobals->hConsoleBuffer,
211                        pszTarget-2,
212                        2,
213                        &ulPostCounter,                      /* dummy result */
214                        NULL, NULL);
215
216                }
217
218                break;
219
220              case 0x08: // backspace
221                if (ulCounter > 0)
222                {
223                  ulCounter--;
224                  pszTarget--;
225                                                     /* local echo enabled ? */
226                  if (pConsoleInput->dwConsoleMode & ENABLE_ECHO_INPUT)
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--)
286                    HMWriteFile(pConsoleGlobals->hConsoleBuffer,
287                        " ",
288                        1,
289                        &ulPostCounter,                      /* dummy result */
290                        NULL, NULL);
291                }
292
293                *pszTarget = InputRecord.Event.KeyEvent.uChar.AsciiChar;
294                pszTarget++;
295                ulCounter++;
296                break;
297
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));
304
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 */
313                        NULL, NULL);
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 */
332                        NULL, NULL);
333          }
334
335          // buffer filled?
336          if (ulCounter >= nNumberOfBytesToRead)        /* at buffer's end ? */
337            fLoop = FALSE;
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
363BOOL HMDeviceConsoleInClass::WriteFile(PHMHANDLEDATA pHMHandleData,
364                                        LPCVOID       lpBuffer,
365                                        DWORD         nNumberOfBytesToWrite,
366                                        LPDWORD       lpNumberOfBytesWritten,
367                                        LPOVERLAPPED  lpOverlapped,
368                                        LPOVERLAPPED_COMPLETION_ROUTINE  lpCompletionRoutine)
369{
370
371#ifdef DEBUG_LOCAL
372  WriteLog("KERNEL32/CONSOLE:HMDeviceConsoleInClass:WriteFile %s(%08x,%08x,%08x,%08x,%08x)\n",
373           lpHMDeviceName,
374           pHMHandleData->hHMHandle,
375           lpBuffer,
376           nNumberOfBytesToWrite,
377           lpNumberOfBytesWritten,
378           lpOverlapped);
379#endif
380
381  SetLastError(ERROR_ACCESS_DENIED_W);
382  return FALSE;
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
411    case DRQ_GETCONSOLEMODE:
412      return (HMDeviceConsoleInClass
413              ::GetConsoleMode(pHMHandleData,
414                               (LPDWORD)arg1));
415
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
466    case DRQ_SETCONSOLEMODE:
467      return (HMDeviceConsoleInClass
468              ::SetConsoleMode(pHMHandleData,
469                               (DWORD)arg1));
470
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,
490           pHMHandleData->hHMHandle,
491           ulRequestCode,
492           arg1,
493           arg2,
494           arg3,
495           arg4);
496#endif
497
498  SetLastError(ERROR_INVALID_FUNCTION_W);           /* request not implemented */
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
524  //get all pending events
525  iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_PEEK);
526
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
591  //get all pending events and return number of events
592  *lpNumberOfEvents = iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_PEEK);
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
633  if (iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_PEEK) == 0)        /* if queue is currently empty */
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
705  if (iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_PEEK) == 0)        /* if queue is currently empty */
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,
780                                           NULL, NULL));
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;
807  LPSTR          lpstrAscii;
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
818  // create ascii buffer
819  lpstrAscii = (LPSTR)HEAP_malloc(cchToRead * sizeof( WCHAR ));
820  if (lpstrAscii == NULL)
821     return ERROR_NOT_ENOUGH_MEMORY;
822
823                               /* simply forward the request to that routine */
824  // FIXME : if results of ReadFile() have MBCS string, some data might be lost on next call.
825  dwResult = HMDeviceConsoleInClass::ReadFile(pHMHandleData,
826                                              lpstrAscii,
827                                              cchToRead * sizeof( WCHAR ),
828                                              lpcchRead,
829                                              NULL, NULL);
830
831  /* Ascii -> unicode translation */
832  if (dwResult == TRUE)
833    *lpcchRead = MultiByteToWideChar( GetConsoleCP(), 0, lpstrAscii, *lpcchRead, ( LPWSTR )lpvBuffer, cchToRead );
834
835  HEAP_free(lpstrAscii);
836
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
872  iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_WAIT);
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
921  iConsoleInputQueryEvents(pConsoleInput, QUERY_EVENT_WAIT);
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.