Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427/*++
Copyright (c) Microsoft Corporation
Module Name:
FxTelemetryUm.cpp
Abstract:
This module implements a telemetry methods.
Author:
Environment:
User mode only
Revision History:
Notes:
--*/
#include "fxsupportpch.hpp"#include "DriverFrameworks-UserMode-UmEvents.h"#include "FxldrUm.h"#include <winmeta.h>#include <TraceLoggingProvider.h>#include <telemetry\MicrosoftTelemetry.h>#include <rpc.h>#include <rpcndr.h>
extern "C" {#if defined(EVENT_TRACING)#include "FxTelemetryUm.tmh"#endif}
/* 8ad60765-a021-4494-8594-9346970cf50f */TRACELOGGING_DEFINE_PROVIDER(g_TelemetryProvider, UMDF_FX_TRACE_LOGGING_PROVIDER_NAME, (0x8ad60765, 0xa021, 0x4494, 0x85, 0x94, 0x93, 0x46, 0x97, 0x0c, 0xf5, 0x0f), TraceLoggingOptionMicrosoftTelemetry());
VOIDAllocAndInitializeTelemetryContext( _In_ PFX_TELEMETRY_CONTEXT* TelemetryContext ){ PFX_TELEMETRY_CONTEXT context = NULL; RPC_STATUS status;
context = (PFX_TELEMETRY_CONTEXT)MxMemory::MxAllocatePoolWithTag(NonPagedPool, sizeof(FX_TELEMETRY_CONTEXT), FX_TAG); if (NULL == context) { goto exit; }
status = UuidCreate(&(context->DriverSessionGUID)); if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) { MxMemory::MxFreePool(context); context = NULL; goto exit; }
context->DoOnceFlagsBitmap = 0;exit: *TelemetryContext = context;}
VOIDRegisterTelemetryProvider( VOID ){ EventRegisterMicrosoft_Windows_DriverFrameworks_UserMode();
TraceLoggingRegister(g_TelemetryProvider);}
VOIDUnregisterTelemetryProvider( VOID ){ EventUnregisterMicrosoft_Windows_DriverFrameworks_UserMode();
TraceLoggingUnregister(g_TelemetryProvider);}
VOIDLogDeviceStartTelemetryEvent( _In_ PFX_DRIVER_GLOBALS Globals, _In_opt_ FxDevice* Fdo ){ // If provider is not enabled we're done. if (FALSE == FX_TELEMETRY_ENABLED(g_TelemetryProvider, Globals)) { return; }
// // If we already fired an event during PnP start we are done. This avoids // repeatedly firing events during PnP rebalance. // if (InterlockedBitTestAndSet( &Globals->TelemetryContext->DoOnceFlagsBitmap, DeviceStartEventBit) == 1) { return; }
// // log the DriverInfo stream. // LogDriverInfoStream(Globals, Fdo);}
VOIDLogDriverInfoStream( _In_ PFX_DRIVER_GLOBALS DriverGlobals, _In_ FxDevice* Fdo ){ LONG error = ERROR_SUCCESS; PWCHAR str = NULL; UFxTelemetryDriverInfo driverInfo = {0}; LPCWSTR hardwareIds = NULL; LPCWSTR setupClass = NULL; LPCWSTR busEnum = NULL; LPCWSTR manufacturer = NULL; UMDF_DRIVER_REGSITRY_INFO devRegInfo = {0}; PCWSTR groupId = NULL; IWudfDeviceStack* devStack = NULL;
if (Fdo == NULL) { // // Telemetry events are logged during DriverEntry as well to capture non-pnp // and class extension (which are non-pnp drivers) driver info. Although // current UMDF datapoint doesn't have a separate flag for non-pnp driver, // we still want to log the driver name and its properies if available. // devStack = DriverGlobals->Driver->GetDriverObject()->WudfDevStack; if (devStack != NULL) { devStack->GetPdoProperties(&hardwareIds, &setupClass, &busEnum, &manufacturer); } } else { devStack = Fdo->GetDeviceStack(); devStack->GetPdoProperties(&hardwareIds, &setupClass, &busEnum, &manufacturer);
Fdo->RetrieveDeviceInfoRegistrySettings(&groupId, &devRegInfo); }
// // Log Driver info // if (Fdo != NULL) { GetDriverInfo(Fdo, &devRegInfo, &driverInfo); }
UMDF_CENSUS_EVT_WRITE_DEVICE_START(g_TelemetryProvider, DriverGlobals, driverInfo, setupClass, busEnum, hardwareIds, manufacturer);
if (groupId != NULL) { delete [] groupId; groupId = NULL; }}
VOIDGetDriverInfo( _In_ FxDevice* Fdo, _In_ PUMDF_DRIVER_REGSITRY_INFO RegInfo, _Out_ UFxTelemetryDriverInfo* DriverInfo ){ FxPkgPnp* pnpPkg; USHORT devInfo = 0; WDF_DEVICE_IO_TYPE readWritePreference; WDF_DEVICE_IO_TYPE ioControlPreference; UMDF_DRIVER_REGSITRY_INFO devRegInfo = {0}; PWSTR groupId = NULL;
pnpPkg = (FxPkgPnp*)Fdo->GetFdoPkg(); devInfo = Fdo->GetDeviceTelemetryInfoFlags(); Fdo->GetDeviceStackIoType(&readWritePreference, &ioControlPreference);
DriverInfo->bitmap.IsFilter = Fdo->IsFilter(); DriverInfo->bitmap.IsPowerPolicyOwner = pnpPkg->IsPowerPolicyOwner(); DriverInfo->bitmap.IsS0IdleWakeFromS0Enabled = pnpPkg->IsS0IdleWakeFromS0Enabled(); DriverInfo->bitmap.IsS0IdleUsbSSEnabled = pnpPkg->IsS0IdleUsbSSEnabled(); DriverInfo->bitmap.IsS0IdleSystemManaged = pnpPkg->IsS0IdleSystemManaged(); DriverInfo->bitmap.IsSxWakeEnabled = pnpPkg->IsSxWakeEnabled(); DriverInfo->bitmap.IsUsingLevelTriggeredLineInterrupt = IsDeviceInfoFlagSet(devInfo, DeviceInfoLineBasedLevelTriggeredInterrupt); DriverInfo->bitmap.IsUsingEdgeTriggeredLineInterrupt = IsDeviceInfoFlagSet(devInfo, DeviceInfoLineBasedEdgeTriggeredInterrupt); DriverInfo->bitmap.IsUsingMsiXOrSingleMsi22Interrupt = IsDeviceInfoFlagSet(devInfo, DeviceInfoMsiXOrSingleMsi22Interrupt); DriverInfo->bitmap.IsUsingMsi22MultiMessageInterrupt = IsDeviceInfoFlagSet(devInfo, DeviceInfoMsi22MultiMessageInterrupt); DriverInfo->bitmap.IsUsingMultipleInterrupt = pnpPkg->HasMultipleInterrupts(); DriverInfo->bitmap.IsDirectHardwareAccessAllowed = Fdo->IsDirectHardwareAccessAllowed(); DriverInfo->bitmap.IsUsingUserModemappingAccessMode = Fdo->AreRegistersMappedToUsermode(); DriverInfo->bitmap.IsKernelModeClientAllowed = RegInfo->IsKernelModeClientAllowed; DriverInfo->bitmap.IsNullFileObjectAllowed = RegInfo->IsNullFileObjectAllowed; DriverInfo->bitmap.IsPoolingDisabled = RegInfo->IsHostProcessSharingDisabled; DriverInfo->bitmap.IsMethodNeitherActionCopy = RegInfo->IsMethodNeitherActionCopy; DriverInfo->bitmap.IsUsingDirectIoForReadWrite = (readWritePreference == WdfDeviceIoDirect); DriverInfo->bitmap.IsUsingDirectIoForIoctl = (ioControlPreference == WdfDeviceIoDirect); DriverInfo->bitmap.IsUsingDriverWppRecorder = Fdo->GetDriver()->IsDriverObjectFlagSet(DriverObjectUmFlagsLoggingEnabled);
return;}
_Must_inspect_result_NTSTATUSGetImageName( _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, _Out_ PUNICODE_STRING ImageName )/*++
Routine Description: Retrieve the ImageName value from the named Service registry key.
Caller is responsible for freeing the buffer allocated in ImageName::Buffer.
Arguments: DriverGlobals - pointer to FX_DRIVER_GLOBALS
ImageeName - Pointer to a UNICODE_STRING which will receive the image name upon a return value of NT_SUCCESS()
Return Value: NTSTATUS
--*/{ NTSTATUS status; FxAutoRegKey hKey; DECLARE_CONST_UNICODE_STRING(valueName, L"ImagePath"); UNICODE_STRING imagePath = {0}; UNICODE_STRING imageName = {0}; PKEY_VALUE_PARTIAL_INFORMATION value = NULL; USHORT size; ULONG length, type; PVOID dataBuffer;
type = REG_SZ; length = 0;
ASSERT(ImageName != NULL); RtlZeroMemory(ImageName, sizeof(UNICODE_STRING));
// // Open driver's Service base key // status = FxRegKey::_OpenKey(NULL, FxDriverGlobals->Driver->GetRegistryPathUnicodeString(), &hKey.m_Key, KEY_READ); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER, "Unable to open driver's service key, %!STATUS!", status); return status; }
// // Find out how big a buffer we need to allocate if the value is present // status = FxRegKey::_QueryValue(FxDriverGlobals, hKey.m_Key, &valueName, length, NULL, &length, &type);
// // We expect the list to be bigger then a standard partial, so if it is // not, just bail now. // if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) { return STATUS_UNSUCCESSFUL; }
// // Pool can be paged b/c we are running at PASSIVE_LEVEL and we are going // to free it at the end of this function. // dataBuffer = FxPoolAllocate(FxDriverGlobals, PagedPool, length); if (dataBuffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER, "Failed to allocate memory for image path string, %!STATUS!", status); return status; }
// // Requery now that we have a big enough buffer // status = FxRegKey::_QueryValue(FxDriverGlobals, hKey.m_Key, &valueName, length, dataBuffer, &length, &type); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER, "Failed to get Image name from service key, %!STATUS!", status); goto cleanUp; }
// // Verify that the data from the registry is a valid string. // if (type != REG_SZ && type != REG_EXPAND_SZ) { return STATUS_OBJECT_TYPE_MISMATCH; }
if (length == 0 || length > USHORT_MAX) { return STATUS_INVALID_PARAMETER; }
// // string must be NULL-terminated // PWCHAR str = (PWCHAR) dataBuffer; if (str[(length/sizeof(WCHAR)) - 1] != UNICODE_NULL) { status = STATUS_INVALID_PARAMETER; DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER, "ERROR: string not terminated with NULL, %!status!\n", status); goto cleanUp; }
RtlInitUnicodeString(&imagePath, (PCWSTR) dataBuffer);
// // Now read the "ImagePath" and extract just the driver filename as a new // unicode string. // GetNameFromPath(&imagePath, &imageName);
if (imageName.Length == 0x0) { status = STATUS_INVALID_PARAMETER; DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER, "ERROR: GetNameFromPath could not find a name, %!status!\n", status); goto cleanUp; }
// // Check for interger overflow for length before we allocate memory // size = path->Length + sizeof(UNICODE_NULL); // len is used below to compute the string size including the NULL, so // compute len to include the terminating NULL. // status = RtlUShortAdd(imageName.Length, sizeof(UNICODE_NULL), &size); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER, "ERROR: size computation failed, %!status!\n", status); goto cleanUp; }
// // allocate a buffer to hold Unicode string + null char. // ImageName->Buffer = (PWCH) FxPoolAllocate(FxDriverGlobals, PagedPool, size);
if (ImageName->Buffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER, "ERROR: ExAllocatePoolWithTag failed, %!status!\n", status); goto cleanUp; }
RtlZeroMemory(ImageName->Buffer, size); ImageName->Length = 0x0; ImageName->MaximumLength = size;
HRESULT hr = StringCbCopy(ImageName->Buffer, size, imageName.Buffer); if (FAILED(hr)) { status = STATUS_UNSUCCESSFUL; DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER, "ERROR: failed to copy string buffer, HRESULT 0x%x, %!status!\n", hr, status); goto cleanUp; }
// // The copy cannot fail since we setup the buffer to hold enough space for // the contents of the ImagePath value. // ASSERT(NT_SUCCESS(status));
cleanUp:
if (!NT_SUCCESS(status)) { if (ImageName->Buffer != NULL) { FxPoolFree(ImageName->Buffer); RtlInitUnicodeString(ImageName, NULL); } }
if (dataBuffer != NULL) { FxPoolFree(dataBuffer); }
return status;}