TDIClient.c
资源名称:虚拟串口驱动程序.rar [点击查看]
上传用户:zanmei2
上传日期:2010-03-06
资源大小:775k
文件大小:32k
源码类别:
通讯编程文档
开发平台:
C/C++
- /*++
- Copyright (c) 2005 Changzhi Zhou All Rights Reserved
- Module Name:
- TDIClient.c
- Abstract:
- This module contains the routines relevant to TDI client calls.
- Environment:
- Kernel mode
- Revision History:
- Changzhi Zhou Feb 5, 2005
- --*/
- #include "TDIClient.h"
- #include "main.h"
- NTSTATUS InitializeConnection( PDEVICE_EXTENSION deviceExtension )
- /*++
- Routine Description:
- 1. Open a transport address and get the highest deviceobject of the transport stack.
- 2. Build RecvContext in the DeviceExtension
- 3. SetTdiEventHandle, includes TDI_EVENT_RECEIVE_DATAGRAM and TDI_EVENT_ERROR
- Arguments:
- deviceExtension - pointer to a device object extension.
- Return Value:
- NT status code.
- --*/
- {
- NTSTATUS status;
- static USHORT Port = LOCAL_PORT;
- if ( ( deviceExtension->hTransAddr ) || ( deviceExtension->lpTransAddrFileObject ) )
- return STATUS_INVALID_DEVICE_STATE;
- status = TDIOpenTransportAddress( wcharNetDevName,
- &deviceExtension->hTransAddr,
- &deviceExtension->lpTransAddrFileObject,
- Port
- );
- DebugPrint(("OpenTransAddr: handle = %x, lpFileObj = %x, status = %xn",
- deviceExtension->hTransAddr, deviceExtension->lpTransAddrFileObject, status ));
- if ( status != STATUS_SUCCESS )
- {
- deviceExtension->lpTransAddrFileObject = NULL;
- deviceExtension->hTransAddr = NULL;
- return status;
- }
- Port += 0x100;
- deviceExtension->TDILowerDeviceObject = IoGetRelatedDeviceObject( deviceExtension->lpTransAddrFileObject );
- DebugPrint(("TDI Provider: 0x%xn", deviceExtension->TDILowerDeviceObject ));
- if ( deviceExtension->TDILowerDeviceObject == NULL )
- {
- ObDereferenceObject ( deviceExtension->lpTransAddrFileObject );
- ZwClose ( deviceExtension->hTransAddr );
- deviceExtension->lpTransAddrFileObject = NULL;
- deviceExtension->hTransAddr = NULL;
- return STATUS_UNSUCCESSFUL;
- }
- TDIBuildRecvContext( &deviceExtension->recvContext );
- TDIClnSetEventHandler( deviceExtension->lpTransAddrFileObject,
- deviceExtension->TDILowerDeviceObject, TDI_EVENT_RECEIVE_DATAGRAM,
- TDIEventRecvDatagram, deviceExtension );
- TDIClnSetEventHandler( deviceExtension->lpTransAddrFileObject,
- deviceExtension->TDILowerDeviceObject, TDI_EVENT_ERROR,
- TDIEventError, NULL );
- return status;
- }
- NTSTATUS Disconnection ( PDEVICE_EXTENSION deviceExtension )
- /*++
- Routine Description:
- 1. SetTdiEventhandle TDI_EVENT_RECEIVE_DATAGRAM to NULL
- 2. Free RecvContext in the DeviceExtension
- 3. Close an opened transport address.
- 3. SetTdiEventHandle, includes TDI_EVENT_RECEIVE_DATAGRAM and TDI_EVENT_ERROR
- Arguments:
- deviceExtension - pointer to a device object extension.
- Return Value:
- NT status code.
- --*/
- {
- NTSTATUS status;
- if ( ( deviceExtension->hTransAddr == NULL ) || ( deviceExtension->lpTransAddrFileObject == NULL ) )
- return STATUS_INVALID_DEVICE_STATE;
- TDIClnSetEventHandler( deviceExtension->lpTransAddrFileObject,
- deviceExtension->TDILowerDeviceObject, TDI_EVENT_RECEIVE_DATAGRAM,
- NULL, deviceExtension );
- TDIFreeRecvContext( &deviceExtension->recvContext );
- ObDereferenceObject ( deviceExtension->lpTransAddrFileObject );
- deviceExtension->lpTransAddrFileObject = NULL;
- status = ZwClose ( deviceExtension->hTransAddr );
- if ( status == STATUS_SUCCESS )
- deviceExtension->hTransAddr = NULL;
- else
- {
- DebugPrint(("ZwClose hTransAddr failed with status %x !n", status ));
- }
- return status;
- }
- NTSTATUS TDISendDatagram(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
- /*++
- Routine Description:
- This function is called in SampleWrite. It builds a internel irp and send down
- to the underlying transport. Until the irp completes or timeout, it will return.
- The remote peer's IP address and port are indicated by RemoteAddress and
- RemotePort in deviceExtension.
- 1. TdiBuildInternalDeviceControlIrp for TDI_SEND_DATAGRAM
- 2. Allocate and lockpage a MDL based on Irp->MdlAddress
- 3. TdiBuildSendDatagram and pass down to the underlying transport device.
- 4. Wait 3 seconds for the completion. If timeout, cancel the irp
- 5. Set the Irp according with the completed irp.
- Note:
- This routine is synchronous.
- It must be running at IRQL = PASSIVE_LEVEL
- Arguments:
- DeviceObject - pointer to a device object.
- Irp - pointer to an I/O Request Packet for IRP_MJ_WRITE.
- Return Value:
- NT status code.
- --*/
- {
- NTSTATUS status;
- PIRP pIrp;
- PDEVICE_EXTENSION deviceExtension;
- KEVENT Event;
- IO_STATUS_BLOCK IoStatus;
- PMDL pMdl;
- PVOID VirtualAddress;
- ULONG Length;
- EXCEPTION_POINTERS * pExceptionInfo;
- ULONG lclExceptionCode;
- PVOID lclExceptionAddr;
- PVOID SystemAddress;
- TA_IP_ADDRESS RmtAddress = {1, {TDI_ADDRESS_LENGTH_IP, TDI_ADDRESS_TYPE_IP, { REMOTE_PORT, REMOTE_ADDRESS}}};
- TDI_CONNECTION_INFORMATION RmtInfo = {0, 0, 0, 0, sizeof(RmtAddress), &RmtAddress};
- deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
- RmtAddress.Address->Address->sin_port = deviceExtension->RemotePort;
- RmtAddress.Address->Address->in_addr = deviceExtension->RemoteAddress;
- status = STATUS_SUCCESS;
- KeInitializeEvent( &Event, NotificationEvent, FALSE);
- pIrp = TdiBuildInternalDeviceControlIrp(
- TDI_SEND_DATAGRAM,
- deviceExtension->TDILowerDeviceObject,
- deviceExtension->lpTransAddrFileObject,
- &Event,
- &IoStatus );
- if ( NULL == pIrp )
- {
- DebugPrint(("TDISendDatagram: Allocate Irp failedn"));
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- VirtualAddress = MmGetMdlVirtualAddress ( Irp->MdlAddress );
- Length = MmGetMdlByteCount( Irp->MdlAddress );
- ASSERT ( VirtualAddress && Length );
- pMdl = IoAllocateMdl ( VirtualAddress, Length, FALSE, FALSE, pIrp );
- if ( NULL == pMdl )
- {
- DebugPrint(("TDISendDatagram: Allocate Mdl failedn"));
- return STATUS_INSUFFICIENT_RESOURCES;
- }
- _try
- {
- MmProbeAndLockPages(pMdl, // (Try to) fix buffer.
- KernelMode,
- IoModifyAccess
- );
- }
- _except(
- pExceptionInfo = GetExceptionInformation(),
- lclExceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode,
- lclExceptionAddr = pExceptionInfo->ExceptionRecord->ExceptionAddress,
- EXCEPTION_EXECUTE_HANDLER
- )
- {
- DebugPrint((".TDISendDatagram: MmProbeAndLockPages() failed. Error = 0x%08x at 0x%08xn",
- lclExceptionCode, lclExceptionAddr));
- status = STATUS_UNSUCCESSFUL;
- IoFreeMdl ( pMdl );
- CompleteRequest ( pIrp, status, 0 );
- Irp->IoStatus.Information = 0;
- return status;
- }
- TdiBuildSendDatagram(
- pIrp,
- deviceExtension->TDILowerDeviceObject,
- deviceExtension->lpTransAddrFileObject,
- NULL,
- NULL,
- pMdl,
- Length,
- &RmtInfo
- );
- status = IoCallDriver ( deviceExtension->TDILowerDeviceObject, pIrp );
- if( ( status != STATUS_SUCCESS ) || ( STATUS_PENDING != status ) )
- {
- DebugPrint(("TDISendDatagram: Problem in IoCallDriver with status %xn", status ));
- }
- if ( status == STATUS_PENDING )
- {
- LARGE_INTEGER TimeOut;
- NTSTATUS waitStatus;
- DebugPrint(("Send data pending... wait for 3 secondsn"));
- TimeOut.QuadPart = -30000 * 1000; // Calculate timeout value (5 seconds from now).
- waitStatus = KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, &TimeOut);
- if ( STATUS_TIMEOUT == waitStatus )
- {
- DebugPrint(("TDISendDatagram: Send data time out...n"));
- IoCancelIrp ( pIrp );
- KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, 0);
- }
- }
- Irp->IoStatus.Information = IoStatus.Information;
- DebugPrint(("TDISendDatagram: Send %d bytesn", Irp->IoStatus.Information ));
- status = ((STATUS_SUCCESS==status) || (STATUS_PENDING== status)) ? IoStatus.Status : status;
- return status;
- }
- NTSTATUS TDIEventError(
- IN PVOID TdiEventContext, // The endpoint's file object.
- IN NTSTATUS Status // Status code indicating error type.
- )
- /*++
- Tdi error handle.
- --*/
- {
- DebugPrint(("Sample ErrorEventHandler: Status: 0x%8.8Xn", Status) );
- return( STATUS_SUCCESS );
- }
- NTSTATUS TDIEventRecvDatagram(
- IN PVOID TdiEventContext,
- IN LONG SourceAddressLength,
- IN PVOID SourceAddress,
- IN LONG OptionsLength,
- IN PVOID Options,
- IN ULONG ReceiveDatagramFlags,
- IN ULONG BytesIndicated,
- IN ULONG BytesAvailable,
- OUT ULONG *BytesTaken,
- IN PVOID Tsdu,
- OUT PIRP *IoRequestPacket
- )
- /*++
- Routine Description:
- TDI_EVENT_RECEIVE_DATAGRAM handle.
- When a UDP packet from particular address and port arrive, this callback function will be called.
- Usually BytesIndicated is less than or equal to BytesAvailable. If less, a Irp should be buildt
- for the remainder data. This irp has be pre-allocated by TDIBuildRecvContext.
- Note:
- Don't forget to call IoSetNextIrpStackLocation to handle the IoRequestPacket.
- Because the stack locations of this irp between this function and underlying transport are identical.
- Pls refer to Windows DDK documentation chapter relevant to this handle.
- --*/
- {
- LONG i;
- PUCHAR p;
- PIRP pIrp;
- NTSTATUS status;
- ULONG BytesToCopy;
- ULONG stageSize;
- PDEVICE_EXTENSION deviceExtension;
- deviceExtension = (PDEVICE_EXTENSION)TdiEventContext;
- DebugPrint(("SourceAddress: "));
- p = (PUCHAR)SourceAddress;
- for( i = 0; i < SourceAddressLength; i++)
- {
- DbgPrint("%2x ", p[ i ] );
- }
- DbgPrint(("n"));
- DebugPrint(("ReceiveDatagramFlags: %xn", ReceiveDatagramFlags ));
- DebugPrint(("BytesIndicated: %dn", BytesIndicated ));
- DebugPrint(("BytesAvailable: %dn", BytesAvailable ));
- *BytesTaken = BytesIndicated;
- CopyToRingBuffer( deviceExtension, (PUCHAR)Tsdu, BytesIndicated );
- *IoRequestPacket = NULL;
- status = STATUS_SUCCESS;
- if ( BytesIndicated < BytesAvailable )
- {
- if ( deviceExtension->recvContext.pIrp )
- {
- pIrp = deviceExtension->recvContext.pIrp;
- DebugPrint(("EventRecvDatagram: pIrp = %xn", deviceExtension->recvContext.pIrp ));
- TdiBuildReceiveDatagram( pIrp,
- deviceExtension->TDILowerDeviceObject,
- deviceExtension->lpTransAddrFileObject,
- TDIRecvRemainderCompRoutine,
- deviceExtension,
- deviceExtension->recvContext.pMdl,
- 0,
- &(deviceExtension->recvContext.ReceiveDatagramInfo),
- &(deviceExtension->recvContext.ReturnInfo),
- TDI_RECEIVE_NORMAL);
- IoSetNextIrpStackLocation ( pIrp );
- *IoRequestPacket = pIrp;
- status = STATUS_MORE_PROCESSING_REQUIRED;
- }
- }
- return status;
- }
- VOID CopyToRingBuffer(
- PDEVICE_EXTENSION deviceExtension,
- PUCHAR LinearBuffer,
- ULONG BytesIndicated )
- /*++
- Routine Description:
- This function is called by TDIEventRecvDatagram and TDIRecvRemainderCompRoutine.
- It copies linear buffer containing network packet to ring buffer. If source buffer length
- is more than the length of ReceiveBuffer, the last part of LinearBuffer will be copied
- to destination buffer.
- If there is WaitOnMaskIrp in deviceExtension and the WaitMask meets SERIAL_EV_RXCHAR || SERIAL_EV_RLSD,
- it will complete the WaitOnMaskIrp to indicate the application that there are some data arrive.
- The destination ringbuffer, deviceExtension->RxBuffer, is shared with IRP_MJ_READ.
- So the access to the ringbuffer must be synchronous.
- Arguments:
- deviceExtension - pointer to device object extension
- LinearBuffer - Tsdu containing network packets.
- BytesIndicated - the length of LinearBuffer
- Return Value:
- NT status code.
- --*/
- {
- ULONG stageSize;
- KIRQL oldIrql;
- ULONG BytesToCopy;
- PUCHAR lpSrc;
- BytesToCopy = BytesIndicated;
- lpSrc = LinearBuffer;
- if ( BytesIndicated > RINGBUFFER_SIZE )
- {
- lpSrc = (PUCHAR)LinearBuffer + BytesIndicated - RINGBUFFER_SIZE;
- BytesToCopy = RINGBUFFER_SIZE;
- }
- KeAcquireSpinLock(&deviceExtension->ThreadSpinLock, &oldIrql);
- stageSize = deviceExtension->RxBuffer + RINGBUFFER_SIZE - deviceExtension->lpRx;
- if( BytesToCopy <= stageSize )
- RtlCopyMemory ( deviceExtension->lpRx, lpSrc, BytesToCopy );
- else
- {
- RtlCopyMemory ( deviceExtension->lpRx, lpSrc, stageSize );
- RtlCopyMemory ( deviceExtension->RxBuffer, lpSrc + stageSize, ( BytesToCopy - stageSize ) );
- }
- deviceExtension->lpRx = deviceExtension->RxBuffer + ( ( RINGBUFFER_SIZE - stageSize + BytesToCopy ) % RINGBUFFER_SIZE );
- deviceExtension->SerialStatus.AmountInInQueue += BytesToCopy;
- if ( deviceExtension->SerialStatus.AmountInInQueue > RINGBUFFER_SIZE )
- {
- deviceExtension->lpRead = deviceExtension->lpRx;
- deviceExtension->SerialStatus.AmountInInQueue = RINGBUFFER_SIZE;
- }
- if( ( deviceExtension->WaitOnMaskIrp ) &&
- ( ( deviceExtension->WaitMask & SERIAL_EV_RXCHAR ) || ( deviceExtension->WaitMask & SERIAL_EV_RLSD ) ) )
- {
- DebugPrint(("ClientEventRecv: Complete WaitOnMaskIrpn"));
- deviceExtension->SerialStatus.EofReceived = TRUE;
- *(PULONG)deviceExtension->WaitOnMaskIrp->AssociatedIrp.SystemBuffer = ( SERIAL_EV_RXCHAR | SERIAL_EV_RLSD );
- CompleteRequest( deviceExtension->WaitOnMaskIrp, STATUS_SUCCESS, sizeof( ULONG ) );
- deviceExtension->WaitOnMaskIrp = NULL;
- SampleIoDecrement( deviceExtension );
- }
- KeReleaseSpinLock( &deviceExtension->ThreadSpinLock, oldIrql );
- }
- NTSTATUS TDIBuildRecvContext( PRECV_CONTEXT lpContext)
- /*++
- Routine Description:
- This function is called by InitializeConnection.
- It builds RecvContext, including pIrp, pMdl, and locks the Mdl.
- Arguments:
- lpContext - pointer to deviceExtension->recvContext
- Return Value:
- NT status code.
- --*/
- {
- PIRP pIrp;
- PMDL pMdl;
- PDEVICE_EXTENSION deviceExtension;
- EXCEPTION_POINTERS * pExceptionInfo;
- ULONG lclExceptionCode;
- PVOID lclExceptionAddr;
- PIO_STACK_LOCATION ioStack;
- if( lpContext->pIrp || lpContext->pMdl || ( lpContext->RemainderBuffer == NULL ) )
- return STATUS_UNSUCCESSFUL;
- deviceExtension = CONTAINING_RECORD( lpContext, DEVICE_EXTENSION, recvContext );
- pIrp = IoAllocateIrp ( deviceExtension->TDILowerDeviceObject->StackSize + 2, FALSE );
- /*
- Because the irp will be used for many times, TdiBuildInternalDeviceControlIrp is not best.
- */
- /* pIrp = TdiBuildInternalDeviceControlIrp(
- TDI_RECEIVE_DATAGRAM,
- deviceExtension->TDILowerDeviceObject,
- deviceExtension->lpTransAddrFileObject,
- &lpContext->Event,
- &lpContext->IoStatus
- );
- */
- if (NULL == pIrp)
- {
- DebugPrint(("TdiBuildInternalIrp failedn"));
- return STATUS_INSUFFICIENT_RESOURCES;
- }else
- {
- DebugPrint(("TDIBuildRecvContext: pIrp = %xn", pIrp ));
- }
- pMdl = IoAllocateMdl ( lpContext->RemainderBuffer,
- RECVREMAINDER_BUFFER_SIZE, FALSE, FALSE, NULL );
- if (NULL==pMdl)
- {
- goto Error_Exit;
- }
- _try
- {
- // lockpage the Mdl, even though it is allocated based on NonPagesPool
- MmProbeAndLockPages(pMdl, // (Try to) fix buffer.
- KernelMode,
- IoModifyAccess
- );
- lpContext->bLocked = TRUE;
- DebugPrint(("RemainderBuffer: 0x%x, pMdl: 0x%xn", lpContext->RemainderBuffer, pMdl ));
- }
- _except(
- pExceptionInfo = GetExceptionInformation(),
- lclExceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode,
- lclExceptionAddr = pExceptionInfo->ExceptionRecord->ExceptionAddress,
- EXCEPTION_EXECUTE_HANDLER
- )
- {
- DebugPrint((".TDIClnRecv: MmProbeAndLockPages() failed. Error = 0x%08x at 0x%08xn",
- lclExceptionCode, lclExceptionAddr));
- goto Error_Exit;
- }
- lpContext->pIrp = pIrp;
- lpContext->pMdl = pMdl;
- return STATUS_SUCCESS;
- Error_Exit:
- if ( pMdl )
- IoFreeMdl ( pMdl );
- if ( pIrp )
- IoFreeIrp ( pIrp );
- return STATUS_UNSUCCESSFUL;
- }
- NTSTATUS
- TDIRecvRemainderCompRoutine(
- PDEVICE_OBJECT DeviceObject, // TDI driver's device object.
- PIRP pIrp, // Address of completed Irp.
- PVOID pCtx // Pointer to context.
- )
- /*++
- Routine Description:
- Completion routine of IoRequestPacket in TDIEventRecvDatagram.
- It copies receiving data in recvContext.RemainderBuffer to RxBuffer.
- The length of receining data is indicated by pIrp->IoStatus.Information.
- Arguments:
- DeviceObject - pointer to the device object
- pIrp - pointer to completed Irp, which is recvContext->pIrp
- pCtx - pointer to context, which is deviceExtension
- Return Value:
- NT status code.
- --*/
- {
- PDEVICE_EXTENSION deviceExtension;
- PRECV_CONTEXT lpContext;
- ULONG RecvDataLength;
- PUCHAR lpSrc;
- DebugPrint(("TDIRecvRemainderCompRoutine...n"));
- RecvDataLength = pIrp->IoStatus.Information;
- deviceExtension = (PDEVICE_EXTENSION)pCtx;
- DebugPrint(("Remainder length: %dn", RecvDataLength ));
- CopyToRingBuffer ( deviceExtension,
- (PUCHAR)deviceExtension->recvContext.RemainderBuffer,
- RecvDataLength );
- return STATUS_MORE_PROCESSING_REQUIRED;
- }
- NTSTATUS TDIFreeRecvContext( PRECV_CONTEXT lpContext )
- /*++
- 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 = %xn", 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%08xn",
- 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 %dn", 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%08xn",
- 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 %xn", 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 %xn", status ));
- ZwClose ( *pHandle );
- *pHandle = NULL;
- }
- return status;
- }