📄 functions.c
字号:
* This is where we perform our Network Writes
*
**********************************************************************/
VOID TdiExample_NetworkWriteThread(PVOID StartContext)
{
PTDI_EXAMPLE_CONTEXT pTdiExampleContext = (PVOID)StartContext;
PVOID pEvents[2];
NTSTATUS NtStatus;
DbgPrint("TdiExample_NetworkWriteThread Called \r\n");
/*
* This thread will continue until the instance handle is closed.
*
*/
while(pTdiExampleContext->bWriteThreadAlive)
{
pEvents[0] = (PVOID)&pTdiExampleContext->kWriteIrpReady;
pEvents[1] = (PVOID)&pTdiExampleContext->kWakeWriteIrpThread;
NtStatus = KeWaitForMultipleObjects(2, (PVOID)pEvents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);
/*
* The first wait object will return "STATUS_WAIT_0". Other objects will
* increment from there. We only send data on a wait of 0. The other
* return values from this function are simply used to wake up not send data.
*/
if(NtStatus == STATUS_WAIT_0)
{
BOOLEAN bMoreIrps = FALSE;
PIRP Irp;
/*
* We will need to remove an IRP from the Queue and then send the data. We will
* continue to do this until there are no more IRP's to send or the thread
* has been terminated.
*/
do {
bMoreIrps = FALSE;
Irp = HandleIrp_RemoveNextIrp(pTdiExampleContext->pWriteIrpListHead);
if(Irp)
{
NTSTATUS NtStatus;
UINT uiDataSent;
PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation(Irp);
Irp->Tail.Overlay.DriverContext[0] = NULL;
bMoreIrps = TRUE;
NtStatus = TdiFuncs_Send(pTdiExampleContext->TdiHandle.pfoConnection, Irp->AssociatedIrp.SystemBuffer, pIoStackLocation->Parameters.Write.Length, &uiDataSent);
Irp->IoStatus.Status = NtStatus;
Irp->IoStatus.Information = uiDataSent;
DbgPrint("TdiExample_NetworkWriteThread Complete IRP = 0x%0x \r\n", Irp);
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
}
} while(pTdiExampleContext->bWriteThreadAlive && bMoreIrps);
}
}
DbgPrint("TdiExample_NetworkWriteThread Exit \r\n");
}
/**********************************************************************
*
* TdiExample_CleanUp
*
* This is called when an instance of this driver is closed (CloseHandle)
*
* This is actually IRP_MJ_CLEANUP so we can release the IRP's.
*
**********************************************************************/
NTSTATUS TdiExample_CleanUp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION pIoStackIrp = NULL;
PTDI_EXAMPLE_CONTEXT pTdiExampleContext = NULL;
DbgPrint("TdiExample_CleanUp Called \r\n");
pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
pTdiExampleContext = (PTDI_EXAMPLE_CONTEXT)pIoStackIrp->FileObject->FsContext;
if(pTdiExampleContext)
{
/*
* The first thing we want to do is close the write thread. We will do this
* by signaling the thread and then waiting for it to be destroyed.
*
* 1. Set Boolean to False
* 2. Signal Thread to Wake Up
* 3. Wait for Thread Object to become signaled
* 4. Remove Reference to Thread Object
*
*/
pTdiExampleContext->bWriteThreadAlive = FALSE;
KeSetEvent(&pTdiExampleContext->kWakeWriteIrpThread, IO_NO_INCREMENT, FALSE);
NtStatus = KeWaitForSingleObject(pTdiExampleContext->pWriteThread, Executive, KernelMode, FALSE, NULL);
DbgPrint("Write Thread Close - 0x%0x\n", NtStatus);
NtStatus = STATUS_SUCCESS;
ObDereferenceObject(pTdiExampleContext->pWriteThread);
pTdiExampleContext->pWriteThread = NULL;
/*
* If the handle is connected disconnect. We no longer
* require the connection lock since we are currently closing this handle.
*/
if(pTdiExampleContext->csConnectionState == CS_CONNECTED)
{
TdiFuncs_Disconnect(pTdiExampleContext->TdiHandle.pfoConnection);
pTdiExampleContext->csConnectionState = CS_NOT_CONNECTED;
}
/*
* Free Handles, IRPs, etc.
*/
TdiFuncs_FreeHandles(&pTdiExampleContext->TdiHandle);
HandleIrp_FreeIrpListWithCleanUp(pTdiExampleContext->pReadIrpListHead);
HandleIrp_FreeIrpListWithCleanUp(pTdiExampleContext->pWriteIrpListHead);
DbgPrint("TdiExample_CleanUp Free = 0x%0x \r\n", pTdiExampleContext);
KMem_FreeNonPagedMemory(pTdiExampleContext);
pIoStackIrp->FileObject->FsContext = NULL;
}
Irp->IoStatus.Status = NtStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("TdiExample_CleanUp Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* TdiExample_IoControlInternal
*
* These are IOCTL's which can only be sent by other drivers.
*
**********************************************************************/
NTSTATUS TdiExample_IoControlInternal(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_NOT_SUPPORTED;
PIO_STACK_LOCATION pIoStackIrp = NULL;
DbgPrint("TdiExample_IoControlInternal Called \r\n");
Irp->IoStatus.Status = NtStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("TdiExample_IoControlInternal Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* TdiExample_IoControl
*
* This is called when an IOCTL is issued on the device handle (DeviceIoControl)
*
**********************************************************************/
NTSTATUS TdiExample_IoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_NOT_SUPPORTED;
PIO_STACK_LOCATION pIoStackIrp = NULL;
PTDI_EXAMPLE_CONTEXT pTdiExampleContext = NULL;
DbgPrint("TdiExample_IoControl Called \r\n");
/*
* Each time the IRP is passed down the driver stack a new stack location is added
* specifying certain parameters for the IRP to the driver.
*/
pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
if(pIoStackIrp) /* Should Never Be NULL! */
{
DbgPrint("Example_IoControl Called IOCTL = 0x%0x\r\n", pIoStackIrp->Parameters.DeviceIoControl.IoControlCode);
pTdiExampleContext = (PTDI_EXAMPLE_CONTEXT)pIoStackIrp->FileObject->FsContext;
switch(pIoStackIrp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_TDIEXAMPLE_CONNECT:
NtStatus = TdiExample_Connect(pTdiExampleContext, Irp->AssociatedIrp.SystemBuffer, pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength);
break;
case IOCTL_TDIEXAMPLE_DISCONNECT:
NtStatus = TdiExample_Disconnect(pTdiExampleContext);
break;
}
}
Irp->IoStatus.Status = NtStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DbgPrint("TdiExample_IoControl Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* TdiExample_Write
*
* This is called when a write is issued on the device handle (WriteFile/WriteFileEx)
*
*
**********************************************************************/
NTSTATUS TdiExample_Write(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION pIoStackIrp = NULL;
PTDI_EXAMPLE_CONTEXT pTdiExampleContext = NULL;
DbgPrint("TdiExample_Write Called 0x%0x\r\n", Irp);
/*
* Each time the IRP is passed down the driver stack a new stack location is added
* specifying certain parameters for the IRP to the driver.
*/
pIoStackIrp = IoGetCurrentIrpStackLocation(Irp);
pTdiExampleContext = (PTDI_EXAMPLE_CONTEXT)pIoStackIrp->FileObject->FsContext;
if(pTdiExampleContext->csConnectionState == CS_CONNECTED)
{
/*
* We can use the "Overlay.DriverContext" data on the IRP to use driver specific contexts
* onto an IRP but only WHILE WE OWN THE IRP. Since we will be owning this IRP
* we can use this as the context we can find in our cancel routine. The problem
* is that we cannot use teh IO_STACK_LOCATION in the cancel routine since we
* can't be guarentteed what the current stack location is when the cancel
* routine is called.
*
* We then add our IRP to the list.
*/
Irp->Tail.Overlay.DriverContext[0] = (PVOID)pTdiExampleContext->pWriteIrpListHead;
NtStatus = HandleIrp_AddIrp(pTdiExampleContext->pWriteIrpListHead, Irp, TdiExample_CancelRoutine, TdiExample_IrpCleanUp, NULL);
if(NT_SUCCESS(NtStatus))
{
KeSetEvent(&pTdiExampleContext->kWriteIrpReady, IO_NO_INCREMENT, FALSE);
NtStatus = STATUS_PENDING;
}
}
else
{
Irp->IoStatus.Status = NtStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
DbgPrint("TdiExample_Write Exit 0x%0x \r\n", NtStatus);
return NtStatus;
}
/**********************************************************************
*
* TdiExample_Read
*
* This is called when a read is issued on the device handle (ReadFile/ReadFileEx)
*
*
**********************************************************************/
NTSTATUS TdiExample_Read(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS NtStatus = STATUS_BUFFER_TOO_SMALL;
PIO_STACK_LOCATION pIoStackIrp = NULL;
PTDI_EXAMPLE_CONTEXT pTdiExampleContext = NULL;
DbgPrint("TdiExample_Read Called 0x%0x \r\n", Irp);
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -