2023-08-20 16:12:04 +02:00
|
|
|
#include "queue.h"
|
|
|
|
|
2023-09-02 10:54:04 +02:00
|
|
|
#include "callbacks.h"
|
|
|
|
|
|
|
|
#include "driver.h"
|
|
|
|
|
|
|
|
#include "queue.h"
|
|
|
|
#include "pool.h"
|
|
|
|
#include "thread.h"
|
2023-08-30 18:29:44 +02:00
|
|
|
#include "common.h"
|
|
|
|
|
2023-09-02 10:54:04 +02:00
|
|
|
/*
|
|
|
|
* This mutex is to prevent a new item being pushed to the queue
|
|
|
|
* while the HandlePeriodicCallbackReportQueue is iterating through
|
|
|
|
* the objects. This can be an issue because the spinlock is released
|
|
|
|
* after each report is placed in the IRP buffer which means a new report
|
|
|
|
* can be pushed into the queue before the next iteration can take ownership
|
|
|
|
* of the spinlock.
|
|
|
|
*/
|
|
|
|
typedef struct _REPORT_QUEUE_CONFIGURATION
|
|
|
|
{
|
|
|
|
QUEUE_HEAD head;
|
2023-10-11 18:05:29 +02:00
|
|
|
volatile BOOLEAN is_driver_unloading;
|
2023-09-02 10:54:04 +02:00
|
|
|
KGUARDED_MUTEX lock;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
}REPORT_QUEUE_CONFIGURATION, * PREPORT_QUEUE_CONFIGURATION;
|
2023-09-02 10:54:04 +02:00
|
|
|
|
|
|
|
REPORT_QUEUE_CONFIGURATION report_queue_config = { 0 };
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
VOID
|
2023-09-27 06:22:14 +02:00
|
|
|
InitialiseGlobalReportQueue(
|
2023-10-07 17:37:47 +02:00
|
|
|
_Out_ PBOOLEAN Status
|
2023-09-02 10:54:04 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
report_queue_config.head.start = NULL;
|
|
|
|
report_queue_config.head.end = NULL;
|
|
|
|
report_queue_config.head.entries = 0;
|
2023-10-11 18:05:29 +02:00
|
|
|
report_queue_config.is_driver_unloading = FALSE;
|
2023-09-02 10:54:04 +02:00
|
|
|
|
2023-10-11 08:35:20 +02:00
|
|
|
KeInitializeGuardedMutex(&report_queue_config.head.lock);
|
2023-10-05 08:27:17 +02:00
|
|
|
KeInitializeGuardedMutex(&report_queue_config.lock);
|
2023-09-02 10:54:04 +02:00
|
|
|
|
|
|
|
*Status = TRUE;
|
|
|
|
}
|
|
|
|
|
2023-08-21 11:45:00 +02:00
|
|
|
//PQUEUE_HEAD QueueCreate()
|
|
|
|
//{
|
2023-08-22 10:51:52 +02:00
|
|
|
// PQUEUE_HEAD head = ExAllocatePool2( POOL_FLAG_NON_PAGED, sizeof( QUEUE_HEAD ), QUEUE_POOL_TAG );
|
2023-08-21 11:45:00 +02:00
|
|
|
//
|
|
|
|
// if ( !head )
|
|
|
|
// return NULL;
|
|
|
|
//
|
|
|
|
// head->end = NULL;
|
|
|
|
// head->start = NULL;
|
|
|
|
// head->entries = 0;
|
|
|
|
//
|
|
|
|
// KeInitializeSpinLock( &head->lock );
|
|
|
|
//
|
|
|
|
// return head;
|
|
|
|
//}
|
2023-08-20 16:12:04 +02:00
|
|
|
|
2023-10-11 18:05:29 +02:00
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
2023-10-11 08:35:20 +02:00
|
|
|
_Acquires_lock_(_Lock_kind_mutex_)
|
|
|
|
_Releases_lock_(_Lock_kind_mutex_)
|
2023-10-05 08:27:17 +02:00
|
|
|
VOID
|
|
|
|
QueuePush(
|
2023-10-07 17:37:47 +02:00
|
|
|
_Inout_ PQUEUE_HEAD Head,
|
2023-08-20 16:12:04 +02:00
|
|
|
_In_ PVOID Data
|
|
|
|
)
|
|
|
|
{
|
2023-10-11 08:35:20 +02:00
|
|
|
KeAcquireGuardedMutex(&Head->lock);
|
2023-08-20 16:12:04 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
PQUEUE_NODE temp = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(QUEUE_NODE), QUEUE_POOL_TAG);
|
2023-08-20 16:12:04 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!temp)
|
2023-08-20 16:12:04 +02:00
|
|
|
goto end;
|
|
|
|
|
2023-08-20 17:04:53 +02:00
|
|
|
Head->entries += 1;
|
|
|
|
|
2023-08-20 16:12:04 +02:00
|
|
|
temp->data = Data;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (Head->end != NULL)
|
2023-08-20 16:12:04 +02:00
|
|
|
Head->end->next = temp;
|
|
|
|
|
|
|
|
Head->end = temp;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (Head->start == NULL)
|
2023-08-20 16:12:04 +02:00
|
|
|
Head->start = temp;
|
|
|
|
|
|
|
|
end:
|
2023-10-11 08:35:20 +02:00
|
|
|
KeReleaseGuardedMutex(&Head->lock);
|
2023-08-20 16:12:04 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 18:05:29 +02:00
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
2023-10-11 08:35:20 +02:00
|
|
|
_Acquires_lock_(_Lock_kind_mutex_)
|
|
|
|
_Releases_lock_(_Lock_kind_mutex_)
|
2023-10-05 08:27:17 +02:00
|
|
|
PVOID
|
2023-09-27 06:22:14 +02:00
|
|
|
QueuePop(
|
2023-10-07 17:37:47 +02:00
|
|
|
_Inout_ PQUEUE_HEAD Head
|
2023-08-20 16:12:04 +02:00
|
|
|
)
|
|
|
|
{
|
2023-10-11 08:35:20 +02:00
|
|
|
KeAcquireGuardedMutex(&Head->lock);
|
2023-08-20 16:12:04 +02:00
|
|
|
|
|
|
|
PVOID data = NULL;
|
|
|
|
PQUEUE_NODE temp = Head->start;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (temp == NULL)
|
2023-08-20 16:12:04 +02:00
|
|
|
goto end;
|
|
|
|
|
2023-08-21 06:45:33 +02:00
|
|
|
Head->entries = Head->entries - 1;
|
2023-08-20 17:04:53 +02:00
|
|
|
|
2023-08-20 16:12:04 +02:00
|
|
|
data = temp->data;
|
|
|
|
Head->start = temp->next;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (Head->end == temp)
|
2023-08-20 16:12:04 +02:00
|
|
|
Head->end = NULL;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
ExFreePoolWithTag(temp, QUEUE_POOL_TAG);
|
2023-08-20 16:12:04 +02:00
|
|
|
|
|
|
|
end:
|
2023-10-11 08:35:20 +02:00
|
|
|
KeReleaseGuardedMutex(&Head->lock);
|
2023-08-20 16:12:04 +02:00
|
|
|
return data;
|
|
|
|
}
|
2023-09-02 10:54:04 +02:00
|
|
|
|
2023-10-10 15:52:42 +02:00
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
|
|
|
_Acquires_lock_(_Lock_kind_mutex_)
|
|
|
|
_Releases_lock_(_Lock_kind_mutex_)
|
2023-10-05 08:27:17 +02:00
|
|
|
VOID
|
2023-09-27 06:22:14 +02:00
|
|
|
InsertReportToQueue(
|
2023-09-02 10:54:04 +02:00
|
|
|
_In_ PVOID Report
|
|
|
|
)
|
|
|
|
{
|
2023-10-11 18:05:29 +02:00
|
|
|
if (InterlockedExchange(&report_queue_config.is_driver_unloading, report_queue_config.is_driver_unloading))
|
|
|
|
return;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
KeAcquireGuardedMutex(&report_queue_config.lock);
|
|
|
|
QueuePush(&report_queue_config.head, Report);
|
|
|
|
KeReleaseGuardedMutex(&report_queue_config.lock);
|
2023-09-02 10:54:04 +02:00
|
|
|
}
|
|
|
|
|
2023-10-10 15:52:42 +02:00
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
|
|
|
_Acquires_lock_(_Lock_kind_mutex_)
|
|
|
|
_Releases_lock_(_Lock_kind_mutex_)
|
2023-10-05 08:27:17 +02:00
|
|
|
VOID
|
2023-09-27 06:22:14 +02:00
|
|
|
FreeGlobalReportQueueObjects()
|
2023-09-02 10:54:04 +02:00
|
|
|
{
|
2023-10-11 18:05:29 +02:00
|
|
|
InterlockedExchange(&report_queue_config.is_driver_unloading, TRUE);
|
2023-10-05 08:27:17 +02:00
|
|
|
KeAcquireGuardedMutex(&report_queue_config.lock);
|
2023-09-02 10:54:04 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
PVOID report = QueuePop(&report_queue_config.head);
|
2023-09-02 10:54:04 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
while (report != NULL)
|
2023-09-02 10:54:04 +02:00
|
|
|
{
|
2023-10-05 08:27:17 +02:00
|
|
|
ExFreePoolWithTag(report, REPORT_POOL_TAG);
|
|
|
|
report = QueuePop(&report_queue_config.head);
|
2023-10-11 18:05:29 +02:00
|
|
|
DEBUG_LOG("Queu Unload Remaining Entries: %i", report_queue_config.head.entries);
|
2023-09-02 10:54:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
2023-10-05 08:27:17 +02:00
|
|
|
KeReleaseGuardedMutex(&report_queue_config.lock);
|
2023-09-02 10:54:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function handles sending all the pending reports in the global report
|
|
|
|
* queue to the usermode application. This function is called periodically by the
|
|
|
|
* usermode application. The reason I have implemented this is because as this application
|
|
|
|
* expanded, it became apparent that some of the driver functions will generate multiple
|
|
|
|
* reports as a result of a single usermode request and hence it makes dealing with
|
|
|
|
* reports generated from ObRegisterCallbacks for example much easier.
|
|
|
|
*/
|
2023-10-10 15:52:42 +02:00
|
|
|
_IRQL_requires_max_(APC_LEVEL)
|
|
|
|
_Acquires_lock_(_Lock_kind_mutex_)
|
|
|
|
_Releases_lock_(_Lock_kind_mutex_)
|
2023-10-05 08:27:17 +02:00
|
|
|
NTSTATUS
|
2023-09-27 06:22:14 +02:00
|
|
|
HandlePeriodicGlobalReportQueueQuery(
|
2023-10-07 17:37:47 +02:00
|
|
|
_Inout_ PIRP Irp
|
2023-09-02 10:54:04 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
PVOID report = NULL;
|
|
|
|
INT count = 0;
|
|
|
|
GLOBAL_REPORT_QUEUE_HEADER header;
|
|
|
|
PVOID report_buffer = NULL;
|
|
|
|
PREPORT_HEADER report_header;
|
|
|
|
SIZE_T total_size = NULL;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
KeAcquireGuardedMutex(&report_queue_config.lock);
|
2023-10-11 18:05:29 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
report = QueuePop(&report_queue_config.head);
|
2023-09-02 10:54:04 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
report_buffer = ExAllocatePool2(
|
|
|
|
POOL_FLAG_NON_PAGED,
|
|
|
|
sizeof(INVALID_PROCESS_ALLOCATION_REPORT) * MAX_REPORTS_PER_IRP + sizeof(GLOBAL_REPORT_QUEUE_HEADER),
|
2023-09-23 13:25:48 +02:00
|
|
|
REPORT_QUEUE_TEMP_BUFFER_TAG
|
|
|
|
);
|
2023-09-02 10:54:04 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!report_buffer)
|
2023-09-02 10:54:04 +02:00
|
|
|
{
|
2023-10-05 08:27:17 +02:00
|
|
|
KeReleaseGuardedMutex(&report_queue_config.lock);
|
2023-09-02 10:54:04 +02:00
|
|
|
return STATUS_MEMORY_NOT_ALLOCATED;
|
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (report == NULL)
|
2023-09-02 10:54:04 +02:00
|
|
|
{
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("callback report queue is empty, returning");
|
2023-09-02 10:54:04 +02:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
while (report != NULL)
|
2023-09-02 10:54:04 +02:00
|
|
|
{
|
2023-10-05 08:27:17 +02:00
|
|
|
if (count >= MAX_REPORTS_PER_IRP)
|
2023-09-02 10:54:04 +02:00
|
|
|
goto end;
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
report_header = (PREPORT_HEADER)report;
|
2023-09-02 10:54:04 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
switch (report_header->report_id)
|
2023-09-02 10:54:04 +02:00
|
|
|
{
|
|
|
|
case REPORT_ILLEGAL_HANDLE_OPERATION:
|
|
|
|
|
|
|
|
RtlCopyMemory(
|
2023-10-05 08:27:17 +02:00
|
|
|
(UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) + total_size,
|
2023-09-02 10:54:04 +02:00
|
|
|
report,
|
2023-10-05 08:27:17 +02:00
|
|
|
sizeof(OPEN_HANDLE_FAILURE_REPORT)
|
2023-09-02 10:54:04 +02:00
|
|
|
);
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
total_size += sizeof(OPEN_HANDLE_FAILURE_REPORT);
|
2023-09-02 10:54:04 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case REPORT_ILLEGAL_ATTACH_PROCESS:
|
|
|
|
|
|
|
|
RtlCopyMemory(
|
2023-10-05 08:27:17 +02:00
|
|
|
(UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) + total_size,
|
2023-09-02 10:54:04 +02:00
|
|
|
report,
|
2023-10-05 08:27:17 +02:00
|
|
|
sizeof(ATTACH_PROCESS_REPORT)
|
2023-09-02 10:54:04 +02:00
|
|
|
);
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
total_size += sizeof(ATTACH_PROCESS_REPORT);
|
2023-09-02 10:54:04 +02:00
|
|
|
break;
|
2023-09-18 05:15:26 +02:00
|
|
|
|
|
|
|
case REPORT_INVALID_PROCESS_ALLOCATION:
|
|
|
|
|
|
|
|
RtlCopyMemory(
|
2023-10-05 08:27:17 +02:00
|
|
|
(UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) + total_size,
|
2023-09-18 05:15:26 +02:00
|
|
|
report,
|
2023-10-05 08:27:17 +02:00
|
|
|
sizeof(INVALID_PROCESS_ALLOCATION_REPORT)
|
2023-09-18 05:15:26 +02:00
|
|
|
);
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
total_size += sizeof(INVALID_PROCESS_ALLOCATION_REPORT);
|
2023-09-18 05:15:26 +02:00
|
|
|
break;
|
2023-09-28 15:56:07 +02:00
|
|
|
|
|
|
|
case REPORT_APC_STACKWALK:
|
|
|
|
|
|
|
|
RtlCopyMemory(
|
2023-10-05 08:27:17 +02:00
|
|
|
(UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) + total_size,
|
2023-09-28 15:56:07 +02:00
|
|
|
report,
|
2023-10-05 08:27:17 +02:00
|
|
|
sizeof(APC_STACKWALK_REPORT)
|
2023-09-28 15:56:07 +02:00
|
|
|
);
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
total_size += sizeof(APC_STACKWALK_REPORT);
|
2023-09-28 15:56:07 +02:00
|
|
|
break;
|
|
|
|
|
2023-10-06 07:47:01 +02:00
|
|
|
case REPORT_HIDDEN_SYSTEM_THREAD:
|
|
|
|
|
|
|
|
RtlCopyMemory(
|
|
|
|
(UINT64)report_buffer + sizeof(GLOBAL_REPORT_QUEUE_HEADER) + total_size,
|
|
|
|
report,
|
|
|
|
sizeof(HIDDEN_SYSTEM_THREAD_REPORT)
|
|
|
|
);
|
|
|
|
|
|
|
|
total_size += sizeof(HIDDEN_SYSTEM_THREAD_REPORT);
|
|
|
|
break;
|
|
|
|
|
2023-09-02 10:54:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* QueuePop frees the node, but we still need to free the returned data */
|
2023-10-05 08:27:17 +02:00
|
|
|
ExFreePoolWithTag(report, REPORT_POOL_TAG);
|
2023-09-02 10:54:04 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
report = QueuePop(&report_queue_config.head);
|
2023-09-02 10:54:04 +02:00
|
|
|
count += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
KeReleaseGuardedMutex(&report_queue_config.lock);
|
2023-09-03 19:33:27 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
Irp->IoStatus.Information = sizeof(GLOBAL_REPORT_QUEUE_HEADER) + total_size;
|
2023-09-02 10:54:04 +02:00
|
|
|
|
|
|
|
header.count = count;
|
|
|
|
|
|
|
|
RtlCopyMemory(
|
|
|
|
report_buffer,
|
|
|
|
&header,
|
2023-10-05 08:27:17 +02:00
|
|
|
sizeof(GLOBAL_REPORT_QUEUE_HEADER));
|
2023-09-02 10:54:04 +02:00
|
|
|
|
|
|
|
RtlCopyMemory(
|
|
|
|
Irp->AssociatedIrp.SystemBuffer,
|
|
|
|
report_buffer,
|
2023-10-05 08:27:17 +02:00
|
|
|
sizeof(GLOBAL_REPORT_QUEUE_HEADER) + total_size
|
2023-09-02 10:54:04 +02:00
|
|
|
);
|
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (report_buffer)
|
|
|
|
ExFreePoolWithTag(report_buffer, REPORT_QUEUE_TEMP_BUFFER_TAG);
|
2023-09-02 10:54:04 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
DEBUG_LOG("Moved all reports into the IRP, sending !");
|
2023-09-02 10:54:04 +02:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2023-09-25 17:41:38 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
VOID
|
2023-09-27 06:22:14 +02:00
|
|
|
ListInit(
|
2023-10-08 16:07:49 +02:00
|
|
|
_Inout_ PSINGLE_LIST_ENTRY Head,
|
2023-10-11 08:35:20 +02:00
|
|
|
_Inout_ PKGUARDED_MUTEX Lock
|
2023-09-25 17:41:38 +02:00
|
|
|
)
|
|
|
|
{
|
2023-10-11 08:35:20 +02:00
|
|
|
KeInitializeGuardedMutex(Lock);
|
2023-10-08 16:07:49 +02:00
|
|
|
Head->Next = NULL;
|
2023-09-25 17:41:38 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 08:35:20 +02:00
|
|
|
_Acquires_lock_(_Lock_kind_mutex_)
|
|
|
|
_Releases_lock_(_Lock_kind_mutex_)
|
2023-10-08 16:07:49 +02:00
|
|
|
VOID
|
2023-09-27 06:22:14 +02:00
|
|
|
ListInsert(
|
2023-10-08 16:07:49 +02:00
|
|
|
_Inout_ PSINGLE_LIST_ENTRY Head,
|
|
|
|
_Inout_ PSINGLE_LIST_ENTRY NewEntry,
|
2023-10-11 08:35:20 +02:00
|
|
|
_In_ PKGUARDED_MUTEX Lock
|
2023-09-25 17:41:38 +02:00
|
|
|
)
|
|
|
|
{
|
2023-10-11 08:35:20 +02:00
|
|
|
KeAcquireGuardedMutex(Lock);
|
2023-09-25 17:41:38 +02:00
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
PSINGLE_LIST_ENTRY old_entry = Head->Next;
|
2023-09-25 17:41:38 +02:00
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
Head->Next = NewEntry;
|
|
|
|
NewEntry->Next = old_entry;
|
2023-09-25 17:41:38 +02:00
|
|
|
|
2023-10-11 08:35:20 +02:00
|
|
|
KeReleaseGuardedMutex(Lock);
|
2023-09-25 17:41:38 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 08:35:20 +02:00
|
|
|
_Acquires_lock_(_Lock_kind_mutex_)
|
|
|
|
_Releases_lock_(_Lock_kind_mutex_)
|
2023-10-08 16:07:49 +02:00
|
|
|
BOOLEAN
|
|
|
|
ListFreeFirstEntry(
|
|
|
|
_Inout_ PSINGLE_LIST_ENTRY Head,
|
2023-10-11 08:35:20 +02:00
|
|
|
_In_ PKGUARDED_MUTEX Lock
|
2023-09-25 17:41:38 +02:00
|
|
|
)
|
|
|
|
{
|
2023-10-08 16:07:49 +02:00
|
|
|
BOOLEAN result = FALSE;
|
2023-10-11 08:35:20 +02:00
|
|
|
KeAcquireGuardedMutex(Lock);
|
2023-09-25 17:41:38 +02:00
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
if (Head->Next)
|
2023-09-25 17:41:38 +02:00
|
|
|
{
|
2023-10-08 16:07:49 +02:00
|
|
|
PSINGLE_LIST_ENTRY entry = Head->Next;
|
|
|
|
Head->Next = Head->Next->Next;
|
|
|
|
ExFreePoolWithTag(entry, POOL_TAG_THREAD_LIST);
|
|
|
|
result = TRUE;
|
2023-09-25 17:41:38 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 08:35:20 +02:00
|
|
|
KeReleaseGuardedMutex(Lock);
|
2023-10-08 16:07:49 +02:00
|
|
|
return result;
|
2023-09-25 17:41:38 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 08:35:20 +02:00
|
|
|
_Acquires_lock_(_Lock_kind_mutex_)
|
|
|
|
_Releases_lock_(_Lock_kind_mutex_)
|
2023-10-08 16:07:49 +02:00
|
|
|
VOID
|
|
|
|
ListRemoveEntry(
|
|
|
|
_Inout_ PSINGLE_LIST_ENTRY Head,
|
|
|
|
_Inout_ PSINGLE_LIST_ENTRY Entry,
|
2023-10-11 08:35:20 +02:00
|
|
|
_In_ PKGUARDED_MUTEX Lock
|
2023-09-25 17:41:38 +02:00
|
|
|
)
|
|
|
|
{
|
2023-10-11 08:35:20 +02:00
|
|
|
KeAcquireGuardedMutex(Lock);
|
2023-09-25 17:41:38 +02:00
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
PSINGLE_LIST_ENTRY entry = Head->Next;
|
2023-09-25 17:41:38 +02:00
|
|
|
|
2023-10-05 08:27:17 +02:00
|
|
|
if (!entry)
|
2023-09-25 17:41:38 +02:00
|
|
|
goto unlock;
|
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
if (entry == Entry)
|
2023-09-25 17:41:38 +02:00
|
|
|
{
|
2023-10-08 16:07:49 +02:00
|
|
|
Head->Next = entry->Next;
|
|
|
|
ExFreePoolWithTag(Entry, POOL_TAG_THREAD_LIST);
|
2023-09-25 17:41:38 +02:00
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
while (entry->Next)
|
2023-09-25 17:41:38 +02:00
|
|
|
{
|
2023-10-08 16:07:49 +02:00
|
|
|
if (entry->Next == Entry)
|
2023-09-25 17:41:38 +02:00
|
|
|
{
|
2023-10-08 16:07:49 +02:00
|
|
|
entry->Next = Entry->Next;
|
|
|
|
ExFreePoolWithTag(Entry, POOL_TAG_THREAD_LIST);
|
2023-09-25 17:41:38 +02:00
|
|
|
goto unlock;
|
|
|
|
}
|
|
|
|
|
2023-10-08 16:07:49 +02:00
|
|
|
entry = entry->Next;
|
2023-09-25 17:41:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
unlock:
|
2023-10-11 08:35:20 +02:00
|
|
|
KeReleaseGuardedMutex(Lock);
|
2023-09-25 17:41:38 +02:00
|
|
|
}
|