📄 ioctl.c
字号:
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Module Name:
ioctl.c
Abstract:
This is the ioctl handler for the fakemodem.
Environment:
Kernel mode
Revision History:
Nar Ganapathy - Sept 19, 2003
--*/
#include "fakemodem.h"
VOID
FmEvtIoDeviceControl(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength,
IN ULONG IoControlCode
)
/*++
Routine Description:
This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
requests from the system.
Arguments:
Queue - Handle to the framework queue object that is associated
with the I/O request.
Request - Handle to a framework request object.
OutputBufferLength - length of the request's output buffer,
if an output buffer is available.
InputBufferLength - length of the request's input buffer,
if an input buffer is available.
IoControlCode - the driver-defined or system-defined I/O control code
(IOCTL) that is associated with the request.
Return Value:
VOID
--*/
{
PFM_DEVICE_DATA fmDeviceData = FmDeviceDataGet(WdfIoQueueGetDevice(Queue));
NTSTATUS status ;
PVOID requestBuffer;
ULONG information = 0;
size_t bufSize;
UNREFERENCED_PARAMETER(OutputBufferLength);
UNREFERENCED_PARAMETER(InputBufferLength);
status = STATUS_SUCCESS;
switch (IoControlCode) {
case IOCTL_SERIAL_GET_WAIT_MASK: {
status = WdfRequestRetrieveOutputBuffer ( Request,
sizeof(ULONG),
&requestBuffer,
&bufSize );
if( !NT_SUCCESS(status) ) {
KdPrint(( "Could not get request memory buffer status %X\n", status));
information = 0;
break;
}
*((PULONG)requestBuffer)= fmDeviceData->CurrentMask;
information = sizeof(ULONG);
break;
}
case IOCTL_SERIAL_SET_WAIT_MASK: {
WDFREQUEST currentWaitRequest=NULL;
ULONG newMask;
status = WdfRequestRetrieveInputBuffer (Request,
sizeof(ULONG),
&requestBuffer,
&bufSize );
if( !NT_SUCCESS(status) ) {
KdPrint(("Could not get request memory buffer status %X\n", status));
information = 0;
break;
}
else {
NTSTATUS tempStatus;
//
// get rid of the current wait
//
newMask = *((ULONG *)requestBuffer);
fmDeviceData->CurrentMask = newMask;
KdPrint(("FAKEMODEM: set wait mask, %08lx\n", newMask));
tempStatus = WdfIoQueueRetrieveNextRequest(fmDeviceData->FmMaskWaitQueue,
¤tWaitRequest);
// save the new mask
if (NT_SUCCESS(tempStatus)) {//currentWaitRequest != NULL) {
PULONG outBuffer;
KdPrint(("FAKEMODEM: set wait mask- complete wait\n"));
//
// The length was validated already.
//
tempStatus = WdfRequestRetrieveOutputBuffer(currentWaitRequest,
sizeof(ULONG),
&outBuffer,
&bufSize);
ASSERT(NT_SUCCESS(tempStatus));
if (outBuffer) { // FIXME SAL
*outBuffer = 0;
}
WdfRequestCompleteWithInformation(currentWaitRequest,
STATUS_SUCCESS,
sizeof(ULONG));
}
information = sizeof(ULONG);
}
break;
}
case IOCTL_SERIAL_WAIT_ON_MASK: {
WDFREQUEST currentWaitRequest = NULL;
NTSTATUS tempStatus;
status = WdfRequestRetrieveOutputBuffer (Request,
sizeof(ULONG),
&requestBuffer,
&bufSize );
if( !NT_SUCCESS(status) ) {
KdPrint(("Could not get request memory buffer status %X\n", status));
information = 0;
status = STATUS_BUFFER_TOO_SMALL;
break;
}
KdPrint(("FAKEMODEM: wait on mask\n"));
//
// remove the current request if any
//
tempStatus = WdfIoQueueRetrieveNextRequest(fmDeviceData->FmMaskWaitQueue,
¤tWaitRequest);
if (NT_SUCCESS(tempStatus)) { //currentWaitRequest != NULL) {
PULONG outBuffer;
KdPrint(("FAKEMODEM: wait on mask- complete wait\n"));
//
// The length was validated already.
//
tempStatus = WdfRequestRetrieveOutputBuffer(currentWaitRequest,
sizeof(ULONG),
&outBuffer,
&bufSize);
ASSERT(NT_SUCCESS(tempStatus));
if (outBuffer) { // FIXME SAL
*((PULONG)outBuffer) = 0;
}
WdfRequestCompleteWithInformation(currentWaitRequest,
STATUS_SUCCESS,
sizeof(ULONG));
}
if (fmDeviceData->CurrentMask == 0) {
//
// can only set if mask is not zero
//
status=STATUS_UNSUCCESSFUL;
} else {
//
// add the current request to the wait queue
//
status = WdfRequestForwardToIoQueue(Request, fmDeviceData->FmMaskWaitQueue);
if (!NT_SUCCESS(status)) {
WdfRequestCompleteWithInformation(Request, STATUS_UNSUCCESSFUL, 0);
return;
}
status=STATUS_PENDING;
}
break;
}
case IOCTL_SERIAL_PURGE: {
ULONG mask;
status = WdfRequestRetrieveInputBuffer (Request,
sizeof(ULONG),
&requestBuffer,
&bufSize );
if( !NT_SUCCESS(status) ) {
KdPrint(("Could not get request memory buffer status %X\n", status));
information = 0;
break;
}
mask=*((PULONG)requestBuffer);
if (mask & SERIAL_PURGE_RXABORT) {
WdfIoQueuePurge( fmDeviceData->FmReadQueue,
WDF_NO_EVENT_CALLBACK,
WDF_NO_CONTEXT );
WdfIoQueueStart(fmDeviceData->FmReadQueue);
}
information = sizeof(ULONG);
break;
}
case IOCTL_SERIAL_GET_MODEMSTATUS: {
status = WdfRequestRetrieveOutputBuffer ( Request,
sizeof(ULONG),
&requestBuffer,
&bufSize );
if( !NT_SUCCESS(status) ) {
KdPrint(( "Could not get request memory buffer status %X\n", status));
information = 0;
break;
}
information = sizeof(ULONG);
*((PULONG)requestBuffer) = fmDeviceData->ModemStatus;
break;
}
case IOCTL_SERIAL_SET_TIMEOUTS: {
PSERIAL_TIMEOUTS NewTimeouts;
status = WdfRequestRetrieveInputBuffer (Request,
sizeof(SERIAL_TIMEOUTS),
&requestBuffer,
&bufSize );
if( !NT_SUCCESS(status) ) {
KdPrint(("Could not get request memory buffer status %X\n", status));
information = 0;
break;
}
NewTimeouts= ((PSERIAL_TIMEOUTS)(requestBuffer));
if ((NewTimeouts->ReadIntervalTimeout == MAXULONG) &&
(NewTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) &&
(NewTimeouts->ReadTotalTimeoutConstant == MAXULONG))
{
status = STATUS_INVALID_PARAMETER;
break;
}
information = sizeof(SERIAL_TIMEOUTS);
break;
}
case IOCTL_SERIAL_GET_TIMEOUTS: {
status = WdfRequestRetrieveOutputBuffer ( Request,
sizeof(SERIAL_TIMEOUTS),
&requestBuffer,
&bufSize );
if( !NT_SUCCESS(status) ) {
KdPrint(( "Could not get request memory buffer status %X\n", status));
information = 0;
break;
}
*((PSERIAL_TIMEOUTS)requestBuffer) =
fmDeviceData->CurrentTimeouts;
information = sizeof(SERIAL_TIMEOUTS);
break;
}
case IOCTL_SERIAL_GET_COMMSTATUS: {
PSERIAL_STATUS serialStatus ;
status = WdfRequestRetrieveOutputBuffer ( Request,
sizeof(SERIAL_STATUS),
&requestBuffer,
&bufSize );
if( !NT_SUCCESS(status) ) {
KdPrint(( "Could not get request memory buffer status %X\n", status));
information = 0;
break;
}
serialStatus = (PSERIAL_STATUS) requestBuffer;
RtlZeroMemory( serialStatus, sizeof(*serialStatus) ); // FIXME SAL
serialStatus->AmountInInQueue = fmDeviceData->BytesInReadBuffer;
information = sizeof(SERIAL_STATUS);
break;
}
case IOCTL_SERIAL_SET_DTR:
case IOCTL_SERIAL_CLR_DTR: {
if (IoControlCode == IOCTL_SERIAL_SET_DTR) {
//
// raising DTR
//
fmDeviceData->ModemStatus=SERIAL_DTR_STATE | SERIAL_DSR_STATE;
KdPrint(("FAKEMODEM: Set DTR\n"));
} else {
//
// dropping DTR, drop connection if there is one
//
KdPrint(("FAKEMODEM: Clear DTR\n"));
if (fmDeviceData->CurrentlyConnected == TRUE) {
//
// not connected any more
//
fmDeviceData->CurrentlyConnected=FALSE;
fmDeviceData->ConnectionStateChanged=TRUE;
}
}
ProcessConnectionStateChange( fmDeviceData);
information = sizeof(ULONG);
break;
}
case IOCTL_SERIAL_SET_QUEUE_SIZE: {
status = WdfRequestRetrieveInputBuffer (Request,
sizeof(SERIAL_QUEUE_SIZE),
&requestBuffer,
&bufSize );
if( !NT_SUCCESS(status) ) {
KdPrint(("Could not get request memory buffer status %X\n", status));
information = 0;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -