342 lines
7.9 KiB
C
342 lines
7.9 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1996 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
misc.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Stolen from afd\misc.c
|
||
|
|
||
|
Author:
|
||
|
|
||
|
mbert 9-97
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <ntosp.h>
|
||
|
#include <cxport.h>
|
||
|
#include <tdikrnl.h>
|
||
|
#define UINT ULONG //tmp
|
||
|
#include <refcnt.h>
|
||
|
#include <af_irda.h>
|
||
|
#include <irdatdi.h>
|
||
|
#include <irtdicl.h>
|
||
|
#include <irtdiclp.h>
|
||
|
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
IrdaRestartDeviceControl (
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp,
|
||
|
IN PVOID Context
|
||
|
)
|
||
|
{
|
||
|
//
|
||
|
// N.B. This routine can never be demand paged because it can be
|
||
|
// called before any endpoints have been placed on the global
|
||
|
// list--see IrdaAllocateEndpoint() and it's call to
|
||
|
// IrdaGetTransportInfo().
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// If there was an MDL in the IRP, free it and reset the pointer to
|
||
|
// NULL. The IO system can't handle a nonpaged pool MDL being freed
|
||
|
// in an IRP, which is why we do it here.
|
||
|
//
|
||
|
|
||
|
if ( Irp->MdlAddress != NULL ) {
|
||
|
IoFreeMdl( Irp->MdlAddress );
|
||
|
Irp->MdlAddress = NULL;
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
|
||
|
} // IrdaRestartDeviceControl
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
IrdaSetEventHandler (
|
||
|
IN PFILE_OBJECT FileObject,
|
||
|
IN ULONG EventType,
|
||
|
IN PVOID EventHandler,
|
||
|
IN PVOID EventContext
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Sets up a TDI indication handler on a connection or address object
|
||
|
(depending on the file handle). This is done synchronously, which
|
||
|
shouldn't usually be an issue since TDI providers can usually complete
|
||
|
indication handler setups immediately.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
FileObject - a pointer to the file object for an open connection or
|
||
|
address object.
|
||
|
|
||
|
EventType - the event for which the indication handler should be
|
||
|
called.
|
||
|
|
||
|
EventHandler - the routine to call when tghe specified event occurs.
|
||
|
|
||
|
EventContext - context which is passed to the indication routine.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NTSTATUS -- Indicates the status of the request.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
TDI_REQUEST_KERNEL_SET_EVENT parameters;
|
||
|
|
||
|
PAGED_CODE( );
|
||
|
|
||
|
parameters.EventType = EventType;
|
||
|
parameters.EventHandler = EventHandler;
|
||
|
parameters.EventContext = EventContext;
|
||
|
|
||
|
return IrdaIssueDeviceControl(
|
||
|
NULL,
|
||
|
FileObject,
|
||
|
¶meters,
|
||
|
sizeof(parameters),
|
||
|
NULL,
|
||
|
0,
|
||
|
TDI_SET_EVENT_HANDLER
|
||
|
);
|
||
|
|
||
|
} // IrdaSetEventHandler
|
||
|
|
||
|
NTSTATUS
|
||
|
IrdaIssueDeviceControl (
|
||
|
IN HANDLE FileHandle OPTIONAL,
|
||
|
IN PFILE_OBJECT FileObject OPTIONAL,
|
||
|
IN PVOID IrpParameters,
|
||
|
IN ULONG IrpParametersLength,
|
||
|
IN PVOID MdlBuffer,
|
||
|
IN ULONG MdlBufferLength,
|
||
|
IN UCHAR MinorFunction
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Issues a device control returst to a TDI provider and waits for the
|
||
|
request to complete.
|
||
|
|
||
|
Note that while FileHandle and FileObject are both marked as optional,
|
||
|
in reality exactly one of these must be specified.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
FileHandle - a TDI handle.
|
||
|
|
||
|
FileObject - a pointer to the file object corresponding to a TDI
|
||
|
handle
|
||
|
|
||
|
IrpParameters - information to write to the parameters section of the
|
||
|
stack location of the IRP.
|
||
|
|
||
|
IrpParametersLength - length of the parameter information. Cannot be
|
||
|
greater than 16.
|
||
|
|
||
|
MdlBuffer - if non-NULL, a buffer of nonpaged pool to be mapped
|
||
|
into an MDL and placed in the MdlAddress field of the IRP.
|
||
|
|
||
|
MdlBufferLength - the size of the buffer pointed to by MdlBuffer.
|
||
|
|
||
|
MinorFunction - the minor function code for the request.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NTSTATUS -- Indicates the status of the request.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
NTSTATUS status;
|
||
|
PFILE_OBJECT fileObject;
|
||
|
PIRP irp;
|
||
|
PIO_STACK_LOCATION irpSp;
|
||
|
KEVENT event;
|
||
|
IO_STATUS_BLOCK ioStatusBlock;
|
||
|
PDEVICE_OBJECT deviceObject;
|
||
|
PMDL mdl;
|
||
|
|
||
|
PAGED_CODE( );
|
||
|
|
||
|
//
|
||
|
// Initialize the kernel event that will signal I/O completion.
|
||
|
//
|
||
|
|
||
|
KeInitializeEvent( &event, SynchronizationEvent, FALSE );
|
||
|
|
||
|
if( FileHandle != NULL ) {
|
||
|
|
||
|
ASSERT( FileObject == NULL );
|
||
|
|
||
|
//
|
||
|
// Get the file object corresponding to the directory's handle.
|
||
|
// Referencing the file object every time is necessary because the
|
||
|
// IO completion routine dereferences it.
|
||
|
//
|
||
|
|
||
|
status = ObReferenceObjectByHandle(
|
||
|
FileHandle,
|
||
|
0L, // DesiredAccess
|
||
|
NULL, // ObjectType
|
||
|
KernelMode,
|
||
|
(PVOID *)&fileObject,
|
||
|
NULL
|
||
|
);
|
||
|
if ( !NT_SUCCESS(status) ) {
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
ASSERT( FileObject != NULL );
|
||
|
|
||
|
//
|
||
|
// Reference the passed in file object. This is necessary because
|
||
|
// the IO completion routine dereferences it.
|
||
|
//
|
||
|
|
||
|
ObReferenceObject( FileObject );
|
||
|
|
||
|
fileObject = FileObject;
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set the file object event to a non-signaled state.
|
||
|
//
|
||
|
|
||
|
(VOID) KeResetEvent( &fileObject->Event );
|
||
|
|
||
|
//
|
||
|
// Attempt to allocate and initialize the I/O Request Packet (IRP)
|
||
|
// for this operation.
|
||
|
//
|
||
|
|
||
|
deviceObject = IoGetRelatedDeviceObject ( fileObject );
|
||
|
|
||
|
irp = IoAllocateIrp( (deviceObject)->StackSize, TRUE );
|
||
|
if ( irp == NULL ) {
|
||
|
ObDereferenceObject( fileObject );
|
||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Fill in the service independent parameters in the IRP.
|
||
|
//
|
||
|
|
||
|
irp->Flags = (LONG)IRP_SYNCHRONOUS_API;
|
||
|
irp->RequestorMode = KernelMode;
|
||
|
irp->PendingReturned = FALSE;
|
||
|
|
||
|
irp->UserIosb = &ioStatusBlock;
|
||
|
irp->UserEvent = &event;
|
||
|
|
||
|
irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
|
||
|
|
||
|
irp->AssociatedIrp.SystemBuffer = NULL;
|
||
|
irp->UserBuffer = NULL;
|
||
|
|
||
|
irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||
|
irp->Tail.Overlay.OriginalFileObject = fileObject;
|
||
|
irp->Tail.Overlay.AuxiliaryBuffer = NULL;
|
||
|
|
||
|
/*
|
||
|
DEBUG ioStatusBlock.Status = STATUS_UNSUCCESSFUL;
|
||
|
DEBUG ioStatusBlock.Information = (ULONG)-1;
|
||
|
*/
|
||
|
//
|
||
|
// If an MDL buffer was specified, get an MDL, map the buffer,
|
||
|
// and place the MDL pointer in the IRP.
|
||
|
//
|
||
|
|
||
|
if ( MdlBuffer != NULL ) {
|
||
|
|
||
|
mdl = IoAllocateMdl(
|
||
|
MdlBuffer,
|
||
|
MdlBufferLength,
|
||
|
FALSE,
|
||
|
FALSE,
|
||
|
irp
|
||
|
);
|
||
|
if ( mdl == NULL ) {
|
||
|
IoFreeIrp( irp );
|
||
|
ObDereferenceObject( fileObject );
|
||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
|
||
|
MmBuildMdlForNonPagedPool( mdl );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
irp->MdlAddress = NULL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Put the file object pointer in the stack location.
|
||
|
//
|
||
|
|
||
|
irpSp = IoGetNextIrpStackLocation( irp );
|
||
|
irpSp->FileObject = fileObject;
|
||
|
irpSp->DeviceObject = deviceObject;
|
||
|
|
||
|
//
|
||
|
// Fill in the service-dependent parameters for the request.
|
||
|
//
|
||
|
|
||
|
ASSERT( IrpParametersLength <= sizeof(irpSp->Parameters) );
|
||
|
RtlCopyMemory( &irpSp->Parameters, IrpParameters, IrpParametersLength );
|
||
|
|
||
|
irpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
|
||
|
irpSp->MinorFunction = MinorFunction;
|
||
|
|
||
|
//
|
||
|
// Set up a completion routine which we'll use to free the MDL
|
||
|
// allocated previously.
|
||
|
//
|
||
|
|
||
|
IoSetCompletionRoutine( irp, IrdaRestartDeviceControl, NULL, TRUE, TRUE, TRUE );
|
||
|
|
||
|
//
|
||
|
// Queue the IRP to the thread and pass it to the driver.
|
||
|
//
|
||
|
|
||
|
IoEnqueueIrp( irp );
|
||
|
|
||
|
status = IoCallDriver( deviceObject, irp );
|
||
|
|
||
|
//
|
||
|
// If necessary, wait for the I/O to complete.
|
||
|
//
|
||
|
|
||
|
if ( status == STATUS_PENDING ) {
|
||
|
KeWaitForSingleObject( (PVOID)&event, UserRequest, KernelMode, FALSE, NULL );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the request was successfully queued, get the final I/O status.
|
||
|
//
|
||
|
|
||
|
if ( NT_SUCCESS(status) ) {
|
||
|
status = ioStatusBlock.Status;
|
||
|
}
|
||
|
|
||
|
return status;
|
||
|
|
||
|
} // IrdaIssueDeviceControl
|
||
|
|