📄 encryptedioqueue.c
字号:
}
// Divide data block to fragments to enable efficient overlapping of encryption and IO operations
dataRemaining = item->OriginalLength;
fragmentOffset = item->OriginalOffset;
while (dataRemaining > 0)
{
BOOL isLastFragment = dataRemaining <= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
ULONG dataFragmentLength = isLastFragment ? dataRemaining : TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
activeFragmentBuffer = (activeFragmentBuffer == queue->FragmentBufferA ? queue->FragmentBufferB : queue->FragmentBufferA);
// Create IO request
request = (EncryptedIoRequest *) TCalloc (sizeof (EncryptedIoRequest));
if (!request)
{
while (InterlockedExchangeAdd (&item->OutstandingRequestCount, 0) > 0)
KeWaitForSingleObject (&queue->RequestCompletedEvent, Executive, KernelMode, FALSE, NULL);
CompleteOriginalIrp (item, STATUS_INSUFFICIENT_RESOURCES, 0);
break;
}
request->Item = item;
request->CompleteOriginalIrp = isLastFragment;
request->Offset = fragmentOffset;
request->Data = activeFragmentBuffer;
request->OrigDataBufferFragment = dataBuffer;
request->Length = dataFragmentLength;
if (queue->IsFilterDevice)
{
// Get intersection of data fragment with encrypted area
GetIntersection (fragmentOffset.QuadPart, dataFragmentLength, queue->EncryptedAreaStart, queue->EncryptedAreaEnd, &intersectStart, &intersectLength);
request->EncryptedOffset = intersectStart - fragmentOffset.QuadPart;
request->EncryptedLength = intersectLength;
}
else
{
request->EncryptedOffset = 0;
request->EncryptedLength = dataFragmentLength;
}
AcquireFragmentBuffer (queue, activeFragmentBuffer);
if (item->Write)
{
// Encrypt data
memcpy (activeFragmentBuffer, dataBuffer, dataFragmentLength);
if (request->EncryptedLength > 0)
{
UINT64_STRUCT dataUnit;
ASSERT (request->EncryptedOffset + request->EncryptedLength <= request->Offset.QuadPart + request->Length);
dataUnit.Value = (request->Offset.QuadPart + request->EncryptedOffset) / ENCRYPTION_DATA_UNIT_SIZE;
if (queue->CryptoInfo->bPartitionInInactiveSysEncScope)
dataUnit.Value += queue->CryptoInfo->FirstDataUnitNo.Value;
EncryptDataUnits (activeFragmentBuffer + request->EncryptedOffset, &dataUnit, request->EncryptedLength / ENCRYPTION_DATA_UNIT_SIZE, queue->CryptoInfo);
}
}
// Queue IO request
InterlockedIncrement (&item->OutstandingRequestCount);
ExInterlockedInsertTailList (&queue->IoThreadQueue, &request->ListEntry, &queue->IoThreadQueueLock);
KeSetEvent (&queue->IoThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE);
if (isLastFragment)
break;
dataRemaining -= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
dataBuffer += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
fragmentOffset.QuadPart += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
}
}
}
PsTerminateSystemThread (STATUS_SUCCESS);
}
NTSTATUS EncryptedIoQueueAddIrp (EncryptedIoQueue *queue, PIRP irp)
{
EncryptedIoQueueItem *item;
PIO_STACK_LOCATION origIrpSp = IoGetCurrentIrpStackLocation (irp);
NTSTATUS status;
InterlockedIncrement (&queue->OutstandingIoCount);
if (queue->StopPending)
{
Dump ("STATUS_DEVICE_NOT_READY out=%d\n", queue->OutstandingIoCount);
status = STATUS_DEVICE_NOT_READY;
goto err;
}
if (queue->IsFilterDevice)
{
status = IoAcquireRemoveLock (&queue->RemoveLock, irp);
if (!NT_SUCCESS (status))
goto err;
}
item = TCalloc (sizeof (EncryptedIoQueueItem));
if (!item)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto err;
}
memset (item, 0, sizeof (EncryptedIoQueueItem));
switch (origIrpSp->MajorFunction)
{
case IRP_MJ_READ:
item->Write = FALSE;
item->OriginalOffset = origIrpSp->Parameters.Read.ByteOffset;
item->OriginalLength = origIrpSp->Parameters.Read.Length;
break;
case IRP_MJ_WRITE:
item->Write = TRUE;
item->OriginalOffset = origIrpSp->Parameters.Write.ByteOffset;
item->OriginalLength = origIrpSp->Parameters.Write.Length;
break;
default:
TCfree (item);
status = STATUS_INVALID_PARAMETER;
goto err;
}
item->Queue = queue;
item->OriginalIrp = irp;
item->OutstandingRequestCount = 0;
item->Status = STATUS_SUCCESS;
IoMarkIrpPending (irp);
//Dump ("Queue add %I64d %I64d out=%d\n", item->OriginalOffset, item->OriginalLength, queue->OutstandingIoCount);
ExInterlockedInsertTailList (&queue->MainThreadQueue, &item->ListEntry, &queue->MainThreadQueueLock);
KeSetEvent (&queue->MainThreadQueueNotEmptyEvent, IO_DISK_INCREMENT, FALSE);
return STATUS_PENDING;
err:
DecrementOutstandingIoCount (queue);
return status;
}
NTSTATUS EncryptedIoQueueHoldWhenIdle (EncryptedIoQueue *queue, int64 timeout)
{
NTSTATUS status;
ASSERT (!queue->Suspended);
queue->SuspendPending = TRUE;
while (TRUE)
{
while (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) > 0)
{
LARGE_INTEGER waitTimeout;
waitTimeout.QuadPart = timeout * -10000;
status = KeWaitForSingleObject (&queue->NoOutstandingIoEvent, Executive, KernelMode, FALSE, timeout != 0 ? &waitTimeout : NULL);
if (status == STATUS_TIMEOUT)
status = STATUS_UNSUCCESSFUL;
if (!NT_SUCCESS (status))
return status;
}
KeClearEvent (&queue->QueueResumedEvent);
queue->Suspended = TRUE;
if (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) == 0)
break;
queue->Suspended = FALSE;
KeSetEvent (&queue->QueueResumedEvent, IO_DISK_INCREMENT, FALSE);
}
queue->SuspendPending = FALSE;
//Dump ("Queue suspended out=%d\n", queue->OutstandingIoCount);
return STATUS_SUCCESS;
}
BOOL EncryptedIoQueueIsSuspended (EncryptedIoQueue *queue)
{
return queue->Suspended;
}
BOOL EncryptedIoQueueIsRunning (EncryptedIoQueue *queue)
{
return !queue->StopPending;
}
NTSTATUS EncryptedIoQueueResumeFromHold (EncryptedIoQueue *queue)
{
ASSERT (queue->Suspended);
queue->Suspended = FALSE;
KeSetEvent (&queue->QueueResumedEvent, IO_DISK_INCREMENT, FALSE);
//Dump ("Queue resumed out=%d\n", queue->OutstandingIoCount);
return STATUS_SUCCESS;
}
NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue, PEPROCESS process)
{
NTSTATUS status;
queue->ThreadExitRequested = FALSE;
KeInitializeEvent (&queue->NoOutstandingIoEvent, SynchronizationEvent, FALSE);
KeInitializeEvent (&queue->RequestCompletedEvent, SynchronizationEvent, FALSE);
KeInitializeEvent (&queue->QueueResumedEvent, SynchronizationEvent, FALSE);
queue->FragmentBufferA = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE);
if (!queue->FragmentBufferA)
goto noMemory;
queue->FragmentBufferB = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE);
if (!queue->FragmentBufferB)
goto noMemory;
KeInitializeEvent (&queue->FragmentBufferAFreeEvent, SynchronizationEvent, TRUE);
KeInitializeEvent (&queue->FragmentBufferBFreeEvent, SynchronizationEvent, TRUE);
// Main thread
InitializeListHead (&queue->MainThreadQueue);
KeInitializeSpinLock (&queue->MainThreadQueueLock);
KeInitializeEvent (&queue->MainThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE);
status = TCStartThread (MainThreadProc, queue, &queue->MainThread);
if (!NT_SUCCESS (status))
goto err;
// IO thread
InitializeListHead (&queue->IoThreadQueue);
KeInitializeSpinLock (&queue->IoThreadQueueLock);
KeInitializeEvent (&queue->IoThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE);
status = TCStartThreadInProcess (IoThreadProc, queue, &queue->IoThread, process);
if (!NT_SUCCESS (status))
{
queue->ThreadExitRequested = TRUE;
TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent);
goto err;
}
// Completion thread
InitializeListHead (&queue->CompletionThreadQueue);
KeInitializeSpinLock (&queue->CompletionThreadQueueLock);
KeInitializeEvent (&queue->CompletionThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE);
status = TCStartThread (CompletionThreadProc, queue, &queue->CompletionThread);
if (!NT_SUCCESS (status))
{
queue->ThreadExitRequested = TRUE;
TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent);
TCStopThread (queue->IoThread, &queue->IoThreadQueueNotEmptyEvent);
goto err;
}
queue->StopPending = FALSE;
Dump ("Queue started\n");
return STATUS_SUCCESS;
noMemory:
status = STATUS_INSUFFICIENT_RESOURCES;
err:
if (queue->FragmentBufferA)
TCfree (queue->FragmentBufferA);
if (queue->FragmentBufferB)
TCfree (queue->FragmentBufferB);
return status;
}
NTSTATUS EncryptedIoQueueStop (EncryptedIoQueue *queue)
{
ASSERT (!queue->StopPending);
queue->StopPending = TRUE;
while (InterlockedExchangeAdd (&queue->OutstandingIoCount, 0) > 0)
{
KeWaitForSingleObject (&queue->NoOutstandingIoEvent, Executive, KernelMode, FALSE, NULL);
}
Dump ("Queue stopping out=%d\n", queue->OutstandingIoCount);
queue->ThreadExitRequested = TRUE;
TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent);
TCStopThread (queue->IoThread, &queue->IoThreadQueueNotEmptyEvent);
TCStopThread (queue->CompletionThread, &queue->CompletionThreadQueueNotEmptyEvent);
TCfree (queue->FragmentBufferA);
TCfree (queue->FragmentBufferB);
Dump ("Queue stopped out=%d\n", queue->OutstandingIoCount);
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -