diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/os2/client/dllioctl.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/os2/client/dllioctl.c')
-rw-r--r-- | private/os2/client/dllioctl.c | 3792 |
1 files changed, 3792 insertions, 0 deletions
diff --git a/private/os2/client/dllioctl.c b/private/os2/client/dllioctl.c new file mode 100644 index 000000000..a686c8301 --- /dev/null +++ b/private/os2/client/dllioctl.c @@ -0,0 +1,3792 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + dllioctl.c + +Abstract: + + This module implements 32 equivalents of OS/2 V1.21 File System + API Calls that are not trivially mapped to Cruiser APIs. These + are called from 16->32 thunks (i386\doscalls.asm). + + +Author: + + Yaron Shamir (YaronS) 30-May-1991 + +Revision History: + + Patrick Questembert (patrickq) 2-Feb-1992: + Added Dos16QFSAttach + Patrick Questembert (patrickq) 10-Feb-1992: + Added Dos16MkDir2 + Beni Lavi (benil) 3-May-92 + This file was split from dllfs16.c + +--*/ + +#define NTOS2_ONLY + +#define INCL_OS2V20_TASKING +#define INCL_OS2V20_MEMORY +#define INCL_OS2V20_FILESYS +#define INCL_OS2V20_ERRORS +#define INCL_OS2V20_FSD +#define INCL_OS2V20_ERRORMSG +#include "os2dll.h" +#include "os2dll16.h" +#include "sesport.h" +#include "conrqust.h" +#include <ntdddisk.h> +#include "os2flopy.h" + +#include "ntddser.h" +#include "ntddpar.h" +#if PMNT +#define INCL_32BIT +#include "pmnt.h" +#endif + +NTSTATUS +Od2AlertableWaitForSingleObject( + IN HANDLE handle + ); + +#ifdef JAPAN +// MSKK May.07.1993 V-AkihiS +extern USHORT KbdType, KbdSubType; +extern BYTE OemId, OemSubType; + +#define Od2IsIBM02_Keyboard(KbdType, OEMId, OEMSubType) \ + (KbdType == 7 && OEMId == 0 && OEMSubType == 3) +#endif + +union _IO { + SERIAL_BAUD_RATE SerialBaudRate; + SERIAL_LINE_CONTROL SerialLineControl; + UCHAR SerialImmediateChar; + SERIAL_STATUS SerialStatus; + SERIAL_TIMEOUTS SerialTimeouts; + SERIAL_HANDFLOW SerialHandflow; + ULONG SerialWaitMask; + SERIAL_CHARS SerialChars; + SERIAL_QUEUE_SIZE SerialQueueSize; + ULONG SerialDTRRTS; + PAR_QUERY_INFORMATION ParQueryInformation; + PAR_SET_INFORMATION ParSetInformation; +} IO; + +static BYTE ParCharPerLine; +static BYTE ParLinesPerInch; +static BYTE ParInfiniteRetry; + +#if PMNT +extern APIRET MouSetPtrPosPM(PPTRLOC p); +extern APIRET MouGetPtrPosPM(PPTRLOC p); +#endif + +USHORT +MapSerialCommErr(ULONG SerErr) +{ + USHORT MappedSerErr = 0; + + if (SerErr & SERIAL_ERROR_FRAMING) { + MappedSerErr |= FRAMING_ERROR; + } + if (SerErr & SERIAL_ERROR_OVERRUN) { + MappedSerErr |= RX_HARDWARE_OVERRUN; + } + if (SerErr & SERIAL_ERROR_QUEUEOVERRUN) { + MappedSerErr |= RX_QUE_OVERRUN; + } + if (SerErr & SERIAL_ERROR_PARITY) { + MappedSerErr |= PARITY_ERROR; + } + return(MappedSerErr); +} + +BOOLEAN +ErrorAtWaitForAsyncComIOCtl( + NTSTATUS Status, + HANDLE ComEvent, + APIRET *RetCode + ) +{ + if (Status == STATUS_SUCCESS) { + return (FALSE); + } else if (Status == STATUS_PENDING) { + Status = Od2AlertableWaitForSingleObject(ComEvent); + if (!NT_SUCCESS(Status)) { + *RetCode = ERROR_PROTECTION_VIOLATION; + return(TRUE); + } + } else { + *RetCode = Or2MapNtStatusToOs2Error(Status, ERROR_PROTECTION_VIOLATION); +#if DBG + KdPrint(("OS2DLL: ErrorAtWaitForAsyncComIOCtl - Status = %x\n", Status)); +#endif + return (TRUE); + } +} + +#if DBG +UCHAR DosDevIOCtl2NotValidStr[] = "DosDevIOCtl2: Category %d, Function 0x%x Not Valid\n"; +UCHAR DosDevIOCtlNotValidStr[] = "DosDevIOCtl: Category %d, Function 0x%x Not Valid\n"; +UCHAR DosDevIOCtl2NotImplementedYetStr[] = "DosDevIOCtl2: Category %d, Function 0x%x Not Implemented Yet\n"; +UCHAR DosDevIOCtlNotImplementedYetStr[] = "DosDevIOCtl: Category %d, Function 0x%x Not Implemented Yet\n"; +#endif + +APIRET +DosDevIOCtl2( + PVOID pvData, + ULONG cbData, + PVOID pvParmList, + ULONG cbParmList, + ULONG Function, + ULONG Category, + HFILE hDev + ) +{ + NTSTATUS Status = 0; + APIRET RetCode; + ULONG IoControlCode; + ULONG IoCtlParamLength; + PCHAR IoOutputBuffer; + ULONG IoOutputBufferLength; + HANDLE NtHandle; + IO_STATUS_BLOCK IoStatus; + PVOID Io = (PVOID)&IO; + PLINECONTROL pLineCtrl; + PDCBINFO pDCBInfo; + PRXQUEUE pRXQueue; + PFRAME pFrame; + PFONTINFO pFontInfo; + BYTE ParInfo; + UCHAR MaskOn, MaskOff; + int SetOnlyFunction = FALSE; + int ComSetOnlyFunction = FALSE; + IO_VECTOR_TYPE IoVectorType; + USHORT NumChar; + PKBDKEYINFO pKbdInfo; + ULONG WaitFlag, Handle; + BYTE Byte; + ULONG ModemStatus; + BYTE LineStatus; + FILE_FS_DEVICE_INFORMATION FsDeviceInfoBuffer; + ULONG TmpReadTimeout; + HANDLE ComIOCtlEvent; + HANDLE ComReadEvent; + PFILE_HANDLE hFileRecord; + + ULONG DriveNumber; + PULONG pDriveNumberPermanentStorageLocation; + PBIOSPARAMETERBLOCK pBPB; + ULONG BpbRequestType; + ULONG DiskCommand; + BIOSPARAMETERBLOCK PrivateBpb; + MEDIA_TYPE PrivateMediaType; + DISK_GEOMETRY PrivateTrueGeometry; + PTRACKLAYOUT TrackLayout; + ULONG CountSectors; + PTRACKFORMAT TrackFormat; + BYTE FormatSectorSizeType; + + #if DBG + PSZ RoutineName; + RoutineName = "DosDevIOCtl2 (Called directly or redirected from DosDevIOCtl)"; + #endif + + AcquireFileLockShared( + #if DBG + RoutineName + #endif + ); + +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DosDevIOCtl2: Category: %ld, Function: %lx\n", Category, Function)); + } +#endif + + // + // Check for invalid handle. + // + + RetCode = DereferenceFileHandle(hDev, &hFileRecord); + if (RetCode) { + ReleaseFileLockShared( + #if DBG + RoutineName + #endif + ); + return RetCode; + } + NtHandle = hFileRecord->NtHandle; + IoVectorType = hFileRecord->IoVectorType; + ComIOCtlEvent = hFileRecord->NtAsyncIOCtlEvent; + pDriveNumberPermanentStorageLocation = (PULONG) &hFileRecord->NtAsyncIOCtlEvent; + ComReadEvent = hFileRecord->NtAsyncReadEvent; + ReleaseFileLockShared( + #if DBG + RoutineName + #endif + ); + + switch (Category) { + + case IOCTL_ASYNC: /* Serial Device Control */ + + if (IoVectorType != ComVectorType) { +#if DBG + KdPrint(("DosDevIOCtl[2]: Category %d, Function 0x%x with non-COM(%d) type handle\n", + Category, Function, IoVectorType)); +#endif + RetCode = ERROR_BAD_COMMAND; + break; + } + + switch (Function) { + + case ASYNC_SETBAUDRATE: /* Set Baud Rate */ + + if (cbParmList < sizeof(USHORT)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForRead(pvParmList, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + IoControlCode = IOCTL_SERIAL_SET_BAUD_RATE; + IO.SerialBaudRate.BaudRate = (ULONG)(*(PUSHORT)pvParmList); + IoCtlParamLength = sizeof(SERIAL_BAUD_RATE); + IoOutputBuffer = NULL; + IoOutputBufferLength = 0; + ComSetOnlyFunction = TRUE; + break; + + case ASYNC_SETLINECTRL: /* Set Line Control */ + + if (cbParmList < 3) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForRead(pvParmList, 3, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + IoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL; + pLineCtrl = (PLINECONTROL)pvParmList; + IO.SerialLineControl.StopBits = pLineCtrl->bStopBits; + IO.SerialLineControl.Parity = pLineCtrl->bParity; + IO.SerialLineControl.WordLength = pLineCtrl->bDataBits; + IoCtlParamLength = sizeof(SERIAL_LINE_CONTROL); + IoOutputBuffer = NULL; + IoOutputBufferLength = 0; + ComSetOnlyFunction = TRUE; + break; + + case ASYNC_TRANSMITIMM: /* Transmit Immediate Char */ + + if (cbParmList < 1) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForRead(pvParmList, 1, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + IoControlCode = IOCTL_SERIAL_IMMEDIATE_CHAR; + IO.SerialImmediateChar = *(PUCHAR)pvParmList; + IoCtlParamLength = sizeof(UCHAR); + IoOutputBuffer = NULL; + IoOutputBufferLength = 0; + ComSetOnlyFunction = TRUE; + break; + + case ASYNC_SETBREAKOFF: /* Set Break Off */ + + case ASYNC_SETBREAKON: /* Set Break On */ + + if (cbData < sizeof(USHORT)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + if (Function == ASYNC_SETBREAKOFF) { + IoControlCode = IOCTL_SERIAL_SET_BREAK_OFF; + } + else { + IoControlCode = IOCTL_SERIAL_SET_BREAK_ON; + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IoControlCode, + NULL, + 0, + NULL, + 0 + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_COMMSTATUS, + NULL, + 0, + &IO, + sizeof(SERIAL_STATUS) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + *(PUSHORT)pvData = MapSerialCommErr(IO.SerialStatus.Errors); + break; + + + case ASYNC_SETMODEMCTRL: /* Set Modem Control Signals */ + + if (cbData < sizeof(USHORT)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + if (cbParmList < 2) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForRead(pvParmList, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + MaskOn = *(PUCHAR)pvParmList; + MaskOff = *((PUCHAR)pvParmList + 1); + if (MaskOn & 0x1) { /* Set DTR */ + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_SET_DTR, + NULL, + 0, + NULL, + 0 + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + } + if (MaskOn & 0x2) { /* Set RTS */ + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_SET_RTS, + NULL, + 0, + NULL, + 0 + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + } + if (!(MaskOff & 0x1)) { /* Clear DTR */ + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_CLR_DTR, + NULL, + 0, + NULL, + 0 + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + } + if (MaskOn & 0x1) { /* Clear RTS */ + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_CLR_RTS, + NULL, + 0, + NULL, + 0 + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_COMMSTATUS, + NULL, + 0, + &IO, + sizeof(SERIAL_STATUS) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + *(PUSHORT)pvData = MapSerialCommErr(IO.SerialStatus.Errors); + break; + + + case ASYNC_STOPTRANSMIT: /* Stop Transmit */ + + IoControlCode = IOCTL_SERIAL_SET_XOFF; + Io = NULL; + IoCtlParamLength = 0; + IoOutputBuffer = NULL; + IoOutputBufferLength = 0; + ComSetOnlyFunction = TRUE; + + case ASYNC_STARTTRANSMIT: /* Start Transmit */ + + IoControlCode = IOCTL_SERIAL_SET_XON; + Io = NULL; + IoCtlParamLength = 0; + IoOutputBuffer = NULL; + IoOutputBufferLength = 0; + ComSetOnlyFunction = TRUE; + + case ASYNC_GETBAUDRATE: /* Get Baud Rate */ + + if (cbData < 2) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_BAUD_RATE, + NULL, + 0, + &IO, + sizeof(SERIAL_BAUD_RATE) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + *(PUSHORT)pvData = (USHORT)IO.SerialBaudRate.BaudRate; + break; + + case ASYNC_GETLINECTRL: /* Get Line Control */ + + if (cbData < 4) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, 4, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_LINE_CONTROL, + NULL, + 0, + &IO, + sizeof(SERIAL_LINE_CONTROL) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + pLineCtrl = (PLINECONTROL)pvData; + pLineCtrl->bDataBits = IO.SerialLineControl.WordLength; + pLineCtrl->bParity = IO.SerialLineControl.Parity; + pLineCtrl->bStopBits = IO.SerialLineControl.StopBits; + /* + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_HANDFLOW, + NULL, + 0, + &IO, + sizeof(SERIAL_HANDFLOW) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + pLineCtrl->fTransBreak = + (IO.SerialHandflow.FlowReplace & SERIAL_BREAK_CHAR) ? (BYTE)1 : (BYTE)0; + */ + /* BUGBUG - How to determine if a break is being sent? */ + pLineCtrl->fTransBreak = 0; + break; + + case ASYNC_GETCOMMSTATUS: /* Get Comm Status */ + + if (cbData < 1) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, 1, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_COMMSTATUS, + NULL, + 0, + &IO, + sizeof(SERIAL_STATUS) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + *(PUCHAR)pvData = (UCHAR)(IO.SerialStatus.HoldReasons & ~SERIAL_RX_WAITING_FOR_DSR); + if (IO.SerialStatus.HoldReasons & SERIAL_RX_WAITING_FOR_DSR) { + *(PUCHAR)pvData |= RX_WAITING_FOR_DSR; + } + if (IO.SerialStatus.WaitForImmediate) { + *(PUCHAR)pvData |= TX_WAITING_TO_SEND_IMM; + } + break; + + case ASYNC_GETCOMMERROR: /* Get COM Error Word */ + + if (cbData < sizeof(USHORT)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_COMMSTATUS, + NULL, + 0, + &IO, + sizeof(SERIAL_STATUS) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + *(PUSHORT)pvData = MapSerialCommErr(IO.SerialStatus.Errors); + break; + + case ASYNC_GETCOMMEVENT: /* Get COM Event Information */ + + // BUGBUG the Nt has no IOCTL to support this yet + // 6-Feb-92 + // Following code is not correct. + if (cbData < sizeof(USHORT)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_WAIT_MASK, + NULL, + 0, + &IO, + sizeof(ULONG) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + *(PUSHORT)pvData = (USHORT)(IO.SerialWaitMask & 0x1ff); + break; + + case ASYNC_GETDCBINFO: /* Get Device Control Block */ + + if (cbData < sizeof(DCBINFO)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(DCBINFO), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + pDCBInfo = (PDCBINFO)pvData; + pDCBInfo->fbTimeout = 0; + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_TIMEOUTS, + NULL, + 0, + &IO, + sizeof(SERIAL_TIMEOUTS) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + if (IO.SerialTimeouts.ReadIntervalTimeout == 0) { + pDCBInfo->usReadTimeout = (USHORT)((IO.SerialTimeouts.ReadTotalTimeoutConstant - 10) / 10); + pDCBInfo->fbTimeout |= MODE_READ_TIMEOUT; + } + else if (IO.SerialTimeouts.ReadTotalTimeoutConstant != 0) { + pDCBInfo->usReadTimeout = (USHORT)((IO.SerialTimeouts.ReadTotalTimeoutConstant - 10) / 10); + pDCBInfo->fbTimeout |= MODE_WAIT_READ_TIMEOUT; + } + else { + pDCBInfo->usReadTimeout = 0; + pDCBInfo->fbTimeout |= MODE_NOWAIT_READ_TIMEOUT; + } + if ((IO.SerialTimeouts.WriteTotalTimeoutMultiplier != 0) || + (IO.SerialTimeouts.WriteTotalTimeoutConstant != 0)) { + pDCBInfo->usWriteTimeout = (USHORT)((IO.SerialTimeouts.WriteTotalTimeoutConstant - 10) / 10); + } + else { + pDCBInfo->fbTimeout |= MODE_NO_WRITE_TIMEOUT; + pDCBInfo->usWriteTimeout = 0; + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_CHARS, + NULL, + 0, + &IO, + sizeof(SERIAL_CHARS) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + pDCBInfo->bErrorReplacementChar = IO.SerialChars.ErrorChar; + pDCBInfo->bBreakReplacementChar = IO.SerialChars.BreakChar; + pDCBInfo->bXONChar = IO.SerialChars.XonChar; + pDCBInfo->bXOFFChar = IO.SerialChars.XoffChar; + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_HANDFLOW, + NULL, + 0, + &IO, + sizeof(SERIAL_HANDFLOW) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + pDCBInfo->fbCtlHndShake = (BYTE)IO.SerialHandflow.ControlHandShake; + pDCBInfo->fbFlowReplace = (BYTE)IO.SerialHandflow.FlowReplace; +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("ASYNC_GETDCBINFO\n")); + KdPrint(("Write Timeout: %x\n", pDCBInfo->usWriteTimeout & 0xffff)); + KdPrint(("Read Timeout: %x\n", pDCBInfo->usReadTimeout & 0xffff)); + KdPrint(("Flags1 : %x\n", pDCBInfo->fbCtlHndShake & 0xff)); + KdPrint(("Flags2 : %x\n", pDCBInfo->fbFlowReplace & 0xff)); + KdPrint(("Flags3 : %x\n", pDCBInfo->fbTimeout & 0xff)); + } +#endif + break; + + case ASYNC_SETDCBINFO: /* Set Device Control Block */ + + if (cbParmList < sizeof(DCBINFO)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForRead(pvParmList, sizeof(DCBINFO), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + pDCBInfo = (PDCBINFO)pvParmList; + +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("ASYNC_SETDCBINFO\n")); + KdPrint(("Write Timeout: %x\n", pDCBInfo->usWriteTimeout & 0xffff)); + KdPrint(("Read Timeout: %x\n", pDCBInfo->usReadTimeout & 0xffff)); + KdPrint(("Flags1 : %x\n", pDCBInfo->fbCtlHndShake & 0xff)); + KdPrint(("Flags2 : %x\n", pDCBInfo->fbFlowReplace & 0xff)); + KdPrint(("Flags3 : %x\n", pDCBInfo->fbTimeout & 0xff)); + } +#endif + TmpReadTimeout = (ULONG) pDCBInfo->usReadTimeout * 10L + 10L; + + // + // BUGBUG: Prevent NT from waiting more than 1000 MSec + // inside the device driver when the mode is + // MODE_WAIT_READ_TIMEOUT. + // OS/2 cancels pending IOs when ASYNC_SETDCBINFO + // with MODE_WAIT_READ_TIMEOUT + // is called with 0 ReadTimeout while NT does not. + // Therefore, we have to force a timeout exit. + // + +#if 0 + if (((pDCBInfo->fbTimeout & 0x6) == MODE_WAIT_READ_TIMEOUT) && + (TmpReadTimeout > 1000) + ) { + TmpReadTimeout = 1000; + } +#else + // + // New better handling: Sets the read event. This releases + // any thread which might be waiting in ComReadRoutine(). + // That thread will figure out its been aborted, and will cancel + // the I/O operation. + // + + if (((pDCBInfo->fbTimeout & 0x6) == MODE_WAIT_READ_TIMEOUT) && + (pDCBInfo->usReadTimeout == 0) + ) { + + Status = NtSetEvent( + ComReadEvent, + NULL); + + if (!NT_SUCCESS(Status)) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DosDevIoCtl2: SETDCBINFO - NtSetEvent failed, Status = %lx", Status)); + } +#endif + } + } +#endif + + switch (pDCBInfo->fbTimeout & 0x6) { + case 0: + /* Illegal value */ + return(ERROR_PROTECTION_VIOLATION); + break; + + case MODE_READ_TIMEOUT: + /* Normal read timeout processing */ + IO.SerialTimeouts.ReadIntervalTimeout = 0; + IO.SerialTimeouts.ReadTotalTimeoutMultiplier = 0; + IO.SerialTimeouts.ReadTotalTimeoutConstant = TmpReadTimeout; + break; + + case MODE_WAIT_READ_TIMEOUT: + /* Wait for something */ + IO.SerialTimeouts.ReadIntervalTimeout = 0xffffffffL; + IO.SerialTimeouts.ReadTotalTimeoutMultiplier = 0xffffffffL; + IO.SerialTimeouts.ReadTotalTimeoutConstant = TmpReadTimeout; + break; + + case MODE_NOWAIT_READ_TIMEOUT: + /* No wait timeout */ + IO.SerialTimeouts.ReadIntervalTimeout = 0xffffffff; + IO.SerialTimeouts.ReadTotalTimeoutMultiplier = 0; + IO.SerialTimeouts.ReadTotalTimeoutConstant = 0; + break; + + } + if (pDCBInfo->fbTimeout & MODE_NO_WRITE_TIMEOUT) { /* infinite write timeout */ + IO.SerialTimeouts.WriteTotalTimeoutMultiplier = 0; + IO.SerialTimeouts.WriteTotalTimeoutConstant = 0; + } + else { + IO.SerialTimeouts.WriteTotalTimeoutMultiplier = 0; + IO.SerialTimeouts.WriteTotalTimeoutConstant = (ULONG) pDCBInfo->usWriteTimeout * 10L + 10L; + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_SET_TIMEOUTS, + &IO, + sizeof(SERIAL_TIMEOUTS), + NULL, + 0 + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_CHARS, + NULL, + 0, + &IO, + sizeof(SERIAL_CHARS) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + IO.SerialChars.ErrorChar = pDCBInfo->bErrorReplacementChar; + IO.SerialChars.BreakChar = pDCBInfo->bBreakReplacementChar; + + // + // The NT driver does not allow XON == XOFF. + // OS/2 programs usually set XON = XOFF = 0 when not using XON/XOFF + // handshaking. Therefore, we allow this situation by leaving the + // XON/XOFF chars at their previous values (an alternative is to set + // XON = 0, XOFF = 1). + // + + if (((pDCBInfo->fbFlowReplace & (MODE_AUTO_TRANSMIT|MODE_AUTO_RECEIVE)) == 0) && + (pDCBInfo->bXONChar == pDCBInfo->bXOFFChar)) { + // + // leave chars at previous values + // + } else { + IO.SerialChars.XonChar = pDCBInfo->bXONChar; + IO.SerialChars.XoffChar = pDCBInfo->bXOFFChar; + } + + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_SET_CHARS, + &IO, + sizeof(SERIAL_CHARS), + NULL, + 0 + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_HANDFLOW, + NULL, + 0, + &IO, + sizeof(SERIAL_HANDFLOW) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + IO.SerialHandflow.ControlHandShake = + ((ULONG) pDCBInfo->fbCtlHndShake) & ~SERIAL_CONTROL_INVALID; + IO.SerialHandflow.FlowReplace = + ((ULONG) pDCBInfo->fbFlowReplace) & ~SERIAL_FLOW_INVALID; + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_SET_HANDFLOW, + &IO, + sizeof(SERIAL_HANDFLOW), + NULL, + 0 + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + break; + + case ASYNC_GETINQUECOUNT: /* Get Receive Queue Characters */ + + case ASYNC_GETOUTQUECOUNT: /* Get Transmit Queue Characters */ + + if (cbData < sizeof(RXQUEUE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(RXQUEUE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + pRXQueue = (PRXQUEUE)pvData; + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_COMMSTATUS, + NULL, + 0, + &IO, + sizeof(SERIAL_STATUS) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + if (Function == ASYNC_GETINQUECOUNT) { + pRXQueue->cch = (USHORT)IO.SerialStatus.AmountInInQueue; + pRXQueue->cb = 1024; /* according to the PRM */ + } + else { + pRXQueue->cch = (USHORT)IO.SerialStatus.AmountInOutQueue; + pRXQueue->cb = 1024; /* according to the PRM */ + } + break; + + case ASYNC_GETMODEMINPUT: /* Get Modem Input */ + + if (cbData < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_MODEMSTATUS, + NULL, + 0, + &ModemStatus, + sizeof(ModemStatus) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + *(PBYTE)pvData = (BYTE)ModemStatus; + break; + + case ASYNC_GETLINESTATUS: /* Get Line Status */ + + if (cbData < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_COMMSTATUS, + NULL, + 0, + &IO, + sizeof(SERIAL_STATUS) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + LineStatus = 0; + if (IO.SerialStatus.AmountInOutQueue != 0) { + LineStatus |= (WRITE_REQUEST_QUEUED | DATA_IN_TX_QUE); + } + if (((IO.SerialStatus.HoldReasons & + (SERIAL_TX_WAITING_FOR_CTS | + SERIAL_TX_WAITING_FOR_DSR | + SERIAL_TX_WAITING_FOR_DCD | + SERIAL_TX_WAITING_FOR_XON | + SERIAL_TX_WAITING_XOFF_SENT | + SERIAL_TX_WAITING_ON_BREAK)) == 0) && + (IO.SerialStatus.AmountInOutQueue != 0) + ) { + LineStatus |= HARDWARE_TRANSMITTING; + } + if (IO.SerialStatus.WaitForImmediate) { + LineStatus |= CHAR_READY_TO_SEND_IMM; + } + *(PBYTE)pvData = LineStatus; + break; + + case ASYNC_GETMODEMOUTPUT: /* Get Modem Output */ + + if (cbData < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IOCTL_SERIAL_GET_DTRRTS, + NULL, + 0, + &IO, + sizeof(IO.SerialDTRRTS) + ); + if (ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode)) { + return (RetCode); + } + + *(PBYTE)pvData = 0; + if (IO.SerialDTRRTS & SERIAL_DTR_STATE) { + *(PBYTE)pvData |= DTR_ON; + } + if (IO.SerialDTRRTS & SERIAL_RTS_STATE) { + *(PBYTE)pvData |= RTS_ON; + } + break; + + default: + +#if DBG + KdPrint((DosDevIOCtl2NotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_PRINTER: /* Printer Device Control */ + + switch (Function) { + + case PRT_SETFRAMECTL: /* Set Frame Control */ + + if (cbData < sizeof(FRAME)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForRead(pvData, sizeof(FRAME), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + pFrame = (PFRAME)pvData; + ParCharPerLine = pFrame->bCharsPerLine; + ParLinesPerInch = pFrame->bLinesPerInch; + break; + + case PRT_SETINFINITERETRY: /* Set Infinite Retry */ + + if (cbData < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForRead(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + ParInfiniteRetry = *(PBYTE)pvData; + break; + + case PRT_INITPRINTER: /* Init Printer */ + + IoControlCode = IOCTL_PAR_SET_INFORMATION; + IO.ParSetInformation.Init = PARALLEL_INIT; + IoCtlParamLength = sizeof(PAR_SET_INFORMATION); + IoOutputBuffer = NULL; + IoOutputBufferLength = 0; + SetOnlyFunction = TRUE; + break; + + case PRT_ACTIVATEFONT: /* Activate Font */ + + break; + + case PRT_GETFRAMECTL: /* Get Frame Control */ + + if (cbData < sizeof(FRAME)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(FRAME), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + pFrame = (PFRAME)pvData; + pFrame->bCharsPerLine = ParCharPerLine; + pFrame->bLinesPerInch = ParLinesPerInch; + break; + + case PRT_GETINFINITERETRY: /* Get Infinite Retry */ + + if (cbData < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + *(PBYTE)pvData = ParInfiniteRetry; + break; + + case PRT_GETPRINTERSTATUS: /* Get Printer Status */ + + if (cbData < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + Status = NtDeviceIoControlFile( NtHandle, + 0, + NULL, + NULL, + &IoStatus, + IOCTL_PAR_QUERY_INFORMATION, + NULL, + 0, + &IO, + sizeof(PAR_QUERY_INFORMATION) + ); + if (!NT_SUCCESS(Status)) { + return(ERROR_PROTECTION_VIOLATION); + } + ParInfo = 0; + if (IO.ParQueryInformation.Status & PARALLEL_SELECTED) { + ParInfo |= PRINTER_SELECTED; + } + if (IO.ParQueryInformation.Status & PARALLEL_PAPER_EMPTY) { + ParInfo |= PRINTER_OUT_OF_PAPER; + } + if ((IO.ParQueryInformation.Status & PARALLEL_BUSY) == 0) { + ParInfo |= PRINTER_NOT_BUSY; + } + *(PBYTE)pvData = ParInfo; + break; + + case PRT_QUERYACTIVEFONT: /* Query Active Font */ + + if (cbData < sizeof(FONTINFO)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(FONTINFO), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + pFontInfo = (PFONTINFO)pvData; + pFontInfo->idCodePage = 0; + pFontInfo->idFont = 0; + break; + + case PRT_VERIFYFONT: /* Verify Font */ + + break; + + default: +#if DBG + KdPrint((DosDevIOCtl2NotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_SCR_AND_PTRDRAW: /* PTR : Screen/Pointer-Draw Control */ + if (IoVectorType != MouseVectorType) + { +#if DBG + KdPrint(("DosDevIOCtl2: Category %d, Function 0x%x with non-Mouse(%d) type handle\n", + Category, Function, IoVectorType)); +#endif + RetCode = ERROR_BAD_COMMAND; + break; + } + + switch (Function) + { + case PTR_GETPTRDRAWADDRESS: /* retrives entry-point address for the pointer-draw function */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + default: + +#if DBG + KdPrint((DosDevIOCtl2NotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_KEYBOARD: /* KBD : Keyboard Control */ + if ((IoVectorType != KbdVectorType) && + (IoVectorType != ScreenVectorType)) + { +#if DBG + KdPrint(("DosDevIOCtl2: Category %d, Function 0x%x with non-Kbd(%d) type handle\n", + Category, Function, IoVectorType)); +#endif + RetCode = ERROR_BAD_COMMAND; + break; + } + + switch (Function) + { + case KBD_CREATE: /* Create Logical Keyboard */ + + case KBD_DESTROY: /* Free Logical Keyboard */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + case KBD_GETCODEPAGEID: /* Get Code Page */ + + if ((cbData < sizeof(CPID)) || + (cbParmList != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(CPID), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = KbdGetCpId((PUSHORT)pvData, + (ULONG)hDev); + + break; + + case KBD_GETINPUTMODE: /* Get Input Mode */ + + if ((cbData < sizeof(BYTE)) || + (cbParmList != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = KbdGetInputMode((PBYTE)pvData, + (ULONG)hDev); + + break; + + case KBD_GETINTERIMFLAG: /* Get Interim Flag */ + + if ((cbData < sizeof(BYTE)) || + (cbParmList != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = KbdGetInterimFlag((PBYTE)pvData, + (ULONG)hDev); + + break; + + case KBD_GETKEYBDTYPE: /* Get Keybaord Type */ + + if ((cbData < sizeof(KBDTYPE)) || + (cbParmList != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(KBDTYPE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + ((PKBDTYPE)pvData)->reserved1 = 0; + ((PKBDTYPE)pvData)->reserved2 = 0; + + RetCode = KbdGetKbdType((PUSHORT)pvData, + (ULONG)hDev); + + break; + + case KBD_GETSESMGRHOTKEY: /* Get Hot-Key Info */ + + if ((cbData < sizeof(HOTKEY)) || + (cbParmList < 2)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(KBDTYPE), 1); + Od2ProbeForRead(pvParmList, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = KbdGetHotKey((PUSHORT)pvParmList, + (PBYTE)pvData, + (ULONG)hDev); + + break; + + case KBD_GETSHIFTSTATE: /* Get Shift State */ + + if ((cbData < sizeof(SHIFTSTATE)) || + (cbParmList != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(SHIFTSTATE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = KbdGetShiftState((PBYTE)pvData, + (ULONG)hDev); + + break; + + case KBD_PEEKCHAR: /* Peek Character Data Record */ + + if ((cbData < sizeof(KBDKEYINFO)) || + (cbParmList < 2)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(KBDKEYINFO), 1); + Od2ProbeForWrite(pvParmList, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = KbdPeek((PKBDKEYINFO)pvData, + (ULONG)hDev); + + if (((PKBDKEYINFO)pvData)->fbStatus & 0x40) + { + *(PUSHORT)pvParmList = KBD_DATA_RECEIVED; + } else + *(PUSHORT)pvParmList = 0; + + if (SesGrp->ModeFlag & 1) + { + *(PUSHORT)pvParmList |= KBD_DATA_BINARY; + } + + break; + + case KBD_READCHAR: /* Read Character Data Record */ + + try + { + Od2ProbeForWrite(pvParmList, sizeof(USHORT), 1); + NumChar = (USHORT)(*((PUSHORT) pvParmList) & 0x7FFF); + Od2ProbeForWrite(pvData, sizeof(KBDKEYINFO) * NumChar, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + if ((cbData < (NumChar * sizeof(KBDKEYINFO))) || + (cbParmList < 2)) + { + return ERROR_INVALID_PARAMETER; + } + + if (NumChar > 16) + { + NumChar = 16; // return ERROR_INVALID_PARAMETER; + } + + pKbdInfo = (PKBDKEYINFO)pvData; + + WaitFlag = ((*(PUSHORT)pvParmList) & KBD_READ_NOWAIT) ? + IO_NOWAIT : IO_WAIT; + + if (SesGrp->ModeFlag & 1) + { + *(PUSHORT)pvParmList = KBD_DATA_BINARY; + } else + *(PUSHORT)pvParmList = 0; + + for (; NumChar ; NumChar-- ) + { + + if (RetCode = KbdCharIn(pKbdInfo, + WaitFlag, + (ULONG)hDev)) + { + break; + } + + (*(PUSHORT)pvParmList)++ ; + } + + break; + + case KBD_SETFGNDSCREENGRP: /* Set Foreground Screen Group */ + +#if DBG + KdPrint(("DosDevIOCtl2: Category %d, Function 0x%x Illegal For User\n", + Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + case KBD_SETFOCUS: /* Set Keyboard Focus */ + + if ((pvData != 0L) || + (cbData != 0) || + (cbParmList < 2 )) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + Handle = (ULONG)(*(PUSHORT)pvParmList); + + // + // Check for invalid handle. + // + + RetCode = DereferenceFileHandle((HFILE)Handle, &hFileRecord); + if (RetCode) { + ReleaseFileLockShared( + #if DBG + RoutineName + #endif + ); + break; + } + NtHandle = hFileRecord->NtHandle; + IoVectorType = hFileRecord->IoVectorType; + ReleaseFileLockShared( + #if DBG + RoutineName + #endif + ); + + if ((IoVectorType != KbdVectorType) && + (IoVectorType != ScreenVectorType)) + { +#if DBG + KdPrint(("DosDevIOCtl2: Category %d, Function 0x%x with non-logical-Kbd(%d) type handle\n", + Category, Function, IoVectorType)); +#endif + RetCode = ERROR_INVALID_PARAMETER; + break; + } + + RetCode = KbdGetFocus(IO_NOWAIT, /* *(PUSHORT)pvData, */ + Handle); + + break; + + case KBD_SETINTERIMFLAG: /* Set Interim Flag */ + + if ((cbParmList < sizeof(BYTE)) || + (cbData != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + if ((Byte = *(PBYTE)pvParmList) & ~(CONVERSION_REQUEST | INTERIM_CHAR)) + { + return ERROR_INVALID_PARAMETER; + } + + RetCode = KbdSetInterimFlag(Byte, + (ULONG)hDev); + + break; + + case KBD_SETKCB: /* Bind Logical Keyboard to the Physical */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + case KBD_SETINPUTMODE: /* Set Input Mode */ + + if ((cbParmList < sizeof(BYTE)) || + (cbData != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + +#if PMNT + // Accept 0x82: + // 0x80 - BINARY_MODE + // 0x02 - ? (but issued by PM - BUGBUG - find out what it does) + if ((Byte = *(PBYTE)pvParmList & ~0x2) // Clear 0x2 bit + & ~(BINARY_MODE | SHIFT_REPORT_MODE)) +#else + if ((Byte = *(PBYTE)pvParmList) & ~(BINARY_MODE | SHIFT_REPORT_MODE)) +#endif + { + return ERROR_INVALID_PARAMETER; + } + + RetCode = KbdSetInputMode(Byte, + (ULONG)hDev); + break; + + case KBD_SETNLS: /* Install Code Page */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + case KBD_SETSESMGRHOTKEY: /* Set New Hot-Key Info */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + case KBD_SETSHIFTSTATE: /* Set Shift State */ + + if ((cbParmList < sizeof(SHIFTSTATE)) || + (cbData != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvParmList, sizeof(SHIFTSTATE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = KbdSetShiftState((PBYTE)pvParmList, + (ULONG)hDev); + + break; + + case KBD_SETTRANSTABLE: /* Set Translation Table */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + case KBD_SETTYPAMATICRATE: /* Set Keyboard Typamatic Rate */ + + if ((cbParmList < sizeof(RATEDELAY)) || + (cbData != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(RATEDELAY), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = KbdSetTypamaticRate((PBYTE)pvParmList, + (ULONG)hDev); + + break; + + case KBD_XLATESCAN: /* Translate Scan Code */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + +#if PMNT + // Called by InitKeyboard(), PMWIN + case KBD_GETHARDWAREID: + if ((cbData < 2) || + (cbParmList != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + // For structure fields, see p7-90 of the IBM I/O Subsystems + // and Device Support, Vol. 1 + + try + { + // The value below is what we get under OS/2 1.3 + // & AST Premium 386/33 (got them by single-step tru + // PM with OS/2 KD) + *(USHORT *)pvData = 2*sizeof(USHORT); + + if (cbData < 4) + break; + +#ifdef JAPAN +// MSKK May.07.1993 V-AkihiS + if (Od2IsIBM02_Keyboard(KbdType, OemId, OemSubType)) { + // + // Hardware ID of IBM-J 5576-002 keyboard is 0xAB90. + // + *(USHORT *)((ULONG)pvData + sizeof(USHORT)) = 0xAB90; + } + else + { + // BUGBUG - get the keyboard HW ID at run-time ! + *(USHORT *)((ULONG)pvData + sizeof(USHORT)) = 0xAB41; + } +#else + // We check we can copy the HW ID field + // 0xAB41 is for the 102 keys keyboard + *(USHORT *)((ULONG)pvData + sizeof(USHORT)) = 0xAB41; +#endif + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = NO_ERROR; + break; + + // Called by InitKeyboard(), PMWIN + case KBD_GETCPANDCOUNTRY: + if ((cbData < 2) || + (cbParmList != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + // For structure fields, see p7-91 of the IBM I/O Subsystems + // and Device Support, Vol. 1 + + try + { + // The values below are what we get under OS/2 1.3 + // & AST Premium 386/33 (got them by single-step tru + // PMWIN.InitKeyboard with OS/2 KD) +#ifdef JAPAN +// MSKK May.07.1993 V-AkihiS + *(USHORT *)pvData = 2*sizeof(USHORT) + + strlen("JP") + 1 + + strlen("103 ") + 1; +#else + *(USHORT *)pvData = 12; // 2*sizeof(USHORT) + 3 + 5 +#endif + + if (cbData < 4) + break; + +#ifdef JAPAN +// MSKK May.07.1993 V-AkihiS + // We checked we can copy the kbCP field + *(USHORT *)((ULONG)pvData + sizeof(USHORT)) = 0x3A4; +#else +#if DBG + DbgPrint("Os2: KBD_GETCPANDCOUNTRY - code-page values:\n"); + DbgPrint(" PrimaryCp: %d\n", + SesGrp->PrimaryCP); + DbgPrint(" DosCp: %d\n", + SesGrp->DosCP); + DbgPrint(" KbdCp: %d\n", + SesGrp->KbdCP); +#endif //DBG + if (SesGrp->PrimaryCP != 0) + { + // We checked we can copy the kbCP field + *(USHORT *)((ULONG)pvData + sizeof(USHORT)) = (USHORT)SesGrp->PrimaryCP; + } + else if (SesGrp->DosCP != 0) + { + *(USHORT *)((ULONG)pvData + sizeof(USHORT)) = (USHORT)SesGrp->DosCP; + } + else if (SesGrp->KbdCP != 0) + { + *(USHORT *)((ULONG)pvData + sizeof(USHORT)) = (USHORT)SesGrp->KbdCP; + } + else + *(USHORT *)((ULONG)pvData + sizeof(USHORT)) = 0x1B5; +#endif + + // Copy as much as we can +#ifdef JAPAN +// MSKK May.07.1993 V-AkihiS + strncpy((char *)pvData + 2*sizeof(USHORT), + "JP", + cbData - 4); +#else + strncpy((char *)pvData + 2*sizeof(USHORT), + &SesGrp->KeyboardLayout[0], + (((cbData - 4) < 2) ? cbData - 4 : 2)); + // Make it null-terminated if less than 2 chars + if ((cbData > 2*sizeof(USHORT)+ 2) && + (strlen(&SesGrp->KeyboardLayout[0]) < 2)) + *((char *)pvData + 2*sizeof(USHORT) + 2) = '\0'; + else + { + // Make it null-terminated if 2 chars + if (cbData > 2*sizeof(USHORT)+ 3) + *((char *)pvData + 2*sizeof(USHORT) + 3) = '\0'; + } +#if DBG + DbgPrint("Os2: KBD_GETCPANDCOUNTRY - keyboard layout: <%s>\n", + (char *)pvData + 2*sizeof(USHORT)); +#endif //DBG +#endif // not JAPAN +#ifdef JAPAN +// MSKK May.19.1993 V-AkihiS + strncpy((char *)pvData + 2*sizeof(USHORT)+ 3, + "103 ", + cbData - 4 - 3); +#else + //Copy the subcountry keyboard code + //Usually 103 for US, 189 for FR + memcpy((char *)pvData + 2*sizeof(USHORT) + 3, + &SesGrp->KeyboardName[0], + (((cbData - 2*sizeof(USHORT) - 3) < 4) ? + cbData - 2*sizeof(USHORT) - 3 : 4)); +#if DBG + DbgPrint("Os2: KBD_GETCPANDCOUNTRY - keyboard name: <%s>\n", + (char *)pvData + 2*sizeof(USHORT) + 3); +#endif //DBG +#endif // not JAPAN + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = NO_ERROR; + break; + +#endif // PMNT + default: + +#if DBG + KdPrint((DosDevIOCtl2NotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_POINTINGDEVICE: /* MOU : Pointing-Device (Mouse) Control */ + if (IoVectorType != MouseVectorType) + { +#if DBG + KdPrint(("DosDevIOCtl2: Category %d, Function 0x%x with non-Mouse(%d) type handle\n", + Category, Function, IoVectorType)); +#endif + RetCode = ERROR_BAD_COMMAND; + break; + } + + switch (Function) + { + case MOU_ALLOWPTRDRAW: + + if ((cbParmList != 0) || + (pvParmList != 0L) || + (cbData != 0) || + (pvData != 0L)) + { + return ERROR_INVALID_PARAMETER; + } + + RetCode = MouAllowPtrDraw((ULONG)hDev); + + break; + + case MOU_DRAWPTR: /* Draw Ptr Anywhere */ + + if ((cbParmList != 0) || + (pvParmList != 0L) || + (cbData != 0) || + (pvData != 0L)) + { + return ERROR_INVALID_PARAMETER; + } + + RetCode = MouDrawPtr((ULONG)hDev); + + break; + + case MOU_GETBUTTONCOUNT: /* Get Button Number */ + + if ((cbParmList != 0) || + (pvParmList != 0L) || + (cbData < 2)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouGetNumButtons((PUSHORT)pvData, + (ULONG)hDev); + + break; + + case MOU_GETEVENTMASK: /* Get Event Mask */ + + if ((cbParmList != 0) || + (pvParmList != 0L) || + (cbData < 2)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouGetEventMask((PUSHORT)pvData, + (ULONG)hDev); + + break; + + case MOU_GETHOTKEYBUTTON: /* Get Mouse Equivalent for the HotKey */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + case MOU_GETMICKEYCOUNT: /* Get Count of Mickeys per Centimeter */ + + if ((cbParmList != 0) || + (pvParmList != 0L) || + (cbData < 2)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouGetNumMickeys((PUSHORT)pvData, + (ULONG)hDev); + + break; + + case MOU_GETMOUSTATUS: /* Get Mouse Status */ + + if ((cbParmList != 0) || + (pvParmList != 0L) || + (cbData < 2)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouGetDevStatus((PUSHORT)pvData, + (ULONG)hDev); + + break; + + case MOU_GETPTRPOS: /* Get Mouse Position */ + + if ((cbParmList != 0) || + (pvParmList != 0L) || + (cbData < sizeof(PTRLOC))) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(PTRLOC), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + +#if PMNT + if (ProcessIsPMProcess()) + { + RetCode = MouGetPtrPosPM((PPTRLOC)pvData); + } + else + RetCode = MouGetPtrPos((PPTRLOC)pvData, + (ULONG)hDev); +#else + RetCode = MouGetPtrPos((PPTRLOC)pvData, + (ULONG)hDev); +#endif // else of #if PMNT + + break; + + case MOU_GETPTRSHAPE: /* Get Mouse Shape */ + + if ((cbParmList < 10) || + (cbData < sizeof(PTRSHAPE))) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvParmList, cbParmList, 1); + Od2ProbeForWrite(pvData, sizeof(PTRSHAPE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouGetPtrShape((PBYTE)pvParmList, + (PPTRSHAPE)pvData, + (ULONG)hDev); + + break; + + case MOU_GETQUESTATUS: /* Get Queue Status */ + + if ((cbParmList != 0) || + (pvParmList != 0L) || + (cbData < sizeof(MOUQUEINFO))) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(MOUQUEINFO), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouGetNumQueEl((PMOUQUEINFO)pvData, + (ULONG)hDev); + + break; + + case MOU_GETSCALEFACTORS: /* Get Scaling Factor */ + + if ((cbParmList != 0) || + (pvParmList != 0L) || + (cbData < sizeof(SCALEFACT))) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForWrite(pvData, sizeof(SCALEFACT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouGetScaleFact((PSCALEFACT)pvData, + (ULONG)hDev); + + break; + + case MOU_READEVENTQUE: /* Read Event Queue */ + + if ((cbParmList < 2) || + (cbData < sizeof(MOUEVENTINFO))) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(USHORT), 1); + Od2ProbeForWrite(pvData, sizeof(MOUEVENTINFO), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouReadEventQue((PMOUEVENTINFO)pvData, + (PUSHORT)pvParmList, + (ULONG)hDev); + + break; + + case MOU_REMOVEPTR: /* Remove Ptr */ + + if ((cbData != 0) || + (pvData != 0L) || + (cbParmList < sizeof(NOPTRRECT))) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(NOPTRRECT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouRemovePtr((PNOPTRRECT)pvParmList, + (ULONG)hDev); + + break; + + case MOU_SCREENSWITCH: /* Screen Switch */ + + if ((cbParmList < sizeof(SCREENGROUP)) || + (cbData != 0) || + (pvData != 0L)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(SCREENGROUP), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouScreenSwitch((PBYTE)pvParmList, + (ULONG)hDev); + + break; + + case MOU_SETEVENTMASK: /* Set Evenet Mask */ + + if ((cbParmList < 2) || + (pvData != 0L) || + (cbData != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouSetEventMask((PUSHORT)pvParmList, + (ULONG)hDev); + + break; + + case MOU_SETHOTKEYBUTTON: /* Set Mouse Equivalent for the HotKey */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + case MOU_SETMOUSTATUS: /* Set Mouse Status */ + + if ((cbParmList < 2) || + (pvData != 0L) || + (cbData != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(USHORT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouSetDevStatus((PUSHORT)pvParmList, + (ULONG)hDev); + + break; + + case MOU_SETPROTDRAWADDRESS: /* Notified Mouse Device Drive Address */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + case MOU_SETPTRPOS: /* Set Mouse Position */ + + if ((cbParmList < sizeof(PTRLOC)) || + (pvData != 0L) || + (cbData != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(PTRLOC), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + +#if PMNT + if (ProcessIsPMProcess()) + { + RetCode = MouSetPtrPosPM((PPTRLOC)pvParmList); + } + else + RetCode = MouSetPtrPos((PPTRLOC)pvParmList, + (ULONG)hDev); +#else + RetCode = MouSetPtrPos((PPTRLOC)pvParmList, + (ULONG)hDev); +#endif // else of #if PMNT + + break; + + case MOU_SETPTRSHAPE: /* Set Mouse Shape */ + + if ((cbParmList < sizeof(PTRSHAPE)) || + (cbData < 10)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, cbParmList, 1); + Od2ProbeForRead(pvParmList, sizeof(PTRSHAPE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouSetPtrShape((PBYTE)pvParmList, + (PPTRSHAPE)pvData, + (ULONG)hDev); + + break; + + case MOU_SETREALDRAWADDRESS: /* Notified Mouse Device Drive Address */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + case MOU_SETSCALEFACTORS: /* Set Scaling Factor */ + + if ((cbParmList < sizeof(SCALEFACT)) || + (pvData != 0L) || + (cbData != 0)) + { + return ERROR_INVALID_PARAMETER; + } + + try + { + Od2ProbeForRead(pvParmList, sizeof(SCALEFACT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + RetCode = MouSetScaleFact((PSCALEFACT)pvParmList, + (ULONG)hDev); + + break; + + case MOU_UPDATEDISPLAYMODE: /* New Display Mode */ + +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + default: + +#if DBG + KdPrint((DosDevIOCtl2NotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_MONITOR: /* MON : Character-Monitor Control */ + if (IoVectorType != MonitorVectorType) + { +#if DBG + KdPrint(("DosDevIOCtl2: Category %d, Function 0x%x with non-Monitor(%d) type handle\n", + Category, Function, IoVectorType)); +#endif + RetCode = ERROR_BAD_COMMAND; + break; + } + + switch (Function) + { + case MON_REGISTERMONITOR: /* Register a Monitor */ + + try + { + Od2ProbeForRead(pvData, sizeof(MONITORPOSITION), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + if (cbData != sizeof(MONITORPOSITION)) + { + return ERROR_INVALID_PARAMETER; + } + + RetCode = DosMonReg((ULONG)hDev, + (PBYTE)((PMONITORPOSITION)pvData)->pbInBuf, + (PBYTE)((PMONITORPOSITION)pvData)->pbInBuf+ + ((PMONITORPOSITION)pvData)->offOutBuf, + (ULONG)(((PMONITORPOSITION)pvData)->fPosition), + (ULONG)(((PMONITORPOSITION)pvData)->index)); + break; + + default: + +#if DBG + KdPrint((DosDevIOCtl2NotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_GENERAL: /* DEV : General Device Control */ + switch (Function) + { + case DEV_FLUSHINPUT: + + try + { + Od2ProbeForRead(pvParmList, cbParmList, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + break; + + case DEV_FLUSHOUTPUT: /* flush the output buffer */ + + try + { + Od2ProbeForRead(pvParmList, cbParmList, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + NtFlushBuffersFile(NtHandle, &IoStatus); + break; + + case DEV_QUERYMONSUPPORT: /* query for monitor support */ + + if ((IoVectorType != MouseVectorType) && + (IoVectorType != KbdVectorType)) + { +#if DBG + KdPrint(("DosDevIOCtl2: Monitor Not supported for Device type %d\n", + IoVectorType)); +#endif + RetCode = ERROR_MONITORS_NOT_SUPPORTED; + break; + } + + try + { + Od2ProbeForRead(pvParmList, 1, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + + if (*(PBYTE)pvParmList != 0) + { + return ERROR_INVALID_PARAMETER; + } + + break; + + default: + +#if DBG + KdPrint((DosDevIOCtl2NotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + + case IOCTL_DISK: /* Disk/Diskette Control */ + + switch (Function) { + + case DSK_LOCKDRIVE: + case DSK_UNLOCKDRIVE: + + if (cbParmList < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForRead(pvParmList, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + + // + // Ignore pvParmList -- it's just a reserved value + // + + Status = NtFsControlFile( + NtHandle, + NULL, + NULL, + NULL, + &IoStatus, + (Function == DSK_LOCKDRIVE) ? + FSCTL_LOCK_VOLUME : + FSCTL_UNLOCK_VOLUME, + NULL, + 0L, + NULL, + 0L); + + if (!NT_SUCCESS(Status)) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- (UN)LOCKVOLUME, unable to NtFsControlFile, Status == %lx\n", + Status)); + } +#endif + RetCode = Or2MapNtStatusToOs2Error(Status, ERROR_BUSY_DRIVE); + break; + } + break; + + case DSK_SETLOGICALMAP: /* Set Logical Map */ + + if (cbData < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + *(PBYTE)pvData = 0; + break; + + case DSK_BLOCKREMOVABLE: /* Check if block Device is Removable */ + + if (cbData < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + // RetryIO() is not applied to DosDevIOCtl() + Status = NtQueryVolumeInformationFile(NtHandle, + &IoStatus, + &FsDeviceInfoBuffer, + sizeof(FsDeviceInfoBuffer), + FileFsDeviceInformation + ); + if (NT_SUCCESS(Status)) { + *(PBYTE)pvData = (FsDeviceInfoBuffer.Characteristics & FILE_REMOVABLE_MEDIA) ? 0 : 1; + } + else { + *(PBYTE)pvData = 1; /* Non Removable */ + } + break; + + case DSK_GETLOGICALMAP: /* Get Logical Map */ + + if (cbData < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForWrite(pvData, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + *(PBYTE)pvData = 0; + break; + + case DSK_GETDEVICEPARAMS: + + if (cbData < sizeof(BIOSPARAMETERBLOCK) || + cbParmList < 1) { + return(ERROR_INVALID_PARAMETER); + } + + try { + Od2ProbeForWrite(pvData, cbData, 1); + Od2ProbeForRead(pvParmList, cbParmList, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + + pBPB = (PBIOSPARAMETERBLOCK) pvData; + BpbRequestType = (ULONG) (*(PBYTE) pvParmList); + + // + // BpbRequestType is a byte designating: + // 0 - return recommended BPB for the drive type + // 1 - return current BPB for the media + // + + RetCode = Od2IdentifyDiskDrive( + NtHandle, + pDriveNumberPermanentStorageLocation, + &DriveNumber); + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- GETDEVICEPARAMS, unable to Od2IdentifyDiskDrive, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + + if (BpbRequestType & 0x1) { + + RetCode = Od2AcquireMediaBPB( + DriveNumber, + NtHandle, + TRUE, + TRUE, + FALSE, + pBPB, + NULL, + NULL); + } else { + + RetCode = Od2AcquireDeviceBPB( + DriveNumber, + NtHandle, + TRUE, + TRUE, + pBPB); + } + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- GETDEVICEPARAMS, unable to Od2AcquireBPB, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + + break; + + case DSK_SETDEVICEPARAMS: + + if (cbData < sizeof(BIOSPARAMETERBLOCK) || + cbParmList < 1) { + return(ERROR_INVALID_PARAMETER); + } + + try { + Od2ProbeForRead(pvData, cbData, 1); + Od2ProbeForRead(pvParmList, cbParmList, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + + pBPB = (PBIOSPARAMETERBLOCK) pvData; + BpbRequestType = (ULONG) (*(PBYTE) pvParmList); + + RetCode = Od2IdentifyDiskDrive( + NtHandle, + pDriveNumberPermanentStorageLocation, + &DriveNumber); + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- SETDEVICEPARAMS, unable to Od2IdentifyDiskDrive, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + + switch (BpbRequestType) { + + case BUILD_BPB_FROM_MEDIUM: + + RetCode = Od2AcquireMediaBPB( + DriveNumber, + NtHandle, + FALSE, + TRUE, + FALSE, + NULL, + NULL, + NULL); + break; + + case REPLACE_BPB_FOR_DEVICE: + + RetCode = Od2AcquireDeviceBPB( + DriveNumber, + NtHandle, + FALSE, + FALSE, + pBPB); + break; + + case REPLACE_BPB_FOR_MEDIUM: + + RetCode = Od2AcquireMediaBPB( + DriveNumber, + NtHandle, + FALSE, + FALSE, + FALSE, + pBPB, + NULL, + NULL); + break; + + default: + + RetCode = ERROR_INVALID_PARAMETER; + break; + } + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- SETDEVICEPARAMS, unable to Od2AcquireBPB, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + break; + + case DSK_READTRACK: + case DSK_WRITETRACK: + case DSK_VERIFYTRACK: + + if (cbParmList < sizeof(TRACKLAYOUT)) { + return(ERROR_INVALID_PARAMETER); + } + + try { + Od2ProbeForRead(pvParmList, cbParmList, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + + TrackLayout = (PTRACKLAYOUT) pvParmList; + + { + ULONG l = (ULONG) TrackLayout->usFirstSector + (ULONG) TrackLayout->cSectors; + + if (l > 1 && (cbParmList < sizeof(TRACKLAYOUT) + (l-1) * 2 * sizeof(USHORT))) { + return(ERROR_INVALID_PARAMETER); + } + } + + RetCode = Od2IdentifyDiskDrive( + NtHandle, + pDriveNumberPermanentStorageLocation, + &DriveNumber); + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- READWRITEVERIFYTRACK, unable to Od2IdentifyDiskDrive, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + + RetCode = Od2AcquireMediaBPB( + DriveNumber, + NtHandle, + TRUE, + TRUE, + FALSE, + &PrivateBpb, + &PrivateMediaType, + &PrivateTrueGeometry); + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- READWRITEVERIFYTRACK, unable to Od2AcquireMediaBPB, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + + if (PrivateMediaType == Unknown || + PrivateMediaType == RemovableMedia || + PrivateMediaType == FixedMedia) { + + RetCode = ERROR_INVALID_DRIVE; + break; + } + + CountSectors = (ULONG) TrackLayout->cSectors; + + if (CountSectors > (ULONG) PrivateBpb.usSectorsPerTrack) { + + RetCode = ERROR_SECTOR_NOT_FOUND; + break; + } + + if (Function != DSK_VERIFYTRACK) { + + if (cbData != 0) { + + if (cbData < CountSectors * (ULONG) PrivateBpb.usBytesPerSector) { + RetCode = ERROR_INVALID_PARAMETER; + break; + } + + } else { + cbData = CountSectors * (ULONG) PrivateBpb.usBytesPerSector; + } + + try { + if (Function == DSK_READTRACK) { + Od2ProbeForWrite(pvData, cbData, 1); + } else { + Od2ProbeForRead(pvData, cbData, 1); + } + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + } + + { + ULONG i, j; + + for (i = 0, j = (ULONG) TrackLayout->usFirstSector; + i < CountSectors; + i++, j++) { + + if ((ULONG) (TrackLayout->TrackTable[j].usSectorSize) != + (ULONG) PrivateBpb.usBytesPerSector) { + + return(ERROR_BAD_LENGTH); + } + } + } + + switch (Function) { + case DSK_READTRACK: + DiskCommand = READ_TRACK_CMD; + break; + case DSK_WRITETRACK: + DiskCommand = WRITE_TRACK_CMD; + break; + case DSK_VERIFYTRACK: + DiskCommand = VERIFY_TRACK_CMD; + break; + } + + RetCode = Od2ReadWriteVerifyTrack( + NtHandle, + DiskCommand, + TrackLayout, + pvData, + CountSectors, + &PrivateBpb, + &PrivateTrueGeometry); + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- Od2ReadWriteVerifyTrack failed, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + + break; + + case DSK_FORMATVERIFY: + + if (cbParmList < sizeof(TRACKFORMAT)) { + return(ERROR_INVALID_PARAMETER); + } + + try { + Od2ProbeForRead(pvParmList, cbParmList, 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + + TrackFormat = (PTRACKFORMAT) pvParmList; + + { + ULONG l = (ULONG) TrackFormat->cSectors; + + if (l > 1 && (cbParmList < sizeof(TRACKFORMAT) + (l-1) * 4 * sizeof(BYTE))) { + return(ERROR_INVALID_PARAMETER); + } + } + + if (TrackFormat->bCommand != 1) { + + // + // We only support a standard track format command + // (since that's what NT supports...) + // + + return(ERROR_NOT_SUPPORTED); + } + + RetCode = Od2IdentifyDiskDrive( + NtHandle, + pDriveNumberPermanentStorageLocation, + &DriveNumber); + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- FORMATVERIFY, unable to Od2IdentifyDiskDrive, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + + RetCode = Od2AcquireMediaBPB( + DriveNumber, + NtHandle, + TRUE, + TRUE, + TRUE, + &PrivateBpb, + &PrivateMediaType, + NULL); + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- FORMATVERIFY, unable to Od2AcquireMediaBPB, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + + if (PrivateMediaType == Unknown || + PrivateMediaType == RemovableMedia || + PrivateMediaType == FixedMedia) { + + RetCode = ERROR_INVALID_DRIVE; + break; + } + + CountSectors = (ULONG) TrackFormat->cSectors; + + FormatSectorSizeType = TrackFormat->FormatTable[0].bBytesSector; + + { + ULONG i; + + for (i = 1; + i < CountSectors; + i++) { + + if (TrackFormat->FormatTable[i].bBytesSector != + FormatSectorSizeType) { + + return(ERROR_NOT_SUPPORTED); + } + } + } + + RetCode = Od2FormatTrack( + NtHandle, + TrackFormat, + CountSectors, + FormatSectorSizeType, + &PrivateBpb, + PrivateMediaType); + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- Od2FormatTrack failed, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + + break; + + case 0x4: + + // + // This is an undocumented IOCTL that DSKIMAGE uses. Apparently it + // has something to do with mounting an FSD, whatever that means. + // Anyway, I don't think we need to do anything, so we return success. + // + +#if DBG + KdPrint(("DosDevIOCtl[2]: Category %d, Function 0x%x Not implemented. Returning NO_ERROR\n", Category, Function)); +#endif + break; + + case DSK_REDETERMINEMEDIA: + + if (cbParmList < sizeof(BYTE)) { + return ERROR_INVALID_PARAMETER; + } + try { + Od2ProbeForRead(pvParmList, sizeof(BYTE), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + + // + // Ignore pvParmList -- it's just a reserved value + // + + RetCode = Od2IdentifyDiskDrive( + NtHandle, + pDriveNumberPermanentStorageLocation, + &DriveNumber); + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- REDETERMINEMEDIA, unable to Od2IdentifyDiskDrive, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + + RetCode = Od2AcquireMediaBPB( + DriveNumber, + NtHandle, + FALSE, + TRUE, + FALSE, + NULL, + NULL, + NULL); + + + if (RetCode != NO_ERROR) { +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DevDevIoCtl2() -- REDETERMINEMEDIA, unable to Od2AcquireMediaBPB, RetCode == %lx\n", + RetCode)); + } +#endif + break; + } + break; + + default: +#if DBG + KdPrint((DosDevIOCtl2NotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + + default: + // Check for User defined categories + if ((Category >= 0x80) && (Category <= 0xff)) { +#if DBG + KdPrint(("DosDevIOCtl2: User Category %d, Function 0x%x was called\n", Category, Function)); +#endif + Status = NtDeviceIoControlFile( NtHandle, + 0, + NULL, + NULL, + &IoStatus, + CTL_CODE(Category|0x8000,Function|0x800,METHOD_BUFFERED,FILE_ANY_ACCESS), + pvParmList, + cbParmList, + pvData, + cbData + ); + if (!NT_SUCCESS(Status)) { + RetCode = ERROR_PROTECTION_VIOLATION; + } + } + else { +#if DBG + KdPrint((DosDevIOCtl2NotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_CATEGORY; + } + break; + } + + if (ComSetOnlyFunction) { + Status = NtDeviceIoControlFile( NtHandle, + ComIOCtlEvent, + NULL, + NULL, + &IoStatus, + IoControlCode, + Io, + IoCtlParamLength, + IoOutputBuffer, + IoOutputBufferLength + ); + + // Wait and Set the value at RetCode only + + ErrorAtWaitForAsyncComIOCtl(Status, ComIOCtlEvent, &RetCode); + } + else if (SetOnlyFunction) { + Status = NtDeviceIoControlFile( NtHandle, + NULL, + NULL, + NULL, + &IoStatus, + IoControlCode, + Io, + IoCtlParamLength, + IoOutputBuffer, + IoOutputBufferLength + ); + if (!NT_SUCCESS(Status)) { + RetCode = ERROR_PROTECTION_VIOLATION; + } + } + +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("Exit from DosDevIOCtl[2](), retcode = %d\n", RetCode)); + } +#endif + + return(RetCode); +} + +APIRET +DosDevIOCtl( + PVOID pvData, + PVOID pvParmList, + ULONG Function, + ULONG Category, + HFILE hDev + ) +{ + APIRET RetCode = NO_ERROR; + PVOID pData; + ULONG cbData; + PVOID pParmList; + ULONG cbParmList; + + #if DBG + PSZ RoutineName; + RoutineName = "DosDevIOCtl"; + #endif + + // + // The following line is necessary because OS/2 ignores the high + // byte of Category + // + + Category &= 0xffL; + + pData = pvData; + pParmList = pvParmList; + + switch (Category) { + case IOCTL_ASYNC: /* Serial Device Control */ + + switch (Function) { + + case ASYNC_SETBAUDRATE: /* Set Baud Rate */ + + pData = NULL; + cbData = 0; + cbParmList = sizeof(SERIAL_BAUD_RATE); + break; + + case ASYNC_SETLINECTRL: /* Set Line Control */ + + pData = NULL; + cbData = 0; + cbParmList = 3; + break; + + case ASYNC_TRANSMITIMM: /* Transmit Immediate Char */ + + pData = NULL; + cbData = 0; + cbParmList = 1; + break; + + case ASYNC_SETBREAKOFF: /* Set Break Off */ + + case ASYNC_SETBREAKON: /* Set Break On */ + + cbData = sizeof(USHORT); + pParmList = NULL; + cbParmList = 0; + break; + + case ASYNC_SETMODEMCTRL: /* Set Modem Control Signals */ + + cbData = sizeof(USHORT); + cbParmList = 2; /* sizeof(MODEMSTATUS) */ + break; + + case ASYNC_STOPTRANSMIT: /* Stop Tarnsmit */ + + cbData = 0; + cbParmList = 0; + break; + + case ASYNC_STARTTRANSMIT: /* Start Transmit */ + + cbData = 0; + cbParmList = 0; + break; + + case ASYNC_GETBAUDRATE: /* Get Baud Rate */ + + cbData = sizeof(USHORT); + cbParmList = 0; + break; + + case ASYNC_GETLINECTRL: /* Get Line Control */ + + cbData = 4; + cbParmList = 0; + break; + + case ASYNC_GETCOMMSTATUS: /* Get Comm Status */ + + cbData = sizeof(BYTE); + cbParmList = 0; + break; + + case ASYNC_GETCOMMERROR: /* Get COM Error Word */ + + cbData = sizeof(USHORT); + cbParmList = 0; + break; + + case ASYNC_GETCOMMEVENT: /* Get COM Event Information */ + + cbData = sizeof(USHORT); + cbParmList = 0; + break; + + case ASYNC_SETDCBINFO: /* Set Device Control Block */ + + cbData = 0; + cbParmList = sizeof(DCBINFO); + break; + + case ASYNC_GETDCBINFO: /* Get Device Control Block */ + + cbData = sizeof(DCBINFO); + cbParmList = 0; + break; + + case ASYNC_GETINQUECOUNT: /* Get Receive Queue Characters */ + + case ASYNC_GETOUTQUECOUNT: /* Get Transmit Queue Characters */ + + cbData = sizeof(RXQUEUE); + cbParmList = 0; + break; + + case ASYNC_GETMODEMINPUT: /* Get Modem Input */ + + case ASYNC_GETLINESTATUS: /* Get Line Status */ + + case ASYNC_GETMODEMOUTPUT: /* Get Modem Output */ + + cbData = sizeof(BYTE); + cbParmList = 0; + break; + + default: + +#if DBG + KdPrint((DosDevIOCtlNotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_PRINTER: /* Printer Device Control */ + + switch (Function) { + + case PRT_SETFRAMECTL: /* Set Frame Control */ + + case PRT_GETFRAMECTL: /* Get Frame Control */ + + cbData = sizeof(FRAME); + cbParmList = 1; + break; + + case PRT_INITPRINTER: /* Init Printer */ + + cbData = 0; + cbParmList = 1; + break; + + case PRT_SETINFINITERETRY: /* Set Infinite Retry */ + + case PRT_GETINFINITERETRY: /* Get Infinite Retry */ + + case PRT_GETPRINTERSTATUS: /* Get Printer Status */ + + cbData = 1; + cbParmList = 1; + break; + + case PRT_ACTIVATEFONT: /* Activate Font */ + + case PRT_QUERYACTIVEFONT: /* Query Active Font */ + + case PRT_VERIFYFONT: /* Verify Font */ + +#if DBG + KdPrint((DosDevIOCtlNotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + + default: + +#if DBG + KdPrint((DosDevIOCtlNotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_SCR_AND_PTRDRAW: /* PTR : Screen/Pointer-Draw Control */ + switch (Function) + { + case PTR_GETPTRDRAWADDRESS: /* retrives entry-point address for the pointer-draw function */ + + cbData = sizeof(PTRDRAWFUNCTION); + cbParmList = 0; + break; + + default: + +#if DBG + KdPrint((DosDevIOCtlNotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_KEYBOARD: /* KBD : Keyboard Control */ + switch (Function) + { + case KBD_CREATE: /* Create Logical Keyboard */ + + cbData = 0; + cbParmList = 4; // BUGBUG ?? + break; + + case KBD_DESTROY: /* Free Logical Keyboard */ + + cbData = 0; + cbParmList = 2; // BUGBUG ?? + break; + + case KBD_GETCODEPAGEID: /* Get Code Page */ + + cbData = sizeof(CPID); + cbParmList = 0; + break; + + case KBD_GETINPUTMODE: /* Get Input Mode */ + + case KBD_GETINTERIMFLAG: /* Get Interim Flag */ + + cbData = 1; + cbParmList = 0; + break; + + case KBD_GETKEYBDTYPE: /* Get Keyboard Type */ + + cbData = sizeof(KBDTYPE); + cbParmList = 0; + break; + + case KBD_GETSESMGRHOTKEY: /* Get Hot-Key Info */ + + cbData = sizeof(HOTKEY); + cbParmList = 2; + break; + + case KBD_GETSHIFTSTATE: /* Get Shift State */ + + cbData = sizeof(SHIFTSTATE); + cbParmList = 0; + break; + + case KBD_PEEKCHAR: /* Peek Character Data Record */ + + cbData = sizeof(KBDKEYINFO); + cbParmList = 2; + break; + + case KBD_READCHAR: /* Read Character Data Record */ + + cbData = sizeof(KBDKEYINFO) * (*((PUSHORT) pvParmList) & 0x7FFF); + cbParmList = 2; + break; + + case KBD_SETFGNDSCREENGRP: /* Set Foreground Screen Group */ + + cbData = 0; + cbParmList = sizeof(SCREENGROUP); + break; + + case KBD_SETFOCUS: /* Set Keyboard Focus */ + + case KBD_SETKCB: /* Bind Logical Keyboard to the Physical */ + + cbData = 0; + cbParmList = 2; // BUGBUG for 16-bits handle only (except Interim) + break; + + case KBD_SETINPUTMODE: /* Set Input Mode */ + + case KBD_SETINTERIMFLAG: /* Set Interim Flag */ + + cbData = 0; + cbParmList = 1; + break; + + case KBD_SETNLS: /* Install Code Page */ + + cbData = 0; + cbParmList = sizeof(CODEPAGEINFO); + break; + + case KBD_SETSESMGRHOTKEY: /* Set New Hot-Key Info */ + + cbData = 0; + cbParmList = sizeof(HOTKEY); + break; + + case KBD_SETSHIFTSTATE: /* Set Shift State */ + + cbData = 0; + cbParmList = sizeof(SHIFTSTATE); + break; + + case KBD_SETTRANSTABLE: /* Set Translation Table */ + + cbData = 0; + cbParmList = 256; // BUGBUG-check + break; + + case KBD_SETTYPAMATICRATE: /* Set Keyboard Typamatic Rate */ + + cbData = 0; + cbParmList = sizeof(RATEDELAY); + break; + + case KBD_XLATESCAN: /* Translate Scan Code */ + + cbData = sizeof(KBDTRANS); + cbParmList = 2; + break; + +#if PMNT + // Called by InitKeyboard(), PMWIN + case KBD_GETHARDWAREID: + try + { + cbData = *(USHORT *)pvData; + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + cbParmList = 0; + break; + + // Called by InitKeyboard(), PMWIN + case KBD_GETCPANDCOUNTRY: + try + { + cbData = *(USHORT *)pvData; + } except( EXCEPTION_EXECUTE_HANDLER ) + { + Od2ExitGP(); + } + cbParmList = 0; + break; +#endif // PMNT + default: + +#if DBG + KdPrint((DosDevIOCtlNotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_POINTINGDEVICE: /* MOU : Pointing-Device (Mouse) Control */ + switch (Function) + { + case MOU_ALLOWPTRDRAW: /* Allow Ptr Draw */ + + case MOU_DRAWPTR: /* Draw Ptr Anywhere */ + + cbData = 0; + cbParmList = 0; + break; + + case MOU_GETBUTTONCOUNT: /* Get Button Number */ + + case MOU_GETEVENTMASK: /* Get Event Mask */ + + case MOU_GETHOTKEYBUTTON: /* Get Mouse Equivalent for the HotKey */ + + case MOU_GETMICKEYCOUNT: /* Get Count of Mickeys per Centimeter */ + + case MOU_GETMOUSTATUS: /* Get Mouse Status */ + + cbData = 2; + cbParmList = 0; +#if PMNT + pParmList = NULL; +#endif + break; + + case MOU_GETPTRPOS: /* Get Mouse Position */ + + cbData = sizeof(PTRLOC); + cbParmList = 0; + break; + + case MOU_GETPTRSHAPE: /* Get Mouse Shape */ + + cbData = sizeof(PTRSHAPE); + cbParmList = 200; // BUGBUG ?? + break; + + case MOU_GETQUESTATUS: /* Get Queue Status */ + + cbData = sizeof(MOUQUEINFO); + cbParmList = 0; + break; + + case MOU_GETSCALEFACTORS: /* Get Scaling Factor */ + + cbData = sizeof(SCALEFACT); + cbParmList = 0; + break; + + case MOU_READEVENTQUE: /* Read Event Queue */ + + cbData = sizeof(MOUEVENTINFO); + cbParmList = 2; + break; + + case MOU_REMOVEPTR: /* Remove Ptr */ + + cbData = 0; + cbParmList = sizeof(NOPTRRECT); + break; + + case MOU_SCREENSWITCH: /* Screen Switch */ + + cbData = 0; + cbParmList = sizeof(SCREENGROUP); + break; + + case MOU_SETEVENTMASK: /* Set Evenet Mask */ + + case MOU_SETHOTKEYBUTTON: /* Set Mouse Equivalent for the HotKey */ + + case MOU_SETMOUSTATUS: /* Set Mouse Status */ + + cbData = 0; + cbParmList = 2; + break; + + case MOU_SETPROTDRAWADDRESS: /* Notified Mouse Device Drive Address */ + + cbData = 0; + cbParmList = sizeof(PTRDRAWFUNCTION); + break; + + case MOU_SETPTRPOS: /* Set Mouse Position */ + + cbData = 0; + cbParmList = sizeof(PTRLOC); + break; + + case MOU_SETPTRSHAPE: /* Set Mouse Shape */ + + cbData = 200; // BUGBUG ?? + cbParmList = sizeof(PTRSHAPE); + break; + + case MOU_SETREALDRAWADDRESS: /* Notified Mouse Device Drive Address */ + + cbData = 0; + cbParmList = sizeof(PTRDRAWFUNCTION); + break; + + case MOU_SETSCALEFACTORS: /* Set Scaling Factor */ + + cbData = 0; + cbParmList = sizeof(SCALEFACT); + break; + + case MOU_UPDATEDISPLAYMODE: /* New Display Mode */ + + cbData = 0; + cbParmList = sizeof(VIOMODEINFO); + break; + + default: + +#if DBG + KdPrint((DosDevIOCtlNotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_MONITOR: /* MON : Character-Monitor Control */ + switch (Function) + { + case MON_REGISTERMONITOR: /* Register a Monitor */ + + cbData = sizeof(MONITORPOSITION); + cbParmList = 1; + break; + + default: + +#if DBG + KdPrint((DosDevIOCtlNotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_GENERAL: /* DEV : General Device Control */ + switch (Function) + { + case DEV_FLUSHINPUT: /* flush the input buffer */ + case DEV_FLUSHOUTPUT: /* flush the output buffer */ + case DEV_QUERYMONSUPPORT: /* query for monitor support */ + + cbData = 0; + cbParmList = 1; + break; + + default: + +#if DBG + KdPrint((DosDevIOCtlNotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + case IOCTL_DISK: /* Disk/Diskette Control */ + + switch (Function) { + + case DSK_LOCKDRIVE: /* Lock a drive */ + case DSK_UNLOCKDRIVE: /* Unlock a drive */ + + cbData = 0; + cbParmList = 1; + break; + + case DSK_SETLOGICALMAP: /* Set Logical Map */ + + cbData = 1; + cbParmList = 1; + break; + + case DSK_BLOCKREMOVABLE: + + cbData = 1; + cbParmList = 1; + break; + + case DSK_GETLOGICALMAP: + + cbData = 1; + cbParmList = 1; + break; + + case DSK_GETDEVICEPARAMS: + + cbData = sizeof(BIOSPARAMETERBLOCK); + cbParmList = 1; + break; + + case DSK_SETDEVICEPARAMS: + + cbData = sizeof(BIOSPARAMETERBLOCK); + cbParmList = 1; + break; + + case DSK_READTRACK: + case DSK_WRITETRACK: + case DSK_VERIFYTRACK: + + try { + Od2ProbeForRead(pvParmList, sizeof(TRACKLAYOUT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + + { + PTRACKLAYOUT TL = (PTRACKLAYOUT) pvParmList; + ULONG l = (ULONG) TL->usFirstSector + (ULONG) TL->cSectors; + + cbParmList = sizeof(*TL) + + ((l > 1) ? + ((l - 1) * 2 * sizeof(USHORT)) : + 0); + } + + cbData = 0; // bogus -- will be computed later + + break; + + case DSK_FORMATVERIFY: + + try { + Od2ProbeForRead(pvParmList, sizeof(TRACKFORMAT), 1); + } except( EXCEPTION_EXECUTE_HANDLER ) { + Od2ExitGP(); + } + + { + PTRACKFORMAT TF = (PTRACKFORMAT) pvParmList; + ULONG l = (ULONG) TF->cSectors; + + cbParmList = sizeof(*TF) + + ((l > 1) ? + ((l - 1) * 4 * sizeof(BYTE)) : + 0); + } + + cbData = 0; + + break; + + case DSK_REDETERMINEMEDIA: + + cbData = 0; + cbParmList = 1; + break; + + + case 0x4: + + cbParmList = 0; + cbData = 0; + break; + + default: +#if DBG + KdPrint((DosDevIOCtlNotValidStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_FUNCTION; + break; + } + break; + + default: + // Check for User defined categories + if ((Category >= 0x80) && (Category <= 0xff)) { + cbData = 0; + cbParmList = 0; + break; + } + else { +#if DBG + KdPrint((DosDevIOCtlNotImplementedYetStr, Category, Function)); +#endif + RetCode = ERROR_INVALID_CATEGORY; + } + break; + } + + if (RetCode == NO_ERROR) { + RetCode = DosDevIOCtl2(pData, cbData, pParmList, cbParmList, Function, Category, hDev); + } + +#if DBG + IF_OD2_DEBUG( FILESYS ) { + KdPrint(("DosDevIOCtl: Returned from DosDevIOCtl2(), retcode = %d\n", RetCode)); + } +#endif + + return(RetCode); +} + |