#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ÃÊ °æ°ú -> ij½Ã ÃʱâÈ­ 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(¤t_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(¤t_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 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(¤t_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; }