|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
dispatch.c
Abstract:
This module contains the dispatch routines for ws2ifsl.sys driver
Author:
Vadim Eydelman (VadimE) Dec-1996
Revision History: Vadim Eydelman (VadimE) Oct-1997, rewrite to properly handle IRP cancellation
--*/
#include "precomp.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, DispatchCreate)
#pragma alloc_text (PAGE, DispatchCleanup)
#pragma alloc_text (PAGE, DispatchClose)
#pragma alloc_text (PAGE, DispatchReadWrite)
#pragma alloc_text (PAGE, DispatchDeviceControl)
#pragma alloc_text (PAGE, FastIoDeviceControl)
#endif
NTSTATUS DispatchCreate ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++
Routine Description:
This routine is called as the result of a request to create a file associated with WS2IFSL driver device object.
Arguments:
DeviceObject - WS2IFSL device object Irp - create Irp
Return Value:
STATUS_SUCCESS - requested file object can be created STATUS_INVALID_PARAMETER - required extened attribute is missing or invalid STATUS_INSUFFICIENT_RESOURCES - not enough resources to complete this request
--*/ { NTSTATUS status; PIO_STACK_LOCATION irpSp; PFILE_FULL_EA_INFORMATION eaBuffer;
PAGED_CODE ();
// Get extended attribute buffer which identifies the
// type of file that should be created.
eaBuffer = Irp->AssociatedIrp.SystemBuffer; if (eaBuffer!=NULL) { irpSp = IoGetCurrentIrpStackLocation (Irp); if ((eaBuffer->EaNameLength==WS2IFSL_SOCKET_EA_NAME_LENGTH) && (strcmp (eaBuffer->EaName, WS2IFSL_SOCKET_EA_NAME)==0)) { // This is the request to create socket file
status = CreateSocketFile (irpSp->FileObject, Irp->RequestorMode, eaBuffer); } else if ((eaBuffer->EaNameLength==WS2IFSL_PROCESS_EA_NAME_LENGTH) && (strcmp (eaBuffer->EaName, WS2IFSL_PROCESS_EA_NAME)==0)) { // This is the request to create process file
status = CreateProcessFile (irpSp->FileObject, Irp->RequestorMode, eaBuffer); } else status = STATUS_INVALID_PARAMETER; } else status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status; } // DispatchCreate
NTSTATUS DispatchCleanup ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++
Routine Description:
This routine is called when all handles to a file associated with WS2IFSL driver device object are closed, so the driver should cleanup all the outstanding IRPs.
Arguments:
DeviceObject - WS2IFSL device object Irp - cleanup Irp
Return Value:
STATUS_SUCCESS - cleanup operation completed STATUS_PENDING - cleanup operation started and IoCompleteRequest will be called when it is done
--*/ { NTSTATUS status; PIO_STACK_LOCATION irpSp; ULONG eaNameTag;
PAGED_CODE ();
// Get the file type from file object context
irpSp = IoGetCurrentIrpStackLocation (Irp); eaNameTag = *((PULONG)irpSp->FileObject->FsContext);
// Call appropriate routine based on file type
switch (eaNameTag) { case SOCKET_FILE_EANAME_TAG: status = CleanupSocketFile (irpSp->FileObject, Irp); break; case PROCESS_FILE_EANAME_TAG: status = CleanupProcessFile (irpSp->FileObject, Irp); break; default: ASSERTMSG ("Unknown file EA name tag", FALSE); status = STATUS_INVALID_HANDLE; break; }
// Complete the request if it was not marked pending
if (status!=STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT); }
return status; } // DispatchCleanup
NTSTATUS DispatchClose ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++
Routine Description:
This routine is called when all references to a file associated with WS2IFSL driver device object are released and IO system is about to delete the file object itself
Arguments:
DeviceObject - WS2IFSL device object Irp - close Irp
Return Value:
STATUS_SUCCESS - close operation completed
--*/ { NTSTATUS status; PIO_STACK_LOCATION irpSp; ULONG eaNameTag;
PAGED_CODE ();
// Get the file type from file object context
irpSp = IoGetCurrentIrpStackLocation (Irp); eaNameTag = *((PULONG)irpSp->FileObject->FsContext);
// Call appropriate routine based on file type
switch (eaNameTag) { case SOCKET_FILE_EANAME_TAG: CloseSocketFile (irpSp->FileObject); status = STATUS_SUCCESS; break; case PROCESS_FILE_EANAME_TAG: CloseProcessFile (irpSp->FileObject); status = STATUS_SUCCESS; break; default: ASSERTMSG ("Unknown file EA name tag", FALSE); status = STATUS_INVALID_HANDLE; break; }
// Complete the request
Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status; } // DispatchClose
NTSTATUS DispatchReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++
Routine Description:
This routine is called to perform read or write operation on file object. It is only supported for socket files.
Arguments:
DeviceObject - WS2IFSL device object Irp - read/write Irp
Return Value:
STATUS_PENDING - operation is passed onto WS2IFSL DLL to execute STATUS_CANCELED - operation canceled because WS2IFSL DLL has been unloaded STATUS_INVALID_DEVICE_REQUEST - the operation cannot be performed on this file object. STATUS_INVALID_HANDLE - file object is not valid in the context of current process
--*/ { NTSTATUS status; PIO_STACK_LOCATION irpSp; ULONG eaNameTag;
PAGED_CODE ();
// Get the file type from file object context
irpSp = IoGetCurrentIrpStackLocation (Irp); eaNameTag = *((PULONG)irpSp->FileObject->FsContext);
// Call appropriate routine based on file type
switch (eaNameTag) { case SOCKET_FILE_EANAME_TAG: status = DoSocketReadWrite (irpSp->FileObject, Irp); break; default: ASSERTMSG ("Unknown file EA name tag", FALSE); case PROCESS_FILE_EANAME_TAG: // This operation is not valid for process files
status = STATUS_INVALID_DEVICE_REQUEST; break; }
// Complete the request if it was not marked pending
if (status!=STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT); }
return status; } // DispatchReadWrite
NTSTATUS DispatchDeviceControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++
Routine Description:
This routine is called to perform device control operation on file object.
Arguments:
DeviceObject - WS2IFSL device object Irp - device control Irp
Return Value:
STATUS_SUCCESS - device control operation completed STATUS_PENDING - operation is in progress STATUS_INVALID_DEVICE_REQUEST - the operation cannot be performed on this file object. STATUS_INVALID_HANDLE - file object is not valid in the context of current process
--*/ { NTSTATUS status; PIO_STACK_LOCATION irpSp; ULONG eaNameTag; ULONG function;
PAGED_CODE ();
// Get the file type from file object context
irpSp = IoGetCurrentIrpStackLocation (Irp); eaNameTag = *((PULONG)irpSp->FileObject->FsContext);
// Call appropriate routine based on file type
switch (eaNameTag) { case SOCKET_FILE_EANAME_TAG: function = WS2IFSL_IOCTL_FUNCTION(SOCKET,irpSp->Parameters.DeviceIoControl.IoControlCode); if ((function<sizeof(SocketIoControlMap)/sizeof(SocketIoControlMap[0])) && (SocketIoctlCodeMap[function]==irpSp->Parameters.DeviceIoControl.IoControlCode)) { // Use table dispatch to call appropriate internal IOCTL routine
ASSERTMSG ("Socket file device control requests should have been handled" " by FastIo path ", FALSE); SocketIoControlMap[function] ( irpSp->FileObject, Irp->RequestorMode, irpSp->Parameters.DeviceIoControl.Type3InputBuffer, irpSp->Parameters.DeviceIoControl.InputBufferLength, Irp->UserBuffer, irpSp->Parameters.DeviceIoControl.OutputBufferLength, &Irp->IoStatus); status = Irp->IoStatus.Status; } else if ((irpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_AFD_SEND_DATAGRAM) || (irpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_AFD_RECEIVE_DATAGRAM) || (irpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_AFD_RECEIVE)) // Handle some "popular" afd IOCTLs
status = DoSocketAfdIoctl (irpSp->FileObject, Irp); else { WsPrint (DBG_FAILURES, ("WS2IFSL-%04lx DispatchDeviceControl: Unsupported IOCTL - %lx!!!\n", PsGetCurrentProcessId(), irpSp->Parameters.DeviceIoControl.IoControlCode )); status = STATUS_INVALID_DEVICE_REQUEST; } break; case PROCESS_FILE_EANAME_TAG: function = WS2IFSL_IOCTL_FUNCTION(PROCESS,irpSp->Parameters.DeviceIoControl.IoControlCode); if ((function<sizeof(ProcessIoControlMap)/sizeof(ProcessIoControlMap[0])) && (ProcessIoctlCodeMap[function]==irpSp->Parameters.DeviceIoControl.IoControlCode)) { // Use table dispatch to call appropriate internal IOCTL routine
ASSERTMSG ("Process file device control requests should have been handled" " by FastIo path ", FALSE); ProcessIoControlMap[function] ( irpSp->FileObject, Irp->RequestorMode, irpSp->Parameters.DeviceIoControl.Type3InputBuffer, irpSp->Parameters.DeviceIoControl.InputBufferLength, Irp->UserBuffer, irpSp->Parameters.DeviceIoControl.OutputBufferLength, &Irp->IoStatus); status = Irp->IoStatus.Status; } else { WsPrint (DBG_FAILURES, ("WS2IFSL-%04lx DispatchDeviceControl: Unsupported IOCTL - %lx!!!\n", PsGetCurrentProcessId(), irpSp->Parameters.DeviceIoControl.IoControlCode )); status = STATUS_INVALID_DEVICE_REQUEST; } break; default: ASSERTMSG ("Unknown file EA name tag", FALSE); status = STATUS_INVALID_DEVICE_REQUEST; break; }
// Complete the request if it was not marked pending
if (status!=STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT); }
return status; } // DispatchDeviceControl
BOOLEAN FastIoDeviceControl ( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN ULONG IoControlCode, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) /*++
Routine Description:
This routine is called to perform device control operation on file object. This is IO system fast path that assumes immediate action
Arguments:
FileObject - file object to which request is directed; Wait - ??? (always TRUE); InputBuffer - address of the input buffer; InputBufferLength - size of the input buffer; OutputBuffer - address of the output buffer; OutputBufferLength - size of the output buffer; IoControlCode - code of the operation to be performed; IoStatus - status of the operation returned by the driver: DeviceObject - WS2IFSL device object
Return Value:
TRUE - operation completed, FALSE - operation should be preformed using Irps --*/ { BOOLEAN done = FALSE; ULONG eaNameTag; ULONG function;
PAGED_CODE ();
// Get the file type from file object context
eaNameTag = *((PULONG)FileObject->FsContext);
// Call appropriate routine based on file type
switch (eaNameTag) { case SOCKET_FILE_EANAME_TAG: function = WS2IFSL_IOCTL_FUNCTION(SOCKET,IoControlCode); if ((function<sizeof(SocketIoControlMap)/sizeof(SocketIoControlMap[0])) && (SocketIoctlCodeMap[function]==IoControlCode)) { IO_STATUS_BLOCK IoStatusTemp;
// Use table dispatch to call appropriate internal IOCTL routine
SocketIoControlMap[function] ( FileObject, ExGetPreviousMode(), InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &IoStatusTemp);
if (NT_SUCCESS(IoStatusTemp.Status)) { done = TRUE; memcpy(IoStatus, &IoStatusTemp, sizeof(IoStatusTemp)); } } else if ((IoControlCode==IOCTL_AFD_SEND_DATAGRAM) || (IoControlCode==IOCTL_AFD_RECEIVE_DATAGRAM) || (IoControlCode==IOCTL_AFD_RECEIVE)) // AFD ioctls can only be handled on "slow" io path (need IRP)
NOTHING; else { WsPrint (DBG_FAILURES, ("WS2IFSL-%04lx FastIoDeviceControl: Unsupported IOCTL - %lx!!!\n", PsGetCurrentProcessId(), IoControlCode)); //
// Let the real dispatch deal with the error.
NOTHING; } break; case PROCESS_FILE_EANAME_TAG: function = WS2IFSL_IOCTL_FUNCTION(PROCESS,IoControlCode); if ((function<sizeof(ProcessIoControlMap)/sizeof(ProcessIoControlMap[0])) && (ProcessIoctlCodeMap[function]==IoControlCode)) { // Use table dispatch to call appropriate internal IOCTL routine
IO_STATUS_BLOCK IoStatusTemp;
ProcessIoControlMap[function] ( FileObject, ExGetPreviousMode(), InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &IoStatusTemp);
if (NT_SUCCESS(IoStatusTemp.Status)) { done = TRUE; memcpy(IoStatus, &IoStatusTemp, sizeof(IoStatusTemp)); } } else { WsPrint (DBG_FAILURES, ("WS2IFSL-%04lx FastIoDeviceControl: Unsupported IOCTL - %lx!!!\n", PsGetCurrentProcessId(),IoControlCode)); //
// Let the real dispatch deal with the error.
NOTHING; } break; default: ASSERTMSG ("Unknown file EA name tag", FALSE); //
// Let the real dispatch deal with the error.
NOTHING; break; }
return done; } // FastIoDeviceControl
NTSTATUS DispatchPnP ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++
Routine Description:
This routine is called to perform PnP control operation on file object.
Arguments:
DeviceObject - WS2IFSL device object Irp - PnP Irp
Return Value:
STATUS_SUCCESS - device control operation completed STATUS_PENDING - operation is in progress STATUS_INVALID_DEVICE_REQUEST - the operation cannot be performed on this file object.
--*/ { NTSTATUS status; PIO_STACK_LOCATION irpSp; ULONG eaNameTag;
PAGED_CODE ();
// Get the file type from file object context
irpSp = IoGetCurrentIrpStackLocation (Irp); eaNameTag = *((PULONG)irpSp->FileObject->FsContext);
// Call appropriate routine based on file type
switch (eaNameTag) { case SOCKET_FILE_EANAME_TAG: switch (irpSp->MinorFunction) { case IRP_MN_QUERY_DEVICE_RELATIONS: status = SocketPnPTargetQuery (irpSp->FileObject, Irp); break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } break;
default: ASSERTMSG ("Unknown file EA name tag", FALSE);
case PROCESS_FILE_EANAME_TAG: status = STATUS_INVALID_DEVICE_REQUEST; break; } // Complete the request if it was not marked pending
if (status!=STATUS_PENDING) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest (Irp, IO_NO_INCREMENT); }
return status; }
|