📄 tdiclient.c
字号:
Routine Description:
Free recvContext.
Arguments:
lpContext - pointer to recvContext.
Return Value:
NT status code.
--*/
{
if ( lpContext->pIrp )
{
IoFreeIrp ( lpContext->pIrp );
lpContext->pIrp = NULL;
}
if ( lpContext->bLocked )
{
MmUnlockPages ( lpContext->pMdl );
lpContext->bLocked = FALSE;
}
if ( lpContext->pMdl )
{
IoFreeMdl ( lpContext->pMdl );
lpContext->pMdl = NULL;
}
return STATUS_SUCCESS;
}
/**************************************************************************************************/
/* */
/* Build and send down an Irp for Receive. */
/* */
/* Notes: */
/* 1) This routine is NOT synchronous (no particular reason it's not, other than to show */
/* off asynchronous operation of an Irp). */
/* */
/* 2) There are indications that an MDL and probe-and-lock are needed even if the buffer */
/* is from the non-paged pool. Eg, microsoft.public.win32.programmer.kernel, */
/* "MmProbeAndLockPages bug checks," dave porter, 2001-03-02. But see the further */
/* discussion in comp.os.ms-windows.programmer.nt.kernel-mode, "Free MDL in completion */
/* routine," 1999/05/09. */
/* */
/* 3) Although not documented, it appears that the Irp, the Mdl and the locking are undone */
/* by the transport. There are claims to that effect in several places in newsgroups, */
/* and freeing the MDL always caused errors in a test (eg, bad pool caller or touching */
/* paged storage at wrong IRQL). Further, testing showed that IoFreeMdl() was being */
/* called by somebody (presumably, the transport) for a given MDL. */
/* */
/* 4) The supplied context (pCtx) is an event, which the I/O completion routine for the */
/* Receive Irp will signal. */
/* */
/**************************************************************************************************/
NTSTATUS TDIQueryNetworkInformation( PDEVICE_OBJECT DeviceObject, PIRP Irp )
{
PDEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION IrpStack;
IO_STATUS_BLOCK IoStatus;
NTSTATUS status;
ULONG InputLength, OutputLength;
ULONG QType;
PIRP pIrp;
KEVENT Event;
PMDL pMdl;
ULONG_PTR virtualAddress;
EXCEPTION_POINTERS * pExceptionInfo;
ULONG lclExceptionCode;
PVOID lclExceptionAddr;
BOOLEAN pageLocked;
deviceExtension = DeviceObject->DeviceExtension;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
QType = *((ULONG *)Irp->AssociatedIrp.SystemBuffer);
DebugPrint(("QueryNetworkInformation: QType = %x\n", QType ));
KeInitializeEvent(&Event, NotificationEvent, FALSE);
pIrp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION ,
deviceExtension->TDILowerDeviceObject, // TDI driver's device object.
deviceExtension->lpTransAddrFileObject, // Address file object.
&Event, // Event to be signalled when Irp completes.
&IoStatus // I/O status block.
);
if (NULL==pIrp)
return STATUS_INSUFFICIENT_RESOURCES;
virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(Irp->MdlAddress);
OutputLength = MmGetMdlByteCount(Irp->MdlAddress);
pMdl = IoAllocateMdl( (PVOID)virtualAddress, OutputLength, FALSE, FALSE, NULL);
pageLocked = FALSE;
_try{
MmProbeAndLockPages(pMdl, KernelMode, IoModifyAccess );
pageLocked = TRUE;
}
_except(
pExceptionInfo = GetExceptionInformation(),
lclExceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode,
lclExceptionAddr = pExceptionInfo->ExceptionRecord->ExceptionAddress,
EXCEPTION_EXECUTE_HANDLER
)
{
DebugPrint((".TDIClnRecv: MmProbeAndLockPages() failed. Error = 0x%08x at 0x%08x\n",
lclExceptionCode, lclExceptionAddr));
status = lclExceptionCode;
goto done;
}
TdiBuildQueryInformation ( pIrp, deviceExtension->TDILowerDeviceObject,
deviceExtension->lpTransAddrFileObject,
NULL, NULL, QType, pMdl );
status = IoCallDriver ( deviceExtension->TDILowerDeviceObject, pIrp );
if (STATUS_PENDING==status)
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, 0);
done:
status = ((STATUS_SUCCESS==status) || (STATUS_PENDING==status)) ? IoStatus.Status : status;
Irp->IoStatus.Information = IoStatus.Information;
DebugPrint(("QueryInfo: status %x, Info %d\n", status, Irp->IoStatus.Information ));
return status;
}
NTSTATUS
TDIClnSetEventHandler(
PFILE_OBJECT pAddrFileObj, // Address file object.
PDEVICE_OBJECT pTcpDevObj, // TDI driver's device object.
LONG EventType, // Type of event.
PVOID pEventHandler, // Event handler routine.
PVOID pEventContext // Context for event handler.
)
/**************************************************************************************************/
/* */
/* Set up an event handler. */
/* */
/* Note: This routine is synchronous. */
/* */
/**************************************************************************************************/
{
NTSTATUS status;
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
PIRP pIrp;
do { // Single-iteration loop, to make possible escape via break.
KeInitializeEvent(&Event, NotificationEvent, FALSE);
// Get an Irp for internal device ioctl.
pIrp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER,
pTcpDevObj, // TDI driver's device object.
pAddrFileObj, // Address file object.
&Event, // Event to be signalled when Irp completes.
&IoStatus // I/O status block.
);
if (NULL==pIrp)
{
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
TdiBuildSetEventHandler(pIrp,
pTcpDevObj,
pAddrFileObj,
NULL, // I/O completion routine.
NULL, // Context for I/O completion routine.
EventType,
pEventHandler, // Event handler routine.
pEventContext // Context for event handler routine.
);
status = IoCallDriver(pTcpDevObj, pIrp);
if (STATUS_PENDING==status) // Have to wait on this Irp?
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, 0);
// Problem from IoCallDriver() or Problem discovered in completion?
if ( ( STATUS_SUCCESS!=status && STATUS_PENDING!=status )
|| ( STATUS_PENDING==status && 0!=IoStatus.Status ) )
{
// Note: If problem was in IoCallDriver(), IoStatus.Status probably won't be meaningful.
DebugPrint(("TDIClnSetEventHandler: Problem in IoCallDriver(). status = 0x%08x, IoStatus.Status = 0x%08x\n",
STATUS_PENDING==status ? 0 : status , IoStatus.Status));
}
} while(0); // End 'do-while' single-iteration loop.
status = ((STATUS_SUCCESS==status) || (STATUS_PENDING==status)) ? IoStatus.Status : status;
return status;
} // End TDIClnSetEventHandler().
NTSTATUS
TDIOpenTransportAddress(
PWSTR pTransDevName, // Transport device name.
PHANDLE pHandle, // Output handle address.
PFILE_OBJECT * ppAddrFileObj, // Output address file object.
USHORT Port // Port to open.
)
/**************************************************************************************************/
/* */
/* Open transport address. */
/* */
/**************************************************************************************************/
{
NTSTATUS status;
UNICODE_STRING TransDeviceName;
OBJECT_ATTRIBUTES Attr;
IO_STATUS_BLOCK IoStatus;
PTA_IP_ADDRESS pSin;
PFILE_FULL_EA_INFORMATION pEa;
char Buffer[sizeof(FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + sizeof(TA_IP_ADDRESS)];
ASSERT ( *pHandle == NULL );
ASSERT ( *ppAddrFileObj == NULL );
RtlInitUnicodeString(&TransDeviceName, // Build Unicode transport device name.
pTransDevName
);
InitializeObjectAttributes(&Attr, // Attributes (to be initialized);
&TransDeviceName,
OBJ_CASE_INSENSITIVE
|
OBJ_KERNEL_HANDLE, // Only in kernel mode but in any process.
0,
0
);
pEa = (PFILE_FULL_EA_INFORMATION)Buffer;
pEa->NextEntryOffset= 0;
pEa->Flags = 0;
pEa->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; // Length of TdiTransportAddress, namely of "TransportAddress" string less 1 (ie, without terminator).
RtlCopyMemory ( pEa->EaName, TdiTransportAddress, pEa->EaNameLength + 1 );
pEa->EaValueLength = sizeof(TA_IP_ADDRESS); // Length of structure.
// Point to Buffer just after what's been used (ie, after terminator).
pSin =(PTA_IP_ADDRESS) ( pEa->EaName + pEa->EaNameLength + 1);
pSin->TAAddressCount= 1;
pSin->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
pSin->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
pSin->Address[0].Address[0].sin_port = Port;
pSin->Address[0].Address[0].in_addr = 0;//0x601a8c0; // 192.168.1.6
RtlZeroMemory ( pSin->Address[ 0 ].Address[ 0 ].sin_zero, sizeof ( pSin->Address[ 0 ].Address[ 0 ].sin_zero ) );
status = ZwCreateFile(pHandle, // Actual open of transport address.
GENERIC_READ | GENERIC_WRITE,
&Attr,
&IoStatus,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
0,
pEa, //NULL,
sizeof ( Buffer )
);
if (!NT_SUCCESS(status))
{
DebugPrint(("ZwCreateFile failed with status %x\n", status ));
return status;
}
status = ObReferenceObjectByHandle(*pHandle, // Get the object pointer for the address file object's handle.
GENERIC_READ | GENERIC_WRITE,
0,
KernelMode,
(PVOID *)ppAddrFileObj,
NULL
);
if (!NT_SUCCESS(status))
{
DebugPrint(("ObReferenceObject failed with status %x\n", status ));
ZwClose ( *pHandle );
*pHandle = NULL;
}
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -