768 lines
26 KiB
C
768 lines
26 KiB
C
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
process.c
|
|
|
|
Abstract:
|
|
|
|
This module implements process file object 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"
|
|
|
|
//
|
|
// Internal routine prototypes
|
|
//
|
|
|
|
VOID
|
|
RetrieveDrvRequest (
|
|
IN PFILE_OBJECT ProcessFile,
|
|
IN KPROCESSOR_MODE RequestorMode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength,
|
|
OUT PIO_STATUS_BLOCK IoStatus
|
|
);
|
|
|
|
VOID
|
|
CompleteDrvCancel (
|
|
IN PFILE_OBJECT SocketFile,
|
|
IN KPROCESSOR_MODE RequestorMode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength,
|
|
OUT PIO_STATUS_BLOCK IoStatus
|
|
);
|
|
|
|
VOID
|
|
CallCompleteDrvRequest (
|
|
IN PFILE_OBJECT SocketFile,
|
|
IN KPROCESSOR_MODE RequestorMode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength,
|
|
OUT PIO_STATUS_BLOCK IoStatus
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, CreateProcessFile)
|
|
#pragma alloc_text(PAGE, CleanupProcessFile)
|
|
#pragma alloc_text(PAGE, CloseProcessFile)
|
|
#pragma alloc_text(PAGE, RetrieveDrvRequest)
|
|
#pragma alloc_text(PAGE, CompleteDrvCancel)
|
|
#pragma alloc_text(PAGE, CallCompleteDrvRequest)
|
|
#endif
|
|
|
|
ULONG ProcessIoctlCodeMap[3] = {
|
|
#if WS2IFSL_IOCTL_FUNCTION(PROCESS,IOCTL_WS2IFSL_RETRIEVE_DRV_REQ)!=0
|
|
#error Mismatch between IOCTL function code and ProcessIoControlMap
|
|
#endif
|
|
IOCTL_WS2IFSL_RETRIEVE_DRV_REQ,
|
|
#if WS2IFSL_IOCTL_FUNCTION(PROCESS,IOCTL_WS2IFSL_COMPLETE_DRV_CAN)!=1
|
|
#error Mismatch between IOCTL function code and ProcessIoControlMap
|
|
#endif
|
|
IOCTL_WS2IFSL_COMPLETE_DRV_CAN,
|
|
#if WS2IFSL_IOCTL_FUNCTION(PROCESS,IOCTL_WS2IFSL_COMPLETE_DRV_REQ)!=2
|
|
#error Mismatch between IOCTL function code and ProcessIoControlMap
|
|
#endif
|
|
IOCTL_WS2IFSL_COMPLETE_DRV_REQ
|
|
};
|
|
|
|
PPROCESS_DEVICE_CONTROL ProcessIoControlMap[3] = {
|
|
RetrieveDrvRequest,
|
|
CompleteDrvCancel,
|
|
CallCompleteDrvRequest
|
|
};
|
|
|
|
|
|
NTSTATUS
|
|
CreateProcessFile (
|
|
IN PFILE_OBJECT ProcessFile,
|
|
IN KPROCESSOR_MODE RequestorMode,
|
|
IN PFILE_FULL_EA_INFORMATION eaInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocates and initializes process file context structure
|
|
|
|
Arguments:
|
|
ProcessFile - socket file object
|
|
eaInfo - EA for process file
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - operation completed OK
|
|
STATUS_INSUFFICIENT_RESOURCES - not enough memory to allocate context
|
|
STATUS_INVALID_PARAMETER - invalid creation parameters
|
|
STATUS_INVALID_HANDLE - invalid event handle(s)
|
|
STATUS_OBJECT_TYPE_MISMATCH - event handle(s) is not for event object
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PIFSL_PROCESS_CTX ProcessCtx;
|
|
PETHREAD apcThread;
|
|
|
|
PAGED_CODE ();
|
|
|
|
//
|
|
// Verify the size of the input strucuture
|
|
//
|
|
|
|
if (eaInfo->EaValueLength!=WS2IFSL_PROCESS_EA_VALUE_LENGTH) {
|
|
WsPrint (DBG_PROCESS|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CreateProcessFile: Invalid ea info size (%ld)"
|
|
" for process file %p.\n",
|
|
PsGetCurrentProcessId(),
|
|
eaInfo->EaValueLength,
|
|
ProcessFile));
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
//
|
|
// Reference event handles for signalling to user mode DLL
|
|
//
|
|
status = ObReferenceObjectByHandle(
|
|
GET_WS2IFSL_PROCESS_EA_VALUE(eaInfo)->ApcThread,
|
|
THREAD_SET_CONTEXT, // DesiredAccess
|
|
*PsThreadType,
|
|
RequestorMode,
|
|
(PVOID *)&apcThread,
|
|
NULL
|
|
);
|
|
|
|
if (NT_SUCCESS (status)) {
|
|
if (IoThreadToProcess (apcThread)==IoGetCurrentProcess ()) {
|
|
|
|
// Allocate process context and charge it to the process
|
|
try {
|
|
ProcessCtx = (PIFSL_PROCESS_CTX) ExAllocatePoolWithQuotaTag (
|
|
NonPagedPool,
|
|
sizeof (IFSL_PROCESS_CTX),
|
|
PROCESS_FILE_CONTEXT_TAG);
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
ProcessCtx = NULL;
|
|
status = GetExceptionCode ();
|
|
}
|
|
|
|
if (ProcessCtx!=NULL) {
|
|
// Initialize process context structure
|
|
ProcessCtx->EANameTag = PROCESS_FILE_EANAME_TAG;
|
|
ProcessCtx->UniqueId = PsGetCurrentProcessId();
|
|
ProcessCtx->CancelId = 0;
|
|
InitializeRequestQueue (ProcessCtx,
|
|
(PKTHREAD)apcThread,
|
|
RequestorMode,
|
|
(PKNORMAL_ROUTINE)GET_WS2IFSL_PROCESS_EA_VALUE(eaInfo)->RequestRoutine,
|
|
GET_WS2IFSL_PROCESS_EA_VALUE(eaInfo)->ApcContext);
|
|
InitializeCancelQueue (ProcessCtx,
|
|
(PKTHREAD)apcThread,
|
|
RequestorMode,
|
|
(PKNORMAL_ROUTINE)GET_WS2IFSL_PROCESS_EA_VALUE(eaInfo)->CancelRoutine,
|
|
GET_WS2IFSL_PROCESS_EA_VALUE(eaInfo)->ApcContext);
|
|
#if DBG
|
|
ProcessCtx->DbgLevel
|
|
= GET_WS2IFSL_PROCESS_EA_VALUE(eaInfo)->DbgLevel|DbgLevel;
|
|
#endif
|
|
|
|
|
|
|
|
ProcessFile->FsContext = ProcessCtx;
|
|
WsProcessPrint (ProcessCtx, DBG_PROCESS,
|
|
("WS2IFSL-%04lx CreateProcessFile: Process file %p (ctx: %p).\n",
|
|
PsGetCurrentProcessId(),
|
|
ProcessFile, ProcessFile->FsContext));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
else {
|
|
WsPrint (DBG_PROCESS|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CreateProcessFile: Could not allocate context for"
|
|
" process file %p.\n",
|
|
PsGetCurrentProcessId(),
|
|
ProcessFile));
|
|
if (NT_SUCCESS (status)) {
|
|
ASSERT (FALSE);
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
WsPrint (DBG_PROCESS|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CreateProcessFile: Apc thread (%p)"
|
|
" is not from current process for process file %p.\n",
|
|
PsGetCurrentProcessId(),
|
|
GET_WS2IFSL_PROCESS_EA_VALUE(eaInfo)->ApcThread,
|
|
ProcessFile));
|
|
}
|
|
ObDereferenceObject (apcThread);
|
|
}
|
|
else {
|
|
WsPrint (DBG_PROCESS|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CreateProcessFile: Could not reference apc thread (%p)"
|
|
" for process file %p, status: %lx.\n",
|
|
PsGetCurrentProcessId(),
|
|
GET_WS2IFSL_PROCESS_EA_VALUE(eaInfo)->ApcThread,
|
|
ProcessFile,
|
|
status));
|
|
}
|
|
|
|
return status;
|
|
} // CreateProcessFile
|
|
|
|
|
|
NTSTATUS
|
|
CleanupProcessFile (
|
|
IN PFILE_OBJECT ProcessFile,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Cleanup routine for process file, NOP
|
|
|
|
Arguments:
|
|
ProcessFile - process file object
|
|
Irp - cleanup request
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCESS - operation completed OK
|
|
--*/
|
|
{
|
|
PIFSL_PROCESS_CTX ProcessCtx = ProcessFile->FsContext;
|
|
PAGED_CODE ();
|
|
|
|
ASSERT (ProcessCtx->UniqueId==PsGetCurrentProcessId());
|
|
|
|
WsProcessPrint (ProcessCtx, DBG_PROCESS,
|
|
("WS2IFSL-%04lx CleanupProcessFile: Process file %p (ctx:%p)\n",
|
|
PsGetCurrentProcessId(),
|
|
ProcessFile, ProcessFile->FsContext));
|
|
|
|
return STATUS_SUCCESS;
|
|
} // CleanupProcessFile
|
|
|
|
|
|
VOID
|
|
CloseProcessFile (
|
|
IN PFILE_OBJECT ProcessFile
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deallocate all resources associated with process file
|
|
|
|
Arguments:
|
|
ProcessFile - process file object
|
|
|
|
Return Value:
|
|
None
|
|
--*/
|
|
{
|
|
PIFSL_PROCESS_CTX ProcessCtx = ProcessFile->FsContext;
|
|
PAGED_CODE ();
|
|
|
|
WsProcessPrint (ProcessCtx, DBG_PROCESS,
|
|
("WS2IFSL-%04lx CloseProcessFile: Process file %p (ctx:%p)\n",
|
|
ProcessCtx->UniqueId, ProcessFile, ProcessFile->FsContext));
|
|
|
|
ASSERT (IsListEmpty (&ProcessCtx->RequestQueue.ListHead));
|
|
ASSERT (IsListEmpty (&ProcessCtx->CancelQueue.ListHead));
|
|
|
|
ObDereferenceObject (ProcessCtx->RequestQueue.Apc.Thread);
|
|
|
|
// Now free the context itself
|
|
ExFreePool (ProcessCtx);
|
|
|
|
} // CloseProcessFile
|
|
|
|
|
|
|
|
|
|
VOID
|
|
RetrieveDrvRequest (
|
|
IN PFILE_OBJECT ProcessFile,
|
|
IN KPROCESSOR_MODE RequestorMode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength,
|
|
OUT PIO_STATUS_BLOCK IoStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Retrievs parameters and data of the request to be executed by
|
|
user mode DLL
|
|
|
|
Arguments:
|
|
ProcessFile - Identifies the process
|
|
InputBuffer - input buffer pointer
|
|
- identifies the request to retreive
|
|
and received request parameters
|
|
InputBufferLength - size of the input buffer
|
|
OutputBuffer - output buffer pointer
|
|
- buffer to receive data and address
|
|
for send operation
|
|
OutputBufferLength - size of output buffer
|
|
IoStatus - IO status information block
|
|
Status: STATUS_SUCCESS - operation retreived OK, no more pending
|
|
requests in the queue.
|
|
STATUS_MORE_ENTRIES - operation retrieved OK, more requests
|
|
are available in the queue
|
|
STATUS_CANCELLED - operation was cancelled before it
|
|
could be retrieved
|
|
STATUS_INVALID_PARAMETER - one of the parameters was invalid
|
|
STATUS_INSUFFICIENT_RESOURCES - insufficient resources or
|
|
buffer space to perform the
|
|
operation.
|
|
Information: - number of bytes copied to OutputBuffer
|
|
Return Value:
|
|
None (result returned via IoStatus block)
|
|
--*/
|
|
{
|
|
PIFSL_PROCESS_CTX ProcessCtx = ProcessFile->FsContext;
|
|
PIFSL_SOCKET_CTX SocketCtx;
|
|
PWS2IFSL_RTRV_PARAMS params;
|
|
PIRP irp = NULL;
|
|
PIO_STACK_LOCATION irpSp;
|
|
BOOLEAN more =FALSE;
|
|
ULONG bytesCopied;
|
|
|
|
PAGED_CODE();
|
|
|
|
IoStatus->Information = 0;
|
|
// Check input buffer size
|
|
if (InputBufferLength<sizeof (WS2IFSL_RTRV_PARAMS)) {
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
WsPrint (DBG_RETRIEVE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx RetrieveDrvRequest: Invalid input buffer size (%ld).\n",
|
|
PsGetCurrentProcessId(),
|
|
InputBufferLength));
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Verify buffers
|
|
if (RequestorMode!=KernelMode) {
|
|
ProbeForRead (InputBuffer,
|
|
sizeof (*params),
|
|
sizeof (ULONG));
|
|
if (OutputBufferLength>0)
|
|
ProbeForWrite (OutputBuffer,
|
|
OutputBufferLength,
|
|
sizeof (UCHAR));
|
|
}
|
|
params = InputBuffer;
|
|
|
|
// Dequeue the request indetified in the input buffer
|
|
irp = DequeueRequest (ProcessCtx,
|
|
params->UniqueId,
|
|
&more);
|
|
if (irp!=NULL) {
|
|
//
|
|
// Copy request parameters and data
|
|
//
|
|
irpSp = IoGetCurrentIrpStackLocation (irp);
|
|
|
|
if (OutputBuffer==NULL) {
|
|
//
|
|
// Special condition, dll could not allocate support
|
|
// structures
|
|
//
|
|
ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
SocketCtx = irpSp->FileObject->FsContext;
|
|
params->DllContext = SocketCtx->DllContext;
|
|
|
|
switch (irpSp->MajorFunction) {
|
|
case IRP_MJ_READ:
|
|
params->RequestType = WS2IFSL_REQUEST_READ;
|
|
params->DataLen = irpSp->Parameters.Read.Length;
|
|
params->AddrLen = 0;
|
|
params->Flags = 0;
|
|
break;
|
|
|
|
case IRP_MJ_WRITE:
|
|
bytesCopied = CopyMdlChainToBuffer (irp->MdlAddress,
|
|
OutputBuffer,
|
|
OutputBufferLength);
|
|
if (bytesCopied<irpSp->Parameters.Write.Length) {
|
|
WsPrint (DBG_RETRIEVE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx RetrieveDrvRequest: Invalid output buffer size (%ld).\n",
|
|
PsGetCurrentProcessId(),
|
|
OutputBufferLength));
|
|
ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
params->RequestType = WS2IFSL_REQUEST_WRITE;
|
|
params->DataLen = bytesCopied;
|
|
params->AddrLen = 0;
|
|
params->Flags = 0;
|
|
IoStatus->Information = bytesCopied;
|
|
break;
|
|
|
|
case IRP_MJ_DEVICE_CONTROL:
|
|
switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
|
|
case IOCTL_AFD_RECEIVE_DATAGRAM:
|
|
params->RequestType = WS2IFSL_REQUEST_RECVFROM;
|
|
params->DataLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
|
params->AddrLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;
|
|
params->Flags = (ULONG)(ULONG_PTR)irp->Tail.Overlay.IfslRequestFlags;
|
|
break;
|
|
|
|
case IOCTL_AFD_RECEIVE:
|
|
params->RequestType = WS2IFSL_REQUEST_RECV;
|
|
params->DataLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
|
params->AddrLen = 0;
|
|
params->Flags = (ULONG)(ULONG_PTR)irp->Tail.Overlay.IfslRequestFlags;
|
|
break;
|
|
|
|
case IOCTL_AFD_SEND_DATAGRAM:
|
|
bytesCopied = CopyMdlChainToBuffer (irp->MdlAddress,
|
|
OutputBuffer,
|
|
OutputBufferLength);
|
|
if ((bytesCopied<=irpSp->Parameters.DeviceIoControl.OutputBufferLength)
|
|
|| (ADDR_ALIGN(bytesCopied)+irpSp->Parameters.DeviceIoControl.InputBufferLength
|
|
< OutputBufferLength)) {
|
|
WsPrint (DBG_RETRIEVE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx RetrieveDrvRequest: Invalid output buffer size (%ld).\n",
|
|
PsGetCurrentProcessId(),
|
|
OutputBufferLength));
|
|
ExRaiseStatus (STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
RtlCopyMemory (
|
|
(PUCHAR)OutputBuffer + ADDR_ALIGN(bytesCopied),
|
|
irpSp->Parameters.DeviceIoControl.Type3InputBuffer,
|
|
irpSp->Parameters.DeviceIoControl.InputBufferLength);
|
|
|
|
params->RequestType = WS2IFSL_REQUEST_SENDTO;
|
|
params->DataLen = bytesCopied;
|
|
params->AddrLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;
|
|
params->Flags = (ULONG)(ULONG_PTR)irp->Tail.Overlay.IfslRequestFlags;
|
|
IoStatus->Information = ADDR_ALIGN(bytesCopied)
|
|
+ irpSp->Parameters.DeviceIoControl.InputBufferLength;
|
|
break;
|
|
default:
|
|
ASSERTMSG ("Unknown IOCTL!!!", FALSE);
|
|
ExRaiseStatus( STATUS_INVALID_PARAMETER );
|
|
}
|
|
break;
|
|
case IRP_MJ_PNP:
|
|
params->RequestType = WS2IFSL_REQUEST_QUERYHANDLE;
|
|
params->DataLen = sizeof (HANDLE);
|
|
params->AddrLen = 0;
|
|
params->Flags = 0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Insert the request into the socket list
|
|
//
|
|
if (InsertProcessedRequest (SocketCtx, irp)) {
|
|
if (more)
|
|
IoStatus->Status = STATUS_MORE_ENTRIES;
|
|
else
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
WsProcessPrint (ProcessCtx, DBG_RETRIEVE,
|
|
("WS2IFSL-%04lx RetrieveDrvRequest:"
|
|
" Irp %p (id:%ld), socket file %p, op %ld.\n",
|
|
PsGetCurrentProcessId(),
|
|
irp, params->UniqueId, irpSp->FileObject,
|
|
params->RequestType));
|
|
}
|
|
|
|
else {
|
|
ExRaiseStatus (STATUS_CANCELLED);
|
|
}
|
|
}
|
|
else {
|
|
WsProcessPrint (ProcessCtx, DBG_RETRIEVE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx RetrieveDrvRequest:"
|
|
" Request with id %ld is not in the queue.\n",
|
|
PsGetCurrentProcessId(),
|
|
params->UniqueId));
|
|
IoStatus->Status = STATUS_CANCELLED;
|
|
}
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
//
|
|
// Something failed, complete the request (if any)
|
|
//
|
|
IoStatus->Status = GetExceptionCode ();
|
|
WsProcessPrint (ProcessCtx, DBG_RETRIEVE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx RetrieveDrvRequest: Failed to process"
|
|
" id %ld, status %lx, irp %p (func: %s).\n",
|
|
PsGetCurrentProcessId(),params->UniqueId, IoStatus->Status,
|
|
irp, irp
|
|
? (irpSp->MajorFunction==IRP_MJ_READ
|
|
? "read"
|
|
: (irpSp->MajorFunction==IRP_MJ_WRITE
|
|
? "Write"
|
|
: (irpSp->MajorFunction==IRP_MJ_PNP
|
|
? "PnP"
|
|
: (irpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_AFD_RECEIVE_DATAGRAM
|
|
? "RecvFrom"
|
|
: (irpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_AFD_RECEIVE
|
|
? "Recv"
|
|
: (irpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_AFD_SEND_DATAGRAM
|
|
? "SendTo"
|
|
: "UnknownCtl"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
: "Unknown"));
|
|
|
|
if (irp!=NULL) {
|
|
irp->IoStatus.Status = IoStatus->Status;
|
|
irp->IoStatus.Information = 0;
|
|
CompleteSocketIrp (irp);
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CompleteDrvCancel (
|
|
IN PFILE_OBJECT ProcessFile,
|
|
IN KPROCESSOR_MODE RequestorMode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength,
|
|
OUT PIO_STATUS_BLOCK IoStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Indicates that user mode has completed cancel request
|
|
Arguments:
|
|
ProcessFile - Identifies the process
|
|
InputBuffer - input buffer pointer
|
|
- identifies the request being completed
|
|
InputBufferLength - size of the input buffer
|
|
OutputBuffer - NULL
|
|
OutputBufferLength - 0
|
|
IoStatus - IO status information block
|
|
Status: STATUS_SUCCESS - operation completed OK, no more pending
|
|
requests in the queue.
|
|
STATUS_MORE_ENTRIES - operation completed OK, more requests
|
|
are available in the queue
|
|
Information: - 0
|
|
|
|
Return Value:
|
|
None (result returned via IoStatus block)
|
|
--*/
|
|
{
|
|
PIFSL_PROCESS_CTX ProcessCtx = ProcessFile->FsContext;
|
|
PWS2IFSL_CNCL_PARAMS params;
|
|
BOOLEAN more = FALSE;
|
|
PIFSL_CANCEL_CTX cancelCtx;
|
|
|
|
PAGED_CODE();
|
|
|
|
IoStatus->Information = 0;
|
|
|
|
if (InputBufferLength<sizeof (*params)) {
|
|
WsPrint (DBG_RETRIEVE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CompleteDrvCancel: Invalid input buffer size (%ld)"
|
|
" for process file %p.\n",
|
|
PsGetCurrentProcessId(),
|
|
InputBufferLength,
|
|
ProcessFile));
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
return;
|
|
}
|
|
|
|
// Verify input buffer
|
|
try {
|
|
if (RequestorMode!=KernelMode) {
|
|
ProbeForRead (InputBuffer,
|
|
sizeof (*params),
|
|
sizeof (ULONG));
|
|
}
|
|
params = InputBuffer;
|
|
cancelCtx = DequeueCancel (ProcessCtx,
|
|
params->UniqueId,
|
|
&more);
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER) {
|
|
IoStatus->Status = GetExceptionCode ();
|
|
WsPrint (DBG_RETRIEVE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CompleteDrvCancel: Invalid input buffer (%p).\n",
|
|
PsGetCurrentProcessId(),
|
|
InputBuffer));
|
|
return ;
|
|
}
|
|
|
|
if (cancelCtx!=NULL) {
|
|
FreeSocketCancel (cancelCtx);
|
|
}
|
|
else {
|
|
WsProcessPrint (ProcessCtx, DBG_RETRIEVE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CompleteDrvCancel: Canceled request id %ld is gone already.\n",
|
|
PsGetCurrentProcessId(), params->UniqueId));
|
|
}
|
|
|
|
if (more) {
|
|
IoStatus->Status = STATUS_MORE_ENTRIES;
|
|
}
|
|
else {
|
|
IoStatus->Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
CallCompleteDrvRequest (
|
|
IN PFILE_OBJECT ProcessFile,
|
|
IN KPROCESSOR_MODE RequestorMode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength,
|
|
OUT PIO_STATUS_BLOCK IoStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validate parameters and call to complete request that was
|
|
prviously passed to user mode DLL on a specified socket file
|
|
Arguments:
|
|
SocketFile - Socket file on which to operate
|
|
InputBuffer - input buffer pointer
|
|
identifies the request to complete and
|
|
supplies description of the results
|
|
InputBufferLength - size of the input buffer
|
|
OutputBuffer - result buffer (data and address)
|
|
OutputBufferLength - sizeof result buffer
|
|
IoStatus - IO status information block
|
|
Status: STATUS_SUCCESS - request was completed OK
|
|
STATUS_CANCELLED - request was already cancelled
|
|
STATUS_INVALID_PARAMETER - one of the parameters was invalid
|
|
|
|
Return Value:
|
|
None (result returned via IoStatus block)
|
|
--*/
|
|
{
|
|
WS2IFSL_CMPL_PARAMS params;
|
|
PFILE_OBJECT SocketFile;
|
|
|
|
PAGED_CODE();
|
|
|
|
IoStatus->Information = 0;
|
|
|
|
if (InputBufferLength<sizeof (WS2IFSL_CMPL_PARAMS)) {
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
WsPrint (DBG_DRV_COMPLETE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CompleteDrvRequest: Invalid input buffer size (%ld).\n",
|
|
PsGetCurrentProcessId(),
|
|
InputBufferLength));
|
|
return;
|
|
}
|
|
|
|
// Check and copy parameters
|
|
try {
|
|
if (RequestorMode !=KernelMode) {
|
|
ProbeForRead (InputBuffer,
|
|
sizeof (WS2IFSL_CMPL_PARAMS),
|
|
sizeof (ULONG));
|
|
if (OutputBufferLength>0)
|
|
ProbeForRead (OutputBuffer,
|
|
OutputBufferLength,
|
|
sizeof (UCHAR));
|
|
}
|
|
params = *((PWS2IFSL_CMPL_PARAMS)InputBuffer);
|
|
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER) {
|
|
IoStatus->Status = GetExceptionCode ();
|
|
WsProcessPrint (
|
|
(PIFSL_PROCESS_CTX)ProcessFile->FsContext,
|
|
DBG_DRV_COMPLETE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CallCompleteDrvRequest: Exception accessing"
|
|
" buffers.\n",
|
|
PsGetCurrentProcessId()));
|
|
return;
|
|
}
|
|
if (params.DataLen>OutputBufferLength) {
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
WsPrint (DBG_DRV_COMPLETE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CompleteDrvRequest: Mismatch in output buffer size"
|
|
" (data:%ld, total:%ld) for socket handle %p.\n",
|
|
PsGetCurrentProcessId(),
|
|
params.DataLen,
|
|
OutputBufferLength,
|
|
params.SocketHdl));
|
|
return;
|
|
}
|
|
|
|
if (params.AddrLen>0) {
|
|
if ((params.AddrLen>OutputBufferLength) ||
|
|
(ADDR_ALIGN(params.DataLen)+params.AddrLen
|
|
>OutputBufferLength)) {
|
|
WsPrint (DBG_DRV_COMPLETE|DBG_FAILURES,
|
|
("WS2IFSL-%04lx CompleteDrvRequest: Mismatch in output buffer size"
|
|
" (data:%ld, addr:%ld, total:%ld) for socket handle %p.\n",
|
|
PsGetCurrentProcessId(),
|
|
params.DataLen,
|
|
params.AddrLen,
|
|
OutputBufferLength,
|
|
params.SocketHdl));
|
|
return;
|
|
}
|
|
}
|
|
|
|
IoStatus->Status = ObReferenceObjectByHandle (
|
|
params.SocketHdl,
|
|
FILE_ALL_ACCESS,
|
|
*IoFileObjectType,
|
|
RequestorMode,
|
|
(PVOID *)&SocketFile,
|
|
NULL
|
|
);
|
|
|
|
if (NT_SUCCESS (IoStatus->Status)) {
|
|
|
|
if ((IoGetRelatedDeviceObject (SocketFile)==DeviceObject)
|
|
&& ((*((PULONG)SocketFile->FsContext))
|
|
==SOCKET_FILE_EANAME_TAG)) {
|
|
CompleteDrvRequest (SocketFile,
|
|
¶ms,
|
|
OutputBuffer,
|
|
OutputBufferLength,
|
|
IoStatus
|
|
);
|
|
}
|
|
|
|
ObDereferenceObject (SocketFile);
|
|
}
|
|
}
|