Exemple #1
0
// 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;
}
Exemple #2
0
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(&currentSystemTime);
	ExSystemTimeToLocalTime(&currentSystemTime,&currentLocalTime);
	RtlTimeToTimeFields(&currentLocalTime,&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);
}
Exemple #4
0
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;
}
Exemple #5
0
//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(&currentSystemTime);
	ExSystemTimeToLocalTime(&currentSystemTime,&currentLocalTime);
	RtlTimeToSecondsSince1970(&currentLocalTime, &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(&current_stime);

	LARGE_INTEGER current_ltime;
	ExSystemTimeToLocalTime(&current_stime,&current_ltime);

	TIME_FIELDS current_tinfo;
	RtlTimeToTimeFields(&current_ltime,&current_tinfo);
    
	return current_tinfo;
}
Exemple #9
0
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)
    );
}
Exemple #10
0
// 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;
}
Exemple #11
0
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;
}
Exemple #12
0
// 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;
}
Exemple #14
0
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;
}
Exemple #15
0
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;
}
Exemple #16
0
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;
	}

    
}
Exemple #18
0
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);
	}
}
Exemple #19
0
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;
}
Exemple #20
0
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;
}
Exemple #21
0
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;
}