Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779/*++
Copyright (c) Microsoft Corporation
Module Name:
Version.cpp
Abstract:
This module forms a loadable library from the WDF core libs
Revision History:
--*/
#include <stdarg.h>#include <stddef.h>#include <stdio.h>#include <string.h>#include <ntverp.h>
extern "C" {#include <ntddk.h>#include <ntstrsafe.h>}
#define FX_DYNAMICS_GENERATE_TABLE 1
#include "fx.hpp"
#include <fxldr.h>#include "fxbugcheck.h"// #include "wdfversionlog.h"#include "reactos_special.h"
#define DRIVER_OBJECT_EXTENSION_IDENTIFIER DriverEntry#define DRIVER_PARAMETERS L"Parameters"#define REGISTRY_KMDF_MAJOR_VERSION L"MajorVersion"#define REGISTRY_KMDF_MINOR_VERSION L"MinorVersion"#define REGISTRY_KMDF_BUILD_NUMBER L"BuildNumber"
//-----------------------------------------------------------------------------// These header files are referenced in order to make internal structures// available in public symbols. Various WDFKD debug commands use these// internal structures to provide information about WDF.//-----------------------------------------------------------------------------#include "fxifr.h"
extern "C" {
//// This is the collection of all structure/types to be make public.// This union forces the structure type-info into the PDB file.//union {
WDF_IFR_HEADER * typeWDF_IFR_HEADER; WDF_IFR_RECORD * typeWDF_IFR_RECORD; WDF_IFR_OFFSET * typeWDF_IFR_OFFSET; WDF_BIND_INFO * typeWDF_BIND_INFO; WDF_OBJECT_CONTEXT_TYPE_INFO * typeWDF_OBJECT_CONTEXT_TYPE_INFO; WDF_POWER_ROUTINE_TIMED_OUT_DATA * typeWDF_POWER_ROUTINE_TIMED_OUT_DATA; WDF_BUGCHECK_CODES * typeWDF_BUGCHECK_CODES; WDF_REQUEST_FATAL_ERROR_CODES * typeWDF_REQUEST_FATAL_ERROR_CODES; FX_OBJECT_INFO * typeFX_OBJECT_INFO; FX_POOL_HEADER * typeFX_POOL_HEADER; FX_POOL * typeFX_POOL; FxObject * typeFxObject; FxContextHeader * typeFxContextHeader; FX_DUMP_DRIVER_INFO_ENTRY * typeFX_DUMP_DRIVER_INFO_ENTRY; FxTargetSubmitSyncParams * typeFxTargetSubmitSyncParams;
} uAllPublicTypes;
} // extern "C" end
//----------------------------------------- ------------------------------------
extern "C" {
#include "fxdynamics.h"
#include "fxlibrarycommon.h"
#ifdef __REACTOS__#define KMDF_DEFAULT_NAME "Wdf" \ LITERAL(__WDF_MAJOR_VERSION_STRING) \ "000" //minor version#else#define KMDF_DEFAULT_NAME "Wdf" ## \ LITERAL(__WDF_MAJOR_VERSION_STRING) ## \ "000" //minor version#endif
//-----------------------------------------------------------------------------// local prototype definitions//-----------------------------------------------------------------------------extern "C"DRIVER_UNLOAD DriverUnload;
extern "C"DRIVER_INITIALIZE DriverEntry;
extern "C"__drv_dispatchType(IRP_MJ_CREATE)__drv_dispatchType(IRP_MJ_CLEANUP)__drv_dispatchType(IRP_MJ_CLOSE)DRIVER_DISPATCH FxLibraryDispatch;
RTL_OSVERSIONINFOW gOsVersion = { sizeof(RTL_OSVERSIONINFOW) };
ULONG WdfLdrDbgPrintOn = 0;
PCHAR WdfLdrType = KMDF_DEFAULT_NAME;
} // extern "C"
//-----------------------------------------------------------------------------////-----------------------------------------------------------------------------extern "C"_Must_inspect_result_NTSTATUSNTAPIWDF_LIBRARY_COMMISSION( VOID );
extern "C"_Must_inspect_result_NTSTATUSNTAPIWDF_LIBRARY_DECOMMISSION( VOID );
extern "C"_Must_inspect_result_NTSTATUSNTAPIWDF_LIBRARY_REGISTER_CLIENT( __inout PWDF_BIND_INFO Info, __deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals, __deref_inout PVOID * Context );
extern "C"_Must_inspect_result_NTSTATUSNTAPIWDF_LIBRARY_UNREGISTER_CLIENT( __in PWDF_BIND_INFO Info, __in PWDF_DRIVER_GLOBALS WdfDriverGlobals );
extern "C"VOIDFxLibraryDeleteDevice( VOID );
VOIDFxLibraryCleanup( VOID );
VOIDWdfWriteKmdfVersionToRegistry( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath );
VOIDWdfDeleteKmdfVersionFromRegistry( __in PDRIVER_OBJECT DriverObject );
typedef struct _DRV_EXTENSION { UNICODE_STRING ParametersRegistryPath;} DRV_EXTENSION, *PDRV_EXTENSION;
//-----------------------------------------------------------------------------// Library registeration information//-----------------------------------------------------------------------------extern "C" {#pragma prefast(suppress:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "kernel component.");WDF_LIBRARY_INFO WdfLibraryInfo = { sizeof(WDF_LIBRARY_INFO), (PFNLIBRARYCOMMISSION) WDF_LIBRARY_COMMISSION, (PFNLIBRARYDECOMMISSION) WDF_LIBRARY_DECOMMISSION, (PFNLIBRARYREGISTERCLIENT) WDF_LIBRARY_REGISTER_CLIENT, (PFNLIBRARYUNREGISTERCLIENT) WDF_LIBRARY_UNREGISTER_CLIENT, { __WDF_MAJOR_VERSION, __WDF_MINOR_VERSION, __WDF_BUILD_NUMBER }};
} // extern "C" end
extern "C"NTSTATUSNTAPIFxLibraryDispatch ( __in struct _DEVICE_OBJECT * DeviceObject, __in PIRP Irp ){ NTSTATUS status;
UNREFERENCED_PARAMETER(DeviceObject); ASSERT(FxLibraryGlobals.LibraryDeviceObject == DeviceObject);
status = STATUS_INVALID_DEVICE_REQUEST;
switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction) { case IRP_MJ_CREATE: // // To limit our exposure for this device object, only allow kernel mode // creates. // if (Irp->RequestorMode == KernelMode) { status = STATUS_SUCCESS; } break;
case IRP_MJ_CLEANUP: case IRP_MJ_CLOSE: // // Since we allowed a create to succeed, succeed the cleanup and close // status = STATUS_SUCCESS; break; }
Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0x0; IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;}
//-----------------------------------------------------------------------------////-----------------------------------------------------------------------------
#define KMDF_DEVICE_NAME L"\\Device\\KMDF"
_Must_inspect_result_NTSTATUSFxLibraryCreateDevice( __in PUNICODE_STRING DeviceName ){ NTSTATUS status; ULONG i;
i = 0;
// // Repeatedly try to create a named device object until we run out of buffer // space or we succeed. // do { status = RtlUnicodeStringPrintf(DeviceName, L"%s%d", KMDF_DEVICE_NAME, i++); if (!NT_SUCCESS(status)) { return status; }
// // Create a device with no device extension // status = IoCreateDevice( FxLibraryGlobals.DriverObject, 0, DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &FxLibraryGlobals.LibraryDeviceObject ); } while (STATUS_OBJECT_NAME_COLLISION == status);
if (NT_SUCCESS(status)) { // // Clear the initializing bit now because the loader will attempt to // open the device before we return from DriverEntry // ASSERT(FxLibraryGlobals.LibraryDeviceObject != NULL); FxLibraryGlobals.LibraryDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; }
return status;}
extern "C"VOIDFxLibraryDeleteDevice( VOID ){ FxLibraryCleanup();}
VOIDFxLibraryCleanup( VOID ){ if (FxLibraryGlobals.LibraryDeviceObject != NULL) { IoDeleteDevice(FxLibraryGlobals.LibraryDeviceObject); FxLibraryGlobals.LibraryDeviceObject = NULL; }}
extern "C"NTSTATUSNTAPIDriverEntry( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ){ UNICODE_STRING name; UNICODE_STRING string; NTSTATUS status;
// // This creates a local buffer which is big enough to hold a copy of the // constant string assigned to it. It does not point to the constant // string. As such, it is a writeable buffer. // // NOTE: KMDF_DEVICE_NAME L"XXXX" creates a concatenated string of // KMDF_DEVICE_NAME + L"XXXX". This is done to give us room for // appending a number up to 4 digits long after KMDF_DEVICE_NAME if // you want a null terminated string, 5 digits long if the string is // not null terminated (as is the case for a UNICODE_STRING) // WCHAR buffer[] = KMDF_DEVICE_NAME L"XXXX";
// // Initialize global to make NonPagedPool be treated as NxPool on Win8 // and NonPagedPool on down-level //#ifndef __REACTOS__ ExInitializeDriverRuntime(DrvRtPoolNxOptIn);#endif RtlInitUnicodeString(&string, WDF_REGISTRY_DBGPRINT_ON);
// // Determine if debug prints are on. // (void) WdfLdrDiagnosticsValueByNameAsULONG(&string, &WdfLdrDbgPrintOn);
__Print(("DriverEntry\n"));
DriverObject->DriverUnload = DriverUnload;
FxLibraryGlobals.DriverObject = DriverObject;
DriverObject->MajorFunction[IRP_MJ_CREATE] = FxLibraryDispatch; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FxLibraryDispatch; DriverObject->MajorFunction[IRP_MJ_CLOSE] = FxLibraryDispatch;
RtlZeroMemory(&name, sizeof(name)); name.Buffer = buffer; name.Length = 0x0; name.MaximumLength = sizeof(buffer);
// // We use the string when we declare the buffer to get the right sized // buffer. Now we want to make sure there are no contents before we // use it to create a device object. // RtlZeroMemory(buffer, sizeof(buffer));
status = FxLibraryCreateDevice(&name); if (!NT_SUCCESS(status)) { __Print(("ERROR: FxLibraryCreateDevice failed with Status 0x%x\n", status)); return status; }
// // Register this library with WdfLdr // // NOTE: Once WdfRegisterLibrary returns NT_SUCCESS() we must return // NT_SUCCESS from DriverEntry! // status = WdfRegisterLibrary( &WdfLibraryInfo, RegistryPath, &name ); if (!NT_SUCCESS(status)) { __Print(("ERROR: WdfRegisterLibrary failed with Status 0x%x\n", status)); FxLibraryCleanup(); return status; }
// // Write KMDF version to registry // WdfWriteKmdfVersionToRegistry(DriverObject, RegistryPath);
return STATUS_SUCCESS;}
//-----------------------------------------------------------------------------////-----------------------------------------------------------------------------extern "C"VOIDNTAPIDriverUnload( __in PDRIVER_OBJECT DriverObject ){ __Print(("DriverUnload\n"));
// // Delete KMDF version from registry before destroying the Driver Object // WdfDeleteKmdfVersionFromRegistry(DriverObject);
// // Make sure everything is deleted. Since the driver is considered a legacy // driver, it can be unloaded while there are still outstanding device objects. // FxLibraryCleanup();}
//-----------------------------------------------------------------------------////-----------------------------------------------------------------------------extern "C"_Must_inspect_result_NTSTATUSNTAPIWDF_LIBRARY_COMMISSION( VOID ){ return FxLibraryCommonCommission();}
//-----------------------------------------------------------------------------////-----------------------------------------------------------------------------extern "C"_Must_inspect_result_NTSTATUSNTAPIWDF_LIBRARY_DECOMMISSION( VOID ){ return FxLibraryCommonDecommission();}
#define EVTLOG_MESSAGE_SIZE 70#define RAW_DATA_SIZE 4
extern "C"_Must_inspect_result_NTSTATUSNTAPIWDF_LIBRARY_REGISTER_CLIENT( __in PWDF_BIND_INFO Info, __deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals, __deref_inout PVOID * Context ){ NTSTATUS status = STATUS_INVALID_PARAMETER; PFX_DRIVER_GLOBALS pFxDriverGlobals; WCHAR insertString[EVTLOG_MESSAGE_SIZE]; ULONG rawData[RAW_DATA_SIZE]; PCLIENT_INFO clientInfo = NULL;
__Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) ": enter\n"));
clientInfo = (PCLIENT_INFO)*Context; *Context = NULL;
ASSERT(Info->Version.Major == WdfLibraryInfo.Version.Major);
// // NOTE: If the currently loaded library < drivers minor version fail the load // instead of binding to a lower minor version. The reason for that if there // is a newer API or new contract change made the driver shouldn't be using older // API than it was compiled with. //
if (Info->Version.Minor > WdfLibraryInfo.Version.Minor) { status = RtlStringCchPrintfW(insertString, RTL_NUMBER_OF(insertString), L"Driver Version: %d.%d Kmdf Lib. Version: %d.%d", Info->Version.Major, Info->Version.Minor, WdfLibraryInfo.Version.Major, WdfLibraryInfo.Version.Minor); if (!NT_SUCCESS(status)) { __Print(("ERROR: RtlStringCchPrintfW failed with Status 0x%x\n", status)); return status; } rawData[0] = Info->Version.Major; rawData[1] = Info->Version.Minor; rawData[2] = WdfLibraryInfo.Version.Major; rawData[3] = WdfLibraryInfo.Version.Minor;
LibraryLogEvent(FxLibraryGlobals.DriverObject, WDFVER_MINOR_VERSION_NOT_SUPPORTED, STATUS_OBJECT_TYPE_MISMATCH, insertString, rawData, sizeof(rawData) ); // // this looks like the best status to return // return STATUS_OBJECT_TYPE_MISMATCH;
}
status = FxLibraryCommonRegisterClient(Info, WdfDriverGlobals, clientInfo);
if (NT_SUCCESS(status)) { // // The context will be a pointer to FX_DRIVER_GLOBALS // *Context = GetFxDriverGlobals(*WdfDriverGlobals);
// // Set the WDF_BIND_INFO structure pointer in FxDriverGlobals // pFxDriverGlobals = GetFxDriverGlobals(*WdfDriverGlobals); pFxDriverGlobals->WdfBindInfo = Info; }
return status;}
//-----------------------------------------------------------------------------////-----------------------------------------------------------------------------extern "C"_Must_inspect_result_NTSTATUSNTAPIWDF_LIBRARY_UNREGISTER_CLIENT( __in PWDF_BIND_INFO Info, __in PWDF_DRIVER_GLOBALS WdfDriverGlobals ){ return FxLibraryCommonUnregisterClient(Info, WdfDriverGlobals);}
VOIDWdfWriteKmdfVersionToRegistry( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ){ NTSTATUS status; OBJECT_ATTRIBUTES objectAttributes; HANDLE driverKey; HANDLE parametersKey; UNICODE_STRING valueName; UNICODE_STRING parametersPath; PDRV_EXTENSION driverExtension;
driverKey = NULL; parametersKey = NULL; driverExtension = NULL;
RtlInitUnicodeString(¶metersPath, DRIVER_PARAMETERS);
InitializeObjectAttributes(&objectAttributes, RegistryPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
status = ZwOpenKey(&driverKey, KEY_CREATE_SUB_KEY, &objectAttributes); if (!NT_SUCCESS(status)) { __Print(("WdfWriteKmdfVersionToRegistry: Failed to open HKLM\\%S\n", RegistryPath->Buffer)); goto out; }
InitializeObjectAttributes(&objectAttributes, ¶metersPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, driverKey, NULL);
// // Open or create key and get a handle // status = ZwCreateKey(¶metersKey, KEY_SET_VALUE, &objectAttributes, 0, (PUNICODE_STRING) NULL, REG_OPTION_VOLATILE, NULL);
if (!NT_SUCCESS(status)) { __Print(("WdfWriteKmdfVersionToRegistry: Failed to open HKLM\\%S\\%S\n", RegistryPath->Buffer, parametersPath.Buffer)); goto out; }
// // Set Major Version // RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MAJOR_VERSION);
status = ZwSetValueKey(parametersKey, &valueName, 0, REG_DWORD, &WdfLibraryInfo.Version.Major, sizeof(WdfLibraryInfo.Version.Major));
if (!NT_SUCCESS(status)) { __Print(("WdfWriteKmdfVersionToRegistry: Failed to set Major Version\n")); goto out; }
// // Set Minor Version // RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MINOR_VERSION);
status = ZwSetValueKey(parametersKey, &valueName, 0, REG_DWORD, &WdfLibraryInfo.Version.Minor, sizeof(WdfLibraryInfo.Version.Minor));
if (!NT_SUCCESS(status)) { __Print(("WdfWriteKmdfVersionToRegistry: Failed to set Minor Version\n")); goto out; }
// // Set Build Number // RtlInitUnicodeString(&valueName, REGISTRY_KMDF_BUILD_NUMBER);
status = ZwSetValueKey(parametersKey, &valueName, 0, REG_DWORD, &WdfLibraryInfo.Version.Build, sizeof(WdfLibraryInfo.Version.Build));
if (!NT_SUCCESS(status)) { __Print(("WdfWriteKmdfVersionToRegistry: Failed to set Build Number\n")); goto out; }
// // Create a Driver Extension to store the registry path, where we write the // version of the wdf01000.sys that's loaded in memory // status = IoAllocateDriverObjectExtension(DriverObject, (PVOID) DRIVER_OBJECT_EXTENSION_IDENTIFIER, sizeof(DRV_EXTENSION), (PVOID *)&driverExtension);
if (!NT_SUCCESS(status) || driverExtension == NULL) { goto out; }
driverExtension->ParametersRegistryPath.Buffer = (PWCHAR) ExAllocatePoolWithTag( PagedPool, RegistryPath->MaximumLength, FX_TAG); if (driverExtension->ParametersRegistryPath.Buffer == NULL) { goto out; }
driverExtension->ParametersRegistryPath.MaximumLength = RegistryPath->MaximumLength; RtlCopyUnicodeString(&(driverExtension->ParametersRegistryPath), RegistryPath);
out: if (driverKey != NULL) { ZwClose(driverKey); }
if (parametersKey != NULL) { ZwClose(parametersKey); }
return;}
VOIDWdfDeleteKmdfVersionFromRegistry( __in PDRIVER_OBJECT DriverObject ){ PUNICODE_STRING registryPath; OBJECT_ATTRIBUTES objectAttributes; HANDLE driverKey; HANDLE parametersKey; UNICODE_STRING valueName; NTSTATUS status; UNICODE_STRING parametersPath; PDRV_EXTENSION driverExtension;
RtlInitUnicodeString(¶metersPath, DRIVER_PARAMETERS);
driverKey = NULL; parametersKey = NULL;
driverExtension = (PDRV_EXTENSION)IoGetDriverObjectExtension(DriverObject, (PVOID)DRIVER_OBJECT_EXTENSION_IDENTIFIER);
if (driverExtension == NULL || driverExtension->ParametersRegistryPath.Buffer == NULL) { return; }
registryPath = &driverExtension->ParametersRegistryPath;
InitializeObjectAttributes(&objectAttributes, registryPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
status = ZwOpenKey(&driverKey, KEY_SET_VALUE, &objectAttributes); if (!NT_SUCCESS(status)) { goto out; }
InitializeObjectAttributes(&objectAttributes, ¶metersPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, driverKey, NULL); // // Open the key for deletion // status = ZwOpenKey(¶metersKey, DELETE, &objectAttributes);
if (!NT_SUCCESS(status)) { goto out; }
RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MAJOR_VERSION); ZwDeleteValueKey(parametersKey, &valueName);
RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MINOR_VERSION); ZwDeleteValueKey(parametersKey, &valueName);
RtlInitUnicodeString(&valueName, REGISTRY_KMDF_BUILD_NUMBER); ZwDeleteValueKey(parametersKey, &valueName);
ZwDeleteKey(parametersKey);
out: if (driverExtension->ParametersRegistryPath.Buffer != NULL) { ExFreePool(driverExtension->ParametersRegistryPath.Buffer); }
if (driverKey != NULL) { ZwClose(driverKey); }
if (parametersKey != NULL) { ZwClose(parametersKey); }
return;}