Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

570 lines
17 KiB

/*++
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)) {
// Use table dispatch to call appropriate internal IOCTL routine
SocketIoControlMap[function] (
FileObject,
ExGetPreviousMode(),
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength,
IoStatus);
done = TRUE;
}
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));
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
done = TRUE;
}
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
ProcessIoControlMap[function] (
FileObject,
ExGetPreviousMode(),
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength,
IoStatus);
done = TRUE;
}
else {
WsPrint (DBG_FAILURES,
("WS2IFSL-%04lx FastIoDeviceControl: Unsupported IOCTL - %lx!!!\n",
PsGetCurrentProcessId(),IoControlCode));
IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
done = TRUE;
}
break;
default:
ASSERTMSG ("Unknown file EA name tag", FALSE);
IoStatus->Status = STATUS_INVALID_PARAMETER;
IoStatus->Information = 0;
done = TRUE;
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;
}