440 likes | 910 Views
Toaster Sample Package Eliyas Yakub Windows NT ® DDK Support Engineer Developer Support Microsoft Corporation. Agenda. Introduce various components of Toaster Sample Package Describe how the sample was implemented by highlighting core components. Package Layout.
E N D
Toaster Sample PackageEliyas Yakub Windows NT® DDK Support EngineerDeveloper Support Microsoft Corporation
Agenda • Introduce various components of Toaster Sample Package • Describe how the sample was implemented by highlighting core components
Package Layout • Located under NTDDK\SRC\GENERAL\TOASTER
Objectives Of The Sample • De-mystify Windows® Driver Model • Through the use of sample code demonstrate how to develop: • Bus Driver • Function Driver • Filter Drivers (Class & Device) • Coinstaller DLL • Power Management • WMI • Plug and Play Notification in user-mode and kernel-mode
What Is Toaster Bus • Hypothetical bus for toaster devices • Simulates hot plug-in, unplug, and eject toasters devices • Toasters support power management • Defines a new “Toaster” device class
Bus Driver (BusEnum.sys) • Dual personality driver • Use bus.inf and busf.inf to install through the Add HW Wizard • System root enumerates the bus driver • DriverEntry() • Sets dispatch points • AddDevice() • Creates FDO and attaches it to the PDO provided by the Plug and Play manager
Bus Driver • Registers GUID_TOASTER_BUS_ENUMERATOR_INTERFACE_CLASS interface • Driver typically handles following IRPs: • IRP_MN_FILTER_RESOURCE_REQUIREMENTS • IRP_MN_START_DEVICE • IRP_MN_QUERY_CAPABILITIES • IRP_MN_QUERY_PNP_DEVICE_STATE • IRP_MN_QUERY_DEVICE_RELATIONS (BusRelations) • This is not a complete list. Drivers shouldn’t make any assumptions about the order of these IRPs
Simulating Plug-In Of New Toaster Device • Application opens the interface registered by BusEnum • Application sends IOCTL_BUSENUM_PLUGIN_HARDWARE • Provides Serial Number and HW ID of the device
Plug-In • BusEnum creates a DeviceObject (PDO) for the new device • Initializes device extension • Present = TRUE; • ReportedMissing = FALSE; • BusEnum notifies Plug and Play manager • Calls IoInvalidateDeviceRelations() with BusRelations parameter
Plug-In • Plug and Play manager sends IRP_MN_QUERY_DEVICE_RELATIONS to BusEnum’s FDO • The BusEnum returns a list of PDO pointers • Plug and Play manager starts enumeration after discovering PDO for the new Toaster device
Plug-In • Plug and Play manager sends following IRPs to the new PDO to learn more about the device: • IRP_MN_QUERY_ID (BusQueryDeviceID) • IRP_MN_QUERY_CAPABILITIES • IRP_MN_QUERY_DEVICE_TEXT (Description) • IRP_MN_QUERY_DEVICE_TEXT (Location) • IRP_MN_QUERY_ID (BusInstanceID) • IRP_MN_QUERY_ID (BusQueryHardwareIDs) • IRP_MN_QUERY_ID (BusQueryCompatibleIDs) • IRP_MN_QUERY_RESOURCE_REQUIREMENTS • IRP_MN_QUERY_BUS_INFORMATION • IRP_MN_QUERY_RESOURCES
Plug-In • Plug and Play loads the toaster.sys function driver • Matches the Device ID in toaster.inf • Loads the function Driver (toaster.sys) • Calls AddDevice in toaster.sys • Function driver handles following Plug and Play IRPs: • IRP_MN_FILTER_RESOURCE_REQUIREMENTS • IRP_MN_QUERY_INTERFACE • IRP_MN_START_DEVICE • IRP_MN_QUERY_CAPABILITIES • IRP_MN_QUERY_PNP_DEVICE_STATE
Diagram Of Single Toaster Device Toast.exe Notify.exe Toaster.sys FDO PDO FDO BusEnum.sys . . . . . . . . . PDO FDO Plug and Play Manager PDO
FDO PDO PDO FDO Diagram Of Two Toaster Devices Toast.exe Notify.exe Toaster.sys FDO BusEnum.sys . . . . . . . . . PDO PDO PDO Plug and Play Manager
Unplug A Device • Application sends an IOCTL_BUSENUM_UNPLUG_HARDWARE with the Serial Number • BusEnum marks the device as not present • Present = FALSE; • BusEnum informs Plug and Play manager by calling IoInvalidateDeviceRelations() • Plug and Play manager sends IRP_MN_QUERY_DEVICE_RELATIONS • BusEnum does not include the unplugged PDO in list of PDOs
UnPlug • Set the ReportedMissing to TRUE • ReportedMissing = TRUE; • The Plug and Play manager sends: • IRP_MN_SURPRISE_REMOVAL • IRP_MN_REMOVE_DEVICE • Function driver detaches and deletes its device object • Busenum deletes the PDO after receiving IRP_MN_REMOVE_DEVICE
Eject A Device • User Application sends IOCTL_BUSENUM_EJECT_HARDWARE with the Serial Number • BusEnum calls IoRequestDeviceEject • The Plug and Play manager sends: • IRP_MN_QUERY_REMOVAL • IRP_MN_REMOVE_DEVICE
Eject • Plug and Play manager sends • IRP_MN_EJECT set the Present = FALSE; • IRP_MN_QUERY_DEVICE_RELATIONS (BusRelations) set the ReportedMissing = TRUE; • IRP_MN_REMOVE_DEVICE
typedef enum _DEVICE_PNP_STATE { NotStarted = 0, // Not started yet Started, // Device has received the START_DEVICE IRP StopPending, // Device has received the QUERY_STOP IRP Stopped, // Device has received the STOP_DEVICE IRP RemovePending, // Device has received the QUERY_REMOVE IRP SurpriseRemovePending, // Device has received the SURPRISE_REMOVE IRP Deleted // Device has received the REMOVE_DEVICE IRP } DEVICE_PNP_STATE; Notice the use of following macros: INITIALIZE_PNP_STATE SET_NEW_PNP_STATE RESTORE_PREVIOUS_PNP_STATE Device Plug And Play State
PDO Deletion • Bus drivers must delete the PDO only after device is physically removed • Surprise removal • After receiving IRP_MN_REMOVE_DEVICE • Ejecting • After receiving the second IRP_MN_REMOVE_DEVICE • During ejection Plug and Play manager sends QUERY_REMOVE, REMOVE, EJECT QUERY_DEVICE_RELATIONS, REMOVE • Second IRP_MN_REMOVE_DEVICE is sent in response to missing PDO returned with QUERY_DEVICE_RELATIONS IRP
PDO Deletion • Delete all children PDOs when bus is removed or disabled • EXCEPTION: Do NOT delete PDOs in the process of being surprised removed • Do NOT delete PDO when device is disabled • BUS Driver will receive QUERY_REMOVE / REMOVE IRPs when device is disabled • Do not delete the PDO because the device is still present
Function Driver (toaster.sys) • Demonstrates: • Plug and Play handling • Power management by acting as a power policy owner of the device • WMI • IRP Queuing, Cancel and Cleanup techniques • Demonstrates the use of IoInValidateDeviceState() to hide your device
INF Files • Bus.inf: For the bus driver • Toaster.inf: For the function driver • Busf.inf: Bus driver with upper and lower device filters • Toasterf.inf: Function driver with lower and upper device and class filters • Toastco.inf: Installs function driver and a coinstaller dll • Filter.inf: Installs a device upper filter for the toaster device using Update Driver
Filter Drivers • A single source file is used to generate six different filter drivers: • Devupper.sys • Devlower.sys • Clasupper.sys • Claslower.sys • BFdoLwr.sys • BFdoUpr.sys • To load all the filters you should use busf.inf to install the enumerator and use toasterf.inf to install device and class filters
Device Filters Installation • Use DDInstall.HW sections in the INF file to install filters • [Toaster_Device.NT.HW.AddReg] • HKR,,"UpperFilters",0x00010000,"devupper" • HKR,,"LowerFilters",0x00010000,"devlower" • These sections adds above registry values under the device hardware key • HKLM\System\CurrentControlSet\Enum\MsToaster\1&1a590e2c&1&01 • UpperFilters:REG_MULTI_SZ:Devupper • LowerFilters:REG_MULTI_SZ:Devlower
Toaster Stack With Device Filters Toast.exe Enum.exe DevUpper.sys FiDO Toaster.sys FDO DevLower.sys FiDO PDO FDO BusEnum.sys FDO PDO PDO Plug and Play Manager
Class Filters • Class filters are specified adding UpperFilters or LowerFilters name value under the class key HKLM\System\CurrentControlSet\Control\Class\{B85B7C50-6A01-11d2-B841-00C04FAD5171} UpperFilters:REG_MULTI_SZ:Clasupper LowerFilters:REG_MULTI_SZ:Claslower
FiDO FiDO FiDO FDO FiDO FiDO FiDO FDO FiDO FiDO PDO PDO FDO PDO PDO Toast.exe Enum.exe ClasUpper.sys DevUpper.sys Toaster.sys ClasLower.sys DevLower.sys BusEnum.sys FDO Plug and Play Manager
Co-Installer • Loaded whenever a toaster device is installed or removed • Shows how to process custom sections in an INF file • Shows how to create a friendly name
Notify Application • Simulates plug in, unplug, and ejection of devices • Demonstrates how applications monitor and process user-mode Plug and Play notifications • Combines the functionality of Enum.exe and toast.exe
Register for Interface Change Notification DEV_BROADCAST_DEVICEINTERFACE filter; filter.dbcc_size = sizeof(filter); filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; filter.dbcc_classguid = InterfaceGuid; hInterfaceNotification = RegisterDeviceNotification(hWnd, &filter, 0); Handles Plug and Play notifications DBT_DEVICEARRIVAL DBT_DEVICEREMOVECOMPLETE Notify Application
Open a toster device and register another notification on the file handle filter.dbch_size = sizeof(filter); filter.dbch_devicetype = DBT_DEVTYP_HANDLE; filter.dbch_handle = DeviceInfo[NumDevices].hDevice; DeviceInfo[NumDevices].hHandleNotification = RegisterDeviceNotification(hWnd, &filter, 0); Handle Device Change Notification DBT_DEVICEQUERYREMOVE DBT_DEVICEREMOVECOMPLETE DBT_DEVICEREMOVEPENDING DBT_DEVICEQUERYREMOVEFAILED Notify Application
ToastMon • Demonstrates how drivers monitor Plug and Play events of arbitrary devices • Example: monitors a non-Plug and Play serial device • Uses kernel-mode Plug and Play notification • Use toatmon.inf to install the driver through root enumeration
ToastMon • Register for interface arrival notification in AddDevice status = IoRegisterPlugPlayNotification ( EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_ INTERFACES, (PVOID)&GUID_TOASTER_DEVICE_INTERFACE_CLASS DriverObject, (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) ToastMon_PnpNotifyInterfaceChange, (PVOID)deviceExtension, &deviceExtension->NotificationHandle); • Open the device in response to GUID_TOASTER_DEVICE_INTERFACE_CLASS notification callback
ToastMon • Careful coding required in notification callback • Do NOT open interface that can cause Plug and Play event • Example: SWENUM • Doing so can cause deadlock
ToastMon • Register for Device change notification on the FileObject IoRegisterPlugPlayNotification ( EventCategoryTargetDeviceChange, 0, (PVOID)List->FileObject, List->DeviceExtension-> DeviceObject->DriverObject, (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) ToastMon_PnpNotifyDeviceChange, (PVOID)List, &List->NotificationHandle); • Handle Notification Callback Events For: GUID_TARGET_DEVICE_QUERY_REMOVE GUID_TARGET_DEVICE_REMOVE_COMPLETE GUID_TARGET_DEVICE_REMOVE_CANCELLED
Setup Class GUID • Setup class GUID is specified in the INF file [Version]Signature="$WINDOWS NT$“Class=TOASTERClassGuid={B85B7C50-6A01-11d2-B841-00C04FAD5171} • All the system defined GUIDs are listed in DEVGUID.H
Interface Class GUID • Interface GUIDs are used to interact with the driver • Registered in AddDevice • Enabled during Start • Disabled during Remove • Are defined in device specific header files under the NTDDK\INC directory • Examples:ntdd8042.h, ntddbeep.h, ntddcdrm.h, ntdddisk.h, ntddft.h, ntddft2.h, ntddkbd.h, ntddmou.h, ntddndis.h, ntddpar.h, ntddpcm.h, ntddscsi.h, ntddser.h, ntddstor.h, ntddtdi.h, ntddvol.h
Call To Action • Study the toaster sample to learn how all the components of a device stack fit together • Sample complements the DDK documentation • Contains extensive internal documentation • E-mail me (eliyasy@microsoft.com) with questions regarding the sample
Errata • In Line 63, the driver name should be toastmon.sys instead of genport.sys • In the toaster.c of function driver the line • IoSetCancelRoutine(nextIrp, Null) should be replace by • If(IoSetCancelRoutine(nextIrp, Null) ) • { • KeReleaseSpinlock(); • Continue; • }