mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3792 lines
132 KiB
3792 lines
132 KiB
/*++
|
|
|
|
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);
|
|
}
|
|
|