/*++ 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 #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); }