📄 ksutil.c
字号:
IoFreeIrp( pIrp );
return STATUS_MORE_PROCESSING_REQUIRED;
}
/////////////////////////////////////////////////////////////////////////////
//// KS_SendDatagramOnAddress
//
// Purpose
// Send a chain of MDLs as a datagram on the transport address object.
//
// Parameters
// pSendMdl
// Pointer to the first Memory Descriptor List (MDL) of the datagram
// to be sent.
//
// pKS_Address
// Pointer to the KS_ADDRESS structure that specifies the transport
// address object that the datagram will be sent on.
//
// pIoStatusBlock
// Pointer to a caller provided IO_STATUS_BLOCK structure that received
// final completion status and sent byte count.
//
// UserCompletionRoutine
// Specifies the entry point for the caller-supplied completion routine
// to be called when the lower-level TDI driver completes the operation.
// This routine is declared as follows:
//
// VOID
// (*PKS_REQUEST_COMPLETION_ROUTINE) (
// PVOID UserCompletionContext,
// PIO_STATUS_BLOCK IoStatusBlock,
// ULONG Reserved
// );//
//
// UserCompletionContext
// The value to be passed to UserCompletionRoutine.
//
// Remarks
// This function sends a chain of MDLs that represent the datagram to be sent.
// The number of bytes to be sent is specified is the sum of the MDL byte
// counts for all MDLs in the chain. Having the Next field set to NULL
// identifies the last MDL in the chain. The byte count of each MDL in the
// chain is queried using MmGetMdlByteCount.
//
// Each of the MDLs in the chain must have been probed and locked before
// calling KS_SendDatagramOnAddress.
//
// Synchronous/Asynchronous Operation
// ----------------------------------
// Synchronous Send
// If UserCompletionEvent and UserCompletionRoutine are both NULL the send will
// be performed synchronously.
//
// Asynchronous Send (Event Wait)
// If a UserCompletionEvent is specified then the send will be performed
// asynchronously. The framework will set the specified event when the
// send is completed.
//
// If UserCompletionEvent is specified, then UserCompletionRoutine and
// UserCompletionContext are ignored.
//
// Asynchronous Send (Completion Routine)
// If a UserCompletionEvent is NOT specified (i.e., it is NULL) and a
// UserCompletionRoutine is specified, then the send will be performed
// asynchronously. The framework will call the specified completion
// routine when the send is completed and pass UserCompletionContext
// as the context.
//
// In this implementation it is an error to specify both a UserCompletionEvent
// and a UserCompletionRoutine. Only one of these two methods can be used.
//
// If the synchronous mode of operation is employed, then the caller of
// KS_SendDatagramOnAddress must be running at IRQL PASSIVE_LEVEL. If the
// caller intends to wait on the event specified by UserCompletionEvent,
// then the waiting must be performed at IRQL PASSIVE_LEVEL.
//
// For all methods the IO_STATUS_BLOCK pointed to by pIoStatusBlock will
// receive the final completion status and information about the requested
// send operation.
//
NTSTATUS
KS_SendDatagramOnAddress(
PKS_ADDRESS pKS_Address,
HANDLE UserCompletionEvent, // Optional
PKS_REQUEST_COMPLETION_ROUTINE UserCompletionRoutine, // Optional
PVOID UserCompletionContext, // Optional
PIO_STATUS_BLOCK pIoStatusBlock, // Required
PMDL pSendMdl,
PTDI_CONNECTION_INFORMATION pSendDatagramInfo
)
{
NTSTATUS Status;
PIRP pSendIrp;
ULONG Length;
KEVENT SyncEvent;
BOOLEAN bSynchronous = FALSE;
PKS_ADDRESS_REQUEST_CONTEXT pKS_RequestContext = NULL;
PDEVICE_OBJECT pDeviceObject;
PMDL pNextMdl;
ASSERT( pKS_Address );
//
// Allocate Memory For Private Completion Context
//
Status = NdisAllocateMemory(
&pKS_RequestContext,
sizeof( KS_ADDRESS_REQUEST_CONTEXT ),
0, // Allocate non-paged system-space memory
HighestAcceptableMax
);
if( !NT_SUCCESS( Status ) )
{
return( STATUS_INSUFFICIENT_RESOURCES );
}
RtlZeroMemory( pKS_RequestContext, sizeof( KS_ADDRESS_REQUEST_CONTEXT ) );
if( pIoStatusBlock )
{
pKS_RequestContext->m_pIoStatusBlock = pIoStatusBlock;
}
else
{
pKS_RequestContext->m_pIoStatusBlock = &pKS_RequestContext->m_SafeIoStatusBlock;
}
pKS_RequestContext->m_pKS_Address = pKS_Address;
if( UserCompletionRoutine )
{
pKS_RequestContext->m_CompletionEvent = UserCompletionEvent;
pKS_RequestContext->m_CompletionRoutine = UserCompletionRoutine;
pKS_RequestContext->m_CompletionContext = UserCompletionContext;
bSynchronous = FALSE;
}
else if( UserCompletionEvent )
{
pKS_RequestContext->m_CompletionEvent = UserCompletionEvent;
KeResetEvent( pKS_RequestContext->m_CompletionEvent );
pKS_RequestContext->m_CompletionRoutine = NULL;
pKS_RequestContext->m_CompletionContext = NULL;
bSynchronous = FALSE;
}
else
{
pKS_RequestContext->m_CompletionEvent = &SyncEvent;
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
KeInitializeEvent(
pKS_RequestContext->m_CompletionEvent,
NotificationEvent,
FALSE
);
pKS_RequestContext->m_CompletionRoutine = NULL;
pKS_RequestContext->m_CompletionContext = NULL;
bSynchronous = TRUE;
}
pDeviceObject = IoGetRelatedDeviceObject( pKS_Address->m_pFileObject );
//
// Allocate IRP For Sending
//
pSendIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE );
if( !pSendIrp )
{
return( STATUS_INSUFFICIENT_RESOURCES );
}
Length = 0;
pNextMdl = pSendMdl;
while( pNextMdl )
{
Length += MmGetMdlByteCount( pNextMdl );
pNextMdl = pNextMdl->Next;
}
TdiBuildSendDatagram(
pSendIrp,
pDeviceObject,
pKS_Address->m_pFileObject,
_I_KS_AddressRequestComplete, // Completion routine
pKS_RequestContext, // Completion context
pSendMdl, // the data buffer
Length, // send buffer length
pSendDatagramInfo
);
//
// Reference The Address Object
//
_I_KS_RefTransportAddress( pKS_RequestContext->m_pKS_Address );
//
// Submit the request
//
(pKS_RequestContext->m_pIoStatusBlock)->Status = STATUS_UNSUCCESSFUL;
(pKS_RequestContext->m_pIoStatusBlock)->Information = 0;
Status = IoCallDriver( pDeviceObject, pSendIrp );
if( bSynchronous )
{
if( (Status == STATUS_SUCCESS) || (Status == STATUS_PENDING) )
{
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
Status = KeWaitForSingleObject(
&SyncEvent, // Object to wait on.
Executive, // Reason for waiting
KernelMode, // Processor mode
FALSE, // Alertable
NULL // Timeout
);
if( NT_SUCCESS( Status ) )
{
Status = pSendIrp->IoStatus.Status;
}
}
}
if( !NT_SUCCESS( Status ) )
{
//
// Handle Case Where Completion Function Will Not Be Called...
//
//
// Dereference The Address Object
//
_I_KS_DerefTransportAddress( pKS_RequestContext->m_pKS_Address );
//
// Free Memory Allocated For Private Completion Context
//
NdisFreeMemory(
pKS_RequestContext,
sizeof( KS_ADDRESS_REQUEST_CONTEXT ),
0
);
IoFreeIrp( pSendIrp );
}
return( Status );
}
/////////////////////////////////////////////////////////////////////////////
//// KS_ReceiveDatagramOnAddress
//
// Purpose
// Requests the underlying TDI transport to indicate a received datagram on
// the specified transport address.
//
// Parameters
// pReceiveMdl
// Pointer to the first Memory Descriptor List (MDL), in a possible
// chain of MDLs, that will be filled with the received datagram.
//
// pKS_Address
// Pointer to the KS_ADDRESS structure that specifies the transport
// address object that the datagram will be received on.
//
// pIoStatusBlock
// Pointer to a caller provided IO_STATUS_BLOCK structure that received
// final completion status and received byte count.
//
// UserCompletionRoutine
// Specifies the entry point for the caller-supplied completion routine
// to be called when the lower-level TDI driver completes the operation.
// This routine is declared as follows:
//
// VOID
// (*PKS_REQUEST_COMPLETION_ROUTINE) (
// PVOID UserCompletionContext,
// PIO_STATUS_BLOCK IoStatusBlock,
// ULONG Reserved
// );//
//
// UserCompletionContext
// The value to be passed to UserCompletionRoutine.
//
// Remarks
// This function passes a chain of MDLs to the underlying TDI transport.
// The TDI transport will fill the memory wrapped by these MDLs with a datagram
// received on the specified transport address. The maximum datagram size that
// can be received is the sum of the MDL byte counts for all MDLs in the chain.
// Having the Next field set to NULL identifies the last MDL in the chain. The
// byte count of each MDL in the chain is queried using MmGetMdlByteCount.
//
// Each of the MDLs in the chain must have been probed and locked before calling
// KS_ReceiveDatagramOnAddress.
//
// Synchronous/Asynchronous Operation
// ----------------------------------
// Synchronous Receive
// If UserCompletionEvent and UserCompletionRoutine are both NULL the receive
// will be performed synchronously.
//
// Asynchronous Receive (Event Wait)
// If a UserCompletionEvent is specified then the receive will be performed
// asynchronously. The framework will set the specified event when the
// datagram is received.
//
// If UserCompletionEvent is specified, then UserCompletionRoutine and
// UserCompletionContext are ignored.
//
// Asynchronous Receive (Completion Routine)
// If a UserCompletionEvent is NOT specified (i.e., it is NULL) and a
// UserCompletionRoutine is specified, then the receive will be performed
// asynchronously. The framework will call the specified completion
// routine when the datagram is received and pass UserCompletionContext
// as the context.
//
// In this implementation it is an error to specify both a UserCompletionEvent
// and a UserCompletionRoutine. Only one of these two methods can be used.
//
// If the synchronous mode of operation is employed, then the caller of
// KS_ReceiveDatagramOnAddress must be running at IRQL PASSIVE_LEVEL. If the
// caller intends to wait on the event specified by UserCompletionEvent,
// then the waiting must be performed at IRQL PASSIVE_LEVEL.
//
// For all methods the IO_STATUS_BLOCK pointed to by pIoStatusBlock will
// receive the final completion status and information about the requested
// send operation.
//
NTSTATUS
KS_ReceiveDatagramOnAddress(
PKS_ADDRESS pKS_Address,
HANDLE UserCompletionEvent, // Optional
PKS_REQUEST_COMPLETION_ROUTINE UserCompletionRoutine, // Optional
PVOID UserCompletionContext, // Optional
PIO_STATUS_BLOCK pIoStatusBlock, // Required
PMDL pReceiveMdl,
PTDI_CONNECTION_INFORMATION pReceiveDatagramInfo,
PTDI_CONNECTION_INFORMATION pReturnInfo,
ULONG InFlags
)
{
NTSTATUS Status;
PIRP pReceiveIrp;
ULONG Length;
KEVENT SyncEvent;
BOOLEAN bSynchronous = FALSE;
PKS_ADDRESS_REQUEST_CONTEXT pKS_RequestContext = NULL;
PDEVICE_OBJECT pDeviceObject;
PMDL pNextMdl;
ASSERT( pKS_Address );
//
// Allocate Memory For Private Completion Context
//
Status = NdisAllocateMemory(
&pKS_RequestContext,
sizeof( KS_ADDRESS_REQUEST_CONTEXT ),
0, // Allocate non-paged system-space memory
HighestAcceptableMax
);
if( !NT_SUCCESS( Status ) )
{
return( STATUS_INSUFFICIENT_RESOURCES );
}
RtlZeroMemory( pKS_RequestContext, sizeof( KS_ADDRESS_REQUEST_CONTEXT ) );
if( pIoStatusBlock )
{
pKS_RequestContext->m_pIoStatusBlock = pIoStatusBlock;
}
else
{
pKS_RequestContext->m_pIoStatusBlock = &pKS_RequestContext->m_SafeIoStatusBlock;
}
pKS_RequestContext->m_pKS_Address = pKS_Address;
if( UserCompletionRoutine )
{
pKS_RequestContext->m_CompletionEvent = UserCompletionEvent;
pKS_RequestContext->m_CompletionRoutine = UserCompletionRoutine;
pKS_RequestContext->m_CompletionContext = UserCompletionContext;
bSynchronous = FALSE;
}
else if( UserCompletionEvent )
{
pKS_RequestContext->m_CompletionEvent = UserCompletionEvent;
KeResetEvent( pKS_RequestContext->m_CompletionEvent );
pKS_RequestContext->m_CompletionRoutine = NULL;
pKS_RequestContext->m_CompletionContext = NULL;
bSynchronous = FALSE;
}
else
{
pKS_RequestContext->m_CompletionEvent = &SyncEvent;
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
KeInitializeEvent(
pKS_RequestContext->m_CompletionEvent,
NotificationEvent,
FALSE
);
pKS_RequestContext->m_CompletionRoutine = NULL;
pKS_RequestContext->m_CompletionContext = NULL;
bSynchronous = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -