BSOne.SFC/Tocsg.Module/Bs1Flt/bs1flt/bs1flt_report.c

882 lines
20 KiB
C

#include "precomp.h"
static PROCESS_MANAGER s_exceopionprocess[] =
{
{PG_PID_ALLOW, L"vmtoolsd.exe",12},
{PG_PID_ALLOW, L"lsass.exe", 9},
};
static PROCESS_MANAGER s_Filesystem_exceopionprocess[] =
{
{PG_PID_ALLOW, L"SearchIndexer.exe",17},
{PG_PID_ALLOW, L"svchost.exe", 11},
{PG_PID_ALLOW, L"WUDFHost.exe", 12},
{PG_PID_ALLOW, L"system", 6}
};
typedef struct _LOG_LIST
{
REPORT_DESC a;
LIST_ENTRY list;
}LOG_LIST, * PLOG_LIST;
static LIST_ENTRY s_log_list;
static KSPIN_LOCK s_log_list_lock;
static ULONG s_log_cnt;
static NPAGED_LOOKASIDE_LIST s_log_PoolList;
#define LOG_POOL_TAG 'kdrp'
#define REPORT_KERNEL_EVENT_NAME L"\\BaseNamedObjects\\" LOG_SHARE_EVENT
PKEVENT rptEvent = NULL;
HANDLE rptEventHandle;
void RptNotifyEvent()
{
//HANDLE rptEventHandle;
//PKEVENT rptEvent;
UNICODE_STRING name;
if (InterlockedCompareExchange((volatile LONG*) & s_log_cnt, 0, 0) == 0)
return;
RtlInitUnicodeString(&name, REPORT_KERNEL_EVENT_NAME);
rptEvent = IoCreateNotificationEvent(&name, &rptEventHandle);
//iLog("!!!RptNotifyEvent %08p %08p\n", rptEvent, rptEventHandle);
if (rptEvent)
{
KeSetEvent(rptEvent, FALSE, FALSE);
ZwClose(rptEventHandle);
}
}
//------------------------------------------------------------------------
VOID Initlog()
{
s_log_cnt = 0;
InitializeListHead(&s_log_list);
KeInitializeSpinLock(&s_log_list_lock);
ExInitializeNPagedLookasideList(&s_log_PoolList
, NULL
, NULL
, 0
, sizeof(LOG_LIST)
, LOG_POOL_TAG
, 0);
}
BOOLEAN IsNetWorkExceptionPath(LPWSTR path)
{
static LPCWSTR s_expath[] =
{
L"\\PIPE\\srvsvc",
L"\\;Csc\\.\\.\\",
L"\\pipe\\",
L"\\desktop.ini",
/// 네트워크 드라이브 사용 etc. \Device\Mup\;LanmanRedirector\;Z:00000000001cdd14\KMG-PC\share\allowpl - 복사본 (2).ini
/// L"\\;LanmanRedirector\\",
/// L"\\;lanmanredirector\\",
L"*\\mailslot\\",
L";RdpDr\\;",
L"\\pipe\\spoolss",
/// sqlite 같은 경우 씀
L"\\Device\\Mup\\localhost\\",
NULL
};
/// 20160627 kmg
/// hwp 의 경우 루트 경로 없이 \\Device\\Mup\\\\로만 접근 시도
/// s_expathlen를 기준으로 경로 길이 까지 볼 경우 추가
//static LPCWSTR s_expathlen[] =
//{
// L"\\Device\\Mup\\\\",
// NULL
//};
LPCWSTR* ep = s_expath;
while (*ep)
{
if (wcsstr(path, *ep) != NULL)
return TRUE;
++ep;
}
//ep = s_expathlen;
//while (*ep)
//{
// if (_wcsnicmp(*ep, path, wcslen(path)) == 0)
// return TRUE;
// ++ep;
//}
return FALSE;
}
BOOLEAN IsFileSystemExceptionPath(LPWSTR path)
{
static LPCWSTR s_expath[] =
{
L"\\desktop.ini",
NULL
};
LPCWSTR* ep = s_expath;
while (*ep)
{
if (wcsstr(path, *ep) != NULL)
return TRUE;
++ep;
}
return FALSE;
}
BOOLEAN CreateOptionDebug(PFLT_CALLBACK_DATA data, PREPORT_DESC log)
{
ULONG disposition;
ULONG desired_access = 0;
ULONG create_option = 0;
USHORT create_fileattribute = 0;
//USHORT share_access = 0;
//ULONG devicetype = 0;
if (data == NULL)
return FALSE;
if (data->Iopb->MajorFunction != IRP_MJ_CREATE)
return FALSE;
desired_access = data->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
create_option = data->Iopb->Parameters.Create.Options;
disposition = (create_option >> 24) & 0xFF;
create_fileattribute = data->Iopb->Parameters.Create.FileAttributes;
KLogEx(DEBUG_TRACE_ERROR, "desired_access(%x) create_option(%x) disposition(%x) create_fileattribute(%x) \n", desired_access, create_option, disposition, create_fileattribute);
//KLogEx(DEBUG_TRACE_ERROR, "FileName.Length(%x) Data->Iopb->OperationFlags(%x) TargetFileObject->Flags(%x)\n", fltobject->FileObject->FileName.Length, data->Iopb->OperationFlags, data->Iopb->TargetFileObject->Flags);
KLogEx(DEBUG_TRACE_ERROR, "Path(%S) ProcessName(%S\n", log->path, log->ProcessName);
return TRUE;
}
///차단 메시지 & 로그 예외
BOOLEAN IsException(PFLT_CALLBACK_DATA data, PREPORT_DESC log)
{
/// 불필요한 로그 필터링
ULONG desired_access = 0;
ULONG create_option = 0;
ULONG fileattributes = 0;
ULONG disposition = 0;
if (log->a0 == BDC_NETWORKDRIVEOUT || log->a0 == BDC_NETWORKSHAREOUT)
{
if (IsExceptionProcess(s_Filesystem_exceopionprocess, ARRAYSIZE(s_Filesystem_exceopionprocess), log->ProcessName) == PG_PID_ALLOW)
return TRUE;
/// 예외 경로 필터
if (IsNetWorkExceptionPath(log->path))
return TRUE;
/*if (data && data->Iopb->MajorFunction == IRP_MJ_CREATE)
{
create_option = data->Iopb->Parameters.Create.Options;
disposition = (create_option >> 24) & 0xFF;
desired_access = data->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
KLogEx(DEBUG_TRACE_ERROR, "Network log->a1(%d) disposition(%x) desired_access(%x)\n", log->a1, disposition, desired_access);
if (log->a1 == DISABLE)
{
if (disposition == FILE_OPEN)
{
if (!(desired_access & (FILE_READ_DATA)))
return TRUE;
}
}
else if (log->a1 == READONLY)
{
///20160622 kmg
///FILE_OPEN 의 경우 클릭 시 explorer, office 문서 열떄 들어오므로 차단및 로그 예외.
if (disposition == FILE_OPEN)
{
if (!(desired_access & (FILE_READ_DATA)))
return TRUE;
}
}
}*/
}
else if (log->a0 == BDC_USB_DISK || log->a0 == BDC_EXTERNALHDD)
{
if (IsFileSystemExceptionPath(log->path))
return TRUE;
if (IsExceptionProcess(s_Filesystem_exceopionprocess, ARRAYSIZE(s_Filesystem_exceopionprocess), log->ProcessName) == PG_PID_ALLOW)
return TRUE;
if (data && data->Iopb->MajorFunction == IRP_MJ_CREATE)
{
desired_access = data->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
create_option = data->Iopb->Parameters.Create.Options;
fileattributes = data->Iopb->Parameters.Create.FileAttributes;
disposition = (create_option >> 24) & 0xFF;
KLogEx(DEBUG_TRACE_ERROR, "desired_access(%x) create_option(%x) fileattributes(%x)\n", desired_access, create_option, fileattributes);
if (log->a1 == READONLY)
{
///20160622 kmg
///FILE_OPEN 의 경우 클릭 시 explorer, office 문서 열떄 들어오므로 차단및 로그 예외
if (disposition == FILE_OPEN)
{
if (desired_access & (FILE_WRITE_DATA))
return TRUE;
}
}
else if (!(create_option & 0x1004020))
return TRUE;
}
}
else if (log->a0 == BDC_CDROM)
{
if (data && data->Iopb->MajorFunction == IRP_MJ_CREATE)
{
if (wcsrchr(log->path, '\\') == NULL)
{
return TRUE;
}
// if((create_option & FILE_NON_DIRECTORY_FILE))
// return TRUE;
}
}
///모든 정책에서 예외 프로세스 목록
if (IsExceptionProcess(s_exceopionprocess, ARRAYSIZE(s_exceopionprocess), log->ProcessName) == PG_PID_ALLOW)
return TRUE;
return FALSE;
}
///시간 주기로 중복 로그 예외
BOOLEAN IsOvlappedLog(PFLT_CALLBACK_DATA data, PREPORT_DESC log)
{
//static LARGE_INTEGER s_distime = { 0, };
static LARGE_INTEGER s_LastTick = { 0 };
static REPORT_DESC s_overlap_log[BDC_MAX_DEVICE_TYPE] = { 0, };
LARGE_INTEGER CurrentTick;
ULONG TimeIncrement;
ULONG idx = log->a0;
UNREFERENCED_PARAMETER(data);
if (idx >= BDC_MAX_DEVICE_TYPE)
return FALSE;
///최초 시간 구함
KeQueryTickCount(&CurrentTick);
// 2. 시간 주기 체크 (2초 경과 여부)
// Tick 단위로 계산하는 것이 훨씬 가볍고 빠름
TimeIncrement = KeQueryTimeIncrement(); // 1 Tick당 시간(100ns 단위) 반환
// 최초 실행이거나 2초(2 * 10,000,000 * 100ns) 지났는지 확인
// 간단하게 Tick Count 차이로 계산
if (s_LastTick.QuadPart == 0 ||
(CurrentTick.QuadPart - s_LastTick.QuadPart) * TimeIncrement > 20000000)
{
// 2초 경과 -> 캐시 초기화
RtlZeroMemory(s_overlap_log, sizeof(s_overlap_log));
s_LastTick.QuadPart = CurrentTick.QuadPart;
}
//if (s_distime.LowPart == 0)
//{
// KeQuerySystemTime((PLARGE_INTEGER)&s_distime);
//}
//else
//{
// LONGLONG delay;
// KeQuerySystemTime((PLARGE_INTEGER)&c);
// if (c.QuadPart >= s_distime.QuadPart)
// {
// delay = c.QuadPart - s_distime.QuadPart;
// }
// else
// {
// delay = s_distime.QuadPart;
// delay += (0xFFFFFFFFFFFFFFFF - c.QuadPart);
// }
// /// 2초이상이면 중복로그 버퍼 초기화. 중복로그 예외로 인해 새로운 로그가 안올라오는 현상 방지
// if (delay > (LONGLONG)(2 * 10000 * 1000))
// {
// KLogEx(DEBUG_TRACE_INFO, "delay(%llx), time(%llx) -> (%llx)\n", delay, c.QuadPart, s_distime.QuadPart);
// memset(&s_overlapp_log, 0, sizeof(s_overlapp_log));
// memset(&s_distime, 0, sizeof(LARGE_INTEGER));
// }
//}
/// 중복 로그 필터링
if (s_overlap_log[log->a0].path[0] != 0)
{
KLogEx(DEBUG_TRACE_INFO, "ov (%S), (%S)\n", s_overlap_log[log->a0].path, log->path);
if (_wcsicmp(s_overlap_log[log->a0].path, log->path) == 0 && _wcsicmp(s_overlap_log[log->a0].ProcessName, log->ProcessName) == 0)
{
return TRUE;
}
}
else if (log->a0 == BDC_CDROM)
{
if (_wcsicmp(s_overlap_log[log->a0].ProcessName, log->ProcessName) == 0 && s_overlap_log[log->a0].a1 == log->a1)
return TRUE;
}
memcpy(&s_overlap_log[log->a0], log, sizeof(REPORT_DESC));
return FALSE;
}
NTSTATUS SetLog(
_In_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ ULONG code,
_In_ ULONG a0,
_In_ ULONG a1,
_In_ ULONG a2,
_In_ PWCHAR processName,
_In_ PWCHAR path
)
{
PLOG_LIST log = NULL;
LARGE_INTEGER current_time;
//ULONG path_size = 0;
//ULONG process_size = 0;
PWCHAR name = NULL;
REPORT_DESC desc = { 0, };
KIRQL oldIrql;
UNREFERENCED_PARAMETER(Data);
UNREFERENCED_PARAMETER(a2);
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(processName);
UNREFERENCED_PARAMETER(path);
if (path == NULL || processName == NULL)
{
return STATUS_INVALID_PARAMETER;
}
if (!(g_bs1Flt.LogType & code))
return STATUS_INSUFFICIENT_RESOURCES;
KeQuerySystemTime(&current_time);
desc.time = (LONGLONG)current_time.QuadPart;
desc.pid = HandleToULong(PsGetCurrentProcessId());
desc.code = code;
desc.a0 = a0;
desc.a1 = a1;
if (code == LOG_POLICY)
{
desc.a2 = IsPolicyLog(a0);
///경로 저장
if (!NT_SUCCESS(RtlStringCbCopyW(desc.path, sizeof(desc.path), path)))
{
// 경로가 너무 길 경우 잘라서라도 넣고 싶다면 RtlStringCbCopyN 등을 고려,
// 현재는 에러가 나더라도 desc.path는 비어있지 않고 안전하게 null 종료됨.
}
///프로세스 명만 사용
name = wcsrchr(processName, '\\');
if (!name)
name = processName;
else
++name;
if (!NT_SUCCESS(RtlStringCbCopyW(desc.ProcessName, sizeof(desc.ProcessName), name)))
{
// 복사 실패 처리 (필요시)
}
KLogEx(DEBUG_TRACE_INFO, "LOG_POLICY code(%d), a0(%d), a1(%d), name(%S), path(%S)\n",
code, a0, a1, desc.ProcessName, desc.path);
///차단 메시지 및 로그 예외
if (IsException(Data, &desc))
{
KLogEx(DEBUG_TRACE_INFO, "IsException !!!\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
// /// 사용자에게 차단 메시지를 보내기 위함
// UserNotifyMessage(desc.a0, desc.ProcessName, NULL);
//
// if(!IsPolicyLog(a0))
// return STATUS_INSUFFICIENT_RESOURCES;
/// 중복 로그만 예외 하기 위해 사용
if (IsOvlappedLog(Data, &desc))
{
KLogEx(DEBUG_TRACE_INFO, "IsOvlappedLog !!!\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
}
else if (code == LOG_PROCESS_PROTECT)
{
///경로 저장
if (!NT_SUCCESS(RtlStringCbCopyW(desc.path, sizeof(desc.path), processName)))
{
}
if (!NT_SUCCESS(RtlStringCbCopyW(desc.renamepath, sizeof(desc.renamepath), path)))
{
}
}
else
{
///경로 저장
if (!NT_SUCCESS(RtlStringCbCopyW(desc.path, sizeof(desc.path), path)))
{
// 경로가 너무 길 경우 잘라서라도 넣고 싶다면 RtlStringCbCopyN 등을 고려,
// 현재는 에러가 나더라도 desc.path는 비어있지 않고 안전하게 null 종료됨.
}
///프로세스 명만 사용
name = wcsrchr(processName, '\\');
if (!name)
name = processName;
else
++name;
if (!NT_SUCCESS(RtlStringCbCopyW(desc.ProcessName, sizeof(desc.ProcessName), name)))
{
// 복사 실패 처리 (필요시)
}
KLogEx(DEBUG_TRACE_INFO, "code(%d), a0(%d), a1(%d), name(%S), path(%S)\n",
code, a0, a1, desc.ProcessName, desc.path);
}
log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
if (!log)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(log, s_log_PoolList.L.Size);
memcpy(&log->a, &desc, sizeof(REPORT_DESC));
KeAcquireSpinLock(&s_log_list_lock, &oldIrql);
{
InsertTailList(&s_log_list, &log->list);
++s_log_cnt;
}
KeReleaseSpinLock(&s_log_list_lock, oldIrql);
RptNotifyEvent();
return STATUS_SUCCESS;
}
NTSTATUS SetConnectLog(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ ULONG a0,
_In_ ULONG a1,
_In_ ULONG a2,
_In_ PWCHAR volum,
_In_ PWCHAR processName,
_In_ PWCHAR path
)
{
PLOG_LIST log = NULL;
LARGE_INTEGER current_time;
//REPORT_DESC desc = { 0, };
KIRQL oldIrql;
UNREFERENCED_PARAMETER(a2);
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(processName);
UNREFERENCED_PARAMETER(path);
KLogEx(DEBUG_TRACE_INFO, ", SET_LOG_TYPE(%d)\n", g_bs1Flt.LogType);
if (!(g_bs1Flt.LogType & LOG_CONNECT))
return STATUS_INSUFFICIENT_RESOURCES;
log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
if (!log)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(log, s_log_PoolList.L.Size);
KeQuerySystemTime(&current_time);
log->a.time = (LONGLONG)current_time.QuadPart;
log->a.pid = HandleToULong(PsGetCurrentProcessId());
log->a.code = LOG_CONNECT;
log->a.a0 = a0;
log->a.a1 = a1;
if (processName)
{
RtlStringCbCopyW(log->a.ProcessName, sizeof(log->a.ProcessName), processName);
}
else
{
RtlStringCbCopyW(log->a.ProcessName, sizeof(log->a.ProcessName), L"Unknown");
}
if (path)
{
RtlStringCbCopyW(log->a.path, sizeof(log->a.path), path);
}
else
{
RtlStringCbCopyW(log->a.path, sizeof(log->a.path), L"Unknown Path");
}
if (volum)
{
RtlStringCbCopyW(log->a.renamepath, sizeof(log->a.renamepath), volum);
}
else
{
RtlStringCbCopyW(log->a.renamepath, sizeof(log->a.renamepath), volum);
}
KLogEx(DEBUG_TRACE_INFO, "code(%d), a0(%d), a1(%d), name(%S), path(%S)\n",
log->a.code, log->a.a0, log->a.a1, log->a.ProcessName, log->a.path);
//memcpy(&log->a, &desc, sizeof(REPORT_DESC));
KeAcquireSpinLock(&s_log_list_lock, &oldIrql);
{
InsertTailList(&s_log_list, &log->list);
++s_log_cnt;
}
KeReleaseSpinLock(&s_log_list_lock, oldIrql);
RptNotifyEvent();
return STATUS_SUCCESS;
}
NTSTATUS SetProcessLog(
_In_ ULONG code,
_In_ ULONG a0,
_In_ ULONG a1,
_In_ ULONG a2,
_In_ PWCHAR processName,
_In_ PWCHAR processParameter,
_In_ PWCHAR parentProcessName
)
{
PLOG_LIST log = NULL;
LARGE_INTEGER current_time;
//REPORT_DESC desc = { 0, };
KIRQL oldIrql;
UNREFERENCED_PARAMETER(a1);
UNREFERENCED_PARAMETER(a2);
UNREFERENCED_PARAMETER(processName);
UNREFERENCED_PARAMETER(processParameter);
UNREFERENCED_PARAMETER(parentProcessName);
if (!(g_bs1Flt.LogType & code))
return STATUS_INSUFFICIENT_RESOURCES;
log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
if (!log)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(log, s_log_PoolList.L.Size);
KeQuerySystemTime(&current_time);
log->a.time = (LONGLONG)current_time.QuadPart;
log->a.pid = HandleToULong(PsGetCurrentProcessId());
log->a.code = code;
log->a.a0 = a0;
log->a.a1 = a1;
log->a.a2 = a2;
if (processName)
{
RtlStringCbCopyW(log->a.ProcessName, sizeof(log->a.ProcessName), processName);
}
else
{
RtlStringCbCopyW(log->a.ProcessName, sizeof(log->a.ProcessName), L"Unknown");
}
if (processParameter)
{
RtlStringCbCopyW(log->a.path, sizeof(log->a.path), processParameter);
}
else
{
RtlStringCbCopyW(log->a.path, sizeof(log->a.path), L"Unknown Parameter");
}
if (parentProcessName)
{
RtlStringCbCopyW(log->a.renamepath, sizeof(log->a.renamepath), parentProcessName);
}
else
{
RtlStringCbCopyW(log->a.renamepath, sizeof(log->a.renamepath), L"Unknown Parent");
}
KLogEx(DEBUG_TRACE_INFO, "code(%d), a0(%d), a1(%d), name(%S), parameter(%S), parent(%S)\n",
log->a.code, log->a.a0, log->a.a1, log->a.ProcessName, log->a.path, log->a.renamepath);
//memcpy(&log->a, &desc, sizeof(REPORT_DESC));
KeAcquireSpinLock(&s_log_list_lock, &oldIrql);
{
InsertTailList(&s_log_list, &log->list);
++s_log_cnt;
}
KeReleaseSpinLock(&s_log_list_lock, oldIrql);
RptNotifyEvent();
return STATUS_SUCCESS;
}
NTSTATUS SetENLog(PFLT_CALLBACK_DATA data, ULONG code, ULONG devicetype, ULONG uAction, ULONG filesize, PWCHAR process_name, PWCHAR path, PWCHAR prenampath)
{
PLOG_LIST log = NULL;
LARGE_INTEGER current_time;
ULONG path_size = 0;
ULONG process_size = 0;
PWCHAR name = NULL;
REPORT_DESC desc = { 0, };
KIRQL oldIrql;
if (path == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
if (process_name == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
if(!(g_bs1Flt.LogType & code))
return STATUS_INSUFFICIENT_RESOURCES;
KeQuerySystemTime(&current_time);
desc.time = (LONGLONG)current_time.QuadPart;
desc.pid = (ULONG)(ULONG_PTR)PsGetCurrentProcessId();
desc.code = code;
desc.a0 = devicetype;
desc.a1 = uAction;
desc.a2 = filesize;
///경로 저장
path_size = (ULONG)wcslen(path) * (ULONG)sizeof(WCHAR);
if (path_size >= sizeof(desc.path))
path_size = sizeof(desc.path);
wcsncpy(desc.path, path, path_size);
if (wcslen(prenampath) > 0)
{
path_size = (ULONG)wcslen(prenampath) * (ULONG)sizeof(WCHAR);
if (path_size >= sizeof(desc.renamepath))
path_size = sizeof(desc.renamepath);
wcsncpy(desc.renamepath, prenampath, path_size);
}
///프로세스 명만 사용
name = wcsrchr(process_name, '\\');
if (!name)
name = process_name;
else
++name;
process_size = (ULONG)wcslen(name) * (ULONG)sizeof(WCHAR);
if (process_size >= sizeof(desc.ProcessName))
process_size = sizeof(desc.ProcessName);
wcsncpy(desc.ProcessName, name, process_size);
KLogEx(DEBUG_TRACE_ERROR, "code(%d), devicetype(%d), uAction(%d),filesize(%d) name(%S), path(%S)\n", code, devicetype, uAction, filesize, process_name, path);
///차단 메시지 및 로그 예외
if (IsException(data, &desc))
return STATUS_INSUFFICIENT_RESOURCES;
if (!IsPolicyLog(devicetype))
return STATUS_INSUFFICIENT_RESOURCES;
/// 중복 로그만 예외 하기 위해 사용
if (IsOvlappedLog(data, &desc))
return STATUS_INSUFFICIENT_RESOURCES;
KeAcquireSpinLock(&s_log_list_lock, &oldIrql);
log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
if (!log)
{
KeReleaseSpinLock(&s_log_list_lock, oldIrql);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(log, sizeof(LOG_LIST));
memcpy(&log->a, &desc, sizeof(REPORT_DESC));
++s_log_cnt;
InsertTailList(&s_log_list, &log->list);
KeReleaseSpinLock(&s_log_list_lock, oldIrql);
RptNotifyEvent();
return STATUS_SUCCESS;
}
VOID Cleanuplog()
{
//PLIST_ENTRY pList = NULL;
//PLOG_LIST plog = NULL;
KIRQL oldIrql;
KeAcquireSpinLock(&s_log_list_lock, &oldIrql);
InitializeListHead(&s_log_list);
ExDeleteNPagedLookasideList(&s_log_PoolList);
s_log_cnt = 0;
KeReleaseSpinLock(&s_log_list_lock, oldIrql);
KLogEx(DEBUG_TRACE_INFO, "success\n");
}
NTSTATUS GetLog(PVOID buf, ULONG size, ULONG* req)
{
KIRQL irql;
ULONG require_size = 0;
PLIST_ENTRY current, tmp = NULL; //tail,
PLOG_LIST plog = NULL;
PLOG_NOTIFICATION l = (PLOG_NOTIFICATION)buf;
PREPORT_DESC r = (PREPORT_DESC)&l->desc;
ULONG ulReminCnt = 0;
KeAcquireSpinLock(&s_log_list_lock, &irql);
if (!s_log_cnt && IsListEmpty(&s_log_list))
{
if (req)
*req = 0;
KeReleaseSpinLock(&s_log_list_lock, irql);
return STATUS_UNSUCCESSFUL;
}
if (!MmIsAddressValid(buf))
{
if (req)
*req = require_size;
KeReleaseSpinLock(&s_log_list_lock, irql);
return STATUS_BUFFER_OVERFLOW;
}
require_size = sizeof(ULONG) + sizeof(REPORT_DESC) * s_log_cnt;
if (buf == NULL || size == 0)
{
if (req)
*req = require_size;
KLogEx(DEBUG_TRACE_INFO, "size mistach require_size(%d), size(%d)\n", require_size, size);
KeReleaseSpinLock(&s_log_list_lock, irql);
return STATUS_BUFFER_OVERFLOW;
}
else if (size < require_size)
{
if (s_log_cnt > 1000)
{
ulReminCnt = (size - sizeof(ULONG)) / sizeof(REPORT_DESC);
l->count = ulReminCnt;
}
else
{
if (req)
*req = require_size;
KLogEx(DEBUG_TRACE_INFO, "remain size mistach require_size(%d), size(%d)\n", require_size, size);
KeReleaseSpinLock(&s_log_list_lock, irql);
RptNotifyEvent();
return STATUS_BUFFER_OVERFLOW;
}
}
else
{
ulReminCnt = s_log_cnt;
l->count = s_log_cnt;
}
KLogEx(DEBUG_TRACE_INFO, "s_log_cnt(%d), ulReminCnt(%d)\n", s_log_cnt, ulReminCnt);
current = s_log_list.Flink;
while (&s_log_list != current)
{
if (!ulReminCnt)
break;
tmp = current;
current = current->Flink;
plog = CONTAINING_RECORD(tmp, LOG_LIST, list);
RtlCopyMemory(r, &plog->a, sizeof(REPORT_DESC));
RemoveEntryList(&plog->list);
ExFreeToNPagedLookasideList(&s_log_PoolList, plog);
--s_log_cnt;
--ulReminCnt;
r = (PREPORT_DESC)GetPtr(r, sizeof(REPORT_DESC));
plog = NULL;
}
KeReleaseSpinLock(&s_log_list_lock, irql);
if (!IsListEmpty(&s_log_list))
{
RptNotifyEvent();
}
return STATUS_SUCCESS;
}