NTSTATUS CWdfDevice::CreateSymLink(const UNICODE_STRING &Name) { auto status = WdfDeviceCreateSymbolicLink(m_Device, &Name); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_WDFDEVICE, "%!FUNC! failed %!STATUS!", status); } return status; }
_Use_decl_annotations_ NTSTATUS TreeSampleCreateSecureDeviceContext( WDFDEVICE MasterDevice ) /*++ Routine Description: This routine is called when the secure environment is first started. Arguments: MasterDevice - Supplies a handle to the master device object. DeviceContext - Supplies a pointer to store any context information required for future calls. Return Value: NTSTATUS code. --*/ { WDF_OBJECT_ATTRIBUTES ContextAttributes; PTREE_SAMPLE_DEVICE_CONTEXT MasterContext; NTSTATUS Status; DECLARE_CONST_UNICODE_STRING(SymbolicLink, L"\\DosDevices\\SampleTrEEDriver"); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ContextAttributes, TREE_SAMPLE_DEVICE_CONTEXT); Status = WdfObjectAllocateContext(MasterDevice, &ContextAttributes, &MasterContext); if (!NT_SUCCESS(Status)) { goto TreeSampleCreateSecureDeviceContextEnd; } MasterContext->MasterDevice = MasterDevice; // // Create a symbolic link so that usermode program can access master device. // Status = WdfDeviceCreateSymbolicLink(MasterDevice, &SymbolicLink); if (!NT_SUCCESS(Status)) { goto TreeSampleCreateSecureDeviceContextEnd; } TreeSampleCreateSecureDeviceContextEnd: return Status; }
/////////////////////////////////////////////////////////////////////////////// // // BasicUsbEvtDeviceAdd // // This routine is called by the framework when a device of // the type we support is found in the system. // // INPUTS: // // DriverObject - Our WDFDRIVER object // // DeviceInit - The device iniitalization structure we'll // be using to create our WDFDEVICE // // OUTPUTS: // // None. // // RETURNS: // // STATUS_SUCCESS, otherwise an error indicating why the driver could not // load. // // IRQL: // // This routine is called at IRQL == PASSIVE_LEVEL. // // NOTES: // // /////////////////////////////////////////////////////////////////////////////// NTSTATUS BasicUsbEvtDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit) { NTSTATUS status; WDF_OBJECT_ATTRIBUTES objAttributes; WDFDEVICE device; WDF_IO_QUEUE_CONFIG queueConfig; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; PBASICUSB_DEVICE_CONTEXT devContext; #if DBG DbgPrint("BasicUsbEvtDeviceAdd\n"); #endif // // Our "internal" (native) and user-accessible device names // DECLARE_CONST_UNICODE_STRING(nativeDeviceName, L"\\Device\\BasicUsb"); DECLARE_CONST_UNICODE_STRING(userDeviceName, L"\\Global??\\BasicUsb"); UNREFERENCED_PARAMETER(Driver); // // Life is a bit more complicated in this driver... // // We need an EvtPrepareHardware to configure our device. In addition, we // must handle EvtD0Entry and EvtD0Exit in order to manage our continuous // reader. // // // Prepare for WDFDEVICE creation // // Initialize standard WDF Object Attributes structure // WDF_OBJECT_ATTRIBUTES_INIT(&objAttributes); // // Specify our device context // WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&objAttributes, BASICUSB_DEVICE_CONTEXT); // // We want our device object NAMED, thank you very much // status = WdfDeviceInitAssignName(DeviceInit, &nativeDeviceName); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfDeviceInitAssignName failed 0x%0x\n", status); #endif return(status); } // // Set our I/O type to DIRECT, meaning that we want to receive // MDLs for both read and write requests. // // While we are not obligated to choose direct, USB drivers // typically do so because the USB bus driver needs MDLs to // actually perform the transfer. If we select DIRECT I/O, the // bus driver can just use the MDL that we're given as opposed // to creating his own. // WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); // // In this driver we need to be notified of some Pnp/Power // events, so initialize a pnp power callbacks structure. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // USB drivers configure their device within prepare hardware, // so register an EvtDevicePrepareHardware callback. // pnpPowerCallbacks.EvtDevicePrepareHardware = BasicUsbEvtDevicePrepareHardware; // // Our driver uses a continuous reader on the interrupt pipe to // be notified asynchronously of changes to the OSRFX2's // switchpack. We need to start the reader in D0Entry and stop // it in D0Exit, so register for EvtDeviceD0Entry and // EvtDeviceD0Exit callbacks // pnpPowerCallbacks.EvtDeviceD0Entry = BasicUsbEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = BasicUsbEvtDeviceD0Exit; // // Update the DeviceInit structure to contain the new callbacks. // WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // // We want to send control transfers synchronously from within // EvtIoDeviceControl, so we'll apply a PASSIVE_LEVEL constraint // to our device // objAttributes.ExecutionLevel = WdfExecutionLevelPassive; // // Now let's create our device object // status = WdfDeviceCreate(&DeviceInit, &objAttributes, &device); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfDeviceCreate failed 0x%0x\n", status); #endif return status; } // // Create a symbolic link for the control object so that usermode can open // the device by name. // status = WdfDeviceCreateSymbolicLink(device, &userDeviceName); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfDeviceCreateSymbolicLink failed 0x%0x\n", status); #endif return(status); } // // ALSO create a device interface for the device // This allows usage of the lovely SetupApiXxxx functions to locate // the device // status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BASICUSB, NULL); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfDeviceCreateDeviceInterface failed 0x%0x\n", status); #endif return(status); } // // Configure our queue of incoming requests // // We only use the default queue, and we set it for parallel processing. // We chose this because we may have, say, a bulk read hanging on the bus // driver that won't get completed until we send down a bulk write. // // If we chose a sequential queue we wouldn't be presented the write from // the user until the read completed, but the read wouldn't complete // until we were presented the write from the user - resulting in an "I/O // deadlock". // // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); // // Declare our I/O Event Processing callbacks // // We handle, read, write, and device control requests. // // WDF will automagically handle Create and Close requests for us and will // will complete any OTHER request types with STATUS_INVALID_DEVICE_REQUEST. // queueConfig.EvtIoRead = BasicUsbEvtRead; queueConfig.EvtIoWrite = BasicUsbEvtWrite; queueConfig.EvtIoDeviceControl = BasicUsbEvtDeviceControl; // // Because this is a queue for a real hardware // device, indicate that the queue needs to be // power managed // queueConfig.PowerManaged = WdfTrue; status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, NULL); // optional pointer to receive queue handle if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfIoQueueCreate for default queue failed 0x%0x\n", status); #endif return(status); } devContext = BasicUsbGetContextFromDevice(device); WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &devContext->SwitchPackStateChangeQueue); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfIoQueueCreate for manual queue failed 0x%0x\n", status); #endif return(status); } return(STATUS_SUCCESS); }
VOID VIOSerialPortSymbolicNameWork( IN WDFWORKITEM WorkItem ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WorkItem); PVIOSERIAL_PORT pport = pdoData->port; UNICODE_STRING deviceUnicodeString = {0}; NTSTATUS status = STATUS_SUCCESS; DECLARE_UNICODE_STRING_SIZE(symbolicLinkName, 256); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__); do { if (pport->NameString.Buffer) { status = RtlAnsiStringToUnicodeString( &deviceUnicodeString, &pport->NameString, TRUE ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlAnsiStringToUnicodeString failed 0x%x\n", status); break; } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP,"deviceUnicodeString = %ws\n", deviceUnicodeString.Buffer); status = RtlUnicodeStringPrintf( &symbolicLinkName, L"%ws%ws", L"\\DosDevices\\", deviceUnicodeString.Buffer ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "RtlUnicodeStringPrintf failed 0x%x\n", status); break; } status = WdfDeviceCreateSymbolicLink( pport->Device, &symbolicLinkName ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceCreateSymbolicLink %ws failed 0x%x\n", &symbolicLinkName, status); break; } } } while (0); if (deviceUnicodeString.Buffer != NULL) { RtlFreeUnicodeString( &deviceUnicodeString ); } WdfObjectDelete(WorkItem); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__); }
NTSTATUS DeviceConfigure( _In_ PDEVICE_CONTEXT DeviceContext ) /*++ Routine Description: This method is called after the device callback object has been initialized and returned to the driver. It would setup the device's queues and their corresponding callback objects. Arguments: FxDevice - the framework device object for which we're handling events. Return Value: status --*/ { NTSTATUS status; WDFDEVICE device = DeviceContext->Device; WDFKEY key; LPGUID guid; errno_t errorNo; DECLARE_CONST_UNICODE_STRING(portName, REG_VALUENAME_PORTNAME); DECLARE_UNICODE_STRING_SIZE (comPort, 10); DECLARE_UNICODE_STRING_SIZE (symbolicLinkName, SYMBOLIC_LINK_NAME_LENGTH); #ifdef _FAKE_MODEM // // Compiled as fake modem // guid = (LPGUID) &GUID_DEVINTERFACE_MODEM; #else // // Compiled as virtual serial port // guid = (LPGUID) &GUID_DEVINTERFACE_COMPORT; #endif // // Create device interface // status = WdfDeviceCreateDeviceInterface( device, guid, NULL); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Cannot create device interface"); goto Exit; } // // Read the COM port number from the registry, which has been automatically // created by "MsPorts!PortsClassInstaller" if INF file says "Class=Ports" // status = WdfDeviceOpenRegistryKey( device, PLUGPLAY_REGKEY_DEVICE, KEY_QUERY_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &key); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Failed to retrieve device hardware key root"); goto Exit; } status = WdfRegistryQueryUnicodeString( key, &portName, NULL, &comPort); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Failed to read PortName"); goto Exit; } // // Manually create the symbolic link name. Length is the length in // bytes not including the NULL terminator. // // 6054 and 26035 are code analysis warnings that comPort.Buffer might // not be NULL terminated, while we know that they are. // #pragma warning(suppress: 6054 26035) symbolicLinkName.Length = (USHORT)((wcslen(comPort.Buffer) * sizeof(wchar_t)) + sizeof(SYMBOLIC_LINK_NAME_PREFIX) - sizeof(UNICODE_NULL)); if (symbolicLinkName.Length >= symbolicLinkName.MaximumLength) { Trace(TRACE_LEVEL_ERROR, "Error: Buffer overflow when creating COM port name. Size" " is %d, buffer length is %d", symbolicLinkName.Length, symbolicLinkName.MaximumLength); status = STATUS_BUFFER_OVERFLOW; goto Exit; } errorNo = wcscpy_s(symbolicLinkName.Buffer, SYMBOLIC_LINK_NAME_LENGTH, SYMBOLIC_LINK_NAME_PREFIX); if (errorNo != 0) { Trace(TRACE_LEVEL_ERROR, "Failed to copy %ws to buffer with error %d", SYMBOLIC_LINK_NAME_PREFIX, errorNo); status = STATUS_INVALID_PARAMETER; goto Exit; } errorNo = wcscat_s(symbolicLinkName.Buffer, SYMBOLIC_LINK_NAME_LENGTH, comPort.Buffer); if (errorNo != 0) { Trace(TRACE_LEVEL_ERROR, "Failed to copy %ws to buffer with error %d", comPort.Buffer, errorNo); status = STATUS_INVALID_PARAMETER; goto Exit; } // // Create symbolic link // status = WdfDeviceCreateSymbolicLink( device, &symbolicLinkName); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "Error: Cannot create symbolic link %ws", symbolicLinkName.Buffer); goto Exit; } status = DeviceGetPdoName(DeviceContext); if (!NT_SUCCESS(status)) { goto Exit; } status = DeviceWriteLegacyHardwareKey( DeviceContext->PdoName, comPort.Buffer, DeviceContext->Device); if (NT_SUCCESS(status)) { DeviceContext->CreatedLegacyHardwareKey = TRUE; } status = QueueCreate(DeviceContext); if (!NT_SUCCESS(status)) { goto Exit; } Exit: return status; }
NTSTATUS NonPnpDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Called by the DriverEntry to create a control-device. This call is responsible for freeing the memory for DeviceInit. Arguments: DriverObject - a pointer to the object that represents this device driver. DeviceInit - Pointer to a driver-allocated WDFDEVICE_INIT structure. Return Value: STATUS_SUCCESS if initialized; an error otherwise. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES attributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_FILEOBJECT_CONFIG fileConfig; WDFQUEUE queue; WDFDEVICE controlDevice; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME_STRING) ; DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING) ; UNREFERENCED_PARAMETER( Driver ); PAGED_CODE(); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "NonPnpDeviceAdd DeviceInit %p\n", DeviceInit); // // Set exclusive to TRUE so that no more than one app can talk to the // control device at any time. // WdfDeviceInitSetExclusive(DeviceInit, TRUE); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceInitAssignName failed %!STATUS!", status); goto End; } WdfControlDeviceInitSetShutdownNotification(DeviceInit, NonPnpShutdown, WdfDeviceShutdown); // // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the // framework whether you are interested in handling Create, Close and // Cleanup requests that gets generated when an application or another // kernel component opens an handle to the device. If you don't register // the framework default behaviour would be to complete these requests // with STATUS_SUCCESS. A driver might be interested in registering these // events if it wants to do security validation and also wants to maintain // per handle (fileobject) context. // WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, NonPnpEvtDeviceFileCreate, NonPnpEvtFileClose, WDF_NO_EVENT_CALLBACK // not interested in Cleanup ); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); // // In order to support METHOD_NEITHER Device controls, or // NEITHER device I/O type, we need to register for the // EvtDeviceIoInProcessContext callback so that we can handle the request // in the calling threads context. // WdfDeviceInitSetIoInCallerContextCallback(DeviceInit, NonPnpEvtDeviceIoInCallerContext); // // Specify the size of device context // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CONTROL_DEVICE_EXTENSION); status = WdfDeviceCreate(&DeviceInit, &attributes, &controlDevice); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreate failed %!STATUS!", status); goto End; } // // Create a symbolic link for the control object so that usermode can open // the device. // status = WdfDeviceCreateSymbolicLink(controlDevice, &symbolicLinkName); if (!NT_SUCCESS(status)) { // // Control device will be deleted automatically by the framework. // TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateSymbolicLink failed %!STATUS!", status); goto End; } // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoRead = FileEvtIoRead; ioQueueConfig.EvtIoWrite = FileEvtIoWrite; ioQueueConfig.EvtIoDeviceControl = FileEvtIoDeviceControl; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); // // Since we are using Zw function set execution level to passive so that // framework ensures that our Io callbacks called at only passive-level // even if the request came in at DISPATCH_LEVEL from another driver. // //attributes.ExecutionLevel = WdfExecutionLevelPassive; // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(ioQueueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(controlDevice, &ioQueueConfig, &attributes, &queue // pointer to default queue ); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed %!STATUS!", status); goto End; } // // Control devices must notify WDF when they are done initializing. I/O is // rejected until this call is made. // WdfControlFinishInitializing(controlDevice); End: // // If the device is created successfully, framework would clear the // DeviceInit value. Otherwise device create must have failed so we // should free the memory ourself. // if (DeviceInit != NULL) { WdfDeviceInitFree(DeviceInit); } return status; }
NTSTATUS PVPanicEvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { NTSTATUS status; WDFDEVICE device; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_FILEOBJECT_CONFIG fileConfig; WDF_OBJECT_ATTRIBUTES attributes; WDF_IO_QUEUE_CONFIG queueConfig; PDEVICE_CONTEXT context; DECLARE_CONST_UNICODE_STRING(dosDeviceName, PVPANIC_DOS_DEVICE_NAME); UNREFERENCED_PARAMETER(Driver); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "--> %!FUNC!"); PAGED_CODE(); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = PVPanicEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = PVPanicEvtDeviceReleaseHardware; pnpPowerCallbacks.EvtDeviceD0Entry = PVPanicEvtDeviceD0Entry; pnpPowerCallbacks.EvtDeviceD0Exit = PVPanicEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, PVPanicEvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreate failed: %!STATUS!", status); return status; } status = WdfDeviceCreateSymbolicLink(device, &dosDeviceName); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateSymbolicLink failed: %!STATUS!", status); return status; } WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoDeviceControl = PVPanicEvtQueueDeviceControl; context = GetDeviceContext(device); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &context->IoctlQueue); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed: %!STATUS!", status); return status; } status = WdfDeviceConfigureRequestDispatching(device, context->IoctlQueue, WdfRequestTypeDeviceControl); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceConfigureRequestDispatching failed: %!STATUS!", status); return status; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "<-- %!FUNC!"); return status; }
static NTSTATUS UsbChief_EvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) { WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES fileObjectAttributes, requestAttributes, fdoAttributes; WDF_FILEOBJECT_CONFIG fileConfig; NTSTATUS Status; WDFDEVICE device; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDFQUEUE queue; UNICODE_STRING linkname; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); UsbChief_DbgPrint(DEBUG_CONFIG, ("ExtDeviceAdd\n")); /* Init PnP */ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = UsbChief_EvtDevicePrepareHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); /* Request Attributes */ WDF_OBJECT_ATTRIBUTES_INIT(&requestAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&requestAttributes, REQUEST_CONTEXT); WdfDeviceInitSetRequestAttributes(DeviceInit, &requestAttributes); /* Fileobject init */ WDF_FILEOBJECT_CONFIG_INIT(&fileConfig, UsbChief_EvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK); WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fileObjectAttributes, FILE_CONTEXT); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, &fileObjectAttributes); WDF_OBJECT_ATTRIBUTES_INIT(&fdoAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&fdoAttributes, DEVICE_CONTEXT); Status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &device); if (!NT_SUCCESS(Status)) { UsbChief_DbgPrint(0, ("WdfDeviceCreate: %08x\n", Status)); return Status; } RtlInitUnicodeString(&linkname, L"\\DosDevices\\ChiefUSB"); Status = WdfDeviceCreateSymbolicLink(device, &linkname); if (!NT_SUCCESS(Status)) { UsbChief_DbgPrint(0, ("WdfDeviceCreateSymbolicLink: %08x\n", Status)); goto out; } WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.SurpriseRemovalOK = WdfTrue; WdfDeviceSetPnpCapabilities(device, &pnpCaps); /* Register I/O callbacks */ WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); ioQueueConfig.EvtIoRead = UsbChief_EvtIoRead; ioQueueConfig.EvtIoWrite = UsbChief_EvtIoWrite; ioQueueConfig.EvtIoDeviceControl = UsbChief_EvtIoDeviceControl; ioQueueConfig.EvtIoStop = UsbChief_EvtIoStop; ioQueueConfig.EvtIoResume = UsbChief_EvtIoResume; Status = WdfIoQueueCreate(device, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); if (!NT_SUCCESS(Status)) { UsbChief_DbgPrint(0, ("WdfIoQueueCreate: %08x\n", Status)); goto out; } Status = WdfDeviceCreateDeviceInterface(device, (LPGUID)&GUID_CLASS_USBCHIEF_USB, NULL); if (!NT_SUCCESS(Status)) { UsbChief_DbgPrint(0, ("WdfDeviceCreateDeviceInterface: %08x\n", Status)); goto out; } UsbChief_DbgPrint(3, ("EvtDriverDeviceAdd successful\n")); return STATUS_SUCCESS; out: return Status; }
NTSTATUS RamDiskEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a device object to represent a new instance of the device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES queueAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_EXTENSION pDeviceExtension; PQUEUE_EXTENSION pQueueContext = NULL; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME); PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); // // Storage drivers have to name their FDOs. Since we are not unique'fying // the device name, we wouldn't be able to install more than one instance // of this ramdisk driver. // status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WdfDeviceInitSetExclusive(DeviceInit, FALSE); // // Since this is a pure software only driver, there is no need to register // any PNP/Power event callbacks. Framework will respond to these // events appropriately. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Now that the WDF device object has been created, set up any context // that it requires. // pDeviceExtension = DeviceGetExtension(device); // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE ( &ioQueueConfig, WdfIoQueueDispatchSequential ); ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl; ioQueueConfig.EvtIoRead = RamDiskEvtIoRead; ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION); // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(ioQueueConfig.EvtIoStop != 0); status = WdfIoQueueCreate( device, &ioQueueConfig, &queueAttributes, &queue ); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { return status; } // Context is the Queue handle pQueueContext = QueueGetExtension(queue); // // Set the context for our default queue as our device extension. // pQueueContext->DeviceExtension = pDeviceExtension; #if KMDF_VERSION_MINOR >= 9 // // Enable forward progress on the queue we just created. // NOTE: If you are planning to use this code without forward progress, // comment out the call to SetForwardProgressOnQueue below. // status = SetForwardProgressOnQueue(queue); if (!NT_SUCCESS(status)) { return status; } #endif // // Now do any RAM-Disk specific initialization // pDeviceExtension->DiskRegInfo.DriveLetter.Buffer = (PWSTR) &pDeviceExtension->DriveLetterBuffer; pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength = sizeof(pDeviceExtension->DriveLetterBuffer); // // Get the disk parameters from the registry // RamDiskQueryDiskRegParameters( WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)), &pDeviceExtension->DiskRegInfo ); // // Allocate memory for the disk image. // pDeviceExtension->DiskImage = ExAllocatePoolWithTag( NonPagedPool, pDeviceExtension->DiskRegInfo.DiskSize, RAMDISK_TAG ); if (pDeviceExtension->DiskImage) { UNICODE_STRING deviceName; UNICODE_STRING win32Name; RamDiskFormatDisk(pDeviceExtension); status = STATUS_SUCCESS; // // Now try to create a symbolic link for the drive letter. // RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME); RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME); pDeviceExtension->SymbolicLink.Buffer = (PWSTR) &pDeviceExtension->DosDeviceNameBuffer; pDeviceExtension->SymbolicLink.MaximumLength = sizeof(pDeviceExtension->DosDeviceNameBuffer); pDeviceExtension->SymbolicLink.Length = win32Name.Length; RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name); RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink, &pDeviceExtension->DiskRegInfo.DriveLetter); status = WdfDeviceCreateSymbolicLink(device, &pDeviceExtension->SymbolicLink); } return status; }
NTSTATUS FmCreateDosDevicesSymbolicLink( WDFDEVICE Device, PFM_DEVICE_DATA FmDeviceData ) { NTSTATUS status; UNICODE_STRING comPort; UNICODE_STRING pdoName; UNICODE_STRING symbolicLink; WDFKEY hKey = NULL; DECLARE_CONST_UNICODE_STRING(valueName, L"PortName"); WDFSTRING string = NULL; WDFMEMORY memory; WDF_OBJECT_ATTRIBUTES memoryAttributes; size_t bufferLength; PAGED_CODE(); symbolicLink.Buffer = NULL; // // Open the device registry and read the "PortName" value written by the // class installer. // status = WdfDeviceOpenRegistryKey(Device, PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_ALL, NULL, // PWDF_OBJECT_ATTRIBUTES &hKey); if (!NT_SUCCESS (status)) { goto Error; } status = WdfStringCreate( NULL, WDF_NO_OBJECT_ATTRIBUTES , &string ); if (!NT_SUCCESS(status)) { goto Error; } // // Retrieve the value of ValueName from registry // status = WdfRegistryQueryString( hKey, &valueName, string ); if (!NT_SUCCESS (status)) { goto Error; } // // Retrieve the UNICODE_STRING from string object // WdfStringGetUnicodeString( string, &comPort ); WdfRegistryClose(hKey); hKey = NULL; symbolicLink.Length=0; symbolicLink.MaximumLength = sizeof(OBJECT_DIRECTORY) + comPort.MaximumLength; symbolicLink.Buffer = ExAllocatePoolWithTag(PagedPool, symbolicLink.MaximumLength + sizeof(WCHAR), 'wkaF'); if (symbolicLink.Buffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Error; } RtlZeroMemory(symbolicLink.Buffer, symbolicLink.MaximumLength); RtlAppendUnicodeToString(&symbolicLink, OBJECT_DIRECTORY); RtlAppendUnicodeStringToString(&symbolicLink, &comPort); // // This DDI will get the underlying PDO name and create a symbolic to that // because our FDO doesn't have a name. // status = WdfDeviceCreateSymbolicLink(Device, &symbolicLink); if (!NT_SUCCESS(status)) { goto Error; } WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes); memoryAttributes.ParentObject = Device; status = WdfDeviceAllocAndQueryProperty(Device, DevicePropertyPhysicalDeviceObjectName, PagedPool, &memoryAttributes, &memory); if (!NT_SUCCESS(status)) { // // We expect a zero length buffer. Anything else is fatal. // goto Error; } pdoName.Buffer = WdfMemoryGetBuffer(memory, &bufferLength); if (pdoName.Buffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Error; } pdoName.MaximumLength = (USHORT) bufferLength; pdoName.Length = (USHORT) bufferLength - sizeof(UNICODE_NULL); status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, L"SERIALCOMM", pdoName.Buffer, REG_SZ, comPort.Buffer, comPort.Length); if (!NT_SUCCESS(status)) { goto Error; } FmDeviceData->Flags |= REG_VALUE_CREATED_FLAG; // // Store it so it can be deleted later. // FmDeviceData->PdoName = pdoName; Error: if (symbolicLink.Buffer != NULL) { ExFreePool(symbolicLink.Buffer); } if (hKey != NULL) { WdfRegistryClose(hKey); } if (string != NULL) { WdfObjectDelete(string); } return status; }
NTSTATUS FilterCreateControlDevice( WDFDEVICE Device ) /*++ Routine Description: This routine is called to create a control deviceobject so that application can talk to the filter driver directly instead of going through the entire device stack. This kind of control device object is useful if the filter driver is underneath another driver which prevents ioctls not known to it or if the driver's dispatch routine is owned by some other (port/class) driver and it doesn't allow any custom ioctls. NOTE: Since the control device is global to the driver and accessible to all instances of the device this filter is attached to, we create only once when the first instance of the device is started and delete it when the last instance gets removed. Arguments: Device - Handle to a filter device object. Return Value: WDF status code --*/ { PWDFDEVICE_INIT pInit = NULL; WDFDEVICE controlDevice = NULL; WDF_OBJECT_ATTRIBUTES controlAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; BOOLEAN bCreate = FALSE; NTSTATUS status; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME_STRING) ; DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING) ; PAGED_CODE(); // // First find out whether any ControlDevice has been created. If the // collection has more than one device then we know somebody has already // created or in the process of creating the device. // WdfWaitLockAcquire(FilterDeviceCollectionLock, NULL); if(WdfCollectionGetCount(FilterDeviceCollection) == 1) { bCreate = TRUE; } WdfWaitLockRelease(FilterDeviceCollectionLock); if(!bCreate) { // // Control device is already created. So return success. // return STATUS_SUCCESS; } KdPrint(("Creating Control Device\n")); // // // In order to create a control device, we first need to allocate a // WDFDEVICE_INIT structure and set all properties. // pInit = WdfControlDeviceInitAllocate( WdfDeviceGetDriver(Device), &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R ); if (pInit == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Error; } // // Set exclusive to false so that more than one app can talk to the // control device simultaneously. // WdfDeviceInitSetExclusive(pInit, FALSE); status = WdfDeviceInitAssignName(pInit, &ntDeviceName); if (!NT_SUCCESS(status)) { goto Error; } // // Specify the size of device context // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&controlAttributes, CONTROL_DEVICE_EXTENSION); status = WdfDeviceCreate(&pInit, &controlAttributes, &controlDevice); if (!NT_SUCCESS(status)) { goto Error; } // // Create a symbolic link for the control object so that usermode can open // the device. // status = WdfDeviceCreateSymbolicLink(controlDevice, &symbolicLinkName); if (!NT_SUCCESS(status)) { goto Error; } // // Configure the default queue associated with the control device object // to be Serial so that request passed to EvtIoDeviceControl are serialized. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoDeviceControl = FilterEvtIoDeviceControl; // // Framework by default creates non-power managed queues for // filter drivers. // status = WdfIoQueueCreate(controlDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // pointer to default queue ); if (!NT_SUCCESS(status)) { goto Error; } // // Control devices must notify WDF when they are done initializing. I/O is // rejected until this call is made. // WdfControlFinishInitializing(controlDevice); ControlDevice = controlDevice; return STATUS_SUCCESS; Error: if (pInit != NULL) { WdfDeviceInitFree(pInit); } if (controlDevice != NULL) { // // Release the reference on the newly created object, since // we couldn't initialize it. // WdfObjectDelete(controlDevice); controlDevice = NULL; } return status; }
_Use_decl_annotations_ NTSTATUS OnDeviceAdd( WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: OnDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a device object to represent a new instance of the device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure Return Value: Status --*/ { PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES objectAttributes; PDEVICE_CONTEXT deviceContext; WDFDEVICE device; NTSTATUS status; DECLARE_UNICODE_STRING_SIZE(symbolicLinkName, 128); // // Set PnP callbacks. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = PrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = ReleaseHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // // PWM only allows exclusive access. // WdfDeviceInitSetExclusive(DeviceInit, TRUE); // // Create device object. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, DEVICE_CONTEXT); objectAttributes.EvtCleanupCallback = OnDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &objectAttributes, &device); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create device (0x%08x)", status); goto Exit; } deviceContext = GetContext(device); // // Prepare config spin lock. // WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); status = WdfSpinLockCreate(&objectAttributes, &deviceContext->pwmLock); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create config spin lock (0x%08x)", status); goto Exit; } // // Prepare notification list spin lock. // WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); status = WdfSpinLockCreate(&objectAttributes, &deviceContext->notificationListLock); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create notification list spin lock (0x%08x)", status); goto Exit; } // // Prepare interrupt object. // WDF_INTERRUPT_CONFIG interruptConfig; WDF_INTERRUPT_CONFIG_INIT( &interruptConfig, DmaIsr, DmaDpc ); status = WdfInterruptCreate( device, &interruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceContext->interruptObj ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create interrupt object (0x%08x)", status); goto Exit; } // // Create queues to handle IO. // WDF_IO_QUEUE_CONFIG queueConfig; WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDeviceControl = OnIoDeviceControl; queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate( device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &deviceContext->queueObj ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create IO queue (0x%08x)", status); goto Exit; } // // Create a symbolic link. // status = RtlUnicodeStringInit(&symbolicLinkName, BCM_PWM_SYMBOLIC_NAME); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not process the symbolic name (0x%08x)", status); goto Exit; } status = WdfDeviceCreateSymbolicLink( device, &symbolicLinkName ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_INIT, "Can not create a symbolic name (0x%08x)", status); goto Exit; } Exit: return status; }
// 添加设备 NTSTATUS RamDiskEvtDeviceAdd(IN WDFDRIVER Driver,IN PWDFDEVICE_INIT DeviceInit) { WDF_OBJECT_ATTRIBUTES deviceAttributes; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES queueAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_EXTENSION pDeviceExtension; PQUEUE_EXTENSION pQueueContext = NULL; WDFQUEUE queue; //设备名 DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME); PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); //检查指定名称状态 status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { return status; } //指定设备类型 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK); //IO类型 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); //是否独占 WdfDeviceInitSetExclusive(DeviceInit, FALSE); //初始化 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); //设定cleanup 函数指针 deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup; //获取创建设备状态 status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } pDeviceExtension = DeviceGetExtension(device); // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE (&ioQueueConfig,WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl; ioQueueConfig.EvtIoRead = RamDiskEvtIoRead; ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION); status = WdfIoQueueCreate( device,&ioQueueConfig,&queueAttributes,&queue ); if (!NT_SUCCESS(status)) { return status; } //获得设备扩展 pQueueContext = QueueGetExtension(queue); //设置队列的设备扩展为该设备 pQueueContext->DeviceExtension = pDeviceExtension; status = SetForwardProgressOnQueue(queue); if (!NT_SUCCESS(status)) { return status; } //设备初始化 pDeviceExtension->DiskRegInfo.DriveLetter.Buffer = (PWSTR) &pDeviceExtension->DriveLetterBuffer; pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength = sizeof(pDeviceExtension->DriveLetterBuffer); //从注册表获取信息 RamDiskQueryDiskRegParameters(WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)),&pDeviceExtension->DiskRegInfo); //内存分配 要使用分页内存 pDeviceExtension->DiskImage = ExAllocatePoolWithTag(PagedPool,pDeviceExtension->DiskRegInfo.DiskSize,RAMDISK_TAG); if (pDeviceExtension->DiskImage) { //成功分配 UNICODE_STRING deviceName; UNICODE_STRING win32Name; RamDiskFormatDisk(pDeviceExtension); //格式化 status = STATUS_SUCCESS; //创建符号链接 RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME); RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME); //符号链接初始化 pDeviceExtension->SymbolicLink.Buffer = (PWSTR)&pDeviceExtension->DosDeviceNameBuffer; pDeviceExtension->SymbolicLink.MaximumLength = sizeof(pDeviceExtension->DosDeviceNameBuffer); pDeviceExtension->SymbolicLink.Length = win32Name.Length; RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name); RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink,&pDeviceExtension->DiskRegInfo.DriveLetter); //创建符号链接 status = WdfDeviceCreateSymbolicLink(device,&pDeviceExtension->SymbolicLink); } return status; }
NTSTATUS NdisProtCreateControlDevice( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Called by the DriverEntry to create a control-device. This call is responsible for freeing the memory for DeviceInit. Arguments: Driver - a pointer to the framework object that represents this device driver. DeviceInit - Pointer to a driver-allocated WDFDEVICE_INIT structure. Return Value: STATUS_SUCCESS if initialized; an error otherwise. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES objectAttribs; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDF_FILEOBJECT_CONFIG fileConfig; WDFDEVICE controlDevice = NULL; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME) ; DECLARE_CONST_UNICODE_STRING(dosDeviceName, DOS_DEVICE_NAME) ; UNREFERENCED_PARAMETER( Driver ); DEBUGP(DL_LOUD, ("NdisProtCreateControlDevice DeviceInit %p\n", DeviceInit)); // // I/O type is Buffered by default. We want to do direct I/O for Reads // and Writes so set it explicitly. // WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { goto Error; } // // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the // framework whether you are interested in handle Create, Close and // Cleanup requests that gets genereated when an application or another // kernel component opens an handle to the device. If you don't register, // the framework default behaviour would be complete these requests // with STATUS_SUCCESS. A driver might be interested in registering these // events if it wants to do security validation and also wants to maintain // per handle (fileobject) context. // WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, NdisProtEvtDeviceFileCreate, NdisProtEvtFileClose, NdisProtEvtFileCleanup ); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttribs, FILE_OBJECT_CONTEXT); WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, &objectAttribs); WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs); status = WdfDeviceCreate(&DeviceInit, &objectAttribs, &controlDevice); if (!NT_SUCCESS(status)) { goto Error; } // // DeviceInit is set to NULL if the device is created successfully. // // // Create a symbolic link for the control object so that usermode can open // the device. // status = WdfDeviceCreateSymbolicLink(controlDevice, &dosDeviceName); if (!NT_SUCCESS(status)) { goto Error; } // // Configure a default queue associated with the control device to // to receive read, write, and ioctl requests in parallel. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchParallel); ioQueueConfig.EvtIoWrite = NdisProtEvtIoWrite; ioQueueConfig.EvtIoRead = NdisProtEvtIoRead; ioQueueConfig.EvtIoDeviceControl = NdisProtEvtIoDeviceControl; status = WdfIoQueueCreate(controlDevice, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // pointer to default queue ); if (!NT_SUCCESS(status)) { goto Error; } // // Control devices must notify WDF when they are done initializing. I/O is // rejected until this call is made. // WdfControlFinishInitializing(controlDevice); // // Create our device object using which an application can // access NDIS devices. // Globals.ControlDevice = controlDevice; return status; Error: if(DeviceInit != NULL) { // // Free the WDFDEVICE_INIT structure only if the device // creation fails. Otherwise framework frees the memory // itself. // WdfDeviceInitFree(DeviceInit); } return status; }
NTSTATUS PortIODeviceCreate( PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Worker routine called to create a device and its software resources. Arguments: DeviceInit - Pointer to an opaque init structure. Memory for this structure will be freed by the framework when the WdfDeviceCreate succeeds. So don't access the structure after that point. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; PDEVICE_CONTEXT deviceContext; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDFDEVICE device; NTSTATUS status; UNICODE_STRING ntDeviceName; UNICODE_STRING win32DeviceName; WDF_FILEOBJECT_CONFIG fileConfig; PAGED_CODE(); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); // // Register pnp/power callbacks so that we can start and stop the timer as // the device gets started and stopped. // pnpPowerCallbacks.EvtDevicePrepareHardware = PortIOEvtDevicePrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = PortIOEvtDeviceReleaseHardware; // // Register the PnP and power callbacks. Power policy related callbacks will // be registered later in SotwareInit. // WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); WDF_FILEOBJECT_CONFIG_INIT( &fileConfig, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK, WDF_NO_EVENT_CALLBACK // not interested in Cleanup ); // Let the framework complete create and close fileConfig.AutoForwardCleanupClose = WdfFalse; WdfDeviceInitSetFileObjectConfig(DeviceInit, &fileConfig, WDF_NO_OBJECT_ATTRIBUTES); // // Create a named deviceobject so that legacy applications can talk to us. // Since we are naming the object, we wouldn't able to install multiple // instance of this driver. Please note that as per PNP guidelines, we // should not name the FDO or create symbolic links. We are doing it because // we have a legacy APP that doesn't know how to open an interface. // RtlInitUnicodeString(&ntDeviceName, GPD_DEVICE_NAME); status = WdfDeviceInitAssignName(DeviceInit,&ntDeviceName); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(DeviceInit, GPD_TYPE); // // Call this if the device is not holding a pagefile // crashdump file or hibernate file. // WdfDeviceInitSetPowerPageable(DeviceInit); status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Get the device context and initialize it. WdfObjectGet_DEVICE_CONTEXT is an // inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the // device.h header file. This function will do the type checking and return // the device context. If you pass a wrong object handle // it will return NULL and assert if run under framework verifier mode. // deviceContext = PortIOGetDeviceContext(device); // // This values is based on the hardware design. // I'm assuming the address is in I/O space for our hardware. // Refer http://support.microsoft.com/default.aspx?scid=kb;en-us;Q323595 // for more info. // deviceContext-> PortMemoryType = 1; // // Create a device interface so that application can find and talk // to us. // RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); status = WdfDeviceCreateSymbolicLink( device, &win32DeviceName); if (!NT_SUCCESS(status)) { return status; } // // Initialize the I/O Package and any Queues // status = PortIOQueueInitialize(device); return status; }
VCHIQ_PAGED_SEGMENT_BEGIN /*++ Routine Description: Worker routine called to create a device and its software resources. Arguments: DeviceInitPtr - Pointer to an opaque init structure. Memory for this structure will be freed by the framework when the WdfDeviceCreate succeeds. So don't access the structure after that point. Return Value: NTSTATUS --*/ _Use_decl_annotations_ NTSTATUS VchiqCreateDevice ( WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInitPtr ) { WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES deviceAttributes; DEVICE_CONTEXT* deviceContextPtr; WDFDEVICE device; NTSTATUS status; WDF_IO_TYPE_CONFIG ioConfig; DECLARE_CONST_UNICODE_STRING(vchiqSymbolicLink, VCHIQ_SYMBOLIC_NAME); UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); { WDF_FILEOBJECT_CONFIG fileobjectConfig; WDF_FILEOBJECT_CONFIG_INIT( &fileobjectConfig, WDF_NO_EVENT_CALLBACK, VchiqFileClose, WDF_NO_EVENT_CALLBACK); fileobjectConfig.FileObjectClass = WdfFileObjectWdfCanUseFsContext; WdfDeviceInitSetFileObjectConfig( DeviceInitPtr, &fileobjectConfig, WDF_NO_OBJECT_ATTRIBUTES); } WDF_IO_TYPE_CONFIG_INIT(&ioConfig); ioConfig.ReadWriteIoType = WdfDeviceIoDirect; ioConfig.DeviceControlIoType = WdfDeviceIoDirect; ioConfig.DirectTransferThreshold = 0; WdfDeviceInitSetIoTypeEx(DeviceInitPtr, &ioConfig); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); pnpPowerCallbacks.EvtDevicePrepareHardware = VchiqPrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = VchiqReleaseHardware; pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = VchiqInitOperation; WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInitPtr, &pnpPowerCallbacks); WdfDeviceInitSetIoInCallerContextCallback( DeviceInitPtr, VchiqInCallerContext); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &deviceAttributes, DEVICE_CONTEXT); status = WdfDeviceCreate( &DeviceInitPtr, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { VCHIQ_LOG_ERROR( "WdfDeviceCreate fail %!STATUS!", status); goto End; } { WDF_OBJECT_ATTRIBUTES attributes; WDF_IO_QUEUE_CONFIG queueConfig; WDFQUEUE queue; deviceContextPtr = VchiqGetDeviceContext(device); deviceContextPtr->Device = device; deviceContextPtr->VersionMajor = VCHIQ_VERSION_MAJOR; deviceContextPtr->VersionMinor = VCHIQ_VERSION_MINOR; deviceContextPtr->PhyDeviceObjectPtr = WdfDeviceWdmGetPhysicalDevice(device); WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDeviceControl = VchiqIoDeviceControl; queueConfig.EvtIoStop = VchiqIoStop; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfIoQueueCreate( device, &queueConfig, &attributes, &queue); if (!NT_SUCCESS(status)) { VCHIQ_LOG_ERROR( "WdfIoQueueCreate fail %!STATUS!", status); goto End; } } // Create symbolic and device interface status = WdfDeviceCreateSymbolicLink( device, &vchiqSymbolicLink); if (!NT_SUCCESS(status)) { VCHIQ_LOG_ERROR( "Fail to register symbolic link %!STATUS!", status); goto End; } End: VCHIQ_LOG_INFORMATION("Exit Status %!STATUS!", status); return status; }
// // 作用相当于WDM中的AddDevice函数。 // 他是PNP过程中首当其冲被调用的回调函数。主要任务是创建设备对象。 // 设备对象在系统中以软件形式,代表外部的某个物理硬件设备。 //NTSTATUS PnpAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit) NTSTATUS DrvClass::PnpAdd(IN PWDFDEVICE_INIT DeviceInit) { NTSTATUS status; WDFDEVICE device; int nInstance = 0; PDEVICE_CONTEXT pContext = NULL; UNICODE_STRING DeviceName; UNICODE_STRING DosDeviceName; UNICODE_STRING RefString; WDFSTRING SymbolName; WDF_OBJECT_ATTRIBUTES attributes; WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_DEVICE_PNP_CAPABILITIES pnpCapabilities; WCHAR wcsDeviceName[] = L"\\Device\\CY001-0"; // 设备名 WCHAR wcsDosDeviceName[] = L"\\DosDevices\\CY001-0";// 符号链接名 WCHAR wcsRefString[] = L"CY001-0"; // 符号链接名 int nLen = wcslen(wcsDeviceName); KDBG(DPFLTR_INFO_LEVEL, "[PnpAdd]"); RtlInitUnicodeString(&DeviceName, wcsDeviceName) ; RtlInitUnicodeString(&DosDeviceName, wcsDosDeviceName); RtlInitUnicodeString(&RefString, wcsRefString); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); InitPnpPwrEvents(&pnpPowerCallbacks); WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); // 读、写请求的缓冲方式 // 默认为Buffered方式,另外两种方式是Direct和Neither。 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); // 设定设备环境块长度 // 宏内部会调用sizeof(DEVICE_CONTEXT)求结构体长度 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); // 驱动支持最多8个实例,即当多个开发板连到PC上时,驱动对它们给予并行支持。 // 不同的设备对象,各以其名称的尾数(0-7)相别,并将此尾数称作设备ID。 // 下面的代码逻辑为当前设备对象寻找一个可用ID。 for(nInstance = 0; nInstance < MAX_INSTANCE_NUMBER; nInstance++) { // 修改设备ID wcsDeviceName[nLen-1] += nInstance; // 尝试命名;命名可能失败,失败的原因包括:名称无效、名称已存在等 WdfDeviceInitAssignName(DeviceInit, &DeviceName); // 创建WDF设备 // 如能成功,则命名亦成功。 status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if(!NT_SUCCESS(status)) { if(status == STATUS_OBJECT_NAME_COLLISION)// 名字冲突 { KDBG(DPFLTR_ERROR_LEVEL, "Already exist: %wZ", &DeviceName); } else { KDBG(DPFLTR_ERROR_LEVEL, "WdfDeviceCreate failed with status 0x%08x!!!", status); return status; } }else { KdPrint(("Device name: %wZ", &DeviceName)); break; } } // 如失败,可能是连接的开发板数量太多; // 建议使用WinOBJ查看系统中的设备名称。 if (!NT_SUCCESS(status)) return status; m_hDevice = device;// 保存设备对象句柄 // 创建符号链接,应用程序根据符号链接查看并使用内核设备。 // 除了创建符号链接外,现在更好的方法是使用WdfDeviceCreateDeviceInterface创建设备接口。 // 设备接口能保证名字不会冲突,但不具有可读性,所以我们仍采用符号链接形式。 nLen = wcslen(wcsDosDeviceName); wcsDosDeviceName[nLen-1] += nInstance; status = WdfDeviceCreateSymbolicLink(device, &DosDeviceName); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_INFO_LEVEL, "Failed to create symbol link: 0x%08X", status); return status; } // 初始化环境块 // GetDeviceContext是一个函数指针,由宏WDF_DECLARE_CONTEXT_TYPE_WITH_NAME定义。 // 参看pulibc.h中的说明。 pContext = GetDeviceContext(device); RtlZeroMemory(pContext, sizeof(DEVICE_CONTEXT)); pContext->par1 = this; // 通过this指针可以得到一切 // PNP属性。允许设备异常拔除,系统不会弹出错误框。 WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCapabilities); InitPnpCap(&pnpCapabilities); WdfDeviceSetPnpCapabilities(device, &pnpCapabilities); status = CreateWDFQueues(); if(!NT_SUCCESS(status)) return status; return status; }
NTSTATUS OnDeviceAdd( _In_ WDFDRIVER FxDriver, _Inout_ PWDFDEVICE_INIT FxDeviceInit ) /*++ Routine Description: This routine creates the device object for an SPB controller and the device's child objects. Arguments: FxDriver - the WDF driver object handle FxDeviceInit - information about the PDO that we are loading on Return Value: Status --*/ { //FuncEntry(TRACE_FLAG_WDFLOADING); PDEVICE_CONTEXT pDevice; NTSTATUS status; UNREFERENCED_PARAMETER(FxDriver); // // Setup PNP/Power callbacks. // { WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(FxDeviceInit, &pnpCallbacks); } // // Prepare for file object handling. // { WDF_FILEOBJECT_CONFIG fileObjectConfig; WDF_FILEOBJECT_CONFIG_INIT( &fileObjectConfig, nullptr, nullptr, OnFileCleanup); WDF_OBJECT_ATTRIBUTES fileObjectAttributes; WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes); WdfDeviceInitSetFileObjectConfig( FxDeviceInit, &fileObjectConfig, &fileObjectAttributes); } // // Set request attributes. // { WDF_OBJECT_ATTRIBUTES attributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &attributes, REQUEST_CONTEXT); WdfDeviceInitSetRequestAttributes(FxDeviceInit, &attributes); } // // Create the device. // { WDFDEVICE fxDevice; WDF_OBJECT_ATTRIBUTES deviceAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); status = WdfDeviceCreate( &FxDeviceInit, &deviceAttributes, &fxDevice); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating WDFDEVICE - %!STATUS!", status); goto exit; } pDevice = GetDeviceContext(fxDevice); NT_ASSERT(pDevice != nullptr); pDevice->FxDevice = fxDevice; } // // Ensure device is disable-able // { WDF_DEVICE_STATE deviceState; WDF_DEVICE_STATE_INIT(&deviceState); deviceState.NotDisableable = WdfFalse; WdfDeviceSetDeviceState(pDevice->FxDevice, &deviceState); } // // Create queues to handle IO // { WDF_IO_QUEUE_CONFIG queueConfig; WDFQUEUE queue; // // Top-level queue // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDefault = OnTopLevelIoDefault; queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate( pDevice->FxDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue ); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating top-level IO queue - %!STATUS!", status); goto exit; } // // Sequential SPB queue // WDF_IO_QUEUE_CONFIG_INIT( &queueConfig, WdfIoQueueDispatchSequential); queueConfig.EvtIoRead = OnIoRead; queueConfig.EvtIoWrite = OnIoWrite; queueConfig.EvtIoDeviceControl = OnIoDeviceControl; queueConfig.PowerManaged = WdfFalse; status = WdfIoQueueCreate( pDevice->FxDevice, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &pDevice->SpbQueue ); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating SPB IO queue - %!STATUS!", status); goto exit; } } // // Create a symbolic link. // { DECLARE_UNICODE_STRING_SIZE(symbolicLinkName, 128); status = RtlUnicodeStringPrintf( &symbolicLinkName, L"%ws", sensy_SYMBOLIC_NAME); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating symbolic link string for device " "- %!STATUS!", status); goto exit; } status = WdfDeviceCreateSymbolicLink( pDevice->FxDevice, &symbolicLinkName); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_WDFLOADING, "Error creating symbolic link for device " "- %!STATUS!", status); goto exit; } } // // Retrieve registry settings. // { WDFKEY key = NULL; WDFKEY subkey = NULL; ULONG connectInterrupt = 0; NTSTATUS settingStatus; DECLARE_CONST_UNICODE_STRING(subkeyName, L"Settings"); DECLARE_CONST_UNICODE_STRING(connectInterruptName, L"ConnectInterrupt"); settingStatus = WdfDeviceOpenRegistryKey( pDevice->FxDevice, PLUGPLAY_REGKEY_DEVICE, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &key); if (!NT_SUCCESS(settingStatus)) { Trace( TRACE_LEVEL_WARNING, TRACE_FLAG_WDFLOADING, "Error opening device registry key - %!STATUS!", settingStatus); } if (NT_SUCCESS(settingStatus)) { settingStatus = WdfRegistryOpenKey( key, &subkeyName, KEY_READ, WDF_NO_OBJECT_ATTRIBUTES, &subkey); if (!NT_SUCCESS(settingStatus)) { Trace( TRACE_LEVEL_WARNING, TRACE_FLAG_WDFLOADING, "Error opening registry subkey for 'Settings' - %!STATUS!", settingStatus); } } if (NT_SUCCESS(settingStatus)) { settingStatus = WdfRegistryQueryULong( subkey, &connectInterruptName, &connectInterrupt); if (!NT_SUCCESS(settingStatus)) { Trace( TRACE_LEVEL_WARNING, TRACE_FLAG_WDFLOADING, "Error querying registry value for 'ConnectInterrupt' - %!STATUS!", settingStatus); } } if (key != NULL) { WdfRegistryClose(key); } if (subkey != NULL) { WdfRegistryClose(subkey); } pDevice->ConnectInterrupt = (connectInterrupt == 1); } exit: //FuncExit(TRACE_FLAG_WDFLOADING); return status; }
NTSTATUS RamDiskEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a device object to represent a new instance of the device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES queueAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_EXTENSION pDeviceExtension; PQUEUE_EXTENSION pQueueContext = NULL; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME); PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); // // Storage drivers have to name their FDOs. Since we are not unique'fying // the device name, we wouldn't be able to install more than one instance // of this ramdisk driver. // status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WdfDeviceInitSetExclusive(DeviceInit, FALSE); // // Since this is a pure software only driver, there is no need to register // any PNP/Power event callbacks. Framework will respond to these // events appropriately. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Now that the WDF device object has been created, set up any context // that it requires. // pDeviceExtension = DeviceGetExtension(device); // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE ( &ioQueueConfig, WdfIoQueueDispatchSequential ); ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl; ioQueueConfig.EvtIoRead = RamDiskEvtIoRead; ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION); status = WdfIoQueueCreate( device, &ioQueueConfig, &queueAttributes, &queue ); if (!NT_SUCCESS(status)) { return status; } // Context is the Queue handle pQueueContext = QueueGetExtension(queue); // // Set the context for our default queue as our device extension. // pQueueContext->DeviceExtension = pDeviceExtension; // // Enable forward progress on the queue we just created. // NOTE: If you are planning to use this code without forward progress, // comment out the call to SetForwardProgressOnQueue below. // status = SetForwardProgressOnQueue(queue); if (!NT_SUCCESS(status)) { return status; } // // Now do any RAM-Disk specific initialization // pDeviceExtension->DiskRegInfo.DriveLetter.Buffer = (PWSTR) &pDeviceExtension->DriveLetterBuffer; pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength = sizeof(pDeviceExtension->DriveLetterBuffer); // // Get the disk parameters from the registry // RamDiskQueryDiskRegParameters( WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)), &pDeviceExtension->DiskRegInfo ); // // Allocate memory for the disk image. // pDeviceExtension->DiskImage = ExAllocatePoolWithTag( NonPagedPool, pDeviceExtension->DiskRegInfo.DiskSize, RAMDISK_TAG ); if (pDeviceExtension->DiskImage) { UNICODE_STRING deviceName; UNICODE_STRING win32Name; RamDiskFormatDisk(pDeviceExtension); status = STATUS_SUCCESS; // // Now try to create a symbolic link for the drive letter. // RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME); RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME); pDeviceExtension->SymbolicLink.Buffer = (PWSTR) &pDeviceExtension->DosDeviceNameBuffer; pDeviceExtension->SymbolicLink.MaximumLength = sizeof(pDeviceExtension->DosDeviceNameBuffer); pDeviceExtension->SymbolicLink.Length = win32Name.Length; RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name); RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink, &pDeviceExtension->DiskRegInfo.DriveLetter); status = WdfDeviceCreateSymbolicLink(device, &pDeviceExtension->SymbolicLink); } return status; }