// function like FileTimeToDosDateTime BOOLEAN FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, USHORT *pDosDate, USHORT *pDosTime) { PDOSTIME pdtime = (PDOSTIME) pDosTime; PDOSDATE pddate = (PDOSDATE) pDosDate; TIME_FIELDS TimeFields; LARGE_INTEGER LocalTime; if (SystemTime == NULL) return FALSE; ExSystemTimeToLocalTime (SystemTime, &LocalTime); RtlTimeToTimeFields (&LocalTime, &TimeFields); if (pdtime) { pdtime->Second = TimeFields.Second / 2; pdtime->Minute = TimeFields.Minute; pdtime->Hour = TimeFields.Hour; } if (pddate) { pddate->Day = TimeFields.Day; pddate->Month = TimeFields.Month; pddate->Year = (USHORT) (TimeFields.Year - DeviceExt->BaseDateYear); } return TRUE; }
void AFSTagInitialLogEntry() { LARGE_INTEGER liTime, liLocalTime; TIME_FIELDS timeFields; KeQuerySystemTime( &liTime); ExSystemTimeToLocalTime( &liTime, &liLocalTime); RtlTimeToTimeFields( &liLocalTime, &timeFields); AFSDbgLogMsg( 0, 0, "AFS Log Initialized %d-%d-%d %d:%d Level %d Subsystems %08lX\n", timeFields.Month, timeFields.Day, timeFields.Year, timeFields.Hour, timeFields.Minute, AFSTraceLevel, AFSTraceComponent); return; }
/* Process Callback that is called every time a process event occurs. Creates a kernel event which can be used to notify userspace processes. */ VOID ProcessCallback( IN HANDLE hParentId, IN HANDLE hProcessId, IN BOOLEAN bCreate ) { NTSTATUS status; LARGE_INTEGER currentSystemTime; LARGE_INTEGER currentLocalTime; TIME_FIELDS timeFields; UNICODE_STRING processImagePath; PCAPTURE_PROCESS_MANAGER pProcessManager; /* Get the current time */ KeQuerySystemTime(¤tSystemTime); ExSystemTimeToLocalTime(¤tSystemTime,¤tLocalTime); RtlTimeToTimeFields(¤tLocalTime,&timeFields); /* Get the process manager from the device extension */ pProcessManager = gpDeviceObject->DeviceExtension; pProcessManager->pCurrentProcessEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESS_EVENT), PROCESS_POOL_TAG); if(pProcessManager->pCurrentProcessEvent == NULL) { return; } RtlCopyMemory(&pProcessManager->pCurrentProcessEvent->time, &timeFields, sizeof(TIME_FIELDS)); processImagePath.Length = 0; processImagePath.MaximumLength = 0; status = GetProcessImageName(hProcessId, &processImagePath); if(status == STATUS_BUFFER_OVERFLOW) { processImagePath.Buffer = ExAllocatePoolWithTag(NonPagedPool, processImagePath.MaximumLength, PROCESS_POOL_TAG); if(processImagePath.Buffer != NULL) { status = GetProcessImageName(hProcessId, &processImagePath); if(NT_SUCCESS(status)) { DbgPrint("CaptureProcessMonitor: %i %i=>%i:%wZ\n", bCreate, hParentId, hProcessId, &processImagePath); RtlStringCbCopyUnicodeString(pProcessManager->pCurrentProcessEvent->processPath, 1024, &processImagePath); } ExFreePoolWithTag(processImagePath.Buffer,PROCESS_POOL_TAG); } } pProcessManager->pCurrentProcessEvent->hParentProcessId = hParentId; pProcessManager->pCurrentProcessEvent->hProcessId = hProcessId; pProcessManager->pCurrentProcessEvent->bCreated = bCreate; KeSetEvent(pProcessManager->eNewProcessEvent, 0, FALSE); KeClearEvent(pProcessManager->eNewProcessEvent); }
FAT_TIME_STAMP FatGetCurrentFatTime ( IN PIRP_CONTEXT IrpContext ) /*++ Routine Description: This routine returns the current system time in Fat time Arguments: Return Value: FAT_TIME_STAMP - Receives the current system time --*/ { LARGE_INTEGER Time; TIME_FIELDS TimeFields; FAT_TIME_STAMP FatTime; // // Get the current system time, and map it into a time field record. // KeQuerySystemTime( &Time ); ExSystemTimeToLocalTime( &Time, &Time ); // // Always add almost two seconds to round up to the nearest double second. // Time.QuadPart = Time.QuadPart + AlmostTwoSeconds; (VOID)RtlTimeToTimeFields( &Time, &TimeFields ); // // Now simply copy over the information // FatTime.Time.DoubleSeconds = (USHORT)(TimeFields.Second / 2); FatTime.Time.Minute = (USHORT)(TimeFields.Minute); FatTime.Time.Hour = (USHORT)(TimeFields.Hour); FatTime.Date.Year = (USHORT)(TimeFields.Year - 1980); FatTime.Date.Month = (USHORT)(TimeFields.Month); FatTime.Date.Day = (USHORT)(TimeFields.Day); UNREFERENCED_PARAMETER( IrpContext ); return FatTime; }
//GetTimeStamp void GetTimeStamp(uint64* pTime) { LARGE_INTEGER systemTime; KeQuerySystemTime(&systemTime); LARGE_INTEGER localTime; ExSystemTimeToLocalTime(&systemTime, &localTime); *pTime = (uint64)localTime.QuadPart; }
ULONG GetCurrentTime() { LARGE_INTEGER currentSystemTime; LARGE_INTEGER currentLocalTime; ULONG time; KeQuerySystemTime(¤tSystemTime); ExSystemTimeToLocalTime(¤tSystemTime,¤tLocalTime); RtlTimeToSecondsSince1970(¤tLocalTime, &time); return time; }
//---------------------------------------------------------------------------- void FormatTimestamp(__in char *buffer, __in const size_t size) { LARGE_INTEGER localTime; LARGE_INTEGER systemTime; TIME_FIELDS timeFields; KeQuerySystemTime(&systemTime); ExSystemTimeToLocalTime(&systemTime, &localTime); RtlTimeToTimeFields(&localTime, &timeFields); RtlStringCbPrintfA(buffer, size, "%04d-%02d-%02d %02d:%02d:%02d.%03d", timeFields.Year, timeFields.Month, timeFields.Day, timeFields.Hour, timeFields.Minute, timeFields.Second, timeFields.Milliseconds); }
/** * 获取当前系统时间 * @return TIME_FIELDS 返回当前系统的时间。 */ TIME_FIELDS GetLocalTime() { LARGE_INTEGER current_stime; KeQuerySystemTime(¤t_stime); LARGE_INTEGER current_ltime; ExSystemTimeToLocalTime(¤t_stime,¤t_ltime); TIME_FIELDS current_tinfo; RtlTimeToTimeFields(¤t_ltime,¤t_tinfo); return current_tinfo; }
void natvLogSession( IN const char * prefixStr, IN TRACED_CONNECTION* pItem, IN ULONG prevState, IN const char * sufixStr ) { TIME_FIELDS TimeFields; char timeStr[30]; LARGE_INTEGER time; char dstIpAddrStr[30]; char srcIpAddrStr[30]; KeQuerySystemTime(&time); ExSystemTimeToLocalTime(&time, &time); RtlTimeToTimeFields(&time, &TimeFields); RtlStringCbPrintfA(timeStr, sizeof(timeStr), "%02d:%02d:%02d.%03d ", TimeFields.Hour, TimeFields.Minute, TimeFields.Second, TimeFields.Milliseconds); PRINT_IP(dstIpAddrStr, &pItem->dstIpAddrOrg); PRINT_IP(srcIpAddrStr, &pItem->srcIpAddrOrg); DbgPrint("%s %s session %s %s: %s:%u->%s:%u. State %s->%s\n", timeStr, prefixStr, pItem->out ? "OUT" : "IN ", sufixStr, srcIpAddrStr, RtlUshortByteSwap(pItem->srcPortOrg), dstIpAddrStr, RtlUshortByteSwap(pItem->dstPortOrg), natsState2Name(prevState), natsState2Name(pItem->state) ); }
// Concatenates meta information such as the current time and a process ID to // user given log message. _Use_decl_annotations_ static NTSTATUS LogpMakePrefix( ULONG level, const char *function_name, const char *log_message, char *log_buffer, SIZE_T log_buffer_length) { char const *level_string = nullptr; switch (level) { case kLogpLevelDebug: level_string = "DBG\t"; break; case kLogpLevelInfo: level_string = "INF\t"; break; case kLogpLevelWarn: level_string = "WRN\t"; break; case kLogpLevelError: level_string = "ERR\t"; break; default: return STATUS_INVALID_PARAMETER; } auto status = STATUS_SUCCESS; char time_buffer[20] = {}; if ((g_logp_debug_flag & kLogOptDisableTime) == 0) { // Want the current time. TIME_FIELDS time_fields; LARGE_INTEGER system_time, local_time; KeQuerySystemTime(&system_time); ExSystemTimeToLocalTime(&system_time, &local_time); RtlTimeToTimeFields(&local_time, &time_fields); status = RtlStringCchPrintfA(time_buffer, RTL_NUMBER_OF(time_buffer), "%02u:%02u:%02u.%03u\t", time_fields.Hour, time_fields.Minute, time_fields.Second, time_fields.Milliseconds); if (!NT_SUCCESS(status)) { return status; } } // Want the function name char function_name_buffer[50] = {}; if ((g_logp_debug_flag & kLogOptDisableFunctionName) == 0) { const auto base_function_name = LogpFindBaseFunctionName(function_name); status = RtlStringCchPrintfA(function_name_buffer, RTL_NUMBER_OF(function_name_buffer), "%-40s\t", base_function_name); if (!NT_SUCCESS(status)) { return status; } } // Want the processor number char processro_number[10] = {}; if ((g_logp_debug_flag & kLogOptDisableProcessorNumber) == 0) { status = RtlStringCchPrintfA(processro_number, RTL_NUMBER_OF(processro_number), "#%lu\t", KeGetCurrentProcessorNumberEx(nullptr)); if (!NT_SUCCESS(status)) { return status; } } // It uses PsGetProcessId(PsGetCurrentProcess()) instead of // PsGetCurrentThreadProcessId() because the later sometimes returns // unwanted value, for example: // PID == 4 but its image name != ntoskrnl.exe // The author is guessing that it is related to attaching processes but // not quite sure. The former way works as expected. status = RtlStringCchPrintfA( log_buffer, log_buffer_length, "%s%s%s%5Iu\t%5Iu\t%-15s\t%s%s\r\n", time_buffer, level_string, processro_number, reinterpret_cast<ULONG_PTR>(PsGetProcessId(PsGetCurrentProcess())), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), PsGetProcessImageFileName(PsGetCurrentProcess()), function_name_buffer, log_message); return status; }
BOOLEAN FatNtTimeToFatTime ( IN PIRP_CONTEXT IrpContext, IN PLARGE_INTEGER NtTime, IN BOOLEAN Rounding, OUT PFAT_TIME_STAMP FatTime, OUT OPTIONAL PCHAR TenMsecs ) /*++ Routine Description: This routine converts an NtTime value to its corresponding Fat time value. Arguments: NtTime - Supplies the Nt GMT Time value to convert from Rounding - Indicates whether the NT time should be rounded up to a FAT boundary. This should only be done *once* in the lifetime of a timestamp (important for tunneling, which will cause a timestamp to pass through at least twice). If true, rounded up. If false, rounded down to 10ms boundary. This obeys the rules for non-creation time and creation times (respectively). FatTime - Receives the equivalent Fat time value TenMsecs - Optionally receive the number of tens of milliseconds the NtTime, after any rounding, is greater than the FatTime Return Value: BOOLEAN - TRUE if the Nt time value is within the range of Fat's time range, and FALSE otherwise --*/ { TIME_FIELDS TimeFields; // // Convert the input to the a time field record. // if (Rounding) { // // Add almost two seconds to round up to the nearest double second. // NtTime->QuadPart = NtTime->QuadPart + AlmostTwoSeconds; } ExSystemTimeToLocalTime( NtTime, NtTime ); RtlTimeToTimeFields( NtTime, &TimeFields ); // // Check the range of the date found in the time field record // if ((TimeFields.Year < 1980) || (TimeFields.Year > (1980 + 127))) { ExLocalTimeToSystemTime( NtTime, NtTime ); return FALSE; } // // The year will fit in Fat so simply copy over the information // FatTime->Time.DoubleSeconds = (USHORT)(TimeFields.Second / 2); FatTime->Time.Minute = (USHORT)(TimeFields.Minute); FatTime->Time.Hour = (USHORT)(TimeFields.Hour); FatTime->Date.Year = (USHORT)(TimeFields.Year - 1980); FatTime->Date.Month = (USHORT)(TimeFields.Month); FatTime->Date.Day = (USHORT)(TimeFields.Day); if (TenMsecs) { if (!Rounding) { // // If the number of seconds was not divisible by two, then there // is another second of time (1 sec, 3 sec, etc.) Note we round down // the number of milleconds onto tens of milleseconds boundaries. // *TenMsecs = (TimeFields.Milliseconds / 10) + ((TimeFields.Second % 2) * 100); } else { // // If we rounded up, we have in effect changed the NT time. Therefore, // it does not differ from the FAT time. // *TenMsecs = 0; } } if (Rounding) { // // Slice off non-FAT boundary time and convert back to 64bit form // TimeFields.Milliseconds = 0; TimeFields.Second -= TimeFields.Second % 2; } else { // // Round down to 10ms boundary // TimeFields.Milliseconds -= TimeFields.Milliseconds % 10; } // // Convert back to NT time // (VOID) RtlTimeFieldsToTime(&TimeFields, NtTime); ExLocalTimeToSystemTime( NtTime, NtTime ); UNREFERENCED_PARAMETER( IrpContext ); return TRUE; }
// Concatenates meta information such as the current time and a process ID to // user given log message. EXTERN_C static NTSTATUS LogpMakePrefix(_In_ ULONG Level, _In_ const char *FunctionName, _In_ const char *LogMessage, _Out_ char *LogBuffer, _In_ size_t LogBufferLength) { char const *levelString = nullptr; switch (Level) { case LOGP_LEVEL_DEBUG: levelString = "DBG"; break; case LOGP_LEVEL_INFO: levelString = "INF"; break; case LOGP_LEVEL_WARN: levelString = "WRN"; break; case LOGP_LEVEL_ERROR: levelString = "ERR"; break; default: return STATUS_INVALID_PARAMETER; } auto status = STATUS_SUCCESS; char timeBuffer[20] = {}; if ((g_LogpDebugFlag & LOG_OPT_DISABLE_TIME) == 0) { // Want the current time. TIME_FIELDS timeFields; LARGE_INTEGER systemTime, localTime; KeQuerySystemTime(&systemTime); ExSystemTimeToLocalTime(&systemTime, &localTime); RtlTimeToTimeFields(&localTime, &timeFields); status = RtlStringCchPrintfA(timeBuffer, RTL_NUMBER_OF(timeBuffer), "%02u:%02u:%02u.%03u\t", timeFields.Hour, timeFields.Minute, timeFields.Second, timeFields.Milliseconds); if (!NT_SUCCESS(status)) { return status; } } char functionNameBuffer[50] = {}; if ((g_LogpDebugFlag & LOG_OPT_DISABLE_FUNCTION_NAME) == 0) { // Want the function name const auto baseFunctionName = LogpFindBaseFunctionName(FunctionName); status = RtlStringCchPrintfA(functionNameBuffer, RTL_NUMBER_OF(functionNameBuffer), "%-40s\t", baseFunctionName); if (!NT_SUCCESS(status)) { return status; } } // // It uses PsGetProcessId(PsGetCurrentProcess()) instead of // PsGetCurrentThreadProcessId() because the later sometimes returns // unwanted value, for example: // PID == 4 but its image name != ntoskrnl.exe // The author is guessing that it is related to attaching processes but // not quite sure. The former way works as expected. // status = RtlStringCchPrintfA( LogBuffer, LogBufferLength, "%s%s\t%5lu\t%5lu\t%-15s\t%s%s\r\n", timeBuffer, levelString, reinterpret_cast<ULONG_PTR>(PsGetProcessId(PsGetCurrentProcess())), reinterpret_cast<ULONG_PTR>(PsGetCurrentThreadId()), PsGetProcessImageFileName(PsGetCurrentProcess()), functionNameBuffer, LogMessage); return status; }
NTSTATUS RegistryCallback( _In_ PVOID CallbackContext, _In_opt_ PVOID Argument1, _In_opt_ PVOID Argument2 ) { NTSTATUS status = STATUS_SUCCESS; ULONG ulCallbackCtx; REG_NOTIFY_CLASS ulType = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1; UNICODE_STRING usRegistryPath = { 0 }; BOOLEAN bSuccess = FALSE; LARGE_INTEGER unCurrentSystemTime; LARGE_INTEGER unCurrentLocalTime; PVOID pData = NULL; ULONG ulDataSize = 0; ULONG ulKeyValueType = REG_NONE; WCHAR wzProcessPath[MAX_STRING_LENGTH] = { 0 }; // 时间 KeQuerySystemTime(&unCurrentSystemTime); ExSystemTimeToLocalTime(&unCurrentSystemTime, &unCurrentLocalTime); ulCallbackCtx = (ULONG)(ULONG_PTR)CallbackContext; usRegistryPath.Length = 0; usRegistryPath.MaximumLength = 2048 * sizeof(WCHAR); usRegistryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, usRegistryPath.MaximumLength, MEM_TAG); if (NULL == usRegistryPath.Buffer) { KdPrint(("[RegistryCallback] Failed to call ExAllocPollWithTag.\r\n")); return status; } switch (ulType) { case RegNtPreCreateKeyEx: { PREG_CREATE_KEY_INFORMATION_V1 pCreateInfo = (PREG_CREATE_KEY_INFORMATION_V1)Argument2; UNICODE_STRING usFilter = { 0 }; BOOLEAN bEqual = FALSE; WCHAR *wzFilters[] = { L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\DeviceClasses", L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses", L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters", L"\\REGISTRY\\MACHINE\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters" }; bSuccess = GetRegistryObjectCompleteName( &usRegistryPath, pCreateInfo->CompleteName, pCreateInfo->RootObject); if (bSuccess) { for (size_t nCount = 0; nCount < sizeof(wzFilters) / sizeof(ULONG_PTR); nCount++) { RtlInitUnicodeString(&usFilter, wzFilters[nCount]); if (RtlEqualUnicodeString(&usRegistryPath, &usFilter, TRUE)) { bEqual = TRUE; } } if (!bEqual) { //WCHAR wzProcessPath[MAX_STRING_LENGTH] = { 0 }; //GetProcessPathBySectionObject(PsGetCurrentProcessId(), wzProcessPath); //KdPrint(("[RegNtPreCreateKeyEx] [%ws] %wZ\r\n", wzProcessPath, &usRegistryPath)); } else { usRegistryPath.Length = 0; } } } break; case RegNtPreDeleteKey: { PREG_DELETE_KEY_INFORMATION pDeleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2; bSuccess = GetRegistryObjectCompleteName( &usRegistryPath, NULL, pDeleteKey->Object); if (bSuccess) { // KdPrint(("[RegNtPreDeleteKey]: %wZ\r\n", &usRegistryPath)); } } break; case RegNtPreSetValueKey: { PREG_SET_VALUE_KEY_INFORMATION pSetKeyValue = (PREG_SET_VALUE_KEY_INFORMATION)Argument2; bSuccess = GetRegistryObjectCompleteName( &usRegistryPath, NULL, pSetKeyValue->Object); if (bSuccess && pSetKeyValue->ValueName->Length > 0 && (REG_SZ == pSetKeyValue->Type || REG_DWORD == pSetKeyValue->Type || REG_QWORD == pSetKeyValue->Type)) { RtlUnicodeStringCatString(&usRegistryPath, L"\\"); RtlUnicodeStringCat(&usRegistryPath, pSetKeyValue->ValueName); ulKeyValueType = pSetKeyValue->Type; ulDataSize = pSetKeyValue->DataSize; pData = pSetKeyValue->Data; } else { usRegistryPath.Length = 0; } } break; case RegNtPreDeleteValueKey: { PREG_DELETE_VALUE_KEY_INFORMATION pDeleteValueKey = (PREG_DELETE_VALUE_KEY_INFORMATION)Argument2; bSuccess = GetRegistryObjectCompleteName(&usRegistryPath, NULL, pDeleteValueKey->Object); if (bSuccess && (pDeleteValueKey->ValueName->Length > 0)) { RtlUnicodeStringCatString(&usRegistryPath, L"\\"); RtlUnicodeStringCat(&usRegistryPath, pDeleteValueKey->ValueName); } } break; default: break; } // 创建数据链表 if (usRegistryPath.Length != 0) { PEVENT_DATA_NODE pNode = InitListNode(); HANDLE hProcessId = NULL; hProcessId = PsGetCurrentProcessId(); GetProcessPathBySectionObject(hProcessId, wzProcessPath); ULONG ulProcessPathLength = (ULONG)(wcslen(wzProcessPath) * sizeof(WCHAR) + sizeof(WCHAR)); // 进程的长度 ULONG ulRegistryPathLength = usRegistryPath.Length + sizeof(WCHAR); // 注册表路径的长度 SIZE_T ulNumberOfBytes = sizeof(REGISTRY_EVENT) + ulProcessPathLength + ulRegistryPathLength + ulDataSize; // 总长度=进程+注册表+数据 // 进程路径 pNode->pstRegistryEvent = ExAllocatePoolWithTag(NonPagedPool, ulNumberOfBytes, MEM_TAG); // 给各节点数据赋值 pNode->pstRegistryEvent->hProcessId = hProcessId; pNode->pstRegistryEvent->enRegistryNotifyClass = ulType; pNode->pstRegistryEvent->ulDataLength = ulDataSize; pNode->pstRegistryEvent->ulProcessPathLength = ulProcessPathLength; pNode->pstRegistryEvent->ulRegistryPathLength = ulRegistryPathLength; pNode->pstRegistryEvent->ulKeyValueType = ulKeyValueType; RtlTimeToTimeFields(&unCurrentLocalTime, &pNode->pstRegistryEvent->time); // 时间信息 RtlCopyBytes(pNode->pstRegistryEvent->uData, wzProcessPath, ulProcessPathLength); // 拷贝进程信息 RtlCopyBytes(pNode->pstRegistryEvent->uData + ulProcessPathLength, usRegistryPath.Buffer, usRegistryPath.Length); // 追加注册表路径信息 pNode->pstRegistryEvent->uData[ulProcessPathLength + usRegistryPath.Length + 0] = '\0'; // 给注册表路径后面添加 \0 结束符 pNode->pstRegistryEvent->uData[ulProcessPathLength + usRegistryPath.Length + 1] = '\0'; RtlCopyBytes(pNode->pstRegistryEvent->uData + ulProcessPathLength + ulRegistryPathLength, pData, ulDataSize); // 追加修改的数据信息(如果不是修改值,这里可能为空) ExInterlockedInsertTailList(&g_ListHead, (PLIST_ENTRY)pNode, &g_Lock); KeSetEvent(&g_Event, 0, FALSE); KdPrint(("hProcessId = %ld", hProcessId)); } if (NULL != usRegistryPath.Buffer) { ExFreePoolWithTag(usRegistryPath.Buffer, MEM_TAG); } return status; }
NTSTATUS drvStreamClassify( IN const FWPS_INCOMING_VALUES* inFixedValues, IN const FWPS_INCOMING_METADATA_VALUES* inMetaValues, IN FWPS_STREAM_CALLOUT_IO_PACKET0* packet, IN const FWPS_FILTER* filter, IN UINT64 flowContext, OUT FWPS_CLASSIFY_OUT* classifyOut) { KLOCK_QUEUE_HANDLE packetQueueLockHandle; PENDED_PACKET *pendedPacket = NULL; BOOLEAN signalWorkerThread; LARGE_INTEGER systemTime, localTime; TIME_FIELDS timeFields; KLOCK_QUEUE_HANDLE lockHandle; BOOLEAN localInspectEnabled; KeQuerySystemTime(&systemTime); ExSystemTimeToLocalTime(&systemTime, &localTime); // We don't have the necessary right to alter the classify, exit. if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0) { goto Exit; } // We don't edit TCP urgent data if ((packet->streamData->flags & FWPS_STREAM_FLAG_SEND_EXPEDITED) || (packet->streamData->flags & FWPS_STREAM_FLAG_RECEIVE_EXPEDITED) //|| (packet->streamData->flags & ) { packet->streamAction = FWPS_STREAM_ACTION_NONE; classifyOut->actionType = FWP_ACTION_PERMIT; goto Exit; } ASSERT(packet != NULL); pendedPacket = AllocateAndInitializeStreamPendedPacket( inFixedValues, inMetaValues, (FLOW_DATA*) flowContext, &localTime, packet); if (pendedPacket == NULL) { // Insufficient resources? classifyOut->actionType = FWP_ACTION_CONTINUE; goto Exit; } KeAcquireInStackQueuedSpinLock( &gPacketQueueLock, &packetQueueLockHandle); if (!gDriverUnloading) { signalWorkerThread = IsListEmpty(&gPacketQueue); InsertTailList(&gPacketQueue, &pendedPacket->listEntry); pendedPacket = NULL; // ownership transferred classifyOut->actionType = FWP_ACTION_BLOCK; classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB; } else { // Driver is being unloaded, permit any connect classify. signalWorkerThread = FALSE; classifyOut->actionType = FWP_ACTION_PERMIT; } KeReleaseInStackQueuedSpinLock(&packetQueueLockHandle); if (signalWorkerThread) { KeSetEvent( &gWorkerEvent, 0, FALSE); } Exit: if (pendedPacket != NULL) { FreePendedPacket(pendedPacket); } return STATUS_SUCCESS; }
VOID PrintFtlPkt( IN char *strPrefix, IN FLT_PKT* pFltPkt, IN ULONG uNewIp, IN BOOLEAN bOut ) { TIME_FIELDS TimeFields; char Message[255]; char MessagePart[30]; LARGE_INTEGER time; KeQuerySystemTime(&time); ExSystemTimeToLocalTime(&time, &time); RtlTimeToTimeFields(&time, &TimeFields); RtlStringCbPrintfA(Message, sizeof(Message), "%02d:%02d:%02d.%03d ", TimeFields.Hour, TimeFields.Minute, TimeFields.Second, TimeFields.Milliseconds); if (!bOut) { RtlStringCbCatA(Message, sizeof(Message), "IN "); } else { RtlStringCbCatA(Message, sizeof(Message), "OUT "); } RtlStringCbCatA(Message, sizeof(Message), strPrefix); RtlStringCbCatA(Message, sizeof(Message), " "); if (NULL == pFltPkt->pEth) { goto out; } RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%02x-%02x-%02x-%02x-%02x-%02x", pFltPkt->pEth->ether_src[0], pFltPkt->pEth->ether_src[1], pFltPkt->pEth->ether_src[2], pFltPkt->pEth->ether_src[3], pFltPkt->pEth->ether_src[4], pFltPkt->pEth->ether_src[5]); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbCatA(Message, sizeof(Message), "->"); RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%02x-%02x-%02x-%02x-%02x-%02x", pFltPkt->pEth->ether_dst[0], pFltPkt->pEth->ether_dst[1], pFltPkt->pEth->ether_dst[2], pFltPkt->pEth->ether_dst[3], pFltPkt->pEth->ether_dst[4], pFltPkt->pEth->ether_dst[5]); RtlStringCbCatA(Message, sizeof(Message), MessagePart); switch (pFltPkt->pEth->ether_type) { case ETHERNET_TYPE_ARP_NET: RtlStringCbCatA(Message, sizeof(Message), " ARP "); if (NULL == pFltPkt->pArp) goto out; if (ARP_REQUEST_CODE == pFltPkt->pArp->ea_hdr.ar_op) { RtlStringCbCatA(Message, sizeof(Message), "Request "); } else if (pFltPkt->pArp->ea_hdr.ar_op == ARP_REPLY_CODE) { RtlStringCbCatA(Message, sizeof(Message), "Reply "); } RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "%d.%d.%d.%d", pFltPkt->pArp->arp_spa[0], pFltPkt->pArp->arp_spa[1], pFltPkt->pArp->arp_spa[2], pFltPkt->pArp->arp_spa[3]); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbCatA(Message, sizeof(Message), "->"); PRINT_IP(MessagePart, pFltPkt->pArp->arp_tpa); RtlStringCbCatA(Message, sizeof(Message), MessagePart); break; case ETHERNET_TYPE_IP_NET: RtlStringCbCatA(Message, sizeof(Message), " IP "); if (NULL == pFltPkt->pIp) goto out; RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), "ID %04x ", RtlUshortByteSwap(pFltPkt->pIp->ip_id)); RtlStringCbCatA(Message, sizeof(Message), MessagePart); PRINT_IP(MessagePart, &pFltPkt->pIp->ip_src); RtlStringCbCatA(Message, sizeof(Message), MessagePart); if (uNewIp && bOut) { RtlStringCbCatA(Message, sizeof(Message), "["); PRINT_IP(MessagePart, &uNewIp); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbCatA(Message, sizeof(Message), "]"); } RtlStringCbCatA(Message, sizeof(Message), "->"); PRINT_IP(MessagePart, &pFltPkt->pIp->ip_dst); RtlStringCbCatA(Message, sizeof(Message), MessagePart); if (uNewIp && !bOut) { RtlStringCbCatA(Message, sizeof(Message), "["); PRINT_IP(MessagePart, &uNewIp); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbCatA(Message, sizeof(Message), "]"); } switch (pFltPkt->pIp->ip_proto) { case IPPROTO_TCP: RtlStringCbCatA(Message, sizeof(Message), " TCP"); break; case IPPROTO_ICMP: RtlStringCbCatA(Message, sizeof(Message), " ICMP"); break; case IPPROTO_UDP: RtlStringCbCatA(Message, sizeof(Message), " UDP"); break; default: RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " proto=%04x", pFltPkt->pIp->ip_proto); RtlStringCbCatA(Message, sizeof(Message), MessagePart); break; } if (pFltPkt->pTcp) { RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d->%d ", RtlUshortByteSwap(pFltPkt->pTcp->th_sport), RtlUshortByteSwap(pFltPkt->pTcp->th_dport)); if (pFltPkt->pTcp->th_flags & TCP_FIN_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "F"); if (pFltPkt->pTcp->th_flags & TCP_SYN_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "S"); if (pFltPkt->pTcp->th_flags & TCP_RST_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "R"); if (pFltPkt->pTcp->th_flags & TCP_PSH_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "P"); if (pFltPkt->pTcp->th_flags & TCP_URG_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "U"); if (pFltPkt->pTcp->th_flags & TCP_ACK_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "A"); // https://tools.ietf.org/html/rfc3168 if (pFltPkt->pTcp->th_flags & TCP_ECE_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "E"); if (pFltPkt->pTcp->th_flags & TCP_CWR_FLAG) RtlStringCbCatA(MessagePart, sizeof(MessagePart), "C"); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " SEQ:%u", RtlUlongByteSwap(pFltPkt->pTcp->th_seq)); RtlStringCbCatA(Message, sizeof(Message), MessagePart); RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " ACK:%u", RtlUlongByteSwap(pFltPkt->pTcp->th_ack)); } else if (pFltPkt->pUdp) { RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d->%d", RtlUshortByteSwap(pFltPkt->pUdp->uh_sport), RtlUshortByteSwap(pFltPkt->pUdp->uh_dport)); } else if (pFltPkt->pIcmp) { RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " %d", RtlUshortByteSwap(pFltPkt->pIcmp->icmp_hun.idseq.id)); } else { MessagePart[0] = 0; } RtlStringCbCatA(Message, sizeof(Message), MessagePart); break; default: RtlStringCbPrintfA(MessagePart, sizeof(MessagePart), " UNK %04x", RtlUshortByteSwap(pFltPkt->pEth->ether_type)); RtlStringCbCatA(Message, sizeof(Message), MessagePart); break; } out: RtlStringCbCatA(Message, sizeof(Message), "\n"); DbgPrint(Message); return; }
VOID ExGetNextWakeTime ( OUT PULONGLONG DueTime, OUT PTIME_FIELDS TimeFields, OUT PVOID *TimerObject ) { PLIST_ENTRY Link; PETIMER ExTimer; PETIMER BestTimer; KIRQL OldIrql; ULONGLONG TimerDueTime; ULONGLONG BestDueTime; ULONGLONG InterruptTime; LARGE_INTEGER SystemTime; LARGE_INTEGER CmosTime; ExAcquireSpinLock(&ExpWakeTimerListLock, &OldIrql); BestDueTime = 0; BestTimer = NULL; Link = ExpWakeTimerList.Flink; while (Link != &ExpWakeTimerList) { ExTimer = CONTAINING_RECORD(Link, ETIMER, WakeTimerListEntry); Link = Link->Flink; if (ExTimer->WakeTimer) { TimerDueTime = KeQueryTimerDueTime(&ExTimer->KeTimer); TimerDueTime = 0 - TimerDueTime; // // Is this timers due time closer? // if (TimerDueTime > BestDueTime) { BestDueTime = TimerDueTime; BestTimer = ExTimer; } } else { // // Timer is not an active wake timer, remove it // RemoveEntryList(&ExTimer->WakeTimerListEntry); ExTimer->WakeTimerListEntry.Flink = NULL; } } ExReleaseSpinLock(&ExpWakeTimerListLock, OldIrql); if (BestDueTime) { // // Convert time to timefields // KeQuerySystemTime (&SystemTime); InterruptTime = KeQueryInterruptTime (); BestDueTime = 0 - BestDueTime; SystemTime.QuadPart += BestDueTime - InterruptTime; // // Many system alarms are only good to 1 second resolution. // Add one sceond to the target time so that the timer is really // elasped if this is the wake event. // SystemTime.QuadPart += 10000000; ExSystemTimeToLocalTime(&SystemTime,&CmosTime); RtlTimeToTimeFields(&CmosTime, TimeFields); } *DueTime = BestDueTime; *TimerObject = BestTimer; }
FLT_PREOP_CALLBACK_STATUS PreFileOperationCallback ( __inout PFLT_CALLBACK_DATA Data, __in PCFLT_RELATED_OBJECTS FltObjects, __deref_out_opt PVOID *CompletionContext ) { NTSTATUS status; PFLT_FILE_NAME_INFORMATION pFileNameInformation; PFILE_EVENT pFileEvent; LARGE_INTEGER CurrentSystemTime; LARGE_INTEGER CurrentLocalTime; ULONG returnedLength; //HANDLE hThread; //HANDLE handle5; TIME_FIELDS TimeFields; BOOLEAN pathNameFound = FALSE; UNICODE_STRING filePath; FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK; /* If this is a callback for a FS Filter driver then we ignore the event */ if(FLT_IS_FS_FILTER_OPERATION(Data)) { return FLT_PREOP_SUCCESS_NO_CALLBACK; } /* Allocate a large 64kb string ... maximum path name allowed in windows */ filePath.Length = 0; filePath.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR); filePath.Buffer = ExAllocatePoolWithTag(NonPagedPool, filePath.MaximumLength, FILE_POOL_TAG); if(filePath.Buffer == NULL) { return FLT_PREOP_SUCCESS_NO_CALLBACK; } if (FltObjects->FileObject != NULL && Data != NULL) { status = FltGetFileNameInformation( Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP, &pFileNameInformation ); if(NT_SUCCESS(status)) { if(pFileNameInformation->Name.Length > 0) { RtlUnicodeStringCopy(&filePath, &pFileNameInformation->Name); //RtlStringCbCopyUnicodeString(pFileEvent->filePath, 1024, &pFileNameInformation->Name); pathNameFound = TRUE; } /* Backup the file if it is marked for deletion */ CopyFileIfBeingDeleted (Data,FltObjects,pFileNameInformation); /* Release the file name information structure if it was used */ if(pFileNameInformation != NULL) { FltReleaseFileNameInformation(pFileNameInformation); } } else { NTSTATUS lstatus; PFLT_FILE_NAME_INFORMATION pLFileNameInformation; lstatus = FltGetFileNameInformation( Data, FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP, &pLFileNameInformation); if(NT_SUCCESS(lstatus)) { if(pLFileNameInformation->Name.Length > 0) { RtlUnicodeStringCopy(&filePath, &pLFileNameInformation->Name); //RtlStringCbCopyUnicodeString(pFileEvent->filePath, 1024, &pLFileNameInformation->Name); pathNameFound = TRUE; } /* Backup the file if it is marked for deletion */ CopyFileIfBeingDeleted (Data,FltObjects,pFileNameInformation); /* Release the file name information structure if it was used */ if(pLFileNameInformation != NULL) { FltReleaseFileNameInformation(pLFileNameInformation); } } } } /* If path name could not be found the file monitor uses the file name stored in the FileObject. The documentation says that we shouldn't use this info as it may not be correct. It does however allow us get some nice file events such as the system process writing to the $MFT file etc. Remove this code if problems start to occur */ if( (pathNameFound == FALSE) && (FltObjects->FileObject != NULL) && (FltObjects->FileObject->RelatedFileObject == NULL) && (FltObjects->FileObject->FileName.Length > 0)) { NTSTATUS status; ULONG size; UNICODE_STRING szTempPath; UNICODE_STRING szDevice; UNICODE_STRING szFileNameDevice; /* Check the FileObject->FileName isn't already a complete filepath */ szFileNameDevice.Length = FltObjects->FileObject->FileName.Length; szFileNameDevice.MaximumLength = FltObjects->FileObject->FileName.MaximumLength; szFileNameDevice.Buffer = ExAllocatePoolWithTag(NonPagedPool, szFileNameDevice.MaximumLength, FILE_POOL_TAG); RtlInitUnicodeString(&szDevice, L"\\Device"); if(FltObjects->FileObject->FileName.Length >= szDevice.Length) { RtlUnicodeStringCchCopyN(&szFileNameDevice, &FltObjects->FileObject->FileName, 7); } if(RtlEqualUnicodeString(&szDevice, &szFileNameDevice, TRUE)) { RtlUnicodeStringCopy(&filePath, &FltObjects->FileObject->FileName); pathNameFound = TRUE; } else { szTempPath.Length = 0; szTempPath.MaximumLength = FltObjects->FileObject->FileName.MaximumLength + 2; /* Get the volume name of where the event came from */ status = FltGetVolumeName( FltObjects->Volume, NULL, &size ); if(status == STATUS_BUFFER_TOO_SMALL) { szTempPath.MaximumLength += (USHORT)size; szTempPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, szTempPath.MaximumLength, FILE_POOL_TAG); if(szTempPath.Buffer != NULL) { status = FltGetVolumeName( FltObjects->Volume, &szTempPath, &size ); if(NT_SUCCESS(status)) { /* Append the file event to the volume name */ RtlUnicodeStringCat(&szTempPath, &FltObjects->FileObject->FileName); RtlUnicodeStringCopy(&filePath, &szTempPath); pathNameFound = TRUE; } ExFreePoolWithTag(szTempPath.Buffer, FILE_POOL_TAG); } } } ExFreePoolWithTag(szFileNameDevice.Buffer, FILE_POOL_TAG); } if(!pathNameFound) { RtlUnicodeStringCatString(&filePath, L"UNKNOWN"); } /* Allocate file event and put the values into it */ /* NOTE this is freed in the post op callback (which should always get called) */ pFileEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_EVENT)+filePath.Length+sizeof(WCHAR), FILE_POOL_TAG); if(pFileEvent == NULL) { ExFreePoolWithTag(filePath.Buffer, FILE_POOL_TAG); return FLT_PREOP_SUCCESS_NO_CALLBACK; } /* Copy file path into file event */ pFileEvent->filePathLength = filePath.Length+sizeof(WCHAR); RtlStringCbCopyUnicodeString(pFileEvent->filePath, pFileEvent->filePathLength, &filePath); /* Free the allocated storage for a filepath */ ExFreePoolWithTag(filePath.Buffer, FILE_POOL_TAG); pFileEvent->majorFileEventType = Data->Iopb->MajorFunction; pFileEvent->minorFileEventType = Data->Iopb->MinorFunction; pFileEvent->processId = 0; if (FltObjects->FileObject != NULL) { pFileEvent->flags = FltObjects->FileObject->Flags; } if(Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION) { if(Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation) { PFILE_DISPOSITION_INFORMATION pFileInfo = (PFILE_DISPOSITION_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer; /* If the file is marked for deletion back it up */ if(pFileInfo->DeleteFile) { pFileEvent->majorFileEventType = 0x99; } } } /* Get the process id of the file event */ /* NOTE we are kinda using an undocumented function here but its all available on the interweb. Plus its much better than accessing the PETHREAD structure which could change at any time. Also, this one is available to userspace programs so it should be safe to use. We have to use this function because a file I/O may either be processed in the context of the userspace program or the system context. This uses the thread data from FLT_CALLBACK_DATA to determine which process it actually came from. We default back to getting the current process id if all else fails. */ /* SECOND NOTE FltGetRequestorProcessId does not get the correct process id, it looks like it still get the proces id of the context the pre callback gets called in */ /* status = ObOpenObjectByPointer(Data->Thread, OBJ_KERNEL_HANDLE, NULL, 0, 0, KernelMode, &hThread); if(NT_SUCCESS(status)) { THREAD_BASIC_INFORMATION threadBasicInformation; status = ZwQueryInformationThread(hThread, ThreadBasicInformation, &threadBasicInformation, sizeof(THREAD_BASIC_INFORMATION), &returnedLength ); if(NT_SUCCESS(status)) { pFileEvent->processId = (HANDLE)threadBasicInformation.UniqueProcessId; handle5 = pFileEvent->processId; //DbgPrint("Process4: %i\n", pFileEvent->processId); } else { DbgPrint("ZwQueryInformationThread FAILED: %08x\n", status); } ZwClose(hThread); } else { DbgPrint("ObOpenObjectByPointer FAILED: %08x\n", status); } */ /* New safe get correct process id. One above causes blue screen in some cases */ if(Data->Thread != NULL) { PEPROCESS pProcess = IoThreadToProcess( Data->Thread ); pFileEvent->processId = PsGetProcessId(pProcess); } else { pFileEvent->processId = PsGetCurrentProcessId(); DbgPrint("CaptureFileMonitor: Process id may be incorrect\n"); } /* DbgPrint("%i [%i %i] %s %i %i (%i, %i, %i) %i %i %i %i %i : %ls\n", KeGetCurrentIrql(), PsIsSystemThread(Data->Thread), PsIsSystemThread(PsGetCurrentThread()), FltGetIrpName(Data->Iopb->MajorFunction), Data->Iopb->MajorFunction, Data->Iopb->MinorFunction, pFileEvent->processId, PsGetCurrentProcessId(), FltGetRequestorProcessId(Data), FLT_IS_FASTIO_OPERATION(Data), FLT_IS_FS_FILTER_OPERATION(Data), FLT_IS_IRP_OPERATION(Data), FLT_IS_REISSUED_IO(Data), FLT_IS_SYSTEM_BUFFER(Data), pFileEvent->filePath); */ //ASSERT(pFileEvent->processId != 0); /* Get the time this event occured */ KeQuerySystemTime(&CurrentSystemTime); ExSystemTimeToLocalTime(&CurrentSystemTime,&CurrentLocalTime); RtlTimeToTimeFields(&CurrentLocalTime,&TimeFields); pFileEvent->time = TimeFields; /* Pass the created file event to the post operation of this pre file operation */ if (Data->Iopb->MajorFunction == IRP_MJ_SHUTDOWN) { PostFileOperationCallback( Data, FltObjects, pFileEvent, 0 ); return FLT_PREOP_SUCCESS_NO_CALLBACK; } else { *CompletionContext = pFileEvent; return FLT_PREOP_SUCCESS_WITH_CALLBACK; } }
NTSTATUS KloggerWriteToFile() { HANDLE fileHandle; IO_STATUS_BLOCK ioStatus; OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING fileNameUnicodeString; NTSTATUS status; UNICODE_STRING fileName; fileName.Buffer = NULL; fileName.Length = 0; fileName.MaximumLength = sizeof(DEFAULT_LOG_FILE_NAME) + sizeof(UNICODE_NULL); fileName.Buffer = ExAllocatePool(PagedPool, fileName.MaximumLength); RtlZeroMemory(fileName.Buffer, fileName.MaximumLength); status = RtlAppendUnicodeToString(&fileName, (PWSTR) DEFAULT_LOG_FILE_NAME); InitializeObjectAttributes( &objectAttributes, (PUNICODE_STRING) &fileName, OBJ_CASE_INSENSITIVE, NULL, NULL); //in init status = ZwCreateFile( &fileHandle, FILE_APPEND_DATA, &objectAttributes, &ioStatus, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_ALERT, NULL, 0); if (NT_SUCCESS(status)) { CHAR buf[300]; LARGE_INTEGER time; TIME_FIELDS timefields; ULONG length; KeQuerySystemTime(&time); ExSystemTimeToLocalTime(&time, &time); RtlTimeToTimeFields(&time, &timefields); sprintf(buf, "%2u:%2u:%2u %3ums\n", timefields.Hour, timefields.Minute, timefields.Second, timefields.Milliseconds); length = strlen(buf); ZwWriteFile( fileHandle, NULL, NULL, NULL, &ioStatus, buf, length, NULL, NULL); ZwClose(fileHandle); } if (fileName.Buffer) { ExFreePool(fileName.Buffer); } }
void AFSDumpTraceFiles() { NTSTATUS ntStatus = STATUS_SUCCESS; HANDLE hDirectory = NULL; OBJECT_ATTRIBUTES stObjectAttribs; IO_STATUS_BLOCK stIoStatus; LARGE_INTEGER liTime, liLocalTime; TIME_FIELDS timeFields; ULONG ulBytesWritten = 0; HANDLE hDumpFile = NULL; ULONG ulBytesProcessed, ulCopyLength; LARGE_INTEGER liOffset; ULONG ulDumpLength = 0; BOOLEAN bSetEvent = FALSE; __Enter { AFSAcquireShared( &AFSDbgLogLock, TRUE); ulDumpLength = AFSDbgBufferLength - AFSDbgLogRemainingLength; AFSReleaseResource( &AFSDbgLogLock); if( AFSDumpFileLocation.Length == 0 || AFSDumpFileLocation.Buffer == NULL || AFSDbgBufferLength == 0 || ulDumpLength == 0 || AFSDumpFileName.MaximumLength == 0 || AFSDumpFileName.Buffer == NULL || AFSDumpBuffer == NULL) { try_return( ntStatus); } // // Go open the cache file // InitializeObjectAttributes( &stObjectAttribs, &AFSDumpFileLocation, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus = ZwCreateFile( &hDirectory, GENERIC_READ | GENERIC_WRITE, &stObjectAttribs, &stIoStatus, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } ntStatus = KeWaitForSingleObject( &AFSDumpFileEvent, Executive, KernelMode, FALSE, NULL); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } bSetEvent = TRUE; AFSDumpFileName.Length = 0; RtlZeroMemory( AFSDumpFileName.Buffer, AFSDumpFileName.MaximumLength); KeQuerySystemTime( &liTime); ExSystemTimeToLocalTime( &liTime, &liLocalTime); RtlTimeToTimeFields( &liLocalTime, &timeFields); ntStatus = RtlStringCchPrintfW( AFSDumpFileName.Buffer, AFSDumpFileName.MaximumLength/sizeof( WCHAR), L"AFSDumpFile %d.%d.%d %d.%d.%d.log", timeFields.Month, timeFields.Day, timeFields.Year, timeFields.Hour, timeFields.Minute, timeFields.Second); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } RtlStringCbLengthW( AFSDumpFileName.Buffer, AFSDumpFileName.MaximumLength, (size_t *)&ulBytesWritten); AFSDumpFileName.Length = (USHORT)ulBytesWritten; InitializeObjectAttributes( &stObjectAttribs, &AFSDumpFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDirectory, NULL); ntStatus = ZwCreateFile( &hDumpFile, GENERIC_READ | GENERIC_WRITE, &stObjectAttribs, &stIoStatus, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } // // Write out the trace buffer // liOffset.QuadPart = 0; ulBytesProcessed = 0; while( ulBytesProcessed < ulDumpLength) { ulCopyLength = AFSDumpBufferLength; if( ulCopyLength > ulDumpLength - ulBytesProcessed) { ulCopyLength = ulDumpLength - ulBytesProcessed; } RtlCopyMemory( AFSDumpBuffer, (void *)((char *)AFSDbgBuffer + ulBytesProcessed), ulCopyLength); ntStatus = ZwWriteFile( hDumpFile, NULL, NULL, NULL, &stIoStatus, AFSDumpBuffer, ulCopyLength, &liOffset, NULL); if( !NT_SUCCESS( ntStatus)) { break; } liOffset.QuadPart += ulCopyLength; ulBytesProcessed += ulCopyLength; } try_exit: if( hDumpFile != NULL) { ZwClose( hDumpFile); } if( hDirectory != NULL) { ZwClose( hDirectory); } if( bSetEvent) { KeSetEvent( &AFSDumpFileEvent, 0, FALSE); } } return; }
NTSTATUS Log_Print(LOG_LEVEL Level, LPCSTR pszFormat, ...) { NTSTATUS Status = STATUS_SUCCESS; LARGE_INTEGER SystemTime, LocalTime; TIME_FIELDS TimeFields; PLOG_COUNTED_STRING Line = NULL; va_list args; KIRQL Irql = KeGetCurrentIrql(); LPCSTR StrLevel = " :"; if (!LogFile) return STATUS_INVALID_DEVICE_STATE; if (Irql > DISPATCH_LEVEL) return STATUS_INVALID_LEVEL; KeQuerySystemTime(&SystemTime); ExSystemTimeToLocalTime(&SystemTime, &LocalTime); RtlTimeToTimeFields(&LocalTime, &TimeFields); Line = ExAllocatePoolWithTag(NonPagedPool, MAX_LOG_STRING_SIZE + FIELD_OFFSET(LOG_COUNTED_STRING, Data), LogAllocationTag); if (!Line) return STATUS_INSUFFICIENT_RESOURCES; switch (Level) { case LL_FATAL: #if DBG DbgBreakPointWithStatus(DBG_STATUS_FATAL); #endif StrLevel = "FATAL :"; break; case LL_ERROR: StrLevel = "ERROR :"; break; case LL_WARNING: StrLevel = "WARNING:"; break; case LL_INFO: StrLevel = "INFO :"; break; case LL_VERBOSE: StrLevel = "VERBOSE:"; break; case LL_DEBUG: StrLevel = "DEBUG :"; break; } Status = StringCbPrintfA(Line->Data, MAX_LOG_STRING_SIZE, "%04u.%02u.%02u %02u:%02u:%02u.%03u PR:0x%04X TH:0x%04X IL:%d %s ", TimeFields.Year, TimeFields.Month, TimeFields.Day, TimeFields.Hour, TimeFields.Minute, TimeFields.Second, TimeFields.Milliseconds, (ULONG)PsGetCurrentProcessId() & 0xFFFF, (ULONG)PsGetCurrentThreadId() & 0xFFFF, (ULONG)Irql, StrLevel); if (SUCCEEDED(Status)) { va_start(args, pszFormat); Line->DataLength = (USHORT)strlen(Line->Data); Status = StringCbVPrintfA(Line->Data + Line->DataLength, MAX_LOG_STRING_SIZE - Line->DataLength, pszFormat, args); if (SUCCEEDED(Status)) { Line->DataLength = (USHORT)strlen(Line->Data); if (Irql != PASSIVE_LEVEL) { PIO_WORKITEM pWorkItem = IoAllocateWorkItem(LogDeviceObject); InterlockedIncrement(&LogScheduledPrints); IoQueueWorkItemEx(pWorkItem, Log_WriteWorker, DelayedWorkQueue, Line); Status = STATUS_PENDING; } else { Status = Log_WriteLine(Line); } } va_end(args); } if (Status != STATUS_PENDING) ExFreePoolWithTag(Line, LogAllocationTag); return Status; }
VOID BowserTrace( PCHAR FormatString, ... ) #define LAST_NAMED_ARGUMENT FormatString { CHAR OutputString[1024]; IO_STATUS_BLOCK IoStatus; BOOLEAN ProcessAttached = FALSE; va_list ParmPtr; // Pointer to stack parms. NTSTATUS Status; PAGED_CODE(); if (IoGetCurrentProcess() != BowserFspProcess) { KeAttachProcess(BowserFspProcess); ProcessAttached = TRUE; } if (BrowserTraceLogHandle == NULL) { if (!NT_SUCCESS(BowserOpenTraceLogFile(L"\\SystemRoot\\Bowser.Log"))) { BrowserTraceLogHandle = (HANDLE)0xffffffff; if (ProcessAttached) { KeDetachProcess(); } return; } } else if (BrowserTraceLogHandle == (HANDLE)0xffffffff) { if (ProcessAttached) { KeDetachProcess(); } return; } ExAcquireResourceExclusive(&BrowserTraceLock, TRUE); if (BrowserTraceLogHandle == NULL) { ExReleaseResource(&BrowserTraceLock); if (ProcessAttached) { KeDetachProcess(); } return; } try { LARGE_INTEGER EndOfFile; EndOfFile.HighPart = 0xffffffff; EndOfFile.LowPart = FILE_WRITE_TO_END_OF_FILE; if (LastCharacter == '\n') { LARGE_INTEGER SystemTime; TIME_FIELDS TimeFields; KeQuerySystemTime(&SystemTime); ExSystemTimeToLocalTime(&SystemTime, &SystemTime); RtlTimeToTimeFields(&SystemTime, &TimeFields); // // The last character written was a newline character. We should // timestamp this record in the file. // /**** sprintf(OutputString, "%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d: ", TimeFields.Month, TimeFields.Day, TimeFields.Year, TimeFields.Hour, TimeFields.Minute, TimeFields.Second, TimeFields.Milliseconds); ****/ if (!NT_SUCCESS(Status = ZwWriteFile(BrowserTraceLogHandle, NULL, NULL, NULL, &IoStatus, OutputString, strlen(OutputString), &EndOfFile, NULL))) { KdPrint(("Error writing time to Browser log file: %lX\n", Status)); return; } if (!NT_SUCCESS(IoStatus.Status)) { KdPrint(("Error writing time to Browser log file: %lX\n", IoStatus.Status)); return; } if (IoStatus.Information != strlen(OutputString)) { KdPrint(("Error writing time to Browser log file: %lX\n", IoStatus.Status)); return; } } va_start(ParmPtr, LAST_NAMED_ARGUMENT); // // Format the parameters to the string. // vsprintf(OutputString, FormatString, ParmPtr); if (!NT_SUCCESS(Status = ZwWriteFile(BrowserTraceLogHandle, NULL, NULL, NULL, &IoStatus, OutputString, strlen(OutputString), &EndOfFile, NULL))) { KdPrint(("Error writing string to Browser log file: %ld\n", Status)); return; } if (!NT_SUCCESS(IoStatus.Status)) { KdPrint(("Error writing string to Browser log file: %lX\n", IoStatus.Status)); return; } if (IoStatus.Information != strlen(OutputString)) { KdPrint(("Error writing string to Browser log file: %ld\n", IoStatus.Status)); return; } // // Remember the last character output to the log. // LastCharacter = OutputString[strlen(OutputString)-1]; } finally { ExReleaseResource(&BrowserTraceLock); if (ProcessAttached) { KeDetachProcess(); } } }
// // Helper function that collects current settings into our metadata structure. // METADATA_IMAGEAGGREGATION CImageHardwareSimulation:: GetMetadata() { PAGED_CODE(); METADATA_IMAGEAGGREGATION Metadata; ISP_FRAME_SETTINGS *pSettings = GetIspSettings(); // Wipe the metadata so all settings will default to "Not Set". RtlZeroMemory( &Metadata, sizeof(Metadata) ); // Identify the current PFS frame number. // If PFS not active, then this item is not present. Metadata.FrameId.Set = IsPfsActive(); Metadata.FrameId.Value = (ULONG) m_PfsFrameNumber; DBG_TRACE("Metadata.FrameId.Set=%s, Metadata.FrameId.Value=%d", (Metadata.FrameId.Set?"Yes":"No"), Metadata.FrameId.Value); // Just reflect the exposure time from the setting. //Metadata.ExposureTime.Set = TRUE; //Metadata.ExposureTime.Value = GetCurrentExposureTime(); // Just reflect the ISO Speed from the setting. Metadata.ISOSpeed = CMetadataLong(GetCurrentISOSpeed()); DBG_TRACE("ISO=%d, ISO Flags=0x%016llX", Metadata.ISOSpeed.Value, pSettings->ISOMode); // TODO: Do we need to bracket this by whether or not a flash has been taken? // Report the current flash mode. Metadata.FlashOn = CMetadataLong((ULONG) pSettings->FlashMode); // Report the current flash power. Metadata.FlashPower = CMetadataLong(pSettings->FlashValue); // Set the White Balance lock state. Metadata.WhiteBalanceLocked = CMetadataLong( ( (pSettings->WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK) == KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK) ); // Set the Exposure lock state. Metadata.ExposureLocked = CMetadataLong( ( (pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK) == KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK) ); Metadata.ExposureTime = //CMetadataRational(GetCurrentExposureTime(), 10000000); CMetadataLongLong( GetCurrentExposureTime() ); Metadata.LensPosition = CMetadataLong( pSettings->FocusSetting.VideoProc.Value.ul ); Metadata.SceneMode = CMetadataULongLong(KSCAMERA_EXTENDEDPROP_SCENEMODE_AUTO); //TODO: Need to fill in real value from CCaptureFilter::m_SceneMode Metadata.WhiteBalanceMode = CMetadataLong((ULONG) pSettings->WhiteBalanceMode); CExtendedVidProcSetting Zoom; m_Sensor->GetZoom( &Zoom ); Metadata.ZoomFactor = CMetadataLong(Zoom.GetLONG()); //TODO: Fill in a real value from zoom simulation. Metadata.FocusLocked = CMetadataLong(FALSE); //TODO: Fill in a real value when we complete the focus changes. // Add EVCompensation metadata... Metadata.EVCompensation = CMetadataEVCompensation(pSettings->EVCompensation.Mode, pSettings->EVCompensation.Value); Metadata.Orientation = CMetadataShort(Metadata_Orientation_TopBottomLeftRight); //TODO: Randomize? { LARGE_INTEGER SystemTime; LARGE_INTEGER LocalTime; KeQuerySystemTimePrecise( &SystemTime ); ExSystemTimeToLocalTime( &SystemTime, &LocalTime ); RtlTimeToTimeFields( &LocalTime, &Metadata.LocalTime.Time ); Metadata.LocalTime.Set = TRUE; } Metadata.Make = CMetadataShortString("Make: Microsoft SOC Camera"); Metadata.Model = CMetadataShortString( "Model: AvsCam" ); Metadata.Software = CMetadataShortString( "Software: Microsoft Camera Sim" ); Metadata.ColorSpace.Set = TRUE; Metadata.ColorSpace.Value = 0xFFFF; // 0xFFFF Means "uncalibrated". Use this value for all non-RGB formats. Metadata.Gamma = CMetadataRational(); Metadata.MakerNote = CMetadataShortString( "Maker's Note..." ); // Just reflect the exposure time from the setting. //Metadata.ExposureTime = // CMetadataRational( GetCurrentExposureTime(), 1000 ); // report exposure time as milliseconds. Metadata.FNumber = CMetadataRational(4); // Fake an FNumber of 4. // TODO: It looks like we might be able to calculate this. Metadata.ExposureProgram.Set = TRUE; Metadata.ExposureProgram.Value = GetExposureProgram(); Metadata.ShutterSpeedValue = CMetadataSRational(); // TODO: Calculate this from the ExposureTime. *** Metadata.Aperture = CMetadataRational(4); // TODO: Calculate this from the F-Number. (We're currently faking the FNumber.) Metadata.Brightness = CMetadataSRational(0); // TODO: Find a more reasonable brightness value. Metadata.ExposureBias = CMetadataSRational(0); // TODO: More reasonable? Metadata.SubjectDistance = CMetadataRational(0xFFFFFFFF); // Distance in meters. Infinity. (Anything better?) Metadata.MeteringMode.Set = TRUE; Metadata.MeteringMode.Value = (USHORT) GetRandom( (ULONG) 1, (ULONG) 6); // Pick a number ... any number. Metadata.LightSource.Set = TRUE; Metadata.LightSource.Value = 1; // TODO: Pick a random value; but override when a flash occurs. Metadata.Flash.Set = TRUE; Metadata.Flash.Value = (UINT16) pSettings->FlashMode; // We assume that the flash fires when requested! DBG_TRACE("FlashMode=0x%016llX, FlashPower=%d", pSettings->FlashMode, pSettings->FlashValue); Metadata.FocalLength = CMetadataRational(); // TODO: Calculate? Metadata.FocalPlaneXResolution = CMetadataRational(); // TODO: Calculate? Metadata.FocalPlaneYResolution = CMetadataRational(); // TODO: Calculate? Metadata.ExposureIndex = CMetadataRational(); // TODO: Calculate? Metadata.ExposureMode.Set = TRUE; Metadata.ExposureMode.Value = 0 ; // Assume Auto exposure. if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL ) { Metadata.ExposureMode.Value = 0 ; // Manual exposure. } Metadata.WhiteBalance.Set = TRUE; Metadata.WhiteBalance.Value = 0 ; // Assume Auto white balance. if( pSettings->WhiteBalanceMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL ) { Metadata.WhiteBalance.Value = 0 ; // Manual while balance. } Metadata.DigitalZoomRatio = CMetadataRational(1); Metadata.FocalLengthIn35mmFilm = CMetadataShort(0); Metadata.SceneCaptureType = CMetadataShort(0); Metadata.GainControl = CMetadataRational(); Metadata.Contrast = CMetadataShort(0); Metadata.Saturation = CMetadataShort(0); Metadata.Sharpness = CMetadataShort(0); Metadata.SubjectDistanceRange = CMetadataShort(0); // Report (optional) focus state. KSCAMERA_EXTENDEDPROP_FOCUSSTATE State = KSCAMERA_EXTENDEDPROP_FOCUSSTATE_UNINITIALIZED; if( NT_SUCCESS(m_Sensor->GetFocusState( &State )) ) { Metadata.FocusState = CMetadataLong((UINT32)State); } return Metadata; }