diff options
| author | Dipannita Shaw <[email protected]> | 2021-04-27 14:26:21 -0700 |
|---|---|---|
| committer | Dipannita Shaw <[email protected]> | 2021-04-27 14:26:21 -0700 |
| commit | 78a1795995814a0bac43042f7ca68e83ab525bd5 (patch) | |
| tree | 8e2eb0e8c3a11220f2f119964c6c6e3674eda0da /general | |
| parent | 465e27457dd3b47cf64e4b7274705cc6acc011a6 (diff) | |
| parent | 672fafbcc455cd97172b2df78040c7c405e32d00 (diff) | |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'general')
65 files changed, 2183 insertions, 4200 deletions
diff --git a/general/DCHU/README.md b/general/DCHU/README.md index 4f479c96..878d67a1 100644 --- a/general/DCHU/README.md +++ b/general/DCHU/README.md @@ -5,32 +5,25 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: DHCU - Driver package installation toolkit for universal drivers - platform: UMDF2 - language: cpp - category: General DHCU - description: Illustrates DCHU principles of universal driver design. - samplefwlink: https://aka.ms/sceeqq ----> - # Driver package installation toolkit for universal drivers -This sample illustrates the DCHU principles of universal driver design. The sample uses the [OSR FX2 learning kit](http://store.osr.com/product/osr-usb-fx2-learning-kit-v2/). For a detailed code walkthrough, see [Universal Driver Scenarios](https://docs.microsoft.com/windows-hardware/drivers/develop/universal-driver-scenarios). +This sample illustrates the DCHU principles of universal driver design. The sample uses the [OSR FX2 learning kit](https://osrfx2.sourceforge.net/). For a detailed code walkthrough, see [Universal Driver Scenarios](https://docs.microsoft.com/windows-hardware/drivers/develop/universal-driver-scenarios). There are three Visual Studio solutions in this sample. Each one represents a single submission on the [Windows Hardware Dev Center dashboard](https://developer.microsoft.com/windows/hardware/dashboard-sign-in). The solutions are split into the following subdirectories: -* `osrfx2_DCHU_base` : The driver for the OSR FX2 Learning Kit. This includes the device driver, an upper filter driver for the device (a no-op), a Win32 User Service that controls lights on the device, and a console app that can control the device. +- `osrfx2_DCHU_base` : The driver for the OSR FX2 Learning Kit. This includes the device driver, an upper filter driver for the device (a no-op), a Win32 User Service that controls lights on the device, and a console app that can control the device. -* `osrfx2_DCHU_extension_loose`: An extension INF for the OSR FX2 device. This extension modifies some registry settings originally specified by the base driver (`osrfx2_DCHU_base`) and also uses AddComponent to create a Software Component. There is also a component INF project that would be a separate submission to DevCenter, which runs some simple software. These two projects are loosely coupled, and can be installed in any order on the machine. +- `osrfx2_DCHU_extension_loose`: An extension INF for the OSR FX2 device. This extension modifies some registry settings originally specified by the base driver (`osrfx2_DCHU_base`) and also uses AddComponent to create a Software Component. There is also a component INF project that would be a separate submission to DevCenter, which runs some simple software. These two projects are loosely coupled, and can be installed in any order on the machine. -* `osrfx2_DCHU_extension_tight`: An extension INF for the OSR FX2 device. This extension mimics the behavior of `osrfx2_DCHU_extension_loose`; however, it does so in a tightly coupled manner. Using CopyINF, both the extension and component INF are placed into one driver package (and one submission to DevCenter). Here there is less flexibility with the base/component/extension relationship, but it ensures that the component INF is applied at the same time as the extension. +- `osrfx2_DCHU_extension_tight`: An extension INF for the OSR FX2 device. This extension mimics the behavior of `osrfx2_DCHU_extension_loose`; however, it does so in a tightly coupled manner. Using CopyINF, both the extension and component INF are placed into one driver package (and one submission to DevCenter). Here there is less flexibility with the base/component/extension relationship, but it ensures that the component INF is applied at the same time as the extension. -Both `osrfx2_DCHU_extension_loose` and `osrfx2_DCHU_extension_tight` provide the same functionality, so installing both on the same OSR FX2 device is unnecessary. They are intended to show a different way to use extension and component INF's depending on a project's needs. +Both `osrfx2_DCHU_extension_loose` and `osrfx2_DCHU_extension_tight` provide the same functionality, so installing both on the same OSR FX2 device is unnecessary. They are intended to show a different way to use extension and component INFs depending on a project's needs. -NOTE: osrfx2_DCHU_extension_tight will not currently build on Windows 10 version 1703. You will see an error saying that the directive CopyINF does not work from extension INFs. This has been fixed for the Windows 10 Fall Creators Update. +> [!NOTE] +> osrfx2_DCHU_extension_tight will not currently build on Windows 10 version 1703. You will see an error saying that the directive CopyINF does not work from extension INFs. This has been fixed for the Windows 10 Fall Creators Update. Each of these solutions can be built with the latest WDK on Visual Studio 2015. Additionally, you can also download a [Universal Windows Platform app (UWP)](https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/CustomCapability) that controls the OSR FX2 Learning Kit's device. To learn how to pair a UWP app with a device, see [Hardware access for Universal Windows Platform apps](https://docs.microsoft.com/windows-hardware/drivers/devapps/hardware-access-for-universal-windows-platform-apps) @@ -38,11 +31,12 @@ The app and the contents of this sample can coexist, but on Windows 10 version 1 To install these driver packages, make sure that the target machine is in Test Mode, using `bcdedit /set testsigning on`. -Then, use `pnputil /i /a <PATHTOINF>` to install each of the desired driver packages. They should -be installed in the following order: +Then, use `pnputil /i /a <PATHTOINF>` to install each of the desired driver packages. They should be installed in the following order: + +- `osrfx2_DCHU_base` + +- `osrfx2_DCHU_extension` -* `osrfx2_DCHU_base` -* `osrfx2_DCHU_extension` -* `osrfx2_DCHU_component` +- `osrfx2_DCHU_component` -Technically the order of `osrfx2_DCHU_extension` and `osrfx2_DCHU_component` doesn't matter, but the software within `osrfx2_DCHU_component` will read the registry set by the extension to show that an extension INF's settings are applied *after* the base INF's. +Technically the order of `osrfx2_DCHU_extension` and `osrfx2_DCHU_component` doesn't matter, but the software within `osrfx2_DCHU_component` will read the registry set by the extension to show that an extension's INF settings are applied *after* the base INFs. diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/driver.c b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/driver.c index 2be5d2ed..9f28204f 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/driver.c +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/driver.c @@ -120,7 +120,7 @@ DriverEntry( EventRegisterOSRUSBFX2(); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If you create any resources // in the DriverEntry and want to be cleaned in driver unload, diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx Binary files differindex 8271e39d..73b6d10e 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj index 57439bd9..f78f16b4 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj @@ -26,7 +26,7 @@ <Platform Condition="'$(Platform)' == ''">Win32</Platform> <SampleGuid>{F915ED95-7BE9-4CDB-B09A-0D3F4C9657FE}</SampleGuid> <ProjectName>osrfx2_DCHU_base</ProjectName> - <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj index 36d85583..09724ba5 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj @@ -27,7 +27,7 @@ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> <Platform Condition="'$(Platform)' == ''">Win32</Platform> <SampleGuid>{1A4A32BA-1596-4F52-BC48-B85A6D8D5D12}</SampleGuid> - <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion> <ProjectName>osrfx2_DCHU_filter</ProjectName> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj index 225dcde2..bc56feac 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj @@ -25,7 +25,7 @@ <Platform Condition="'$(Platform)' == ''">Win32</Platform> <SampleGuid>{F19E45AF-8B05-4204-A66B-9BDBFE333233}</SampleGuid> <ProjectName>osrfx2_DCHU_testapp</ProjectName> - <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp deleted file mode 100644 index 98a3975c..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - CppWindowsService.cpp - -Abstract: - - The file defines the entry point of the application. According to the - arguments in the command line, the function installs or uninstalls or - starts the service by calling into different routines. - -Environment: - - User mode - ---*/ - -#pragma region Includes -#include <stdio.h> -#include <windows.h> -#include "ServiceBase.h" -#include "SampleService.h" -#pragma endregion - -// -// Settings of the service -// - -// -// Internal name of the service -// -#define SERVICE_NAME L"OsrUsbFx2UmUserSvc" - - -/*++ - -Routine Description: - - Entry point for the service. - -Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - -Return Value: - - VOID - ---*/ -INT -wmain( - INT Argc, - WCHAR *Argv[] - ) -{ - CSampleService service(SERVICE_NAME); - - if (!CServiceBase::Run(service)) - { - wprintf(L"Service failed to run w/err 0x%08lx\n", GetLastError()); - } - - return 0; -}
\ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp new file mode 100644 index 00000000..318e0dd5 --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp @@ -0,0 +1,856 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + DeviceContext.cpp + +Abstract: + + Implements the functions to create/destroy device context by + registering/unregistering for device notifications. + +Environment: + + User mode + +--*/ + +#include "stdafx.h" + +extern HANDLE SvcStopRequestEvent; +extern HCMNOTIFICATION InterfaceNotificationHandle; +extern DEVICE_LIST_ENTRY DeviceList; +extern SRWLOCK DeviceListLock; + +// +// Keep track of running theads for unregistering device notifications +// +DWORD RunningUnregistrations = 0; +SRWLOCK RunningUnregistrationsLock = SRWLOCK_INIT; +CONDITION_VARIABLE UnregistrationComplete = CONDITION_VARIABLE_INIT; + +/*++ + +Routine Description: + + Setup device interface context by registering for device interface + notifications + +Arguments: + + NULL + +Return Value: + + A Win32 error code. + +--*/ +DWORD +SetupDeviceInterfaceContext( + VOID + ) +{ + DWORD Err = ERROR_SUCCESS; + CONFIGRET Cr = CR_SUCCESS; + PCWSTR DeviceInterface = NULL; + PWSTR DeviceInterfaceList = NULL; + DWORD DeviceInterfaceListSize = 0; + + // + // Register for device interface events to open and close the handle to + // the interface. + // + Err = RegisterInterfaceNotifications(&InterfaceNotificationHandle); + + if (Err != ERROR_SUCCESS) + { + goto cleanup; + } + + // + // The interface may already be present on the system. Retrieve a list of + // existing interfaces + // + do + { + Cr = CM_Get_Device_Interface_List_Size(&DeviceInterfaceListSize, + (LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2, + NULL, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + + if (Cr != CR_SUCCESS) + { + break; + } + + if (DeviceInterfaceList != NULL) + { + free(DeviceInterfaceList); + } + + DeviceInterfaceList = (PWSTR)malloc(DeviceInterfaceListSize * sizeof(WCHAR)); + + if (DeviceInterfaceList == NULL) + { + Cr = CR_OUT_OF_MEMORY; + break; + } + + Cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2, + NULL, + DeviceInterfaceList, + DeviceInterfaceListSize, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + } while (Cr == CR_BUFFER_SMALL); + + if (Cr != CR_SUCCESS) + { + Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA); + goto cleanup; + } + + // + // Register for notifications on existing device interfaces + // + for (DeviceInterface = DeviceInterfaceList; + *DeviceInterface != L'\0'; + DeviceInterface += wcslen(DeviceInterface) + 1) + { + RegisterDeviceNotifications(DeviceInterface); + } + +cleanup: + + if (DeviceInterfaceList != NULL) + { + free(DeviceInterfaceList); + } + + return Err; +} + + +/*++ + +Routine Description: + + Clean up device interface context + +Arguments: + + NULL + +Return Value: + + NULL + +--*/ +VOID +CleanupDeviceInterfaceContext( + VOID + ) +{ + PDEVICE_CONTEXT Context = NULL; + BOOL NeedsUnregister = FALSE; + + // + // Unregister from the interface first, so that re-appearance of the + // interface does not cause us to register device events again. + // + if (InterfaceNotificationHandle != NULL) + { + CM_Unregister_Notification(InterfaceNotificationHandle); + InterfaceNotificationHandle = NULL; + } + + // + // Unregister notifications for device handles. + // + while (TRUE) + { + NeedsUnregister = FALSE; + + AcquireSRWLockShared(&DeviceListLock); + + if (IsDeviceListEmpty(&DeviceList)) + { + ReleaseSRWLockShared(&DeviceListLock); + break; + } + + // + // Get next device context + // + Context = CONTAINING_DEVICE_RECORD(DeviceList.Flink); + + // + // The device context can be unregistered either within notification + // callbacks or cleanup routines. Synchronize these operations to only + // unregister once. + // + EnterCriticalSection(&Context->ContextLock); + + if (!Context->Unregistered) + { + Context->Unregistered = TRUE; + NeedsUnregister = TRUE; + } + + LeaveCriticalSection(&Context->ContextLock); + + ReleaseSRWLockShared(&DeviceListLock); + + if (NeedsUnregister) + { + // + // Remove next device from device list + // + AcquireSRWLockExclusive(&DeviceListLock); + RemoveDeviceListEntry(DeviceList.Flink); + ReleaseSRWLockExclusive(&DeviceListLock); + + UnregisterDeviceNotifications(Context); + } + } + + // + // Wait for all other unregistrations for device handle that is not in + // device list. + // + AcquireSRWLockShared(&RunningUnregistrationsLock); + + while (RunningUnregistrations != 0) + { + SleepConditionVariableSRW(&UnregistrationComplete, + &RunningUnregistrationsLock, + INFINITE, + CONDITION_VARIABLE_LOCKMODE_SHARED); + } + + ReleaseSRWLockShared(&RunningUnregistrationsLock); +} + + +/*++ + +Routine Description: + + Handles a device query remove notification. + +Arguments: + + Context - The callback context + +Return Value: + + NULL + +--*/ +VOID +DeviceQueryRemoveAction( + _In_ PDEVICE_CONTEXT Context + ) +{ + if (Context->DeviceHandle != INVALID_HANDLE_VALUE) + { + // + // Close open handles to allow the device to be query removed + // + CloseHandle(Context->DeviceHandle); + + Context->DeviceHandle = INVALID_HANDLE_VALUE; + } +} + + +/*++ + +Routine Description: + + Handles a device query remove failed notification. + +Arguments: + + Context - The callback context + +Return Value: + + NULL + +--*/ +VOID +DeviceQueryRemoveFailedAction( + _In_ PDEVICE_CONTEXT Context + ) +{ + PWSTR DeviceInterfacePath = NULL; + BOOL NeedsUnregister = FALSE; + + // + // Keep a record of device symbolic link since the callback context will + // be freed up during unregistration + // + DeviceInterfacePath = Context->SymbolicLink; + Context->SymbolicLink = NULL; + + // + // The device context can be unregistered either within notification + // callbacks or cleanup routines. Synchronize these operations to only + // unregister once. + // + EnterCriticalSection(&Context->ContextLock); + + if (!Context->Unregistered) + { + Context->Unregistered = TRUE; + NeedsUnregister = TRUE; + } + + LeaveCriticalSection(&Context->ContextLock); + + // + // Remove device from device list if needed + // + if (NeedsUnregister) + { + AcquireSRWLockExclusive(&DeviceListLock); + RemoveDeviceListEntry(&Context->ListEntry); + ReleaseSRWLockExclusive(&DeviceListLock); + + // + // Unregister notifications for the old device handle from a deferred + // routine since CM_Unregister_Notification can not be called from a + // notification callback + // + AcquireSRWLockExclusive(&RunningUnregistrationsLock); + RunningUnregistrations++; + ReleaseSRWLockExclusive(&RunningUnregistrationsLock); + + QueueUserWorkItem(UnregisterDeviceNotificationsWorkerThread, + Context, + WT_EXECUTEDEFAULT); + } + + // + // Re-register for device notifications on a new device handle + // + RegisterDeviceNotifications(DeviceInterfacePath); + + // + // Free memory that the callback context used to point at but was not freed + // during unregistration + // + free(DeviceInterfacePath); +} + +/*++ + +Routine Description: + + Handles a device remove complete notification. + +Arguments: + + Context - The callback context + +Return Value: + + NULL + +--*/ +VOID +DeviceRemoveCompleteAction( + _In_ PDEVICE_CONTEXT Context + ) +{ + BOOL NeedsUnregister = FALSE; + + // + // The device context can be unregistered either within notification + // callbacks or cleanup routines. Synchronize these operations to only + // unregister once. + // + EnterCriticalSection(&Context->ContextLock); + + if (!Context->Unregistered) + { + Context->Unregistered = TRUE; + NeedsUnregister = TRUE; + } + + LeaveCriticalSection(&Context->ContextLock); + + // + // Remove device from device list if needed + // + if (NeedsUnregister) + { + AcquireSRWLockExclusive(&DeviceListLock); + RemoveDeviceListEntry(&Context->ListEntry); + ReleaseSRWLockExclusive(&DeviceListLock); + + // + // Unregister notifications for the old device handle from a deferred + // routine since CM_Unregister_Notification can not be called from a + // notification callback + // + AcquireSRWLockExclusive(&RunningUnregistrationsLock); + RunningUnregistrations++; + ReleaseSRWLockExclusive(&RunningUnregistrationsLock); + + QueueUserWorkItem(UnregisterDeviceNotificationsWorkerThread, + Context, + WT_EXECUTEDEFAULT); + } +} + +/*++ + +Routine Description: + + Handles device notifications. + +Arguments: + + hNotify - The notification that spurred this callback + + hContext - The callback context + + Action - The type of callback + + EventData - Additional information about this callback + + EventDataSize - The size of EventData + +Return Value: + + A Win32 error code. + +--*/ +DWORD +WINAPI +DeviceCallback( + _In_ HCMNOTIFICATION hNotify, + _In_ PVOID hContext, + _In_ CM_NOTIFY_ACTION Action, + _In_ PCM_NOTIFY_EVENT_DATA EventData, + _In_ DWORD EventDataSize + ) +{ + PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext; + + UNREFERENCED_PARAMETER(EventData); + UNREFERENCED_PARAMETER(EventDataSize); + + // + // In case this callback fires before the registration call returns, make + // sure the notification handle is properly set + // + Context->DeviceNotificationHandle = hNotify; + + switch (Action) + { + case CM_NOTIFY_ACTION_DEVICEQUERYREMOVE: + DeviceQueryRemoveAction(Context); + break; + + case CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED: + DeviceQueryRemoveFailedAction(Context); + break; + + case CM_NOTIFY_ACTION_DEVICEREMOVEPENDING: + case CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE: + DeviceRemoveCompleteAction(Context); + break; + + default: + break; + } + + return ERROR_SUCCESS; +} + + +/*++ + +Routine Description: + + Register for device notifications. + +Arguments: + + DeviceInterfacePath - The symbolic link path of the device interface + +Return Value: + + A Win32 error code. + +--*/ +DWORD +RegisterDeviceNotifications( + _In_ PCWSTR DeviceInterfacePath + ) +{ + DWORD Err = ERROR_SUCCESS; + CONFIGRET Cr = CR_SUCCESS; + PDEVICE_CONTEXT Context = NULL; + PDEVICE_LIST_ENTRY Link = NULL; + DWORD BufferSize = 0; + CM_NOTIFY_FILTER NotifyFilter = {0}; + + // + // Check whether the device interface has already been registered for device + // handle notifications since it can be done either in interface arrival + // callback routine or initial device interface setup routine + // + AcquireSRWLockExclusive(&DeviceListLock); + + for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink) + { + Context = CONTAINING_DEVICE_RECORD(Link); + + if (_wcsicmp(DeviceInterfacePath, Context->SymbolicLink) == 0) + { + break; + } + } + + if (Link != &DeviceList) + { + Err = ERROR_SUCCESS; + goto cleanup; + } + + // + // Create a new device context + // + Context = (PDEVICE_CONTEXT)malloc(sizeof(DEVICE_CONTEXT)); + + if (Context == NULL) + { + Err = ERROR_OUTOFMEMORY; + goto cleanup; + } + + // + // Initialize device context + // + ZeroMemory(Context, sizeof(DEVICE_CONTEXT)); + Context->DeviceHandle = INVALID_HANDLE_VALUE; + InitializeCriticalSection(&Context->ContextLock); + + // + // Fill out the context and register device handle notifications + // + BufferSize = (DWORD)wcslen(DeviceInterfacePath) + 1; + Context->SymbolicLink = (PWSTR)malloc(BufferSize * sizeof(WCHAR)); + + if ((Context->SymbolicLink == NULL) || + (FAILED(StringCchCopy(Context->SymbolicLink, + BufferSize, + DeviceInterfacePath)))) + { + Err = ERROR_OUTOFMEMORY; + goto cleanup; + } + + Context->DeviceHandle = CreateFile(Context->SymbolicLink, + GENERIC_WRITE | GENERIC_READ, + FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, // default security + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); + + if (Context->DeviceHandle == INVALID_HANDLE_VALUE) + { + Err = GetLastError(); + goto cleanup; + } + + NotifyFilter.cbSize = sizeof(NotifyFilter); + NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE; + NotifyFilter.u.DeviceHandle.hTarget = Context->DeviceHandle; + + Cr = CM_Register_Notification(&NotifyFilter, + (PVOID)Context, + (PCM_NOTIFY_CALLBACK)DeviceCallback, + &Context->DeviceNotificationHandle); + + if (Cr != CR_SUCCESS) + { + Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA); + goto cleanup; + } + + // + // Add the device entry to device list + // + InsertTailDeviceListEntry(&DeviceList, &Context->ListEntry); + Context = NULL; + +cleanup: + + ReleaseSRWLockExclusive(&DeviceListLock); + + // + // Clean up device context if an error occurred. + // + if (Context != NULL) + { + if (Context->SymbolicLink != NULL) + { + free(Context->SymbolicLink); + } + + if (Context->DeviceHandle != INVALID_HANDLE_VALUE) + { + CloseHandle(Context->DeviceHandle); + } + + free(Context); + } + + return Err; +} + + +VOID +UnregisterDeviceNotifications( + _Inout_ PDEVICE_CONTEXT Context + ) +{ + if (Context->DeviceNotificationHandle != NULL) + { + CM_Unregister_Notification(Context->DeviceNotificationHandle); + } + + if (Context->DeviceHandle != INVALID_HANDLE_VALUE) + { + CloseHandle(Context->DeviceHandle); + } + + if (Context->SymbolicLink != NULL) + { + free(Context->SymbolicLink); + } + + DeleteCriticalSection(&Context->ContextLock); + + free(Context); +} + + +/*++ + +Routine Description: + + This worker thread avoids a deadlock when unregistering device notifications. + Rather than calling CM_Unregister_Notification from the callback, the + callback gives that work to a separate thread to avoid deadlock. + +Arguments: + + lpThreadParameter - The thread data passed to the function + +Return Value: + + Zero + +--*/ +DWORD +WINAPI +UnregisterDeviceNotificationsWorkerThread( + _In_ PVOID lpThreadParameter + ) +{ + PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)lpThreadParameter; + + UnregisterDeviceNotifications(Context); + + // + // Decrease running unregistrations + // + AcquireSRWLockExclusive(&RunningUnregistrationsLock); + RunningUnregistrations--; + ReleaseSRWLockExclusive(&RunningUnregistrationsLock); + + WakeAllConditionVariable(&UnregistrationComplete); + + return 0; +} + + +/*++ + +Routine Description: + + Handles an interface arrival notification. + +Arguments: + + hNotify - The notification that fired the callback + + hContext - The callback context + + Action - The type of notification + + EventData - Additional information about the callback + + EventDataSize - The size of EventData + +Return Value: + + Notification callback should return ERROR_SUCCESS. + +--*/ +DWORD +WINAPI +InterfaceCallback( + _In_ HCMNOTIFICATION hNotify, + _In_ PVOID hContext, + _In_ CM_NOTIFY_ACTION Action, + _In_ PCM_NOTIFY_EVENT_DATA EventData, + _In_ DWORD EventDataSize + ) +{ + PDEVICE_CONTEXT Context = NULL; + PDEVICE_LIST_ENTRY Link = NULL; + BOOL NeedsUnregister = FALSE; + + UNREFERENCED_PARAMETER(hNotify); + UNREFERENCED_PARAMETER(hContext); + UNREFERENCED_PARAMETER(EventDataSize); + + switch (Action) + { + case CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL: + // + // Register for device notifications + // + RegisterDeviceNotifications(EventData->u.DeviceInterface.SymbolicLink); + break; + + case CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL: + // + // The device may still be running in the case where the driver disables + // its interfaces. Find whether it is still on the device list and clean + // it up. + // + AcquireSRWLockShared(&DeviceListLock); + + for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink) + { + Context = CONTAINING_DEVICE_RECORD(Link); + + if (_wcsicmp(EventData->u.DeviceInterface.SymbolicLink, + Context->SymbolicLink) == 0) + { + // + // The device context can be unregistered either within + // notification callbacks or cleanup routines. Synchronize these + // operations to only unregister once. + // + EnterCriticalSection(&Context->ContextLock); + + if (!Context->Unregistered) + { + Context->Unregistered = TRUE; + NeedsUnregister = TRUE; + } + + LeaveCriticalSection(&Context->ContextLock); + + break; + } + } + + ReleaseSRWLockShared(&DeviceListLock); + + if (NeedsUnregister) + { + // + // Remove the device from device list + // + AcquireSRWLockExclusive(&DeviceListLock); + RemoveDeviceListEntry(&Context->ListEntry); + ReleaseSRWLockExclusive(&DeviceListLock); + + UnregisterDeviceNotifications(Context); + } + + // + // Notify service to stop if this is the last device interface + // + AcquireSRWLockShared(&DeviceListLock); + + if (IsDeviceListEmpty(&DeviceList)) + { + SetEvent(SvcStopRequestEvent); + } + + ReleaseSRWLockShared(&DeviceListLock); + break; + + default: + break; + } + + return ERROR_SUCCESS; +} + + +/*++ + +Routine Description: + + Registers the service for interface notifications + +Arguments: + + pInterfaceNotificationHandle - Pointer to receive the HCMNOTIFICATION handle + +Return Value: + + A Win32 error code. + +--*/ +DWORD +RegisterInterfaceNotifications( + _Out_ PHCMNOTIFICATION pInterfaceNotificationHandle + ) +{ + DWORD Err = ERROR_SUCCESS; + CONFIGRET Cr = CR_SUCCESS; + CM_NOTIFY_FILTER NotifyFilter = {0}; + + NotifyFilter.cbSize = sizeof(NotifyFilter); + NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE; + NotifyFilter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_OSRUSBFX2; + + // + // Register for device interface events to open and close the handle to + // the interface. + // + Cr = CM_Register_Notification(&NotifyFilter, + NULL, + (PCM_NOTIFY_CALLBACK)InterfaceCallback, + pInterfaceNotificationHandle); + + if (Cr != CR_SUCCESS) + { + Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA); + goto cleanup; + } + +cleanup: + + return Err; +} diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h new file mode 100644 index 00000000..4d744989 --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h @@ -0,0 +1,155 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +--*/ + +#pragma once + +// +// Device list +// +typedef struct _DEVICE_LIST_ENTRY { + struct _DEVICE_LIST_ENTRY *Flink; + struct _DEVICE_LIST_ENTRY *Blink; +} DEVICE_LIST_ENTRY, *PDEVICE_LIST_ENTRY; + +FORCEINLINE +VOID +InitializeDeviceListHead( + _Out_ PDEVICE_LIST_ENTRY Head + ) +{ + Head->Blink = Head->Flink = Head; +} + +FORCEINLINE +BOOL +IsDeviceListEmpty( + _In_ const PDEVICE_LIST_ENTRY ListHead + ) + +{ + return (ListHead->Flink == ListHead); +} + +FORCEINLINE +VOID +RemoveDeviceListEntry( + _In_ PDEVICE_LIST_ENTRY Entry + ) +{ + PDEVICE_LIST_ENTRY Prev = Entry->Blink; + PDEVICE_LIST_ENTRY Next = Entry->Flink; + + Prev->Flink = Next; + Next->Blink = Prev; +} + +FORCEINLINE +VOID +InsertTailDeviceListEntry( + _Inout_ PDEVICE_LIST_ENTRY Head, + _Inout_ PDEVICE_LIST_ENTRY Entry + ) +{ + PDEVICE_LIST_ENTRY Tail = Head->Blink; + + Tail->Flink = Entry; + Entry->Blink = Tail; + Entry->Flink = Head; + Head->Blink = Entry; +} + +// +// Context for device handle +// +typedef struct _DEVICE_CONTEXT { + PWSTR SymbolicLink; + HANDLE DeviceHandle; + HCMNOTIFICATION DeviceNotificationHandle; + BOOL Unregistered; + CRITICAL_SECTION ContextLock; + DEVICE_LIST_ENTRY ListEntry; +} DEVICE_CONTEXT, *PDEVICE_CONTEXT; + +#define CONTAINING_DEVICE_RECORD(address) ((PDEVICE_CONTEXT)( \ + (PCHAR)(address) - \ + (ULONG_PTR)(&((PDEVICE_CONTEXT)0)->ListEntry))) + +// +// Device interface context +// +DWORD +SetupDeviceInterfaceContext( + VOID + ); + +VOID +CleanupDeviceInterfaceContext( + VOID + ); + +// +// Device notifications related +// +VOID +DeviceQueryRemoveAction( + _In_ PDEVICE_CONTEXT Context + ); + +VOID +DeviceQueryRemoveFailedAction( + _In_ PDEVICE_CONTEXT Context + ); + +VOID +DeviceRemoveCompleteAction( + _In_ PDEVICE_CONTEXT Context + ); + +DWORD +WINAPI +DeviceCallback( + _In_ HCMNOTIFICATION hNotify, + _In_ PVOID hContext, + _In_ CM_NOTIFY_ACTION Action, + _In_ PCM_NOTIFY_EVENT_DATA EventData, + _In_ DWORD EventDataSize + ); + +DWORD +RegisterDeviceNotifications( + _In_ PCWSTR DeviceInterfacePath + ); + +VOID +UnregisterDeviceNotifications( + _Inout_ PDEVICE_CONTEXT Context + ); + +DWORD +WINAPI +InterfaceCallback( + _In_ HCMNOTIFICATION hNotify, + _In_ PVOID hContext, + _In_ CM_NOTIFY_ACTION Action, + _In_ PCM_NOTIFY_EVENT_DATA EventData, + _In_ DWORD EventDataSize + ); + +DWORD +RegisterInterfaceNotifications( + _Out_ PHCMNOTIFICATION pInterfaceNotificationHandle + ); + +DWORD +WINAPI +UnregisterDeviceNotificationsWorkerThread( + _In_ PVOID lpThreadParameter + ); diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp new file mode 100644 index 00000000..ced895cc --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp @@ -0,0 +1,192 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + DeviceControl.cpp + +Abstract: + + Implements the functions to control the OSR USB FX2 device. + +Environment: + + User mode + +--*/ + +#include "stdafx.h" + +// +// Keep track of where the OSRFX2 device's bar graph currently is. +// +INT CurrentBar; +BAR_GRAPH_STATE BarGraphState; + +/*++ + +Routine Description: + + Initialize global variables for OSRFX2 device. + +Arguments: + + VOID + +Return Value: + + VOID + +--*/ +VOID +OsrFx2InitializeDevice( + VOID + ) +{ + CurrentBar = 0; +} + + +/*++ + +Routine Description: + + Turns off all of the bar graph lights on the OSR USB FX2 device. + +Arguments: + + Context - The callback context + +Return Value: + + VOID + +--*/ +DWORD +OsrFx2ClearAllBars( + _In_ PDEVICE_CONTEXT Context + ) +{ + DWORD Err = ERROR_SUCCESS; + ULONG BytesReturned; + + BarGraphState.BarsAsUChar = 0; + + if (!DeviceIoControl(Context->DeviceHandle, + IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY, + &BarGraphState, // Pointer to InBuffer + sizeof(BAR_GRAPH_STATE), // Length of InBuffer + NULL, // Pointer to OutBuffer + 0, // Length of OutBuffer + &BytesReturned, // BytesReturned + 0)) // Pointer to Overlapped structure + { + Err = GetLastError(); + goto cleanup; + } + +cleanup: + + return Err; +} + + +/*++ + +Routine Description: + + Lights the next bar on the OSR USB FX2 device. + +Arguments: + + Context - The callback context + +Return Value: + + VOID + +--*/ +DWORD +OsrFx2LightNextBar( + _In_ PDEVICE_CONTEXT Context + ) +{ + DWORD Err = ERROR_SUCCESS; + ULONG BytesReturned; + + // + // Normalize to 0-7 + // + CurrentBar += 1; + + if (CurrentBar > 7) + { + CurrentBar = 0; + } + + BarGraphState.BarsAsUChar = 1 << (UCHAR)CurrentBar; + + if (!DeviceIoControl(Context->DeviceHandle, + IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY, + &BarGraphState, // Pointer to InBuffer + sizeof(BAR_GRAPH_STATE), // Length of InBuffer + NULL, // Pointer to OutBuffer + 0, // Length of OutBuffer + &BytesReturned, // BytesReturned + 0)) // Pointer to Overlapped structure + { + Err = GetLastError(); + goto cleanup; + } + +cleanup: + + return Err; +} + +/*++ + +Routine Description: + + Lights the next bar on the OSRFX2 device. + +Arguments: + + Context - The device context + +Return Value: + + A Win32 error code. + +--*/ +DWORD +OsrFx2ControlDevice( + _In_ PDEVICE_CONTEXT Context + ) +{ + DWORD Err = ERROR_SUCCESS; + + Err = OsrFx2ClearAllBars(Context); + + if (Err != ERROR_SUCCESS) + { + goto cleanup; + } + + Err = OsrFx2LightNextBar(Context); + + if (Err != ERROR_SUCCESS) + { + goto cleanup; + } + +cleanup: + + return Err; +} diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h new file mode 100644 index 00000000..235e64ba --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h @@ -0,0 +1,144 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +--*/ + +#pragma once +#pragma warning(disable : 4201) // disable nameless struct/union warning + +// +// {573E8C73-0CB4-4471-A1BF-FAB26C31D384} +// +DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2, + 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84); + +// +// Define the structures that will be used by the IOCTL interface to the driver +// + +// BAR_GRAPH_STATE is a bit field structure with each bit corresponding to one +// of the bar graph on the OSRFX2 Development Board +// +typedef struct _BAR_GRAPH_STATE { + + union { + + struct { + // + // Individual bars starting from the top of the stack of bars + // + // NOTE: There are actually 10 bars, but the very top two do not + // light and are not counted here + // + UCHAR Bar1 : 1; + UCHAR Bar2 : 1; + UCHAR Bar3 : 1; + UCHAR Bar4 : 1; + UCHAR Bar5 : 1; + UCHAR Bar6 : 1; + UCHAR Bar7 : 1; + UCHAR Bar8 : 1; + }; + + // + // The state of all the bar graph as a single + // UCHAR + // + UCHAR BarsAsUChar; + }; + +} BAR_GRAPH_STATE, *PBAR_GRAPH_STATE; + +// +// SWITCH_STATE is a bit field structure with each bit corresponding to one of +// the switches on the OSRFX2 Development Board +// +typedef struct _SWITCH_STATE { + + union { + struct { + // + // Individual switches starting from the left of the set of switches + // + UCHAR Switch1 : 1; + UCHAR Switch2 : 1; + UCHAR Switch3 : 1; + UCHAR Switch4 : 1; + UCHAR Switch5 : 1; + UCHAR Switch6 : 1; + UCHAR Switch7 : 1; + UCHAR Switch8 : 1; + }; + + // + // The state of all the switches as a single + // UCHAR + // + UCHAR SwitchesAsUChar; + }; + +} SWITCH_STATE, *PSWITCH_STATE; + +DWORD +OsrFx2ControlDevice( + _In_ PDEVICE_CONTEXT Context + ); + +VOID +OsrFx2InitializeDevice( + VOID + ); + +#define IOCTL_INDEX 0x800 +#define FILE_DEVICE_OSRUSBFX2 65500U + +#define IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +#define IOCTL_OSRUSBFX2_RESET_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 1, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +#define IOCTL_OSRUSBFX2_REENUMERATE_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 3, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +#define IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 4, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 5, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +#define IOCTL_OSRUSBFX2_READ_SWITCHES CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 6, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +#define IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 7, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +#define IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 8, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +#define IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE CTL_CODE(FILE_DEVICE_OSRUSBFX2,\ + IOCTL_INDEX + 9, \ + METHOD_OUT_DIRECT, \ + FILE_READ_ACCESS) diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp deleted file mode 100644 index a02ac24a..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp +++ /dev/null @@ -1,1217 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - Main.cpp - -Abstract: - - Implements the functions to control the OSR USB FX2 device. - -Environment: - - User mode - ---*/ - -#include "Main.h" -#include "Utils.h" - -// -// Keep track of where the OSRFX2 device's bar graph currently is. -// -INT CurrentBar; -BAR_GRAPH_STATE BarGraphState; - -/*++ - -Routine Description: - - Sets the variables in this service to their default values. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -SetVariables() -{ - CurrentBar = 0; -} - - -/*++ - -Routine Description: - - Retrieves the device path of a given interface. - -Arguments: - - InterfaceGuid - The GUID of the interface to search for - - DevicePath - The resulting device path - - DevicePathLength - The length of DevicePath - -Return Value: - - TRUE if the function succeeded and FALSE otherwise. Errors - are logged in the Application event log. - ---*/ -_Success_(return) -BOOL -GetDevicePath( - _In_ LPGUID InterfaceGuid, - _Out_writes_z_(DevicePathLength) PWCHAR DevicePath, - _In_ size_t DevicePathLength - ) -{ - HRESULT hr = E_FAIL; - CONFIGRET cr = CR_SUCCESS; - PWSTR DeviceInterfaceList = NULL; - ULONG DeviceInterfaceListLength = 0; - PWSTR NextInterface; - - // - // Determine if there are any interfaces that match the OSRFX2 device. - // - cr = CM_Get_Device_Interface_List_Size(&DeviceInterfaceListLength, - InterfaceGuid, - NULL, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - - if (cr != CR_SUCCESS) - { - WriteToErrorLog(L"CM_Get_DeviceInterface_List_Size", - CM_MapCrToWin32Err(cr, ERROR_FILE_NOT_FOUND)); - goto cleanup; - } - - if (DeviceInterfaceListLength < 1) - { - WriteToErrorLog(L"CM_Get_DeviceInterface_List_Size", - CM_MapCrToWin32Err(cr, ERROR_EMPTY)); - goto cleanup; - } - - DeviceInterfaceList = (PWSTR)malloc(DeviceInterfaceListLength * sizeof(WCHAR)); - - if (DeviceInterfaceList == NULL) - { - WriteToEventLog(L"Failed to allocate memory for the device interface list", - TRACE_LEVEL_ERROR); - goto cleanup; - } - - cr = CM_Get_Device_Interface_List(InterfaceGuid, - NULL, - DeviceInterfaceList, - DeviceInterfaceListLength, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - - if (cr != CR_SUCCESS) - { - WriteToErrorLog(L"CM_Get_Device_Interface_List", - CM_MapCrToWin32Err(cr, ERROR_FILE_NOT_FOUND)); - goto cleanup; - } - - if (*DeviceInterfaceList == UNICODE_NULL) - { - WriteToEventLog(L"CM_Get_Device_Interface_List returned an empty list", - TRACE_LEVEL_ERROR); - } - - // - // This sample only expects one interface for the OSRFX2 device. For other - // devices, though, it maybe necessary to sift through the interfaces - // from CM_Get_Device_Interface_List in order to find the correct device. - // - NextInterface = DeviceInterfaceList + wcslen(DeviceInterfaceList) + 1; - - if (*NextInterface != UNICODE_NULL) - { - WriteToEventLog(L"More than one device interface instance found. " - "Selecting first matching device.", - TRACE_LEVEL_WARNING); - } - - hr = StringCchCopy(DevicePath, DevicePathLength, DeviceInterfaceList); - - if (FAILED(hr)) - { - WriteToErrorLog(L"StringCchCopy", HRESULT_CODE(hr)); - goto cleanup; - } - -cleanup: - - if (DeviceInterfaceList != NULL) - { - free(DeviceInterfaceList); - } - - return (cr == CR_SUCCESS); -} - - -/*++ - -Routine Description: - - Opens up the OSR USB FX2 device handle. - -Arguments: - - Synchronous - Whether or not this device should be opened for syncrhonous - access - -Return Value: - - The handle to the OSR USB FX2 device. - ---*/ -_Check_return_ -_Ret_notnull_ -_Success_(return != INVALID_HANDLE_VALUE) -HANDLE -OpenDevice( - _In_ BOOL Synchronous - ) -{ - HANDLE DeviceHandle = INVALID_HANDLE_VALUE; - WCHAR DeviceName[MAX_DEVPATH_LENGTH]; - - if (!GetDevicePath((LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2, - DeviceName, - sizeof(DeviceName) / sizeof(DeviceName[0]))) - { - goto cleanup; - } - - // - // Open a handle to the interface. - // - if (Synchronous) - { - DeviceHandle = CreateFile(DeviceName, - GENERIC_WRITE | GENERIC_READ, - FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, // default security - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - } - else - { - DeviceHandle = CreateFile(DeviceName, - GENERIC_WRITE | GENERIC_READ, - FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, // default security - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - NULL); - } - - if (DeviceHandle == INVALID_HANDLE_VALUE) - { - WriteToErrorLog(L"CreateFile", GetLastError()); - } - else - { - WriteToEventLog(L"Opened Device Successfully", TRACE_LEVEL_INFORMATION); - } - -cleanup: - - return DeviceHandle; -} - - -/*++ - -Routine Description: - - Handles an interface arrival notification. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -InterfaceArrivalAction( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - // - // Now that the interface has arrived, open a handle to it, and then - // register that handle for device events. - // - EnterCriticalSection(&Context->Lock); - - if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - // - // The handle was already retrieved. - // - Err = ERROR_SUCCESS; - goto cleanup; - } - - Context->DeviceInterfaceHandle = OpenDevice(FALSE); - - if (Context->DeviceInterfaceHandle == INVALID_HANDLE_VALUE) - { - Err = GetLastError(); - WriteToErrorLog(L"Could not open device interface", Err); - goto cleanup; - } - - Err = RegisterDeviceNotifications(Context); - - if (Err != ERROR_SUCCESS) - { - WriteToErrorLog(L"Could not register device notifications", Err); - goto cleanup; - } - -cleanup: - - LeaveCriticalSection(&Context->Lock); - - return Err; -} - - -/*++ - -Routine Description: - - Handles an interface arrival notification. - -Arguments: - - hNotify - The notification that fired the callback - - hContext - The callback context - - Action - The type of notification - - EventData - Additional information about the callback - - EventDataSize - The size of EventData - -Return Value: - - A Win32 error code. - ---*/ -DWORD -InterfaceCallback( - _In_ HCMNOTIFICATION hNotify, - _In_ PVOID hContext, - _In_ CM_NOTIFY_ACTION Action, - _In_ PCM_NOTIFY_EVENT_DATA EventData, - _In_ DWORD EventDataSize - ) -{ - DWORD Err = ERROR_SUCCESS; - PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext; - - // - // Validate Context. - // - if (Context == NULL) - { - goto cleanup; - } - - if (Action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL) - { - Err = InterfaceArrivalAction(Context); - } - -cleanup: - - return Err; -} - - -/*++ - -Routine Description: - - Registers the service for notifications using the notification handle in - Context. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -RegisterInterfaceNotifications( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - CONFIGRET cr; - CM_NOTIFY_FILTER NotifyFilter = {0}; - - if (Context == NULL) - { - goto cleanup; - } - - ZeroMemory(&NotifyFilter, sizeof(NotifyFilter)); - NotifyFilter.cbSize = sizeof(NotifyFilter); - NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE; - NotifyFilter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_OSRUSBFX2; - - cr = CM_Register_Notification(&NotifyFilter, - (PVOID)Context, - (PCM_NOTIFY_CALLBACK)InterfaceCallback, - &Context->InterfaceNotificationHandle); - - if (cr != CR_SUCCESS) - { - Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA); - WriteToErrorLog(L"CM_Register_Notification", Err); - goto cleanup; - } - -cleanup: - - return Err; -} - - -/*++ - -Routine Description: - - Unregister for interface notifications. Note, this routine deadlocks - when called from an interface callback. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -UnregisterInterfaceNotifications( - _In_ PDEVICE_CONTEXT Context - ) -{ - CONFIGRET cr; - - if (Context->InterfaceNotificationHandle != NULL) - { - cr = CM_Unregister_Notification(Context->InterfaceNotificationHandle); - - Context->InterfaceNotificationHandle = NULL; - } - - return CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA); -} - - -/*++ - -Routine Description: - - Callback for when a device is being query removed. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -DeviceQueryRemoveAction( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - EnterCriticalSection(&Context->Lock); - - if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - // - // Close open handles to allow the device to exit - // - CloseHandle(Context->DeviceInterfaceHandle); - - Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE; - } - - LeaveCriticalSection(&Context->Lock); - - return Err; -} - - -/*++ - -Routine Description: - - This callback avoids a deadlock when unregistering device notifications. - Rather than calling CM_Unregister_Notification from the callback, the - callback gives that work to a separate thread to avoid deadlock. - -Arguments: - - Instance - The thread's callback instance - - hContext - The callback context - - pWork - The thread handle - -Return Value: - - VOID - ---*/ -VOID -CALLBACK -UnregisterWorkerThreadCallback( - _Inout_ PTP_CALLBACK_INSTANCE Instance, - _Inout_opt_ PVOID hContext, - _Inout_ PTP_WORK pWork - ) -{ - PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext; - - EnterCriticalSection(&Context->Lock); - - UnregisterDeviceNotifications(Context); - - // - // Close the device handle. - // - if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - CloseHandle(Context->DeviceInterfaceHandle); - - Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE; - } - - LeaveCriticalSection(&Context->Lock); -} - - -/*++ - -Routine Description: - - Handles a device query remove failed notification. - -Arguments: - - hNotify - The notification that spurred this callback - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -DeviceQueryRemoveFailedAction( - _In_ HCMNOTIFICATION hNotify, - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - EnterCriticalSection(&Context->Lock); - - // - // In case this callback fires before the registration call returns, make - // sure the notification handle is properly set. - // - Context->InterfaceNotificationHandle = hNotify; - - // - // Unregister the device callback, and then close the handle - // - if (!Context->Unregister) - { - Context->Unregister = TRUE; - SubmitThreadpoolWork(Context->Work); - } - - LeaveCriticalSection(&Context->Lock); - - // - // Wait for the callback and then re-register the device - // - WaitForThreadpoolWorkCallbacks(Context->Work, FALSE); - - EnterCriticalSection(&Context->Lock); - - if (Context->DeviceInterfaceHandle == INVALID_HANDLE_VALUE) - { - Context->DeviceInterfaceHandle = OpenDevice(FALSE); - } - - if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - RegisterDeviceNotifications(Context); - } - - LeaveCriticalSection(&Context->Lock); - - return Err; -} - - -/*++ - -Routine Description: - - Handles a device remove pending notification. - -Arguments: - - hNotify - The notification that spurred this callback - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -DeviceRemovePendingAction( - _In_ HCMNOTIFICATION hNotify, - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - EnterCriticalSection(&Context->Lock); - - // - // In case this callback fires before the registration call returns, make - // sure the notification handle is properly set. - // - Context->InterfaceNotificationHandle = hNotify; - - // - // Unregister the device callback, and then close the handle - // - if (!Context->Unregister) - { - Context->Unregister = TRUE; - SubmitThreadpoolWork(Context->Work); - } - - LeaveCriticalSection(&Context->Lock); - - return Err; -} - - -/*++ - -Routine Description: - - Handles a device remove complete notification. - -Arguments: - - hNotify - The notification that spurred this callback - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -DeviceRemoveCompleteAction( - _In_ HCMNOTIFICATION hNotify, - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - EnterCriticalSection(&Context->Lock); - - // - // In case this callback fires before the registration call returns, make - // sure the notification handle is properly set. - // - Context->InterfaceNotificationHandle = hNotify; - - // - // Unregister the device callback, and then close the handle - // - if (!Context->Unregister) - { - Context->Unregister = TRUE; - SubmitThreadpoolWork(Context->Work); - } - - LeaveCriticalSection(&Context->Lock); - - return Err; -} - - -/*++ - -Routine Description: - - Handles device notifications. - -Arguments: - - hNotify - The notification that spurred this callback - - hContext - The callback context - - Action - The type of callback - - EventData - Additional information about this callback - - EventDataSize - The size of EventData - -Return Value: - - A Win32 error code. - ---*/ -DWORD -DeviceCallback( - _In_ HCMNOTIFICATION hNotify, - _In_ PVOID hContext, - _In_ CM_NOTIFY_ACTION Action, - _In_ PCM_NOTIFY_EVENT_DATA EventData, - _In_ DWORD EventDataSize - ) -{ - DWORD Err = ERROR_SUCCESS; - PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext; - - // - // Validate Context. - // - if (Context == NULL) - { - goto cleanup; - } - - switch (Action) - { - case CM_NOTIFY_ACTION_DEVICEQUERYREMOVE: - DeviceQueryRemoveAction(Context); - break; - - case CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED: - DeviceQueryRemoveFailedAction(hNotify, Context); - break; - - case CM_NOTIFY_ACTION_DEVICEREMOVEPENDING: - DeviceRemovePendingAction(hNotify, Context); - break; - - case CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE: - DeviceRemoveCompleteAction(hNotify, Context); - break; - } - -cleanup: - - return Err; -} - - -/*++ - -Routine Description: - - Register for device notifications. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -RegisterDeviceNotifications( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - CONFIGRET cr; - CM_NOTIFY_FILTER NotifyFilter = {0}; - - NotifyFilter.cbSize = sizeof(NotifyFilter); - NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE; - NotifyFilter.u.DeviceHandle.hTarget = Context->DeviceInterfaceHandle; - - cr = CM_Register_Notification(&NotifyFilter, - (PVOID)Context, - (PCM_NOTIFY_CALLBACK)DeviceCallback, - &Context->DeviceNotificationHandle); - - if (cr != CR_SUCCESS) - { - Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA); - WriteToEventLog(L"Could not register for notifications", TRACE_LEVEL_WARNING); - goto cleanup; - } - - Context->Unregister = FALSE; - -cleanup: - - return Err; -} - - -/*++ - -Routine Description: - - Unregister for device notifications. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -UnregisterDeviceNotifications( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - CONFIGRET cr; - - if (Context->DeviceNotificationHandle != NULL) - { - cr = CM_Unregister_Notification(Context->DeviceNotificationHandle); - - if (cr != CR_SUCCESS) - { - Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA); - WriteToEventLog(L"Could not unregister notifications", TRACE_LEVEL_WARNING); - } - - Context->DeviceNotificationHandle = NULL; - } - - return Err; -} - - -/*++ - -Routine Description: - - Initialize the given PDEVICE_CONTEXT. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -InitializeContext( - _Out_ PDEVICE_CONTEXT *Context - ) -{ - DWORD Err = ERROR_SUCCESS; - BOOL LockInitialized = FALSE; - BOOL LockEntered = FALSE; - BOOL InterfaceNotificationsInitialized = FALSE; - BOOL DeviceNotificationsInitialized = FALSE; - PDEVICE_CONTEXT DeviceContext; - - DeviceContext = (PDEVICE_CONTEXT)malloc(sizeof(DEVICE_CONTEXT)); - - if (DeviceContext == NULL) - { - Err = ERROR_OUTOFMEMORY; - goto cleanup; - } - - DeviceContext->DeviceInterfaceHandle = INVALID_HANDLE_VALUE; - DeviceContext->LockEnabled = FALSE; - DeviceContext->InterfaceNotificationsEnabled = FALSE; - DeviceContext->DeviceNotificationsEnabled = FALSE; - - InitializeCriticalSection(&DeviceContext->Lock); - DeviceContext->LockEnabled = TRUE; - - DeviceContext->Work = CreateThreadpoolWork(UnregisterWorkerThreadCallback, (PVOID)DeviceContext, NULL); - - if (DeviceContext->Work == NULL) - { - Err = GetLastError(); - WriteToErrorLog(L"Could not create worker thread callback", Err); - goto cleanup; - } - - DeviceContext->DeviceNotificationHandle = NULL; - DeviceContext->InterfaceNotificationHandle = NULL; - - // - // Register for device interface events to open and close the handle to - // the interface. - // - Err = RegisterInterfaceNotifications(DeviceContext); - - if (Err != ERROR_SUCCESS) - { - WriteToErrorLog(L"Could not register notifications", Err); - goto cleanup; - } - - DeviceContext->InterfaceNotificationsEnabled = TRUE; - - EnterCriticalSection(&DeviceContext->Lock); - LockEntered = TRUE; - - // - // The interface may already have arrived while registering for - // notifications. The lock could be moved earlier, but for sample - // purposes this is the proper way to initialize notifications. - // - if (DeviceContext->DeviceInterfaceHandle == INVALID_HANDLE_VALUE) - { - DeviceContext->DeviceInterfaceHandle = OpenDevice(FALSE); - } - - if (DeviceContext->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - Err = RegisterDeviceNotifications(DeviceContext); - - if (Err != ERROR_SUCCESS) - { - WriteToErrorLog(L"Could not register device notifications", Err); - goto cleanup; - } - - DeviceContext->DeviceNotificationsEnabled = TRUE; - } - - // - // If OpenDevice ends up returning INVALID_HANDLE_VALUE, that's fine - // since a notification for the interface will arrive later. - // - -cleanup: - - if (LockEntered) - { - LeaveCriticalSection(&DeviceContext->Lock); - } - - *Context = DeviceContext; - DeviceContext = NULL; - - if (DeviceContext != NULL) - { - CloseContext(DeviceContext); - } - - return Err; -} - - -/*++ - -Routine Description: - - Clean up the given PDEVICE_CONTEXT. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -CloseContext( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - BOOL Unregister = FALSE; - - if (Context == NULL) - { - // - // Nothing to remove. - // - goto cleanup; - } - - EnterCriticalSection(&Context->Lock); - - if (!Context->Unregister) - { - // - // Unregister from the callback here. - // - Unregister = TRUE; - Context->Unregister = TRUE; - } - - LeaveCriticalSection(&Context->Lock); - - // - // Unregister from the interface first, so that re-appearance of the interface - // doesn't cause us to register device events again. - // - if (Context->InterfaceNotificationsEnabled) - { - Err = UnregisterInterfaceNotifications(Context); - - if (Err != ERROR_SUCCESS) - { - WriteToErrorLog(L"Could not unregister interface notifications", Err); - } - } - - if (Unregister) - { - if (Context->DeviceNotificationsEnabled) - { - Err = UnregisterDeviceNotifications(Context); - - if (Err != ERROR_SUCCESS) - { - WriteToErrorLog(L"Could not unregister device notifications", Err); - } - } - } - else - { - WaitForThreadpoolWorkCallbacks(Context->Work, FALSE); - } - - // - // No need to lock here, UnregisterDeviceNotifications will wait for all - // outstanding callbacks before returning. - // - if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - CloseHandle(Context->DeviceInterfaceHandle); - - Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE; - } - - if (Context->Work != NULL) - { - CloseThreadpoolWork(Context->Work); - } - - DeleteCriticalSection(&Context->Lock); - - free(Context); - -cleanup: - - return Err; -} - -/*++ - -Routine Description: - - Turns off all of the bar graph lights on the OSR USB FX2 device. - -Arguments: - - Context - The callback context - -Return Value: - - VOID - ---*/ -DWORD -ClearAllBars( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - ULONG BytesReturned; - - BarGraphState.BarsAsUChar = 0; - - if (!DeviceIoControl(Context->DeviceInterfaceHandle, - IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY, - &BarGraphState, // Pointer to InBuffer - sizeof(BAR_GRAPH_STATE), // Length of InBuffer - NULL, // Pointer to OutBuffer - 0, // Length of OutBuffer - &BytesReturned, // BytesReturned - 0)) // Pointer to Overlapped structure - { - Err = GetLastError(); - WriteToErrorLog(L"DeviceIOControl", Err); - goto cleanup; - } - -cleanup: - - return Err; -} - - -/*++ - -Routine Description: - - Lights the next bar on the OSR USB FX2 device. - -Arguments: - - Context - The callback context - -Return Value: - - VOID - ---*/ -DWORD -LightNextBar( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - ULONG BytesReturned; - - // - // Normalize to 0-7 - // - CurrentBar += 1; - - if (CurrentBar > 7) - { - CurrentBar = 0; - } - - BarGraphState.BarsAsUChar = 1 << (UCHAR)CurrentBar; - - if (!DeviceIoControl(Context->DeviceInterfaceHandle, - IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY, - &BarGraphState, // Pointer to InBuffer - sizeof(BAR_GRAPH_STATE), // Length of InBuffer - NULL, // Pointer to OutBuffer - 0, // Length of OutBuffer - &BytesReturned, // BytesReturned - 0)) // Pointer to Overlapped structure - { - Err = GetLastError(); - WriteToErrorLog(L"DeviceIOControl", Err); - goto cleanup; - } - -cleanup: - - return Err; -} - -/*++ - -Routine Description: - - Lights the next bar on the OSRFX2 device. - -Arguments: - - Context - The device context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -ControlDevice( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - EnterCriticalSection(&Context->Lock); - - Err = ClearAllBars(Context); - - if (Err != ERROR_SUCCESS) - { - goto cleanup; - } - - Err = LightNextBar(Context); - - if (Err != ERROR_SUCCESS) - { - goto cleanup; - } - -cleanup: - - LeaveCriticalSection(&Context->Lock); - - return Err; -}
\ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h deleted file mode 100644 index 3b8be711..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h +++ /dev/null @@ -1,328 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - Main.h - -Abstract: - - Implements the functions to control the OSR USB FX2 device. - -Environment: - - User mode - ---*/ - -#pragma once - -#include <Windows.h> -#include <devioctl.h> -#include <cfgmgr32.h> -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include <strsafe.h> -#include <driverspecs.h> -#include <basetyps.h> - -#include <initguid.h> - -// {573E8C73-0CB4-4471-A1BF-FAB26C31D384} -DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2, - 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84); - -// -// Most device interface paths will fit into a buffer of this size. -// However, some could be longer, and a larger buffer or dynamically -// allocated buffer may be needed for robust code. -// -#define MAX_DEVPATH_LENGTH 1024 - -#pragma warning(push) -#pragma warning(disable:4201) // nameless struct/union -#pragma warning(disable:4214) // bit field types other than int - -typedef struct _DEVICE_CONTEXT { - HANDLE DeviceInterfaceHandle; - CRITICAL_SECTION Lock; - BOOL LockEnabled; - PTP_WORK Work; - BOOL Unregister; - HCMNOTIFICATION InterfaceNotificationHandle; - BOOL InterfaceNotificationsEnabled; - HCMNOTIFICATION DeviceNotificationHandle; - BOOL DeviceNotificationsEnabled; -} DEVICE_CONTEXT, *PDEVICE_CONTEXT; - -// -// Define the structures that will be used by the IOCTL -// interface to the driver -// - -// -// BAR_GRAPH_STATE -// -// BAR_GRAPH_STATE is a bit field structure with each -// bit corresponding to one of the bar graph on the -// OSRFX2 Development Board -// -#include <pshpack1.h> -typedef struct _BAR_GRAPH_STATE { - - union { - - struct { - // - // Individual bars starting from the - // top of the stack of bars - // - // NOTE: There are actually 10 bars, - // but the very top two do not light - // and are not counted here - // - UCHAR Bar1 : 1; - UCHAR Bar2 : 1; - UCHAR Bar3 : 1; - UCHAR Bar4 : 1; - UCHAR Bar5 : 1; - UCHAR Bar6 : 1; - UCHAR Bar7 : 1; - UCHAR Bar8 : 1; - }; - - // - // The state of all the bar graph as a single - // UCHAR - // - UCHAR BarsAsUChar; - - }; - -}BAR_GRAPH_STATE, *PBAR_GRAPH_STATE; - -// -// SWITCH_STATE -// -// SWITCH_STATE is a bit field structure with each -// bit corresponding to one of the switches on the -// OSRFX2 Development Board -// -typedef struct _SWITCH_STATE { - - union { - struct { - // - // Individual switches starting from the - // left of the set of switches - // - UCHAR Switch1 : 1; - UCHAR Switch2 : 1; - UCHAR Switch3 : 1; - UCHAR Switch4 : 1; - UCHAR Switch5 : 1; - UCHAR Switch6 : 1; - UCHAR Switch7 : 1; - UCHAR Switch8 : 1; - }; - - // - // The state of all the switches as a single - // UCHAR - // - UCHAR SwitchesAsUChar; - - }; - - -}SWITCH_STATE, *PSWITCH_STATE; - -#include <poppack.h> - -#pragma warning(pop) - -#define IOCTL_INDEX 0x800 -#define FILE_DEVICE_OSRUSBFX2 65500U - -#define IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX, \ - METHOD_BUFFERED, \ - FILE_READ_ACCESS) - -#define IOCTL_OSRUSBFX2_RESET_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 1, \ - METHOD_BUFFERED, \ - FILE_WRITE_ACCESS) - -#define IOCTL_OSRUSBFX2_REENUMERATE_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 3, \ - METHOD_BUFFERED, \ - FILE_WRITE_ACCESS) - -#define IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 4, \ - METHOD_BUFFERED, \ - FILE_READ_ACCESS) - - -#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 5, \ - METHOD_BUFFERED, \ - FILE_WRITE_ACCESS) - - -#define IOCTL_OSRUSBFX2_READ_SWITCHES CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 6, \ - METHOD_BUFFERED, \ - FILE_READ_ACCESS) - - -#define IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 7, \ - METHOD_BUFFERED, \ - FILE_READ_ACCESS) - - -#define IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 8, \ - METHOD_BUFFERED, \ - FILE_WRITE_ACCESS) - -#define IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE CTL_CODE(FILE_DEVICE_OSRUSBFX2,\ - IOCTL_INDEX + 9, \ - METHOD_OUT_DIRECT, \ - FILE_READ_ACCESS) - -/*++ - -Routine Description: - -Lights the next bar on the OSRFX2 device. - -Arguments: - -Context - The device context - -Return Value: - -A Win32 error code. - ---*/ -DWORD -ControlDevice(PDEVICE_CONTEXT Context); - - -/*++ - -Routine Description: - - Sets the variables in this service to their default values. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID SetVariables(VOID); - - -/*++ - -Routine Description: - - Opens up the OSR USB FX2 device handle. - -Arguments: - - Synchronous - Whether or not this device should be - opened for synchronous access - -Return Value: - - The handle to the OSR USB FX2 device. - ---*/ -HANDLE OpenDevice(_In_ BOOL Synchronous); - - -/*++ - -Routine Description: - -Register for device notifications. - -Arguments: - -Context - The callback context - -Return Value: - -A Win32 error code. - ---*/ -DWORD RegisterDeviceNotifications(PDEVICE_CONTEXT Context); - - -/*++ - -Routine Description: - -Unregister for device notifications. - -Arguments: - -Context - The callback context - -Return Value: - -A Win32 error code. - ---*/ -DWORD UnregisterDeviceNotifications(PDEVICE_CONTEXT Context); - - -/*++ - -Routine Description: - -Initialize the given PDEVICE_CONTEXT. - -Arguments: - -Context - The callback context - -Return Value: - -A Win32 error code. - ---*/ -DWORD InitializeContext(PDEVICE_CONTEXT* Context); - - -/*++ - -Routine Description: - -Clean up the given PDEVICE_CONTEXT. - -Arguments: - -Context - The callback context - -Return Value: - -A Win32 error code. - ---*/ -DWORD CloseContext(PDEVICE_CONTEXT Context);
\ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp deleted file mode 100644 index fd3d497f..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - SampleService.cpp - -Abstract: - - Provides a sample service class that derives from the service base class - - CServiceBase. The sample service logs the service start and stop - information to the Application event log, and shows how to run the main - function of the service in a thread pool worker thread. - -Environment: - - User mode - ---*/ - -#pragma region Includes -#include "SampleService.h" -#include "ThreadPool.h" -#pragma endregion - -/*++ - -Routine Description: - - The constructor of CSampleService. It initializes a new instance - of the CSampleService class. The optional parameters (CanStop, - CanShutdown and CanPauseContinue) allow you to specify whether the - service can be stopped, paused and continued, or be notified when system - shutdown occurs. Inherits properties from the class CServiceBase. - -Arguments: - - ServiceName - The name of the service - - CanStop - The service can be stopped - - CanShutdown - The service is notified when system shutdown occurs - - CanPauseContinue - The service can be paused and continued - -Return Value: - - VOID - ---*/ -CSampleService::CSampleService( - PWSTR ServiceName, - BOOL CanStop, - BOOL CanShutdown, - BOOL CanPauseContinue - ) -: CServiceBase(ServiceName, CanStop, CanShutdown, CanPauseContinue) -{ - m_fStopping = FALSE; - - // - // Create a manual-reset event that is not signaled at first to indicate - // the stopped signal of the service. - // - m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - if (m_hStoppedEvent == NULL) - { - throw GetLastError(); - } -} - - -/*++ - -Routine Description: - - The virtual destructor of CSampleService. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -CSampleService::~CSampleService() -{ - if (m_hStoppedEvent) - { - CloseHandle(m_hStoppedEvent); - m_hStoppedEvent = NULL; - } -} - - -/*++ - -Routine Description: - - This function is executed when a Start command is sent to the - service by the SCM or when the operating system starts (for a service - that starts automatically). It specifies actions to take when the - service starts. In this code sample, OnStart logs a service-start - message to the Application log, and queues the main service function for - execution in a thread pool worker thread. - - NOTE: A service application is designed to be long running. Therefore, - it usually polls or monitors something in the system. The monitoring is - set up in the OnStart method. However, OnStart does not actually do the - monitoring. The OnStart method must return to the operating system after - the service's operation has begun. It must not loop forever or block. To - set up a simple monitoring mechanism, one general solution is to create - a timer in OnStart. The timer would then raise events in your code - periodically, at which time your service could do its monitoring. The - other solution is to spawn a new thread to perform the main service - functions, which is demonstrated in this code sample. - -Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - -Return Value: - - VOID - ---*/ -VOID -CSampleService::OnStart( - DWORD Argc, - PWSTR *Argv - ) -{ - __debugbreak(); - - // - // Log a service start message to the Application log. - // - WriteToEventLog(L"SampleService in OnStart", - EVENTLOG_INFORMATION_TYPE); - - // - // Set up any variables the service needs. - // - SetVariables(); - - // - // Set up the context, and register for notifications. - // - InitializeContext(&m_Context); - - // - // Queue the main service function for execution in a worker thread. - // - CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this); -} - - -/*++ - -Routine Description: - - This method performs the main function of the service. It runs - on a thread pool worker thread. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CSampleService::ServiceWorkerThread() -{ - // - // Periodically check if the service is stopping. - // - while (!m_fStopping) - { - // - // Perform main service function here... - // - - ControlDevice(m_Context); - - ::Sleep(2000); // Simulate some lengthy operations. - } - - // - // Signal the stopped event. - // - SetEvent(m_hStoppedEvent); -} - - -/*++ - -Routine Description: - - This function is executed when a Stop command is sent to the service by SCM. - It specifies actions to take when a service stops running. In this code - sample, OnStop logs a service-stop message to the Application log, and - waits for the finish of the main service function. - - Be sure to periodically call ReportServiceStatus() with - SERVICE_STOP_PENDING if the procedure is going to take a long time. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CSampleService::OnStop() -{ - // - // Log a service stop message to the Application log. - // - WriteToEventLog(L"SampleService in OnStop", - EVENTLOG_INFORMATION_TYPE); - - // - // Indicate that the service is stopping and wait for the finish of the - // main service function (ServiceWorkerThread). - // - m_fStopping = TRUE; - - if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0) - { - throw GetLastError(); - } - - // - // Clean up the context after the worker thread has finished. - // - CloseContext(m_Context); -}
\ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h deleted file mode 100644 index 73be42e9..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h +++ /dev/null @@ -1,187 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - SampleService.h - -Abstract: - - Provides a sample service class that derives from the service base class - - CServiceBase. The sample service logs the service start and stop - information to the Application event log, and shows how to run the main - function of the service in a thread pool worker thread. - -Environment: - - User mode - ---*/ - -#pragma once - -#include "ServiceBase.h" -#include "Main.h" - -class CSampleService : public CServiceBase -{ -public: - - /*++ - - Routine Description: - - The constructor of CSampleService. It initializes a new instance - of the CSampleService class. The optional parameters (CanStop, - CanShutdown and CanPauseContinue) allow you to specify whether the - service can be stopped, paused and continued, or be notified when system - shutdown occurs. Inherits properties from the class CServiceBase. - - Arguments: - - ServiceName - The name of the service - - CanStop - The service can be stopped - - CanShutdown - The service is notified when system shutdown occurs - - CanPauseContinue - The service can be paused and continued - - Return Value: - - VOID - - --*/ - CSampleService(PWSTR ServiceName, - BOOL CanStop = TRUE, - BOOL CanShutdown = TRUE, - BOOL CanPauseContinue = FALSE); - - /*++ - - Routine Description: - - The virtual destructor of CSampleService. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual ~CSampleService(); - -protected: - - /*++ - - Routine Description: - - This function is executed when a Start command is sent to the - service by the SCM or when the operating system starts (for a service - that starts automatically). It specifies actions to take when the - service starts. In this code sample, OnStart logs a service-start - message to the Application log, and queues the main service function for - execution in a thread pool worker thread. - - NOTE: A service application is designed to be long running. Therefore, - it usually polls or monitors something in the system. The monitoring is - set up in the OnStart method. However, OnStart does not actually do the - monitoring. The OnStart method must return to the operating system after - the service's operation has begun. It must not loop forever or block. To - set up a simple monitoring mechanism, one general solution is to create - a timer in OnStart. The timer would then raise events in your code - periodically, at which time your service could do its monitoring. The - other solution is to spawn a new thread to perform the main service - functions, which is demonstrated in this code sample. - - Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - - Return Value: - - VOID - - --*/ - virtual VOID OnStart(DWORD Argc, PWSTR *Argv); - - - /*++ - - Routine Description: - - This function is executed when a Stop command is sent to the service by SCM. - It specifies actions to take when a service stops running. In this code - sample, OnStop logs a service-stop message to the Application log, and - waits for the finish of the main service function. - - Be sure to periodically call ReportServiceStatus() with - SERVICE_STOP_PENDING if the procedure is going to take a long time. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual VOID OnStop(); - - - /*++ - - Routine Description: - - This method performs the main function of the service. It runs - on a thread pool worker thread. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - VOID ServiceWorkerThread(); - -private: - - // - // Determines if the service is currently stopping. - // - BOOL m_fStopping; - - // - // The handle to wait for a stop event. - // - HANDLE m_hStoppedEvent; - - // - // The device context to manage notifications with. - // - // NOTE: - // Variables used for device notifications should normally be local. However, - // we must use a global variable here since there is a potential race condition - // when the service needs to restart during device installation that could - // cause the service to prevent the device from being restarted. So, this - // variable is global so that the service's OnStart and OnStart method can - // handle its creation and destruction. - // - PDEVICE_CONTEXT m_Context; -};
\ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp deleted file mode 100644 index 4c20af2e..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp +++ /dev/null @@ -1,794 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - ServiceBase.cpp - -Abstract: - - Provides a base class for a service that will exist as part of a service - application. CServiceBase must be derived from when creating a new service - class. - -Environment: - - User mode - ---*/ - -#pragma region Includes -#include "ServiceBase.h" -#include "Main.h" -#include "Utils.h" -#include <assert.h> -#include <strsafe.h> -#pragma endregion - - -#pragma region Static Members - -// -// Initialize the singleton service instance. -// -CServiceBase *CServiceBase::s_service = NULL; - - -/*++ - -Routine Description: - - Register the executable for a service with the Service Control - Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start - command, which results in a call to the OnStart method in the service. - This method blocks until the service has stopped. - -Arguments: - - Service - The reference to a CServiceBase object. It will become the - singleton service instance of this service application. - -Return Value: - - If the function succeeds, the return value is TRUE. If the function - fails, the return value is FALSE. To get extended error information, - call GetLastError. - ---*/ -BOOL -CServiceBase::Run( - CServiceBase &Service - ) -{ - s_service = &Service; - - SERVICE_TABLE_ENTRY serviceTable[] = - { - { Service.m_name, ServiceMain }, - { NULL, NULL } - }; - - // - // Connects the main thread of a service process to the service control - // manager, which causes the thread to be the service control dispatcher - // thread for the calling process. This call returns when the service has - // stopped. The process should simply terminate when the call returns. - // - return StartServiceCtrlDispatcher(serviceTable); -} - - -/*++ - -Routine Description: - - The entry point for the service. It registers the handler function - for the service and starts the service. - -Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - -Return Value: - - VOID - ---*/ -VOID -WINAPI -CServiceBase::ServiceMain( - DWORD Argc, - PWSTR *Argv - ) -{ - assert(s_service != NULL); - - // - // Register the handler function for the service. - // - s_service->m_statusHandle = RegisterServiceCtrlHandler(s_service->m_name, - ServiceCtrlHandler); - - if (s_service->m_statusHandle == NULL) - { - throw GetLastError(); - } - - // - // Start the service. - // - s_service->Start(Argc, Argv); -} - - -/*++ - -Routine Description: - - Called by the SCM whenever a control code is sent to the service. - -Arguments: - - CtrlCode - The control code. This parameter can be one of - the following values: - - SERVICE_CONTROL_CONTINUE - SERVICE_CONTROL_INTERROGATE - SERVICE_CONTROL_NETBINDADD - SERVICE_CONTROL_NETBINDDISABLE - SERVICE_CONTROL_NETBINDREMOVE - SERVICE_CONTROL_PARAMCHANGE - SERVICE_CONTROL_PAUSE - SERVICE_CONTROL_SHUTDOWN - SERVICE_CONTROL_STOP - - This parameter can also be a user-defined control - code ranging from 128 to 255. - -Return Value: - - VOID - ---*/ -VOID -WINAPI -CServiceBase::ServiceCtrlHandler( - DWORD Ctrl - ) -{ - switch (Ctrl) - { - case SERVICE_CONTROL_STOP: - s_service->Stop(); - break; - case SERVICE_CONTROL_PAUSE: - s_service->Pause(); - break; - case SERVICE_CONTROL_CONTINUE: - s_service->Continue(); - break; - case SERVICE_CONTROL_SHUTDOWN: - s_service->Shutdown(); - break; - case SERVICE_CONTROL_INTERROGATE: - break; - default: - break; - } -} - -#pragma endregion - - -#pragma region Service Constructor and Destructor - -/*++ - -Routine Description: - - The constructor of CServiceBase. It initializes a new instance - of the CServiceBase class. The optional parameters (CanStop, - CanShutdown and CanPauseContinue) allow you to specify whether the - service can be stopped, paused and continued, or be notified when system - shutdown occurs. - -Arguments: - - ServiceName - The name of the service - - CanStop - The service can be stopped - - CanShutdown - The service is notified when system shutdown occurs - - CanPauseContinue - The service can be paused and continued - -Return Value: - - VOID - ---*/ -CServiceBase::CServiceBase( - PWSTR ServiceName, - BOOL CanStop, - BOOL CanShutdown, - BOOL CanPauseContinue - ) -{ - // - // Service name must be a valid string and cannot be NULL. - // - m_name = (ServiceName == NULL) ? L"" : ServiceName; - - m_statusHandle = NULL; - - // - // The service runs in its own process. - // - m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - - // - // The service is starting. - // - m_status.dwCurrentState = SERVICE_START_PENDING; - - // - // The accepted commands of the service. - // - DWORD dwControlsAccepted = 0; - - if (CanStop) - { - dwControlsAccepted |= SERVICE_ACCEPT_STOP; - } - - if (CanShutdown) - { - dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN; - } - - if (CanPauseContinue) - { - dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE; - } - - m_status.dwControlsAccepted = dwControlsAccepted; - - m_status.dwWin32ExitCode = NO_ERROR; - m_status.dwServiceSpecificExitCode = 0; - m_status.dwCheckPoint = 0; - m_status.dwWaitHint = 0; - - SetupEvents(); -} - - -/*++ - -Routine Description: - - The virtual destructor of CServiceBase. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -CServiceBase::~CServiceBase() -{ - DestroyEvents(); -} - -#pragma endregion - - -#pragma region Service Start, Stop, Pause, Continue, and Shutdown - -/*++ - -Routine Description: - - This function starts the service. It calls the OnStart virtual function - in which you can specify the actions to take when the service starts. If - an error occurs during the startup, the error will be logged in the - Application event log, and the service will be stopped. - -Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::Start( - DWORD Argc, - PWSTR *Argv -) -{ - try - { - // - // Tell SCM that the service is starting. - // - SetServiceStatus(SERVICE_START_PENDING); - - // - // Perform service-specific initialization. - // - OnStart(Argc, Argv); - - // - // Tell SCM that the service is started. - // - SetServiceStatus(SERVICE_RUNNING); - } - catch (DWORD Error) - { - // - // Log the error. - // - WriteToErrorLog(L"Service Start", Error); - - // - // Set the service status to be stopped. - // - SetServiceStatus(SERVICE_STOPPED, Error); - } - catch (...) - { - // - // Log the error. - // - WriteToEventLog(L"Service failed to start.", EVENTLOG_ERROR_TYPE); - - // - // Set the service status to be stopped. - // - SetServiceStatus(SERVICE_STOPPED); - } -} - - -/*++ - -Routine Description: - - When implemented in a derived class, executes when a Start - command is sent to the service by the SCM or when the operating system - starts (for a service that starts automatically). Specifies actions to - take when the service starts. Be sure to periodically call - CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the - procedure is going to take long time. You may also consider spawning a - new thread in OnStart to perform time-consuming initialization tasks. - -Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::OnStart( - DWORD Argc, - PWSTR *Argv -) -{ - SetVariables(); -} - - -/*++ - -Routine Description: - - This function stops the service. It calls the OnStop virtual - function in which you can specify the actions to take when the service - stops. If an error occurs, the error will be logged in the Application - event log, and the service will be restored to the original state. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::Stop() -{ - DWORD OriginalState = m_status.dwCurrentState; - - try - { - // - // Tell SCM that the service is stopping. - // - SetServiceStatus(SERVICE_STOP_PENDING); - - // - // Perform service-specific stop operations. - // - OnStop(); - - // - // Tell SCM that the service is stopped. - // - SetServiceStatus(SERVICE_STOPPED); - } - catch (DWORD Error) - { - // - // Log the error. - // - WriteToErrorLog(L"Service Stop", Error); - - // - // Set the orginal service status. - // - SetServiceStatus(OriginalState); - } - catch (...) - { - // - // Log the error. - // - WriteToEventLog(L"Service failed to stop.", EVENTLOG_ERROR_TYPE); - - // - // Set the orginal service status. - // - SetServiceStatus(OriginalState); - } -} - - -/*++ - -Routine Description: - - When implemented in a derived class, executes when a Stop - command is sent to the service by the SCM. Specifies actions to take - when a service stops running. Be sure to periodically call - CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the - procedure is going to take long time. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::OnStop() -{ -} - - -/*++ - -Routine Description: - - The function pauses the service if the service supports pause - and continue. It calls the OnPause virtual function in which you can - specify the actions to take when the service pauses. If an error occurs, - the error will be logged in the Application event log, and the service - will become running. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::Pause() -{ - try - { - // - // Tell SCM that the service is pausing. - // - SetServiceStatus(SERVICE_PAUSE_PENDING); - - // - // Perform service-specific pause operations. - // - OnPause(); - - // - // Tell SCM that the service is paused. - // - SetServiceStatus(SERVICE_PAUSED); - } - catch (DWORD Error) - { - // - // Log the error. - // - WriteToErrorLog(L"Service Pause", Error); - - // - // Tell SCM that the service is still running. - // - SetServiceStatus(SERVICE_RUNNING); - } - catch (...) - { - // - // Log the error. - // - WriteToEventLog(L"Service failed to pause.", EVENTLOG_ERROR_TYPE); - - // - // Tell SCM that the service is still running. - // - SetServiceStatus(SERVICE_RUNNING); - } -} - - -/*++ - -Routine Description: - - When implemented in a derived class, executes when a Pause - command is sent to the service by the SCM. Specifies actions to take - when a service pauses. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::OnPause() -{ -} - - -/*++ - -Routine Description: - - The function resumes normal functioning after being paused if - the service supports pause and continue. It calls the OnContinue virtual - function in which you can specify the actions to take when the service - continues. If an error occurs, the error will be logged in the - Application event log, and the service will still be paused. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::Continue() -{ - try - { - // - // Tell SCM that the service is resuming. - // - SetServiceStatus(SERVICE_CONTINUE_PENDING); - - // - // Perform service-specific continue operations. - // - OnContinue(); - - // - // Tell SCM that the service is running. - // - SetServiceStatus(SERVICE_RUNNING); - } - catch (DWORD Error) - { - // - // Log the error. - // - WriteToErrorLog(L"Service Continue", Error); - - // - // Tell SCM that the service is still paused. - // - SetServiceStatus(SERVICE_PAUSED); - } - catch (...) - { - // - // Log the error. - // - WriteToEventLog(L"Service failed to resume.", EVENTLOG_ERROR_TYPE); - - // - // Tell SCM that the service is still paused. - // - SetServiceStatus(SERVICE_PAUSED); - } -} - - -/*++ - -Routine Description: - - When implemented in a derived class, OnContinue runs when a - Continue command is sent to the service by the SCM. Specifies actions to - take when a service resumes normal functioning after being paused. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::OnContinue() -{ -} - - -/*++ - -Routine Description: - - The function executes when the system is shutting down. It - calls the OnShutdown virtual function in which you can specify what - should occur immediately prior to the system shutting down. If an error - occurs, the error will be logged in the Application event log. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::Shutdown() -{ - try - { - // - // Perform service-specific shutdown operations. - // - OnShutdown(); - - // - // Tell SCM that the service is stopped. - // - SetServiceStatus(SERVICE_STOPPED); - } - catch (DWORD Error) - { - // - // Log the error. - // - WriteToErrorLog(L"Service Shutdown", Error); - } - catch (...) - { - // - // Log the error. - // - WriteToEventLog(L"Service failed to shut down.", EVENTLOG_ERROR_TYPE); - } -} - - -/*++ - -Routine Description: - - When implemented in a derived class, executes when the system - is shutting down. Specifies what should occur immediately prior to the - system shutting down. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::OnShutdown() -{ -} - -#pragma endregion - - -#pragma region Helper Functions - -/*++ - -Routine Description: - - The function sets the service status and reports the status to the SCM. - -Arguments: - - CurrentState - The current state of the service - - Win32ExitCode - The error code to report - - WaitHint - The estimated time for pending operation, in milliseconds - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::SetServiceStatus( - DWORD CurrentState, - DWORD Win32ExitCode, - DWORD WaitHint - ) -{ - static DWORD CheckPoint = 1; - - // - // Fill in the SERVICE_STATUS structure of the service. - // - - m_status.dwCurrentState = CurrentState; - m_status.dwWin32ExitCode = Win32ExitCode; - m_status.dwWaitHint = WaitHint; - - m_status.dwCheckPoint = ((CurrentState == SERVICE_RUNNING) || - (CurrentState == SERVICE_STOPPED)) ? 0 : - CheckPoint++; - - // - // Report the status of the service to the SCM. - // - ::SetServiceStatus(m_statusHandle, &m_status); -} - -#pragma endregion
\ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h deleted file mode 100644 index 106597e1..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h +++ /dev/null @@ -1,423 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - ServiceBase.cpp - -Abstract: - - Provides a base class for a service that will exist as part of a service - application. CServiceBase must be derived from when creating a new service - class. - -Environment: - - User mode - ---*/ - -#pragma once - -#include <windows.h> -#include "Utils.h" - -class CServiceBase -{ -public: - - /*++ - - Routine Description: - - Register the executable for a service with the Service Control - Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start - command, which results in a call to the OnStart method in the service. - This method blocks until the service has stopped. - - Arguments: - - Service - The reference to a CServiceBase object. It will become the - singleton service instance of this service application. - - Return Value: - - If the function succeeds, the return value is TRUE. If the function - fails, the return value is FALSE. To get extended error information, - call GetLastError. - - --*/ - static BOOL Run(CServiceBase &service); - - - /*++ - - Routine Description: - - The constructor of CServiceBase. It initializes a new instance - of the CServiceBase class. The optional parameters (CanStop, - CanShutdown and CanPauseContinue) allow you to specify whether the - service can be stopped, paused and continued, or be notified when system - shutdown occurs. - - Arguments: - - ServiceName - The name of the service - - CanStop - The service can be stopped - - CanShutdown - The service is notified when system shutdown occurs - - CanPauseContinue - The service can be paused and continued - - Return Value: - - VOID - - --*/ - CServiceBase(PWSTR ServiceName, - BOOL CanStop = TRUE, - BOOL CanShutdown = TRUE, - BOOL CanPauseContinue = FALSE); - - - /*++ - - Routine Description: - - The virtual destructor of CServiceBase. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual ~CServiceBase(); - - - /*++ - - Routine Description: - - This function stops the service. It calls the OnStop virtual - function in which you can specify the actions to take when the service - stops. If an error occurs, the error will be logged in the Application - event log, and the service will be restored to the original state. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - VOID Stop(); - -protected: - - /*++ - - Routine Description: - - When implemented in a derived class, executes when a Start - command is sent to the service by the SCM or when the operating system - starts (for a service that starts automatically). Specifies actions to - take when the service starts. Be sure to periodically call - CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the - procedure is going to take long time. You may also consider spawning a - new thread in OnStart to perform time-consuming initialization tasks. - - Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - - Return Value: - - VOID - - --*/ - virtual VOID OnStart(DWORD Argc, PWSTR *Argv); - - - /*++ - - Routine Description: - - When implemented in a derived class, executes when a Stop - command is sent to the service by the SCM. Specifies actions to take - when a service stops running. Be sure to periodically call - CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the - procedure is going to take long time. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual VOID OnStop(); - - - /*++ - - Routine Description: - - When implemented in a derived class, executes when a Pause - command is sent to the service by the SCM. Specifies actions to take - when a service pauses. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual VOID OnPause(); - - - /*++ - - Routine Description: - - When implemented in a derived class, OnContinue runs when a - Continue command is sent to the service by the SCM. Specifies actions to - take when a service resumes normal functioning after being paused. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual VOID OnContinue(); - - - /*++ - - Routine Description: - - When implemented in a derived class, executes when the system - is shutting down. Specifies what should occur immediately prior to the - system shutting down. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual VOID OnShutdown(); - - - /*++ - - Routine Description: - - The function sets the service status and reports the status to the SCM. - - Arguments: - - CurrentState - The current state of the service - - Win32ExitCode - The error code to report - - WaitHint - The estimated time for pending operation, in milliseconds - - Return Value: - - VOID - - --*/ - VOID SetServiceStatus(DWORD CurrentState, - DWORD Win32ExitCode = NO_ERROR, - DWORD WaitHint = 0); - -private: - - /*++ - - Routine Description: - - The entry point for the service. It registers the handler function - for the service and starts the service. - - Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - - Return Value: - - VOID - - --*/ - static VOID WINAPI ServiceMain(DWORD Argc, PWSTR *Argv); - - - /*++ - - Routine Description: - - Called by the SCM whenever a control code is sent to the service. - - Arguments: - - CtrlCode - The control code. This parameter can be one of - the following values: - - SERVICE_CONTROL_CONTINUE - SERVICE_CONTROL_INTERROGATE - SERVICE_CONTROL_NETBINDADD - SERVICE_CONTROL_NETBINDDISABLE - SERVICE_CONTROL_NETBINDREMOVE - SERVICE_CONTROL_PARAMCHANGE - SERVICE_CONTROL_PAUSE - SERVICE_CONTROL_SHUTDOWN - SERVICE_CONTROL_STOP - - This parameter can also be a user-defined control - code ranging from 128 to 255. - - Return Value: - - VOID - - --*/ - static VOID WINAPI ServiceCtrlHandler(DWORD Ctrl); - - - /*++ - - Routine Description: - - This function starts the service. It calls the OnStart virtual function - in which you can specify the actions to take when the service starts. If - an error occurs during the startup, the error will be logged in the - Application event log, and the service will be stopped. - - Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - - Return Value: - - VOID - - --*/ - VOID Start(DWORD Argc, PWSTR *Argv); - - - /*++ - - Routine Description: - - The function pauses the service if the service supports pause - and continue. It calls the OnPause virtual function in which you can - specify the actions to take when the service pauses. If an error occurs, - the error will be logged in the Application event log, and the service - will become running. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - VOID Pause(); - - - /*++ - - Routine Description: - - The function resumes normal functioning after being paused if - the service supports pause and continue. It calls the OnContinue virtual - function in which you can specify the actions to take when the service - continues. If an error occurs, the error will be logged in the - Application event log, and the service will still be paused. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - VOID Continue(); - - - /*++ - - Routine Description: - - The function executes when the system is shutting down. It - calls the OnShutdown virtual function in which you can specify what - should occur immediately prior to the system shutting down. If an error - occurs, the error will be logged in the Application event log. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - VOID Shutdown(); - - - // - // The singleton service instance. - // - static CServiceBase *s_service; - - // - // The name of the service. - // - PWSTR m_name; - - // - // The status of the service. - // - SERVICE_STATUS m_status; - - // - // The service status handle. - // - SERVICE_STATUS_HANDLE m_statusHandle; -};
\ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp new file mode 100644 index 00000000..f6616850 --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp @@ -0,0 +1,375 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + ServiceWin32API.cpp + +Abstract: + + Implements functions to start/run/stop the service. + +Environment: + + User mode + +--*/ + +#include "stdafx.h" + +// +// Settings of the service +// +#define SERVICE_NAME L"OsrUsbFx2UmUserSvc" +#define SERVICE_FLAGS_RUNNING 0x1 + +// +// Service context +// +SERVICE_STATUS_HANDLE SvcStatusHandle = NULL; +volatile LONG SvcControlFlags = 0; +HANDLE SvcStoppedEvent = NULL; +HANDLE SvcStopRequestEvent = NULL; +HANDLE SvcStopWaitObject = NULL; + +// +// Device interface context +// +HCMNOTIFICATION InterfaceNotificationHandle = NULL; +SRWLOCK DeviceListLock = SRWLOCK_INIT; +DEVICE_LIST_ENTRY DeviceList; + +// +// Debugging support during development time +// +//#define DEBUG_SUPPORT + +/*++ + +Routine Description: + + Entry point for the service. + +Arguments: + + Argc - The number of command line arguments + + Argv - The array of command line arguments + +Return Value: + + VOID + +--*/ +INT +wmain( + INT Argc, + WCHAR *Argv[] + ) +{ + UNREFERENCED_PARAMETER(Argc); + UNREFERENCED_PARAMETER(Argv); + + SERVICE_TABLE_ENTRY serviceTable[] = + { + { SERVICE_NAME, ServiceMain }, + { NULL, NULL } + }; + + return StartServiceCtrlDispatcher(serviceTable); +} + +VOID WINAPI ServiceMain( + DWORD Argc, + PWSTR *Argv + ) +{ + DWORD Err = ERROR_SUCCESS; + + UNREFERENCED_PARAMETER(Argc); + UNREFERENCED_PARAMETER(Argv); + + // + // Initialize global variables + // + InitializeDeviceListHead(&DeviceList); + +#ifdef DEBUG_SUPPORT + + while (!IsDebuggerPresent()) { + Sleep(1000); + } + + __debugbreak(); + +#endif + + SvcStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, + ServiceCtrlHandler); + + if (SvcStatusHandle == NULL) + { + Err = GetLastError(); + goto cleanup; + } + + UpdateServiceStatus(SvcStatusHandle, + SERVICE_START_PENDING, + ERROR_SUCCESS); + + // + // Setup device interface context + // + Err = SetupDeviceInterfaceContext(); + + UpdateServiceStatus(SvcStatusHandle, + SERVICE_START_PENDING, + ERROR_SUCCESS); + + // + // Initialize device control + // + OsrFx2InitializeDevice(); + + // + // Register callback function for stop event + // + SvcStopRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (SvcStopRequestEvent == NULL) + { + Err = GetLastError(); + goto cleanup; + } + + if (!RegisterWaitForSingleObject(&SvcStopWaitObject, + SvcStopRequestEvent, + ServiceStopCallback, + NULL, + INFINITE, + WT_EXECUTEONLYONCE | WT_EXECUTEINPERSISTENTTHREAD)) + { + Err = GetLastError(); + goto cleanup; + } + + // + // Create stopped event for the running worker thread + // + SvcStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (SvcStoppedEvent == NULL) + { + Err = GetLastError(); + goto cleanup; + } + + UpdateServiceStatus(SvcStatusHandle, + SERVICE_START_PENDING, + ERROR_SUCCESS); + + // + // Queue the main service function for execution in a worker thread. + // + QueueUserWorkItem(&ServiceRunningWorkerThread, + NULL, + WT_EXECUTELONGFUNCTION); + + UpdateServiceStatus(SvcStatusHandle, + SERVICE_RUNNING, + ERROR_SUCCESS); + +cleanup: + + if (Err != ERROR_SUCCESS) + { + ServiceStop(Err); + } +} + +VOID +WINAPI +ServiceCtrlHandler( + DWORD Ctrl + ) +{ + switch (Ctrl) + { + case SERVICE_CONTROL_STOP: + // + // Set service stop event + // + UpdateServiceStatus(SvcStatusHandle, SERVICE_STOP_PENDING, ERROR_SUCCESS); + SetEvent(SvcStopRequestEvent); + break; + + default: + break; + } +} + +#define SERVICE_WAIT_HINT_TIME 30000 // 30 seconds + +BOOL +UpdateServiceStatus( + __in_opt SERVICE_STATUS_HANDLE hSvcHandle, + __in DWORD dwCurrentState, + __in DWORD dwWin32ExitCode + ) +{ + SERVICE_STATUS SvcStatus; + + static DWORD dwCheckPoint = 1; + + SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + SvcStatus.dwCurrentState = dwCurrentState; + SvcStatus.dwWin32ExitCode = dwWin32ExitCode; + SvcStatus.dwServiceSpecificExitCode = ERROR_SUCCESS; + + if (dwCurrentState == SERVICE_START_PENDING) + { + SvcStatus.dwControlsAccepted = 0; + } + else + { + SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + } + + if ((dwCurrentState == SERVICE_RUNNING) || + (dwCurrentState == SERVICE_STOPPED)) + { + SvcStatus.dwCheckPoint = 0; + SvcStatus.dwWaitHint = 0; + } + else + { + SvcStatus.dwCheckPoint = dwCheckPoint++; + SvcStatus.dwWaitHint = SERVICE_WAIT_HINT_TIME; + } + + return SetServiceStatus(hSvcHandle, &SvcStatus); +} + +DWORD +WINAPI +ServiceRunningWorkerThread( + _In_ PVOID lpThreadParameter + ) +{ + PDEVICE_CONTEXT DeviceContext = NULL; + PDEVICE_LIST_ENTRY Link = NULL; + + UNREFERENCED_PARAMETER(lpThreadParameter); + + InterlockedOr(&SvcControlFlags, SERVICE_FLAGS_RUNNING); + + // + // Periodically check if the service is stopping. + // + while ((InterlockedOr(&SvcControlFlags, 0) & SERVICE_FLAGS_RUNNING) != 0) + { + AcquireSRWLockShared(&DeviceListLock); + + for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink) + { + DeviceContext = CONTAINING_DEVICE_RECORD(Link); + + OsrFx2ControlDevice(DeviceContext); + } + + ReleaseSRWLockShared(&DeviceListLock); + + Sleep(2000); // Simulate some lengthy operations. + } + + // + // Signal the stopped event. + // + SetEvent(SvcStoppedEvent); + + return 0; +} + +VOID +CALLBACK +ServiceStopCallback( + _In_ PVOID lpParameter, + _In_ BOOLEAN TimerOrWaitFired + ) +{ + UNREFERENCED_PARAMETER(TimerOrWaitFired); + + // + // Since wait object can not be unregistered in callback function, queue + // another thread + // + QueueUserWorkItem(ServiceStopWorkerThread, + lpParameter, + WT_EXECUTEDEFAULT); +} + +DWORD +WINAPI +ServiceStopWorkerThread( + _In_ PVOID lpThreadParameter + ) +{ + UNREFERENCED_PARAMETER(lpThreadParameter); + + ServiceStop(ERROR_SUCCESS); + + return 0; +} + +VOID +ServiceStop( + _In_ DWORD ExitCode + ) +{ + if (SvcStatusHandle == NULL) + { + return; + } + + UpdateServiceStatus(SvcStatusHandle, SERVICE_STOP_PENDING, ExitCode); + + // + // Notify the working thread to stop + // + if ((InterlockedOr(&SvcControlFlags, 0) & SERVICE_FLAGS_RUNNING) != 0) + { + InterlockedAnd(&SvcControlFlags, ~SERVICE_FLAGS_RUNNING); + WaitForSingleObject(SvcStoppedEvent, INFINITE); + } + + // + // Clean up device context after the worker thread has finished. + // + CleanupDeviceInterfaceContext(); + + // + // cleanup work + // + if (SvcStopWaitObject != NULL) + { + UnregisterWait(SvcStopWaitObject); + } + + if (SvcStopRequestEvent != NULL) + { + CloseHandle(SvcStopRequestEvent); + } + + if (SvcStoppedEvent != NULL) + { + CloseHandle(SvcStoppedEvent); + } + + UpdateServiceStatus(SvcStatusHandle, SERVICE_STOPPED, ExitCode); +} diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h new file mode 100644 index 00000000..e469ca9d --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +--*/ + +#pragma once + +VOID +WINAPI +ServiceMain( + DWORD Argc, + PWSTR *Argv + ); + +VOID +WINAPI +ServiceCtrlHandler( + DWORD Ctrl + ); + +BOOL +UpdateServiceStatus( + __in_opt SERVICE_STATUS_HANDLE hSvcHandle, + __in DWORD dwCurrentState, + __in DWORD dwWin32ExitCode + ); + +VOID +CALLBACK +ServiceStopCallback( + _In_ PVOID lpParameter, + _In_ BOOLEAN TimerOrWaitFired + ); + +VOID +ServiceStop( + _In_ DWORD ExitCode + ); + +DWORD +WINAPI +ServiceRunningWorkerThread( + _In_ PVOID lpThreadParameter + ); + +DWORD +WINAPI +ServiceStopWorkerThread( + _In_ PVOID lpThreadParameter + ); diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h deleted file mode 100644 index 3d851537..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h +++ /dev/null @@ -1,80 +0,0 @@ -/****************************** Module Header ******************************\ -* Module Name: ThreadPool.h -* Project: CppWindowsService -* Copyright (c) Microsoft Corporation. -* -* The class was designed by Kenny Kerr. It provides the ability to queue -* simple member functions of a class to the Windows thread pool. -* -* Using the thread pool is simple and feels natural in C++. -* -* class CSampleService -* { -* public: -* -* void AsyncRun() -* { -* CThreadPool::QueueUserWorkItem(&Service::Run, this); -* } -* -* void Run() -* { -* // Some lengthy operation -* } -* }; -* -* Kenny Kerr spends most of his time designing and building distributed -* applications for the Microsoft Windows platform. He also has a particular -* passion for C++ and security programming. Reach Kenny at -* http://weblogs.asp.net/kennykerr/ or visit his Web site: -* http://www.kennyandkarin.com/Kenny/. -* -* This source is subject to the Microsoft Public License. -* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. -* All other rights reserved. -* -* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, -* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. -\***************************************************************************/ - -#pragma once - -#include <memory> - - -class CThreadPool -{ -public: - - template <typename T> - static void QueueUserWorkItem(void (T::*function)(void), - T *object, ULONG flags = WT_EXECUTELONGFUNCTION) - { - typedef std::pair<void (T::*)(), T *> CallbackType; - std::auto_ptr<CallbackType> p(new CallbackType(function, object)); - - if (::QueueUserWorkItem(ThreadProc<T>, p.get(), flags)) - { - // The ThreadProc now has the responsibility of deleting the pair. - p.release(); - } - else - { - throw GetLastError(); - } - } - -private: - - template <typename T> - static DWORD WINAPI ThreadProc(PVOID context) - { - typedef std::pair<void (T::*)(), T *> CallbackType; - - std::auto_ptr<CallbackType> p(static_cast<CallbackType *>(context)); - - (p->second->*p->first)(); - return 0; - } -};
\ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp deleted file mode 100644 index e8fc87ee..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - Utils.cpp - -Abstract: - - Provides utility function to SampleApp.cpp. - -Environment: - - User mode - ---*/ - -#include "Utils.h" - -// -// Service trace event provider -// {54a25c42-cd91-4210-98cc-c3447b56e447} -// -EXTERN_C __declspec(selectany) const GUID SERVICE_PROVIDER_GUID = { 0x54a25c42, 0xcd91, 0x4210,{ 0x98, 0xcc, 0xc3, 0x44, 0x7b, 0x56, 0xe4, 0x47 } }; - -REGHANDLE m_etwRegHandle; - - -/*++ - -Routine Description: - - Sets up logging. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -SetupEvents() -{ - NTSTATUS status = EventRegister(&SERVICE_PROVIDER_GUID, - nullptr, - nullptr, - &m_etwRegHandle); - - if (status != ERROR_SUCCESS) - { - wprintf(L"Provider not registered. EventRegister failed with error: 0x%08X\n", status); - } -} - - -/*++ - -Routine Description: - - Destroys logging. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -DestroyEvents() -{ - if (m_etwRegHandle != NULL) - { - EventUnregister(m_etwRegHandle); - } -} - - -/*++ - -Routine Description: - - Log a message. - -Arguments: - - Message - The string message to be logged - - Level - The type of event to be logged. This parameter can - be one of the following values: - - TRACE_LEVEL_CRITICAL - TRACE_LEVEL_ERROR - TRACE_LEVEL_WARNING - TRACE_LEVEL_INFORMATION - TRACE_LEVEL_VERBOSE - -Return Value: - - VOID - ---*/ -VOID -WriteToEventLog( - PWSTR Message, - BYTE Level - ) -{ - if (m_etwRegHandle != NULL) - { - EventWriteString(m_etwRegHandle, Level, 0, Message); - } -} - - -/*++ - -Routine Description: - - Log an error message. - -Arguments: - - Function - The function that gives the error - - Error - The error code - -Return Value: - - VOID - ---*/ -VOID -WriteToErrorLog( - PWSTR Function, - DWORD Error - ) -{ - WCHAR Message[260]; - - StringCchPrintf(Message, ARRAYSIZE(Message), - L"%ws failed with error: 0x%08x", Function, Error); - - WriteToEventLog(Message, TRACE_LEVEL_ERROR); -}
\ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h deleted file mode 100644 index b619f461..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h +++ /dev/null @@ -1,111 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - Utils.cpp - -Abstract: - - Provides utility function to SampleApp.cpp. - -Environment: - - User mode - ---*/ - -#pragma once - -#include <Windows.h> -#include <strsafe.h> -#include <evntprov.h> -#include <evntrace.h> - -/*++ - -Routine Description: - - Sets up logging. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID SetupEvents(); - - -/*++ - -Routine Description: - - Destroys logging. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID DestroyEvents(); - - -/*++ - -Routine Description: - - Log a message. - -Arguments: - - Message - The string message to be logged - - Level - The type of event to be logged. This parameter can - be one of the following values: - - TRACE_LEVEL_CRITICAL - TRACE_LEVEL_ERROR - TRACE_LEVEL_WARNING - TRACE_LEVEL_INFORMATION - TRACE_LEVEL_VERBOSE - -Return Value: - - VOID - ---*/ -VOID WriteToEventLog(PWSTR Message, BYTE Level); - - -/*++ - -Routine Description: - - Log an error message. - -Arguments: - - Function - The function that gives the error - - Error - The error code - -Return Value: - - VOID - ---*/ -VOID WriteToErrorLog(PWSTR Function, DWORD Error);
\ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx Binary files differdeleted file mode 100644 index 61e1e958..00000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx +++ /dev/null diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj index 6965d745..60174c56 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj @@ -23,7 +23,7 @@ <RootNamespace>osrfx2_DCHU_usersvc</RootNamespace> <Keyword>Win32Proj</Keyword> <ProjectName>osrfx2_DCHU_usersvc</ProjectName> - <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> @@ -93,14 +93,13 @@ </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> - <Optimization>Full</Optimization> + <Optimization>Disabled</Optimization> <PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <MinimalRebuild>true</MinimalRebuild> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <PrecompiledHeader> </PrecompiledHeader> - <WarningLevel>Level3</WarningLevel> + <WarningLevel>Level4</WarningLevel> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> </ClCompile> <Link> @@ -108,11 +107,11 @@ <SubSystem>Console</SubSystem> <TargetMachine>MachineX86</TargetMachine> <AdditionalDependencies>onecoreuap.lib;%(AdditionalDependencies);</AdditionalDependencies> + <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> - <Optimization>Full</Optimization> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> @@ -121,6 +120,7 @@ </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <Optimization>Full</Optimization> </ClCompile> <Link> <GenerateDebugInformation>true</GenerateDebugInformation> @@ -138,8 +138,7 @@ <ClCompile> <Optimization>Full</Optimization> <PreprocessorDefinitions>WIN32;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <MinimalRebuild>true</MinimalRebuild> - <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <BasicRuntimeChecks>Default</BasicRuntimeChecks> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <PrecompiledHeader> </PrecompiledHeader> @@ -182,18 +181,15 @@ </Link> </ItemDefinitionGroup> <ItemGroup> - <ClCompile Include="CppWindowsService.cpp" /> - <ClCompile Include="SampleService.cpp" /> - <ClCompile Include="ServiceBase.cpp" /> - <ClCompile Include="Main.cpp" /> - <ClCompile Include="Utils.cpp" /> + <ClCompile Include="DeviceControl.cpp" /> + <ClCompile Include="DeviceContext.cpp" /> + <ClCompile Include="ServiceWin32API.cpp" /> </ItemGroup> <ItemGroup> - <ClInclude Include="SampleService.h" /> - <ClInclude Include="ServiceBase.h" /> - <ClInclude Include="Main.h" /> - <ClInclude Include="ThreadPool.h" /> - <ClInclude Include="Utils.h" /> + <ClInclude Include="DeviceControl.h" /> + <ClInclude Include="DeviceContext.h" /> + <ClInclude Include="stdafx.h" /> + <ClInclude Include="ServiceWin32API.h" /> </ItemGroup> <ItemGroup> <None Include="Documentation\ReadMe.htm"> diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h new file mode 100644 index 00000000..7bd67951 --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +--*/ + +#pragma once + +#include <Windows.h> +#include <strsafe.h> + +// +// Device context +// +#include <cfgmgr32.h> + +#include <initguid.h> + +#include "ServiceWin32API.h" +#include "DeviceContext.h" +#include "DeviceControl.h" diff --git a/general/PLX9x5x/README.md b/general/PLX9x5x/README.md index 8f57513e..85997777 100644 --- a/general/PLX9x5x/README.md +++ b/general/PLX9x5x/README.md @@ -5,32 +5,24 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: PLX9x5x PCI Driver - platform: KMDF - language: cpp - category: General PCI WDF - description: Demonstrates how to write a driver for a generic PCI device using Windows Driver Frameworks (WDF). - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617719 ----> - # PLX9x5x PCI Driver -This sample demonstrates how to write driver for a generic PCI device using Windows Driver Framework. The target hardware for this driver is PLX9656/9653RDK-LITE board. The product kit and the hardware specification are available at <http://www.plxtech.com>. +This sample demonstrates how to write driver for a generic PCI device using Windows Driver Framework. The target hardware for this driver is PLX9656/9653RDK-LITE board. The product kit and the hardware specification are available at the [PLX Technology](https://www.plxtech.com) website. -For more information, see [Peripheral Component Interconnect (PCI) Bus Drivers](http://msdn.microsoft.com/en-us/library/windows/hardware/ff537451). +For more information, see the [PCI driver programming guide](https://docs.microsoft.com/windows-hardware/drivers/pci/). -The device is a PCI device with port, memory, interrupt and DMA resources. Device can be stopped and started at run-time and also supports low power states. The driver is capable of doing concurrent read and write operations to the device but it can handle only one read or write request at any time. The following lists the driver framework interfaces demonstrated in this sample: +The device is a PCI device with port, memory, interrupt and DMA resources. The device can be stopped and started at run-time and also supports low power states. The driver is capable of doing concurrent read and write operations to the device but it can handle only one read or write request at any time. The following driver framework interfaces are demonstrated in this sample: -- Handling PnP & Power Events +- Handling PnP and Power Events - Registering a Device Interface -- Hardware resource mapping: Port, Memory & Interrupt +- Hardware resource mapping: Port, Memory, and Interrupt - DMA Interfaces - Serialized Default Queue for Write requests - Serialized custom Queue for Read requests -- Handling Interrupt & DPC +- Handling Interrupt and DPC To test the driver, run the PLX.EXE test application. diff --git a/general/SimpleMediaSource/README.md b/general/SimpleMediaSource/README.md index ca8e85da..4467f16b 100644 --- a/general/SimpleMediaSource/README.md +++ b/general/SimpleMediaSource/README.md @@ -1,33 +1,32 @@ -<!--- - name: SimpleMediaSource Sample - platform: UMDF2 - language: cpp - category: general - description: Demonstrates how to write a custom media source and driver package. - samplefwlink: ----> +--- +page_type: sample +description: "Demonstrates how to write a custom media source and driver package." +languages: +- cpp +products: +- windows +- windows-wdk +--- -SimpleMediaSource Sample -======================== -This sample demonstrates how to create a custom media source and driver package that can be installed as a Camera and produce frames. +# SimpleMediaSource sample -This sample has accompanying documentation here: https://docs.microsoft.com/en-us/windows-hardware/drivers/stream/frame-server-custom-media-source +This sample demonstrates how to create a custom media source and driver package that can be installed as a camera and produce frames. +For more information, see the accompanying documentation at [Frame Server Custom Media Source](https://docs.microsoft.com/windows-hardware/drivers/stream/frame-server-custom-media-source). -Contents --------- -MediaSource - COM DLL project for the custom media source -SimpleMediaSourceDriver - UMDF driver install package +## Contents -Installation ------------------- +- MediaSource - COM DLL project for the custom media source +- SimpleMediaSourceDriver - UMDF driver install package + +## Installation 1. Build the solution. -2. Navigate to the output folder, e.g. Windows-driver-samples\general\SimpleMediaSource\x64\Release, and the driver package will be in a directory also called SimpleMediaSourceDriver. Check that the folder has `SimpleMediaSource.dll`, `simplemediasourcedriver.cat`, `SimpleMediaSourceDriver.dll`, and `SimpleMediaSourceDriver.inf`. +1. Navigate to the output folder, e.g. Windows-driver-samples\general\SimpleMediaSource\x64\Release, and the driver package will be in a directory also called SimpleMediaSourceDriver. Check that the folder has `SimpleMediaSource.dll`, `simplemediasourcedriver.cat`, `SimpleMediaSourceDriver.dll`, and `SimpleMediaSourceDriver.inf`. -3. Deploy the driver package with +1. Deploy the driver package with the following command: -`devcon dp_add SimpleMediaSourceDriver.inf` + `devcon dp_add SimpleMediaSourceDriver.inf` -4. In Device Manager, locate **SimpleMediaSource Capture Source**, under the Camera category. Open the Microsoft Camera App, switch cameras if necessary until the camera is streaming from the SimpleMediaSource. You should see a scrolling black and white gradient.
\ No newline at end of file +1. In Device Manager, locate **SimpleMediaSource Capture Source**, under the Camera category. Open the Microsoft Camera App, switch cameras if necessary until the camera is streaming from the SimpleMediaSource. You should see a scrolling black and white gradient. diff --git a/general/SimpleMediaSource/general-SimpleMediaSource.yaml b/general/SimpleMediaSource/general-SimpleMediaSource.yaml deleted file mode 100644 index 0a7443ed..00000000 --- a/general/SimpleMediaSource/general-SimpleMediaSource.yaml +++ /dev/null @@ -1,10 +0,0 @@ -### YamlMime:Sample -sample: -- name: SimpleMediaSource Sample - description: Demonstrates how to write a custom media source and driver package. - generateZip: true - author: windows-driver-samples - languages: -- cpp - technologies: -- windows diff --git a/general/SystemDma/wdm/README.md b/general/SystemDma/wdm/README.md index e276d13c..43770319 100644 --- a/general/SystemDma/wdm/README.md +++ b/general/SystemDma/wdm/README.md @@ -5,24 +5,17 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: System DMA sample - platform: WDM - language: cpp - category: General - description: Demonstrates how a driver could use a system DMA controller to write data to a hardware location using V3 System DMA. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617722 ----> - # System DMA This sample demonstrates the usage of V3 System DMA. It shows how a driver could use a system DMA controller supported by Windows to write data to a hardware location using DMA. -The sample consists of a legacy device driver and a Win32 console mode test application. The test application opens a handle to the device exposed by the driver and makes a DeviceIoControl call to initiate the example system DMA. To understand how the V3 system DMA calls are invoked please study SDmaWrite() in SDma.c. +The sample consists of a legacy device driver and a Win32 console mode test application. The test application opens a handle to the device exposed by the driver and makes a DeviceIoControl call to initiate the example system DMA. To understand how the V3 system DMA calls are invoked, see the SDmaWrite function in sdma.c. -**Note** This sample driver is not a PnP driver. This is a minimal driver meant to demonstrate an OS feature. Neither it nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver. +> [!NOTE] +> This sample driver is not a PnP driver. This is a minimal driver meant to demonstrate an OS feature. Neither it nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver. ## Run the sample diff --git a/general/WinHEC 2017 Lab/README.md b/general/WinHEC 2017 Lab/README.md index af806555..eda72f91 100644 --- a/general/WinHEC 2017 Lab/README.md +++ b/general/WinHEC 2017 Lab/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: WinHEC 2017 Lab - platform: KMDF - language: cpp - category: Network - description: WinHEC 2017 Lab - samplefwlink: https://go.microsoft.com/fwlink/p/?linkid=869054 ----> - # WinHEC 2017 Lab -Toaster samples from the WinHEC 2017 Lab: Toaster Driver, PlugInToaster, and Toaster Support App.
\ No newline at end of file +Toaster samples from the WinHEC 2017 Lab: Toaster Driver, PlugInToaster, and Toaster Support App. diff --git a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c b/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c index 6ed215db..7b117240 100644 --- a/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c +++ b/general/WinHEC 2017 Lab/Toaster Driver/toaster/toaster.c @@ -72,7 +72,7 @@ Return Value: KdPrint(("Toaster Function Driver Sample - Driver Framework Edition.\n")); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If DriverEntry creates any resources // that require clean-up in driver unload, diff --git a/general/cancel/README.md b/general/cancel/README.md index 110482d3..a45e145e 100644 --- a/general/cancel/README.md +++ b/general/cancel/README.md @@ -5,20 +5,12 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Cancel-Safe IRP Queue Sample - platform: WDM - language: cpp - category: General - description: Demonstrates the use of the cancel-safe queue routines. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617705 ----> - # Cancel-Safe IRP Queue Sample -This sample demonstrates the use of the cancel-safe queue routines [**IoCsqInitialize**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549054), [**IoCsqInsertIrp**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549066), [**IoCsqRemoveIrp**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549070), [**IoCsqRemoveNextIrp**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff549072). These routines were introduced in Windows for queuing IRPs in the driver's internal device queue. By using these routines, driver developers do not have to worry about IRP cancellation race conditions. A common problem with cancellation of IRPs in a driver is synchronization between the cancel lock or the InterlockedExchange in the I/O Manager with the driver's queue lock. The **IoCsq*Xxx*** routines abstract the cancel logic while allowing the driver to implement the queue and associated synchronization. +This sample demonstrates the use of the cancel-safe queue routines [**IoCsqInitialize**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-iocsqinitialize), [**IoCsqInsertIrp**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-iocsqinsertirp), [**IoCsqRemoveIrp**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-iocsqremoveirp), [**IoCsqRemoveNextIrp**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-iocsqremovenextirp). These routines were introduced in Windows for queuing IRPs in the driver's internal device queue. By using these routines, driver developers do not have to worry about IRP cancellation race conditions. A common problem with cancellation of IRPs in a driver is synchronization between the cancel lock or the InterlockedExchange in the I/O Manager with the driver's queue lock. The **IoCsq*Xxx*** routines abstract the cancel logic while allowing the driver to implement the queue and associated synchronization. The sample is accompanied by a simple multithreaded Win32 console application to stress-test the driver's cancel and cleanup routines. @@ -26,9 +18,9 @@ This driver is written for an hypothetical data-acquisition device that requires This sample driver is not a Plug and Play driver. This is a minimal driver meant to demonstrate a feature of the operating system. Neither this driver nor its sample programs are intended for use in a production environment. Instead, they are intended for educational purposes and as a skeleton driver. -Look in the Startio directory for another version of the sample driver that shows how to use cancel-safe IRP queues to implement I/O queuing functionality similar to the [**IoStartPacket**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550370) and [**IoStartNextPacket**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550358) routines. The same test application works with this driver as well. +Look in the Startio directory for another version of the sample driver that shows how to use cancel-safe IRP queues to implement I/O queuing functionality similar to the [**IoStartPacket**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-iostartpacket) and [**IoStartNextPacket**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-iostartnextpacket) routines. The same test application works with this driver as well. -For more information, see [Cancel-Safe IRP Queues](http://msdn.microsoft.com/en-us/library/windows/hardware/ff540755). +For more information, see [Cancel-Safe IRP Queues](https://docs.microsoft.com/windows-hardware/drivers/kernel/cancel-safe-irp-queues). ## Run the sample @@ -36,4 +28,5 @@ To test this driver, run Testapp.exe, which is a simple Win32 multithreaded cons `Usage: testapp <NumberOfThreads>` -**Note** The `NumberOfThreads` command-line parameter is limited to a maximum of 10 threads; the default value if no parameter is specified is 1. The main thread waits for user input. If you press Q, the application exits gracefully; otherwise, it exits the process abruptly and forces all the threads to be terminated and all pending I/O operations to be canceled. Other threads perform I/O asynchronously in a loop. After every overlapped read, the thread goes into an alertable sleep and wakes as soon as the completion routine runs, which occurs when the driver completes the read IRP. You should run multiple instances of the application to stress test the driver. +> [!NOTE] +> The `NumberOfThreads` command-line parameter is limited to a maximum of 10 threads; the default value if no parameter is specified is 1. The main thread waits for user input. If you press Q, the application exits gracefully; otherwise, it exits the process abruptly and forces all the threads to be terminated and all pending I/O operations to be canceled. Other threads perform I/O asynchronously in a loop. After every overlapped read, the thread goes into an alertable sleep and wakes as soon as the completion routine runs, which occurs when the driver completes the read IRP. You should run multiple instances of the application to stress test the driver. diff --git a/general/echo/kmdf/README.md b/general/echo/kmdf/README.md index 2827d357..2118e3e5 100644 --- a/general/echo/kmdf/README.md +++ b/general/echo/kmdf/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: KMDF Echo Sample - platform: KMDF - language: cpp - category: General WDF - description: Demonstrates how to use a sequential queue to serialize read and write requests presented to the driver. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617706 ----> - # KMDF Echo Sample The ECHO (KMDF) sample demonstrates how to use a sequential queue to serialize read and write requests presented to the driver. @@ -28,7 +20,7 @@ This sample builds a Universal Windows Driver. It uses only APIs and DDIs that a ## Related technologies -[Kernel-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544396) +[Kernel-Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/kernel/) ## Code Tour @@ -50,48 +42,29 @@ Since the queue is a sequential queue, only one request is outstanding in the dr **Usage:** -Echoapp.exe --- Send single write and read request synchronously +- Echoapp.exe --- Send single write and read request synchronously -Echoapp.exe -Async --- Send 100 reads and writes asynchronously +- Echoapp.exe -Async --- Send 100 reads and writes asynchronously Exit the app anytime by pressing Ctrl-C ## File Manifest -File - -Description - -Echo.htm - -Documentation for this sample (this file). - -***(The AutoSync and DriverSync versions of the sample each have their own version of the following files)*** +> [!NOTE] +> The AutoSync and DriverSync versions of the sample each have their own version of the following files: Driver.h, Driver.c -DriverEntry and Events on the Driver Object. +- DriverEntry and Events on the Driver Object. Device.h, Device.c -Events on the Device Object. +- Events on the Device Object. Queue.h, Queue.c -Contains Events on the I/O Queue Objects. +- Contains Events on the I/O Queue Objects. Echo.inx -File that describes the installation of this driver. The build process converts this into an INF file. - -Makefile.inc - -A makefile that defines custom build actions. This includes the conversion of the .INX file into a .INF file - -Makefile - -This file merely redirects to the real makefile that is shared by all the driver components of the Windows NT DDK. - -Sources - -Generic file that lists source files and all the build options. +- File that describes the installation of this driver. The build process converts this into an INF file. diff --git a/general/echo/kmdf/driver/AutoSync/queue.c b/general/echo/kmdf/driver/AutoSync/queue.c index d881c003..7e2e915f 100644 --- a/general/echo/kmdf/driver/AutoSync/queue.c +++ b/general/echo/kmdf/driver/AutoSync/queue.c @@ -423,7 +423,7 @@ Return Value: queueContext->Length = 0L; } - queueContext->Buffer = ExAllocatePoolWithTag(NonPagedPoolNx, Length, 'sam1'); + queueContext->Buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, Length, 'sam1'); if( queueContext->Buffer == NULL ) { KdPrint(("EchoEvtIoWrite: Could not allocate %Iu byte buffer\n", Length)); WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); diff --git a/general/echo/kmdf/driver/DriverSync/queue.c b/general/echo/kmdf/driver/DriverSync/queue.c index 7835b73b..1b34b616 100644 --- a/general/echo/kmdf/driver/DriverSync/queue.c +++ b/general/echo/kmdf/driver/DriverSync/queue.c @@ -649,7 +649,7 @@ Return Value: queueContext->Length = 0L; } - queueContext->Buffer = ExAllocatePoolWithTag(NonPagedPoolNx, Length, 'sam1'); + queueContext->Buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, Length, 'sam1'); if( queueContext->Buffer == NULL ) { KdPrint(("EchoEvtIoWrite: Could not allocate %Iu byte buffer\n",Length)); WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); diff --git a/general/echo/umdf/README.md b/general/echo/umdf/README.md index b4accf05..241e633d 100644 --- a/general/echo/umdf/README.md +++ b/general/echo/umdf/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Echo Sample (UMDF Version 1) - platform: UMDF1 - language: cpp - category: General WDF - description: Demonstrates how to use UMDF version 1 to write a driver and demonstrates best practices. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617707 ----> - # Echo Sample (UMDF Version 1) This sample demonstrates how to use User-Mode Driver Framework (UMDF) version 1 to write a driver and demonstrates best practices. @@ -24,13 +16,11 @@ It also demonstrates the use of a default Serial Dispatch I/O Queue, its request This sample driver is a minimal driver meant to demonstrate the usage of the User-Mode Driver Framework. It is not intended for use in a production environment. -Related technologies --------------------- +## Related technologies -[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456) +[User-Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2) -Testing -------- +## Testing To test the Echo driver, you can run echoapp.exe which is built from \\echo\\exe. @@ -42,14 +32,14 @@ Usage: Echoapp.exe --- Send single write and read request synchronously Echoapp.exe -Async --- Send 100 reads and writes asynchronously Exit the app anytime by pressing Ctrl-C - + D:\>echoapp DevicePath: \\?\root#sample#0000#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a} Opened device successfully 512 Pattern Bytes Written successfully 512 Pattern Bytes Read successfully Pattern Verified successfully - + D:\>echoapp -Async DevicePath: \\?\root#sample#0000#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a} Opened device successfully @@ -81,52 +71,50 @@ Number of bytes written by request number 11 is 1024 Note that the reads and writes are performed by independent threads in the echo test application. As a result the order of the output may not exactly match what you see above. -File Manifest -------------- +## File Manifest -**comsup.cpp & comsup.h** +comsup.cpp and comsup.h - COM Support code - specifically base classes which provide implementations for the standard COM interfaces IUnknown and IClassFactory which are used throughout this sample. + - The implementation of IClassFactory is designed to create instances of the CMyDriver class. If you should change the name of your base driver class, you would also need to modify this file. -**dllsup.cpp** +dllsup.cpp - DLL Support code - provides the DLL's entry point as well as the single required export (DllGetClassObject). + - These depend on comsup.cpp to perform the necessary class creation. -**exports.def** +exports.def - This file lists the functions that the driver DLL exports. -**internal.h** +internal.h - This is the main header file for this driver. -**Driver.cpp and Driver.h** +Driver.cpp and Driver.h - DriverEntry and events on the driver object. -**Device.cpp and Device.h** +Device.cpp and Device.h - The Events on the device object. -**Queue.cpp and Queue.h** +Queue.cpp and Queue.h - Contains Events on the I/O Queue Objects. -**Echo.rc** +Echo.rc - Resource file for the driver. -**WUDFEchoDriver.inx** +WUDFEchoDriver.inx - File that describes the installation of this driver. The build process converts this into an INF file. -**makefile.inc** - -- A makefile that defines custom build actions. This includes the conversion of the .INX - -**echodriver.ctl** +echodriver.ctl - This file lists the WPP trace control GUID(s) for the sample driver. This file can be used with the tracelog command's -guid flag to enable the collection of these trace events within an established trace session. + - These GUIDs must remain in sync with the trace control GUIDs defined in internal.h. diff --git a/general/echo/umdf2/README.md b/general/echo/umdf2/README.md index efe606f7..6ddc0555 100644 --- a/general/echo/umdf2/README.md +++ b/general/echo/umdf2/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Echo Sample (UMDF Version 2) - platform: UMDF2 - language: cpp - category: General WDF - description: Demonstrates how to use UMDF 2 to write a driver and to employ best practices. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617708 ----> - # Echo Sample (UMDF Version 2) The ECHO (UMDF version 2) sample demonstrates how to use a sequential queue to serialize read and write requests presented to the driver. @@ -26,28 +18,25 @@ It also shows how to synchronize execution of these events with other asynchrono This sample builds a Universal Windows Driver. It uses only APIs and DDIs that are included in OneCoreUAP. -Related technologies --------------------- +## Related technologies + +[User-Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2) -[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456) +## Build the sample with Visual Studio -Open the driver solution in Visual Studio ------------------------------------------ +### Open the driver solution in Visual Studio In Microsoft Visual Studio, open the solution file (umdf2echo.sln). Choose **Solution Explorer** from the **View** menu. In Solution Explorer, you can see one solution that contains three projects. There is a driver project (Driver-\>AutoSync-\>echo), an application project (Exe-\>echoapp), and a package project named **package** (lower case). -Set the configuration and platform in Visual Studio ---------------------------------------------------- +### Set the configuration and platform in Visual Studio In Visual Studio, in Solution Explorer, right click **Solution**, and choose **Configuration Manager**. Set the configuration and the platform. Make sure that the configuration and platform are the same for both the driver project and the package project. Do not check the **Deploy** boxes. -Locate the built driver package -------------------------------- +### Locate the built driver package In File Explorer, navigate to the folder that contains your built driver package. The location of this folder varies depending on what you set for configuration and platform. -Run the sample --------------- +## Run the sample The computer where you install the driver is called the *target computer* or the *test computer*. Typically this is a separate computer from where you develop and build the driver package. The computer where you develop and build the driver is called the *host computer*. @@ -55,20 +44,23 @@ The process of moving the driver package to the target computer and installing t ### Automatic deployment (root enumerated) -Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). +Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1). 1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**. + 1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter **root\\ECHO** for the hardware ID. Click **OK**. + 1. On the **Build** menu, choose **Build Solution**. ### Manual deployment (root enumerated) -Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). +Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). 1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\umdf2echoPkg). + 1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command: - **devcon install echoum.inf root\\ECHO** + `devcon install echoum.inf root\\ECHO` ### View the root enumerated driver in Device Manager @@ -76,11 +68,10 @@ On the target computer, in a Command Prompt window, enter **devmgmt** to open De In Device Manager, on the **View** menu, choose **Devices by connection**. Locate **Sample WDF ECHO Driver** as a child of the root node of the device tree. -Build the sample using MSBuild ------------------------------- +## Build the sample using MSBuild As an alternative to building the driver sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, umdf2echo.sln. Use the MSBuild command to build the solution. Here is an example: -**msbuild /p:configuration="Release" /p:platform="Win32" umdf2echo.sln** +`msbuild /p:configuration="Release" /p:platform="Win32" umdf2echo.sln` -For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644). +For more information about using MSBuild to build a driver package, see [MSBuild primer for WDK developers](https://docs.microsoft.com/windows-hardware/drivers/devtest/msbuild-primer-for-wdk-developers). diff --git a/general/echo/umdfSocketEcho/README.md b/general/echo/umdfSocketEcho/README.md index 71af4726..d4a6077f 100644 --- a/general/echo/umdfSocketEcho/README.md +++ b/general/echo/umdfSocketEcho/README.md @@ -5,41 +5,32 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: UMDF SocketEcho Sample (UMDF Version 1) - platform: UMDF1 - language: cpp - category: General WDF - description: Demonstrates how to use UMDF version 1 to write a driver and demonstrates best practices. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617709 ----> - # UMDF SocketEcho Sample (UMDF Version 1) The UMDF SocketEcho sample demonstrates how to use the User-Mode Driver Framework (UMDF) to write a driver and demonstrates best practices. This sample also demonstrates how to use a default parallel dispatch I/O queue, use a Microsoft Win32 dispatcher, and handle a socket handle by using a Win32 file I/O target. -Related technologies --------------------- +## Related technologies -[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456) +[User-Mode Driver Framework](https://docs.microsoft.com/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2) -Code Tour ---------- +## Code Tour This sample driver is a minimal driver that is intended to demonstrate how to use UMDF. It is not intended for use in a production environment. -- **CMyDriver::OnInitialize** in **driver.cpp** is called by the framework when the driver loads. This method initiates use of the Winsock Library. +- **CMyDriver::OnInitialize** in **driver.cpp** is called by the framework when the driver loads. This method initiates use of the Winsock Library. + - **CMyDriver::OnDeviceAdd** in **driver.cpp** is called by the framework to install the driver on a device stack. OnDeviceAdd creates a device callback object, and then calls IWDFDriver::CreateDevice to create an framework device object and to associate the device callback object with the framework device object. + - **CMyQueue::OnCreateFile** in **queue.cpp** is called by the framework to create a socket connection, create a file i/o target that is associated with the socket handle for this connection, and store the socket handle in the file object context. -Installation ------------- +## Installation -In Visual Studio, you can press F5 to build the sample and then deploy it to a target machine. For more information, see [Deploying a Driver to a Test Computer](http://msdn.microsoft.com/en-us/library/windows/hardware/hh454834). Alternatively, you can install the sample from the command line. +In Visual Studio, you can press F5 to build the sample and then deploy it to a target machine. For more information, see [Deploying a Driver to a Test Computer](https://docs.microsoft.com/windows-hardware/drivers/develop/deploying-a-driver-to-a-test-computer). Alternatively, you can install the sample from the command line. To test this sample, you must have a test computer. This test computer can be a second computer or, if necessary, your development computer. @@ -49,11 +40,12 @@ To install the UMDF Echo sample driver from the command line, do the following: 1. Copy the UMDF coinstaller, WUDFUpdate\_*MMmmmm*.dll, from the \\redist\\wdf\\\<architecture\> directory to the same directory (for example, C:\\socketechoSample). - **Note** You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0. + > [!NOTE] + > You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0. 1. Navigate to the directory that contains the INF file and binaries (for example, cd /d c:\\socketechoSample), and run DevCon.exe as follows: - `devcon.exe install socketecho.inf WUDF\\socketecho` + `devcon.exe install socketecho.inf WUDF\\socketecho` You can find DevCon.exe in the \\tools directory of the WDK (for example, \\tools\\devcon\\i386\\devcon.exe). @@ -75,8 +67,7 @@ To test this sample drivers on a checked operating system that you have installe 1. If WdfCoinstaller*MMmmmm*.dll or WinUsbCoinstaller.dll is included in your driver package, repeat step 1 and step 2 for them. -Testing -------- +## Testing To test the SocketEcho driver, you can run socketechoserver.exe, which is built from the \\echo\\umdfSocketEcho\\Exe directory, and echoapp.exe, which is built from the Kernel-Mode Driver Framework (KMDF) samples in the \\echo\\kmdf directory. @@ -84,94 +75,72 @@ First, you must install the device as described earlier. Then, run socketechoser `D:\\\>socketechoserver -h` -Usage ------- +## Usage -```cmd -socketechoserver Display Usage +socketechoserver usage -socketechoserver -h Display Usage +```cmd +D:\>socketechoserver -h socketechoserver -p Start the app as server listening on default port - socketechoserver -p [port\#] Start the app as server listening on this port -D:\\\>socketechoserver -p +D:\>socketechoserver -p Listening on socket... +``` In another Command Prompt window, run echoapp.exe. -D:\\\>echoapp +```cmd +D:\>echoapp DevicePath: \\\\?\\root\#sample\#0000\#{ e5e65b0c-82c8-4689-96d4-f77837971990} Opened device successfully 512 Pattern Bytes Written successfully - 512 Pattern Bytes Read successfully Pattern Verified successfully -D:\\\>echoapp -Async +D:\>echoapp -Async -DevicePath: \\\\?\\root\#sample\#0000\#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a} +DevicePath: \\?\root\#sample\#0000\#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a} Opened device successfully Starting AsyncIo Number of bytes written by request number 0 is 1024 - Number of bytes read by request number 0 is 1024 - +Number of bytes written by request number 1 is 1024 Number of bytes read by request number 1 is 1024 - Number of bytes written by request number 2 is 1024 - Number of bytes read by request number 2 is 1024 - Number of bytes written by request number 3 is 1024 - Number of bytes read by request number 3 is 1024 - Number of bytes written by request number 4 is 1024 - Number of bytes read by request number 4 is 1024 - Number of bytes written by request number 5 is 1024 - Number of bytes read by request number 5 is 1024 - Number of bytes written by request number 6 is 1024 - Number of bytes read by request number 6 is 1024 - Number of bytes written by request number 7 is 1024 - Number of bytes read by request number 7 is 1024 - Number of bytes written by request number 8 is 1024 - Number of bytes read by request number 8 is 1024 - Number of bytes written by request number 9 is 1024 - Number of bytes read by request number 9 is 1024 - Number of bytes written by request number 10 is 1024 - Number of bytes read by request number 10 is 1024 - Number of bytes written by request number 11 is 1024 - ... ``` -Note that independent threads perform the reads and writes in the echo test application. As a result, the order of the output might not exactly match what you see in the preceding output. +> [!NOTE] +> Independent threads perform the reads and writes in the echo test application. As a result, the order of the output might not exactly match what you see in the preceding output example. -File Manifest -------------- +## File Manifest **Dllsup.cpp**: The DLL support code that provides the DLL's entry point and the single required export (DllGetClassObject). diff --git a/general/event/README.md b/general/event/README.md index 3488ea5a..37dadcf1 100644 --- a/general/event/README.md +++ b/general/event/README.md @@ -5,28 +5,21 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Hardware Event Sample - platform: WDM - language: cpp - category: General - description: Demonstrates different ways a kernel-mode driver can notify an application about a hardware event. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617711 ----> - # Hardware Event Sample This sample demonstrates two different ways a Windows kernel-mode driver can notify an application about a hardware event. One way uses an event-based method, and the other uses an IRP-based method. Because the sample driver is not talking to any real hardware, it uses a timer DPC to simulate hardware events. The test application informs the driver whether it wants to be notified by signaling an event or by completing the pending IRP. Additionally, the test application specifies a relative time at which the DPC timer must fire. -*Event-based approach:* The application calls the [**CreateEvent**](http://msdn.microsoft.com/en-us/library/windows/hardware/ms682396) function to create an event. It then passes the event handle to the driver in an I/O control request that uses a private IOCTL code, IOCTL\_REGISTER\_EVENT. Because the driver is a monolithic, top-level driver, its IRP dispatch routines run in the application process context and, as a result, the event handle is still valid in the driver. The driver dereferences the user-mode handle into system space and saves the event object pointer for later use. Next, the driver queues a custom timer DPC. When the DPC fires, the driver signals the event by calling the [**KeSetEvent**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553253) routine at DISPATCH\_LEVEL, and deletes the references to the event object. You can't use this approach if your driver is not a monolithic, top-level driver; that is because a driver can't guarantee the process context in a multi-level driver stack if the driver is not at the top of the stack. +*Event-based approach:* The application calls the [**CreateEvent**](https://docs.microsoft.com/windows/win32/api/synchapi/nf-synchapi-createeventa) function to create an event. It then passes the event handle to the driver in an I/O control request that uses a private IOCTL code, IOCTL\_REGISTER\_EVENT. Because the driver is a monolithic, top-level driver, its IRP dispatch routines run in the application process context and, as a result, the event handle is still valid in the driver. The driver dereferences the user-mode handle into system space and saves the event object pointer for later use. Next, the driver queues a custom timer DPC. When the DPC fires, the driver signals the event by calling the [**KeSetEvent**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-kesetevent) routine at DISPATCH\_LEVEL, and deletes the references to the event object. You can't use this approach if your driver is not a monolithic, top-level driver; that is because a driver can't guarantee the process context in a multi-level driver stack if the driver is not at the top of the stack. *Pending IRP-based approach:* The application makes a synchronous IOCTL\_REGISTER\_EVENT request. The driver sets the status of the device I/O control request to IRP pending, queues a timer DPC, and returns STATUS\_PENDING. When the timer fires to indicate a hardware event, the driver completes the pending IRP to notify the application about the hardware event. There are two advantages of IRP-based approach over the event-based approach. First, the driver can send a message to the application along with the event notification. Second, the driver routines don't have to run in the context of the process that made the request. Instead, the application can send a synchronous or asynchronous (overlapped) I/O control request to the driver. -**Note** This sample driver is not a Plug and Play driver. This is a minimal driver meant to demonstrate a feature of the operating system. Neither this driver nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver. +> [!NOTE] +> This sample driver is not a Plug and Play driver. This is a minimal driver meant to demonstrate a feature of the operating system. Neither this driver nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver. ## Run the sample diff --git a/general/filehistory/README.md b/general/filehistory/README.md index 5f9fa87c..9cbadf3b 100644 --- a/general/filehistory/README.md +++ b/general/filehistory/README.md @@ -5,22 +5,14 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: File History Sample - platform: WDM - language: cpp - category: General - description: A console application that starts the file history service, if it is stopped, and schedules regular backups. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617712 ----> - # File History Sample The FileHistory sample is a console application that starts the file history service, if it is stopped, and schedules regular backups. The application requires, as a command-line parameter, the path name of a storage device to use as the default backup target. -This sample application uses the [File History API](http://msdn.microsoft.com/en-us/library/windows/hardware/hh829789). The File History API enables third parties to automatically configure the File History feature on a Windows platform and customize it in accordance with their unique needs. +This sample application uses the [File History API](https://docs.microsoft.com/windows/win32/devnotes/file-history-api). The File History API enables third parties to automatically configure the File History feature on a Windows platform and customize it in accordance with their unique needs. ## Run the sample diff --git a/general/ioctl/kmdf/README.md b/general/ioctl/kmdf/README.md index 7f99b367..13afa81c 100644 --- a/general/ioctl/kmdf/README.md +++ b/general/ioctl/kmdf/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Non-PnP Driver Sample - platform: KMDF - language: cpp - category: General WDF - description: Demonstrates how to write a non-PnP driver using the Kernel Mode Driver Framework. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620307 ----> - # Non-PnP Driver Sample This sample is primarily meant to demonstrate how to write a NON-PNP driver using the Kernel Mode Driver Framework. @@ -40,23 +32,26 @@ This sample would be useful for writing a driver that does not interact with any The sample is accompanied by a simple multithreaded Win32 console application to test the driver. -*Disclaimer*: This is a minimal driver meant to demonstrate an OS feature. Neither it nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver. +> [!CAUTION] +> This is a minimal driver meant to demonstrate an OS feature. Neither it nor its sample programs are intended for use in a production environment. Rather, they are intended for educational purposes and as a skeleton driver. ## Build the sample -For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644). +For information on how to build a driver solution using Microsoft Visual Studio, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver). If the build succeeds, you will find the driver, nonpnp.sys, and the test application, nonpnpapp.exe, in the binary output directory specified for the build environment. To test this driver, copy the nonpnp.inf into the same folder as the nonpnpapp.exe and the wdfcoinstaller\<version\>.dll . -**Note** You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0. +> [!NOTE] +> You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0. Next, run nonpnpapp.exe, a simple Win32 multithreaded console mode application. The driver will be automatically loaded and started. When you exit the app, the driver will be stopped and removed. Usage: nonpnpapp.exe (-l) (-v version) -**Note** This application first tries to open the device (\\Device\\FileIo). If the device doesn't exist, it takes that as a hint that the driver is not loaded and tries to load the driver using service control manager API. If the service is loaded successfully, it tries to open the device again. If successful, it makes all four different types of DeviceControl calls to the driver. After that it makes a WriteFile call with an arbitrary size buffer. The driver, in response, writes that buffer to a file opened in the Create request. The name of the file was provided by the application as part of the device name and the directory path is hardcoded to %WINDIR%\\temp. When the WriteFile returns, the application makes a ReadFile call to read the file through the driver, and then compares the data returned by the driver with the one it originally wrote. If you specify -l option in command line, the application does this Write and Read operation in an infinite loop. The -v command line option is used to specify the version of the KMDF coinstaller (wdfcoinstaller\<version\>.dll) to load. If none is specified then it loads the coinstaller for v1.0 (wdfcoinstaller01000.dll) +> [!NOTE] +> This application first tries to open the device (\\Device\\FileIo). If the device doesn't exist, it takes that as a hint that the driver is not loaded and tries to load the driver using service control manager API. If the service is loaded successfully, it tries to open the device again. If successful, it makes all four different types of DeviceControl calls to the driver. After that it makes a WriteFile call with an arbitrary size buffer. The driver, in response, writes that buffer to a file opened in the Create request. The name of the file was provided by the application as part of the device name and the directory path is hardcoded to %WINDIR%\\temp. When the WriteFile returns, the application makes a ReadFile call to read the file through the driver, and then compares the data returned by the driver with the one it originally wrote. If you specify -l option in command line, the application does this Write and Read operation in an infinite loop. The -v command line option is used to specify the version of the KMDF coinstaller (wdfcoinstaller\<version\>.dll) to load. If none is specified then it loads the coinstaller for v1.0 (wdfcoinstaller01000.dll) ### WDF SECTION diff --git a/general/ioctl/kmdf/sys/nonpnp.c b/general/ioctl/kmdf/sys/nonpnp.c index 519ae838..a36c98c1 100644 --- a/general/ioctl/kmdf/sys/nonpnp.c +++ b/general/ioctl/kmdf/sys/nonpnp.c @@ -459,10 +459,10 @@ Return Value: // length = directory.Length + fileName->Length; - absFileName.Buffer = ExAllocatePoolWithTag(PagedPool, length, POOL_TAG); + absFileName.Buffer = ExAllocatePool2(POOL_FLAG_PAGED, length, POOL_TAG); if(absFileName.Buffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; - TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "ExAllocatePoolWithTag failed"); + TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "ExAllocatePool2 failed"); goto End; } absFileName.Length = 0; diff --git a/general/ioctl/wdm/README.md b/general/ioctl/wdm/README.md index 0f1fb3b2..564887ef 100644 --- a/general/ioctl/wdm/README.md +++ b/general/ioctl/wdm/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: IOCTL - platform: WDM - language: cpp - category: General - description: Demonstrates usage of four different types of IOCTLs - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617715 ----> - # IOCTL This sample demonstrates the usage of four different types of IOCTLs (METHOD\_IN\_DIRECT, METHOD\_OUT\_DIRECT, METHOD\_NEITHER, and METHOD\_BUFFERED). @@ -24,8 +16,9 @@ The sample shows how the user input and output buffers specified in the **Device The sample consists of a legacy device driver and a Win32 console test application. The test application opens a handle to the device exposed by the driver and makes all four different **DeviceIoControl** calls, one after another. To understand how the IRP fields are set the I/O manager, you should run the checked build version of the driver and look at the debug output. -**Note** This sample driver is not a Plug and Play driver. This is a minimal driver meant to demonstrate a feature of the operating system. Neither this driver nor its sample programs are intended for use in a production environment. Instead, they are intended for educational purposes and as a skeleton driver. +> [!CAUTION] +> This sample driver is not a Plug and Play driver. This is a minimal driver meant to demonstrate a feature of the operating system. Neither this driver nor its sample programs are intended for use in a production environment. Instead, they are intended for educational purposes and as a skeleton driver. -# Run the sample +## Run the sample To test this driver, copy the test app, Ioctlapp.exe, and the driver to the same directory, and run the application. The application will automatically load the driver, if it's not already loaded, and interact with the driver. When you exit the application, the driver will be stopped, unloaded and removed. diff --git a/general/obcallback/README.md b/general/obcallback/README.md index e0efce2c..993b78d6 100644 --- a/general/obcallback/README.md +++ b/general/obcallback/README.md @@ -5,28 +5,20 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: ObCallback Callback Registration Driver - platform: WDM - language: cpp - category: General - description: Demonstrates the use of registered callbacks for process protection. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617716 ----> - # ObCallback Callback Registration Driver The ObCallback sample driver demonstrates the use of registered callbacks for process protection. The driver registers control callbacks which are called at process creation. ## Design and Operation -The sample exercises both the [**PsSetCreateProcessNotifyRoutineEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff559951) and the [**ObRegisterCallbacks**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff558692) routines. The first example uses the **ObRegisterCallbacks** routine and a callback to restrict requested access rights during a open process action. The second example uses the **PsSetCreateProcessNotifyRoutineEx** routine to reject a process creation by examining the command line. +The sample exercises both the [**PsSetCreateProcessNotifyRoutineEx**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-pssetcreateprocessnotifyroutine) and the [**ObRegisterCallbacks**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-obregistercallbacks) routines. The first example uses the **ObRegisterCallbacks** routine and a callback to restrict requested access rights during a open process action. The second example uses the **PsSetCreateProcessNotifyRoutineEx** routine to reject a process creation by examining the command line. The following is a command line usage scenario to exercise access restriction: -``` +```cmd C:\> obcallbacktestctrl.exe -? (for command line help) C:\> obcallbacktestctrl.exe -install (installs the kernel driver) C:\> obcallbacktestctrl.exe -name notepad (specifies that the string "notepad" will be watched as a protected executable) @@ -46,7 +38,7 @@ C:\> obcallbacktestctrl.exe -uninstall (uninstall the kernel drive The following is another sample test you can run to prevent a process from being created: -``` +```cmd C:\> obcallbacktestctrl.exe -install (installs the kernel driver) C:\> obcallbacktestctrl.exe -reject notepad (specifies that the string "notepad" will be watched and prevented from starting as a process) diff --git a/general/pcidrv/README.md b/general/pcidrv/README.md index 1c68893b..877aa103 100644 --- a/general/pcidrv/README.md +++ b/general/pcidrv/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: PCIDRV - WDF Driver for PCI Device - platform: KMDF - language: cpp - category: General PCI WDF - description: Demonstrates how to write a KMDF driver for a PCI device. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617717 ----> - # PCIDRV - WDF Driver for PCI Device This sample demonstrates how to write a KMDF driver for a PCI device. The sample works with the Intel 82557/82558 based PCI Ethernet Adapter (10/100) and Intel compatibles. @@ -50,7 +42,8 @@ The following is a list of key KMDF interfaces demonstrated in this sample: - Reading & Writing to the registry -Note: This sample provides an example of a minimal driver intended for educational purposes. Neither the driver nor its sample test programs are intended for use in a production environment. +> [!NOTE] +> This sample provides an example of a minimal driver intended for educational purposes. Neither the driver nor its sample test programs are intended for use in a production environment. As stated earlier, this sample is meant to demonstrate how to write a KMDF driver for a generic PCI device and not for PCI network controllers. For network controllers, you should write a monolithic NDIS miniport driver based on the samples given under the \\network\\ndis directory. @@ -58,21 +51,21 @@ Note that it is still possible to use a subset of KMDF APIs when writing a NDIS The sample driver has been tested on the following Intel Ethernet controllers: -Device Description | Hardware ID --------------------|------------ -IBM Netfinity 10/100 Ethernet Adapter | PCIVEN_8086&DEV_1229&SUBSYS_005C1014&REV_05 -Intel(R) PRO/100+ Management Adapter with Alert On LAN | PCI\VEN_8086&DEV_1229&SUBSYS_000E8086&REV_08 -Intel 8255x-based PCI Ethernet Adapter (10/100) | PCI\VEN_8086&DEV_1229&SUBSYS_00000000&REV_01 -Intel Pro/100 S Server Adapter | PCI\VEN_8086&DEV_1229&SUBSYS_00508086&REV_0D -Intel 8255x-based PCI Ethernet Adapter (10/100) | PCI\VEN_8086&DEV_1229&SUBSYS_00031179&REV_08 -Intel(R) PRO/100 VE Network Connection | PCI\VEN_8086&DEV_103D&SUBSYS_00011179&REV_83 -Intel(R) PRO/100 VM Network Connection | PCI\VEN_8086&DEV_1031&REV_42 -Intel(R) PRO/100 VE Network Connection | PCI\VEN_8086&DEV_1038&REV_41 -Intel(R) PRO/100 SR Mobile Adapter | PCI\VEN_8086&DEV_1229 +| Device Description | Hardware ID | +| --- | --- | +| IBM Netfinity 10/100 Ethernet Adapter | PCIVEN_8086&DEV_1229&SUBSYS_005C1014&REV_05 | +| Intel(R) PRO/100+ Management Adapter with Alert On LAN | PCI\VEN_8086&DEV_1229&SUBSYS_000E8086&REV_08 | +| Intel 8255x-based PCI Ethernet Adapter (10/100) | PCI\VEN_8086&DEV_1229&SUBSYS_00000000&REV_01 | +| Intel Pro/100 S Server Adapter | PCI\VEN_8086&DEV_1229&SUBSYS_00508086&REV_0D | +| Intel 8255x-based PCI Ethernet Adapter (10/100) | PCI\VEN_8086&DEV_1229&SUBSYS_00031179&REV_08 | +| Intel(R) PRO/100 VE Network Connection | PCI\VEN_8086&DEV_103D&SUBSYS_00011179&REV_83 | +| Intel(R) PRO/100 VM Network Connection | PCI\VEN_8086&DEV_1031&REV_42 | +| Intel(R) PRO/100 VE Network Connection | PCI\VEN_8086&DEV_1038&REV_41 | +| Intel(R) PRO/100 SR Mobile Adapter | PCI\VEN_8086&DEV_1229 | ## Using this sample as a standalone driver -``` +```txt --------------------- | | | MYPING | <-- Usermode test application @@ -102,13 +95,13 @@ You can install the driver as a standalone driver of a custom setup class, calle The PCIDRV sample acts as a power policy owner of the device and implements all the wait-wake and idle detection logic. -## INSTALLATION +## Installation The driver can be installed as a Net class driver or as a standalone driver (user defined class). The KMDF versions of the INF files are dynamically generated from .INX file. In addition to the driver files, you have to include the WDF coinstaller DLL from the \\redist\\wdf folder of the WDK. -You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](http://go.microsoft.com/fwlink/p/?LinkID=226396). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0. +You can obtain redistributable framework updates by downloading the *wdfcoinstaller.msi* package from [WDK 8 Redistributable Components](https://go.microsoft.com/fwlink/p/?LinkID=253170). This package performs a silent install into the directory of your Windows Driver Kit (WDK) installation. You will see no confirmation that the installation has completed. You can verify that the redistributables have been installed on top of the WDK by ensuring there is a redist\\wdf directory under the root directory of the WDK, %ProgramFiles(x86)%\\Windows Kits\\8.0. -### TESTING +### Testing To test standalone driver configuration: You should use the specially developed ping application, called MYPING that comes with the sample. The Ping.exe provided in the system will not work because in this configuration, the test card is not bound to any network protocol - it's not seen as Net device by the system. Currently the test application doesn't have ability to get an IP address from a network DHCP server. As a result, it is better to connect the network device to a private hub and ping another machine connected to that hub. For example, let us say you have a test machine A and another machine B (development box). @@ -154,18 +147,19 @@ Other menu options of myping applications are: - Exit: Terminate the application. -**Note** You can use this application only on a device installed in the standalone configuration. If you run it on a device that's installed as a miniport, you will get an error message. For such devices, you can use the system provided ping.exe. +> [!NOTE] +> You can use this application only on a device installed in the standalone configuration. If you run it on a device that's installed as a miniport, you will get an error message. For such devices, you can use the system provided ping.exe. -## RESOURCES +## Resources For the latest release of the Windows Driver Kit, see [Download the Windows Driver Kit (WDK)](https://docs.microsoft.com/windows-hardware/drivers/download-the-wdk). If you have questions on using or adapting this sample for your project, you can either contact Microsoft Technical Support or post your questions in the Microsoft driver development newsgroup. -## FILE MANIFEST +## File manifest -File | Description ------|------------ -KMDF | Contains the driver. -KMDF\HW | Contains hardware specific code. -TEST | Contains source of test application (MYPING). +| File | Description | +| --- | --- | +| KMDF | Contains the driver | +| KMDF\HW | Contains hardware specific code | +| TEST | Contains source of test application (MYPING) | diff --git a/general/perfcounters/kcs/README.md b/general/perfcounters/kcs/README.md index 358faa65..10316133 100644 --- a/general/perfcounters/kcs/README.md +++ b/general/perfcounters/kcs/README.md @@ -5,23 +5,15 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Kernel Counter Sample (Kcs) - platform: WDM - language: cpp - category: General - description: Demonstrates the use of the kernel-mode performance library. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617718 ----> - # Kernel Counter Sample (Kcs) -The Kcs sample driver demonstrates the use of the [kernel-mode performance library](http://msdn.microsoft.com/en-us/library/windows/hardware/ff548159). The sample driver does not control any hardware; it simply provides example code that demonstrates how to provide counter data from a kernel-mode driver. The code contains comments to explain what each function does. The sample creates geometric wave and trigonometric wave counter sets. +The Kcs sample driver demonstrates the use of the [kernel-mode performance library](https://docs.microsoft.com/windows-hardware/drivers/devtest/kernel-mode-performance-monitoring). The sample driver does not control any hardware; it simply provides example code that demonstrates how to provide counter data from a kernel-mode driver. The code contains comments to explain what each function does. The sample creates geometric wave and trigonometric wave counter sets. This module contains sample code to demonstrate how to provide counter data from a kernel driver. This sample driver should not be used in a production environment. -The Microsoft Windows operating system allows system components and third parties to expose performance metrics in a standard way by using [Performance Counters](http://msdn.microsoft.com/en-us/library/windows/hardware/aa373083). Kernel-mode PCW providers are installed in the system as Performance Counter Library (PERFLIB) (Version 2 providers), which allows their counters to be browsed, and allows for data collection and instance enumeration. Consumers can query KM PCW providers by using PDH and PERFLIB Version 1 without any modification to the consumer code. +The Microsoft Windows operating system allows system components and third parties to expose performance metrics in a standard way by using [Performance Counters](https://docs.microsoft.com/windows/win32/perfctrs/performance-counters-portal). Kernel-mode PCW providers are installed in the system as Performance Counter Library (PERFLIB) (Version 2 providers), which allows their counters to be browsed, and allows for data collection and instance enumeration. Consumers can query KM PCW providers by using PDH and PERFLIB Version 1 without any modification to the consumer code. diff --git a/general/registry/regfltr/README.md b/general/registry/regfltr/README.md index fafe5dbd..b16d92eb 100644 --- a/general/registry/regfltr/README.md +++ b/general/registry/regfltr/README.md @@ -5,33 +5,33 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: RegFltr Sample Driver - platform: WDM - language: cpp - category: General - description: Demonstrates how to write a registry filter driver. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617720 ----> - # RegFltr Sample Driver -The RegFltr sample shows how to write a [registry filter driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff545879).In addition to providing some basic examples, this sample demonstrates the following: +The RegFltr sample shows how to write a [registry filter driver](hhttps://docs.microsoft.com/windows-hardware/drivers/kernel/filtering-registry-calls).In addition to providing some basic examples, this sample demonstrates the following: - How to handle transactional registry operations. + - How and when to capture input parameters. + - Issues and workarounds for version 1.0 of registry filtering. + - Changes in version 1.1 of registry filtering. -- How to use version 1 of the [**REG\_CREATE\_KEY\_INFORMATION**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560920) and [**REG\_OPEN\_KEY\_INFORMATION**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560957) data structures. + +- How to use version 1 of the [**REG\_CREATE\_KEY\_INFORMATION**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_reg_create_key_information) and [**REG\_OPEN\_KEY\_INFORMATION**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_reg_create_key_information) data structures. The RegFltr sample contains several examples of user-mode and kernel-mode registry-filtering operations. Each example comes with its own corresponding registry callback routine, and performs the following steps: 1. Does some setup work. + 1. Registers the callback routine. + 1. Performs one or more registry operations. + 1. Unregisters the callback routine. + 1. Verifies that the sample completed correctly. The sample driver is a minimal driver that is not intended to be used on production systems. To keep the samples simple, the registry callback routines provided do not check for all possible situations and error conditions. This sample is designed to demonstrate typical scenarios and no other registry filtering driver is expected to be active. diff --git a/general/toaster/toastDrv/README.md b/general/toaster/toastDrv/README.md index 022a27ca..fc84c39d 100644 --- a/general/toaster/toastDrv/README.md +++ b/general/toaster/toastDrv/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Toaster Sample Driver - platform: KMDF UMDF1 - language: cpp - category: General WDF - description: An iterative series of samples that demonstrate KDMF and UDMF1 driver development. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620309 ----> - # Toaster Sample Driver The Toaster collection is an iterative series of samples that demonstrate fundamental aspects of Windows driver development for both Kernel-Mode Driver Framework (KMDF) and User-Mode Driver Framework (UMDF) version 1. @@ -26,9 +18,9 @@ The Toaster sample collection comprises driver projects (.vcxproj files) that ar ## Related technologies -[Windows Driver Frameworks](http://msdn.microsoft.com/en-us/library/windows/hardware/ff557565) +[Windows Driver Frameworks](https://docs.microsoft.com/windows-hardware/drivers/wdf/) -For detailed descriptions and code walkthroughs of each project, see [Sample Toaster Driver Programming Tour](http://msdn.microsoft.com/en-us/library/windows/hardware/dn569312). To learn how to build and run the samples, read on. +For detailed descriptions and code walkthroughs of each project, see [Sample Toaster Driver Programming Tour](https://docs.microsoft.com/windows-hardware/drivers/wdf/sample-toaster-driver-programming-tour). To learn how to build and run the samples, read on. ## Run the sample @@ -41,26 +33,32 @@ The process of moving the driver package to the target computer and installing t Before doing this, you should back up your package.vcxproj file, located in your sample directory, for example C:\\Toaster\\C++\\Package. 1. In the Properties for the package project, navigate to **Common Properties \> References**. + 1. Remove all references except WdfSimple. (Use the **Remove Reference** button at the bottom.) ### Automatic deployment (root enumerated) -Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). +Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1). 1. On the host computer, in Visual Studio, in Solution Explorer, right click the **package** project (within the package folder), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**. + 1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, use the drop down to select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter **{b85b7c50-6a01-11d2-b841-00c04fad5171}\\MsToaster** for the hardware ID. (You can find this value in the WdfSimple.inx file.) Click **Apply** and **OK**. + 1. Because this solution contains many projects, you may find it easier to remove some of them before you build and deploy a driver package. To do so, right click **package** (lower case), and choose **Properties**. Navigate to **Common Properties-\>References** and click **Remove Reference** to remove projects you don't want. (You can add them back later by using **Add New Reference**.) Click **OK**. + 1. On the **Build** menu, choose **Build Solution** or **Rebuild Solution** (if you removed references). + 1. If you removed references and deployment does not succeed, try deleting the contents of the c:\\DriverTest\\Drivers folder on the target machine, and then retry deployment. ### Manual deployment (root enumerated) -Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). +Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). 1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WdfSimplePackage). + 1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command: - **devcon install WdfSimple.inf {b85b7c50-6a01-11d2-b841-00c04fad5171}\\MsToaster** + `devcon install WdfSimple.inf {b85b7c50-6a01-11d2-b841-00c04fad5171}\\MsToaster` ### View the root enumerated driver in Device Manager @@ -72,78 +70,95 @@ In Device Manager, on the **View** menu, choose **Devices by connection**. Locat As an alternative to building the Toaster sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, Toaster.sln. Use the MSBuild command to build the solution. Here are some examples: -**msbuild /p:configuration="Debug" /p:platform="x64" Toaster.sln** +`msbuild /p:configuration="Debug" /p:platform="x64" Toaster.sln` -**msbuild /p:configuration="Release" /p:platform="Win32" Toaster.sln** +`msbuild /p:configuration="Release" /p:platform="Win32" Toaster.sln` -For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644). +For more information about using MSBuild to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver). ## UMDF Toaster File Manifest -#### WUDFToaster.idl +### WUDFToaster.idl + Component Interface file -#### WUDFToaster.cpp +### WUDFToaster.cpp + DLL Support code - provides the DLL's entry point as well as the DllGetClassObject export. -#### WUDFToaster.def +### WUDFToaster.def + This file lists the functions that the driver DLL exports. -#### stdafx.h +### stdafx.h + This is the main header file for the sample driver. -#### driver.cpp & driver.h +### driver.cpp and driver.h (WUDFToaster) + Definition and implementation of the IDriverEntry callbacks in CDriver class. -#### device.cpp & device.h +### device.cpp and device.h (WUDFToaster) + Definition and implementation of various interfaces and their callbacks in CDevice class. Add your PnP and Power interfaces specific for your hardware. -#### queue.cpp & queue.h +### queue.cpp and queue.h + Definition and implementation of the base queue callback class (CQueue). IQueueCallbackDevicekIoControl, IQueueCallbackRead and IQueueCallBackWrite callbacks are implemented to handle I/O control requests. -#### WUDFToaster.rc +### WUDFToaster.rc + This file defines resource information for the WUDF Toaster sample driver. -#### WUDFToaster.inf +### WUDFToaster.inf + Sample INF for installing the sample WUDF Toaster driver under the Toaster class of devices. -#### WUDFtoaster.ctl, internal.h +### WUDFtoaster.ctl, internal.h + This file lists the WPP trace control GUID(s) for the sample driver. This file can be used with the tracelog command's -guid flag to enable the collection of these trace events within an established trace session. These GUIDs must remain in sync with the trace control guids defined in internal.h. ## Toastmon File Manifest -#### comsup.cpp & comsup.h +### comsup.cpp and comsup.h + Boilerplate COM Support code - specifically base classes which provide implementations for the standard COM interfaces IUnknown and IClassFactory which are used throughout the sample. The implementation of IClassFactory is designed to create instances of the CMyDriver class. If you should change the name of your base driver class, you would also need to modify this file. -#### dllsup.cpp +### dllsup.cpp + Boilerplate DLL Support code - provides the DLL's entry point as well as the single required export (DllGetClassObject). These depend on comsup.cpp to perform the necessary class creation. -#### exports.def +### exports.def + This file lists the functions that the driver DLL exports. -#### makefile -This file redirects to the real makefile, which is shared by all the driver components of the Windows Driver Kit. +### internal.h -#### internal.h This is the main header file for the ToastMon driver -#### driver.cpp & driver.h +### driver.cpp and driver.h (Toastmon) + Definition and implementation of the driver callback class for the ToastMon sample. -#### device.cpp & device.h +### device.cpp and device.h (Toastmon) + Definition and implementation of the device callback class for the ToastMon sample. This is mostly boilerplate, but also registers for RemoteInterface Arrival notifications. When a RemoteInterface arrival callback occurs, it calls CreateRemoteInterface and creates a CMyRemoteTarget callback object to handle I/O on that RemoteInterface. -#### RemoteTarget.cpp & RemoteTarget.h +### RemoteTarget.cpp and RemoteTarget.h + Definition and implementation of the remote target callback class for the ToastMon sample. -#### list.h +### list.h + Doubly-linked-list code -#### ToastMon.rc +### ToastMon.rc + This file defines resource information for the ToastMon sample driver. -#### UMDFToastMon.inf +### UMDFToastMon.inf + Sample INF for installing the Skeleton driver to control a root enumerated device with a hardware ID of UMDFSamples\\ToastMon diff --git a/general/toaster/toastDrv/kmdf/bus/dynamic/busenum.c b/general/toaster/toastDrv/kmdf/bus/dynamic/busenum.c index 8b79bff1..e8f62064 100644 --- a/general/toaster/toastDrv/kmdf/bus/dynamic/busenum.c +++ b/general/toaster/toastDrv/kmdf/bus/dynamic/busenum.c @@ -58,7 +58,7 @@ Return Value: KdPrint(("WDF Toaster Bus Driver Sample Dynamic Version.\n")); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If you create any resources // in the DriverEntry and want to be cleaned in driver unload, diff --git a/general/toaster/toastDrv/kmdf/bus/dynamic/buspdo.c b/general/toaster/toastDrv/kmdf/bus/dynamic/buspdo.c index d7d2cf54..52c847d3 100644 --- a/general/toaster/toastDrv/kmdf/bus/dynamic/buspdo.c +++ b/general/toaster/toastDrv/kmdf/bus/dynamic/buspdo.c @@ -82,8 +82,8 @@ Return Value: return status; } - dst->HardwareIds = (PWCHAR) ExAllocatePoolWithTag( - NonPagedPoolNx, + dst->HardwareIds = (PWCHAR) ExAllocatePool2( + POOL_FLAG_NON_PAGED, safeMultResult, BUS_TAG); diff --git a/general/toaster/toastDrv/kmdf/bus/static/busenum.c b/general/toaster/toastDrv/kmdf/bus/static/busenum.c index 41e79f0f..cc54d346 100644 --- a/general/toaster/toastDrv/kmdf/bus/static/busenum.c +++ b/general/toaster/toastDrv/kmdf/bus/static/busenum.c @@ -59,7 +59,7 @@ Return Value: KdPrint(("Toaster Static Bus Driver Sample - Driver Framework Edition.\n")); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If you create any resources // in the DriverEntry and want to be cleaned in driver unload, diff --git a/general/toaster/toastDrv/kmdf/filter/generic/filter.c b/general/toaster/toastDrv/kmdf/filter/generic/filter.c index c1dadac2..673f55f7 100644 --- a/general/toaster/toastDrv/kmdf/filter/generic/filter.c +++ b/general/toaster/toastDrv/kmdf/filter/generic/filter.c @@ -67,7 +67,7 @@ Return Value: KdPrint(("Toaster Generic Filter Driver Sample - Driver Framework Edition.\n")); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If you create any resources // in the DriverEntry and want to be cleaned in driver unload, diff --git a/general/toaster/toastDrv/kmdf/func/featured/toaster.c b/general/toaster/toastDrv/kmdf/func/featured/toaster.c index be826982..772b0416 100644 --- a/general/toaster/toastDrv/kmdf/func/featured/toaster.c +++ b/general/toaster/toastDrv/kmdf/func/featured/toaster.c @@ -113,7 +113,7 @@ Return Value: KdPrint(("WDF Toaster Function Driver Sample - Featured version\n")); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If you create any resources // in the DriverEntry and want to be cleaned in driver unload, diff --git a/general/toaster/toastDrv/kmdf/func/featured/wmi.c b/general/toaster/toastDrv/kmdf/func/featured/wmi.c index e7c76a23..f62eacd3 100644 --- a/general/toaster/toastDrv/kmdf/func/featured/wmi.c +++ b/general/toaster/toastDrv/kmdf/func/featured/wmi.c @@ -446,11 +446,9 @@ ToasterFireArrivalEvent( // // Allocate memory for the WNODE from NonPagedPoolNx // - wnode = ExAllocatePoolWithTag(NonPagedPoolNx, size, TOASTER_POOL_TAG); + wnode = ExAllocatePool2(POOL_FLAG_NON_PAGED, size, TOASTER_POOL_TAG); if (NULL != wnode) { - RtlZeroMemory(wnode, size); - wnode->WnodeHeader.BufferSize = size; wnode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId( diff --git a/general/toaster/toastDrv/kmdf/func/simple/toaster.c b/general/toaster/toastDrv/kmdf/func/simple/toaster.c index 6ed215db..7b117240 100644 --- a/general/toaster/toastDrv/kmdf/func/simple/toaster.c +++ b/general/toaster/toastDrv/kmdf/func/simple/toaster.c @@ -72,7 +72,7 @@ Return Value: KdPrint(("Toaster Function Driver Sample - Driver Framework Edition.\n")); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If DriverEntry creates any resources // that require clean-up in driver unload, diff --git a/general/toaster/toastDrv/kmdf/toastmon/toastmon.c b/general/toaster/toastDrv/kmdf/toastmon/toastmon.c index 44f6f5d2..5967d019 100644 --- a/general/toaster/toastDrv/kmdf/toastmon/toastmon.c +++ b/general/toaster/toastDrv/kmdf/toastmon/toastmon.c @@ -77,7 +77,7 @@ Return Value: KdPrint(("ToastMon Driver Sample - Driver Framework Edition.\n")); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If you create any resources // in the DriverEntry and want to be cleaned in driver unload, diff --git a/general/toaster/toastpkg/README.md b/general/toaster/toastpkg/README.md index 0d2b335c..7aceb704 100644 --- a/general/toaster/toastpkg/README.md +++ b/general/toaster/toastpkg/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Toaster Package Sample Driver - platform: WDM - language: cpp - category: General - description: Simulates hardware-first and software-first installation of the toaster sample driver. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617723 ----> - # Toaster Package Sample Driver The Toaster collection is an iterative series of samples that demonstrate fundamental aspects of Windows driver development for both Kernel-Mode Driver Framework (KMDF) and User-Mode Driver Framework (UMDF) version 1. @@ -26,9 +18,9 @@ The Toaster sample collection comprises driver projects (.vcxproj files) that ar ## Related technologies -[Windows Driver Frameworks](http://msdn.microsoft.com/en-us/library/windows/hardware/ff557565) +[Windows Driver Frameworks](https://docs.microsoft.com/windows-hardware/drivers/wdf/) -For detailed descriptions and code walkthroughs of each project, see [Sample Toaster Driver Programming Tour](http://msdn.microsoft.com/en-us/library/windows/hardware/dn569312). To learn how to build and run the samples, read on. +For detailed descriptions and code walkthroughs of each project, see [Sample Toaster Driver Programming Tour](https://docs.microsoft.com/windows-hardware/drivers/wdf/sample-toaster-driver-programming-tour). To learn how to build and run the samples, read on. ## Run the sample @@ -41,23 +33,29 @@ The process of moving the driver package to the target computer and installing t Before doing this, you should back up your package.vcxproj file, located in your sample directory, for example C:\\Toaster\\C++\\Package. 1. In the Properties for the package project, navigate to **Common Properties \> References**. + 1. Remove all references except WdfSimple. (Use the **Remove Reference** button at the bottom.) ### Automatic deployment (root enumerated) -Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). +Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1). 1. On the host computer, in Visual Studio, in Solution Explorer, right click the **package** project (within the package folder), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**. + 1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, use the drop down to select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter **{b85b7c50-6a01-11d2-b841-00c04fad5171}\\MsToaster** for the hardware ID. (You can find this value in the WdfSimple.inx file.) Click **Apply** and **OK**. + 1. Because this solution contains many projects, you may find it easier to remove some of them before you build and deploy a driver package. To do so, right click **package** (lower case), and choose **Properties**. Navigate to **Common Properties-\>References** and click **Remove Reference** to remove projects you don't want. (You can add them back later by using **Add New Reference**.) Click **OK**. + 1. On the **Build** menu, choose **Build Solution** or **Rebuild Solution** (if you removed references). + 1. If you removed references and deployment does not succeed, try deleting the contents of the c:\\DriverTest\\Drivers folder on the target machine, and then retry deployment. ### Manual deployment (root enumerated) -Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). +Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). 1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\WdfSimplePackage). + 1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter the following command: **devcon install WdfSimple.inf {b85b7c50-6a01-11d2-b841-00c04fad5171}\\MsToaster** @@ -72,78 +70,95 @@ In Device Manager, on the **View** menu, choose **Devices by connection**. Locat As an alternative to building the Toaster sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, Toaster.sln. Use the MSBuild command to build the solution. Here are some examples: -**msbuild /p:configuration="Debug" /p:platform="x64" Toaster.sln** +`msbuild /p:configuration="Debug" /p:platform="x64" Toaster.sln` -**msbuild /p:configuration="Release" /p:platform="Win32" Toaster.sln** +`msbuild /p:configuration="Release" /p:platform="Win32" Toaster.sln` -For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644). +For more information about using MSBuild to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver). ## UMDF Toaster File Manifest -#### WUDFToaster.idl +### WUDFToaster.idl + Component Interface file -#### WUDFToaster.cpp +### WUDFToaster.cpp + DLL Support code - provides the DLL's entry point as well as the DllGetClassObject export. -#### WUDFToaster.def +### WUDFToaster.def + This file lists the functions that the driver DLL exports. -#### stdafx.h +### stdafx.h + This is the main header file for the sample driver. -#### driver.cpp & driver.h +### driver.cpp and driver.h (WUDFToaster) + Definition and implementation of the IDriverEntry callbacks in CDriver class. -#### device.cpp & device.h +### device.cpp and device.h (WUDFToaster) + Definition and implementation of various interfaces and their callbacks in CDevice class. Add your PnP and Power interfaces specific for your hardware. -#### queue.cpp & queue.h +### queue.cpp and queue.h + Definition and implementation of the base queue callback class (CQueue). IQueueCallbackDevicekIoControl, IQueueCallbackRead and IQueueCallBackWrite callbacks are implemented to handle I/O control requests. -#### WUDFToaster.rc +### WUDFToaster.rc + This file defines resource information for the WUDF Toaster sample driver. -#### WUDFToaster.inf +### WUDFToaster.inf + Sample INF for installing the sample WUDF Toaster driver under the Toaster class of devices. -#### WUDFtoaster.ctl, internal.h +### WUDFtoaster.ctl, internal.h + This file lists the WPP trace control GUID(s) for the sample driver. This file can be used with the tracelog command's -guid flag to enable the collection of these trace events within an established trace session. These GUIDs must remain in sync with the trace control guids defined in internal.h. ## Toastmon File Manifest -#### comsup.cpp & comsup.h +### comsup.cpp and comsup.h + Boilerplate COM Support code - specifically base classes which provide implementations for the standard COM interfaces IUnknown and IClassFactory which are used throughout the sample. The implementation of IClassFactory is designed to create instances of the CMyDriver class. If you should change the name of your base driver class, you would also need to modify this file. -#### dllsup.cpp +### dllsup.cpp + Boilerplate DLL Support code - provides the DLL's entry point as well as the single required export (DllGetClassObject). These depend on comsup.cpp to perform the necessary class creation. -#### exports.def +### exports.def + This file lists the functions that the driver DLL exports. -#### makefile -This file redirects to the real makefile, which is shared by all the driver components of the Windows Driver Kit. +### internal.h -#### internal.h This is the main header file for the ToastMon driver -#### driver.cpp & driver.h +### driver.cpp and driver.h (Toastmon) + Definition and implementation of the driver callback class for the ToastMon sample. -#### device.cpp & device.h +### device.cpp and device.h (Toastmon) + Definition and implementation of the device callback class for the ToastMon sample. This is mostly boilerplate, but also registers for RemoteInterface Arrival notifications. When a RemoteInterface arrival callback occurs, it calls CreateRemoteInterface and creates a CMyRemoteTarget callback object to handle I/O on that RemoteInterface. -#### RemoteTarget.cpp & RemoteTarget.h +### RemoteTarget.cpp and RemoteTarget.h + Definition and implementation of the remote target callback class for the ToastMon sample. -#### list.h +### list.h + Doubly-linked-list code -#### ToastMon.rc +### ToastMon.rc + This file defines resource information for the ToastMon sample driver. -#### UMDFToastMon.inf +### UMDFToastMon.inf + Sample INF for installing the Skeleton driver to control a root enumerated device with a hardware ID of UMDFSamples\\ToastMon diff --git a/general/toaster/umdf2/README.md b/general/toaster/umdf2/README.md index 3ec98f60..fb3741c6 100644 --- a/general/toaster/umdf2/README.md +++ b/general/toaster/umdf2/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Toaster Sample (UMDF version 2) - platform: UMDF2 - language: cpp - category: General WDF - description: An iterative series of samples that demonstrate driver development using UMDF version 2. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=620310 ----> - # Toaster Sample (UMDF Version 2) The Toaster (UMDF version 2) sample is an iterative series of samples that demonstrate fundamental aspects of Windows driver development. @@ -24,7 +16,7 @@ The Toaster sample collection is comprised of driver projects (.vcxproj files) t ## Related technologies -[User-Mode Driver Framework](http://msdn.microsoft.com/en-us/library/windows/hardware/ff560456) +[Windows Driver Frameworks](https://docs.microsoft.com/windows-hardware/drivers/wdf/) ## Run the sample @@ -34,22 +26,27 @@ The process of moving the driver package to the target computer and installing t ### Automatic deployment (root enumerated) -Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Configuring a Computer for Driver Deployment, Testing, and Debugging](http://msdn.microsoft.com/en-us/library/windows/hardware/). +Before you automatically deploy a driver, you must provision the target computer. For instructions, see [Provision a computer for driver deployment and testing](https://docs.microsoft.com/windows-hardware/drivers/gettingstarted/provision-a-target-computer-wdk-8-1). 1. On the host computer, in Visual Studio, in Solution Explorer, right click **package** (lower case), and choose **Properties**. Navigate to **Configuration Properties \> Driver Install \> Deployment**. + 1. Check **Enable deployment**, and check **Remove previous driver versions before deployment**. For **Target Computer Name**, select the name of a target computer that you provisioned previously. Select **Hardware ID Driver Update**, and enter **root\\toaster** for the hardware ID. Click **OK**. + 1. Because this solution contains many projects, you may find it easier to remove some of them before you build and deploy a driver package. To do so, right click **package** (lower case), and choose **Properties**. Navigate to **Common Properties-\>References** and click **Remove Reference** to remove projects you don't want. (You can add them back later by using **Add New Reference**.) Click **OK**. + 1. On the **Build** menu, choose **Build Solution** or **Rebuild Solution** (if you removed references). + 1. If you removed references and deployment does not succeed, try deleting the contents of the c:\\DriverTest\\Drivers folder on the target machine, and then retry deployment. ### Manual deployment (root enumerated) -Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). +Before you manually deploy a driver, you must turn on test signing and install a certificate on the target computer. You also need to copy the [DevCon](https://docs.microsoft.com/windows-hardware/drivers/devtest/devcon) tool to the target computer. For instructions, see [Preparing a Computer for Manual Driver Deployment](https://docs.microsoft.com/windows-hardware/drivers/develop/preparing-a-computer-for-manual-driver-deployment). 1. Copy all of the files in your driver package to a folder on the target computer (for example, c:\\Umdf2toaster). + 1. On the target computer, open a Command Prompt window as Administrator. Navigate to your driver package folder, and enter a command such as: - **devcon install wdfsimpleum.inf root\\toaster** + `devcon install wdfsimpleum.inf root\\toaster` ### View the root enumerated driver in Device Manager @@ -61,6 +58,6 @@ In Device Manager, on the **View** menu, choose **Devices by connection**. Locat As an alternative to building the driver sample in Visual Studio, you can build it in a Visual Studio Command Prompt window. In Visual Studio, on the **Tools** menu, choose **Visual Studio Command Prompt**. In the Visual Studio Command Prompt window, navigate to the folder that has the solution file, Umdf2toaster.sln. Use the MSBuild command to build the solution. Here is an example: -**msbuild /p:configuration="Release" /p:platform="Win32" Umdf2toaster.sln** +`msbuild /p:configuration="Release" /p:platform="Win32" Umdf2toaster.sln` -For more information about using MSBuild to build a driver package, see [Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644). +For more information about using MSBuild to build a driver package, see [Building a Driver with Visual Studio and the WDK](https://docs.microsoft.com/windows-hardware/drivers/develop/building-a-driver). diff --git a/general/toaster/umdf2/filter/generic/filter.c b/general/toaster/umdf2/filter/generic/filter.c index d245c2ba..b2897dc5 100644 --- a/general/toaster/umdf2/filter/generic/filter.c +++ b/general/toaster/umdf2/filter/generic/filter.c @@ -67,7 +67,7 @@ Return Value: KdPrint(("Toaster Generic Filter Driver Sample - Driver Framework Edition.\n")); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If you create any resources // in the DriverEntry and want to be cleaned in driver unload, diff --git a/general/toaster/umdf2/func/featured/toaster.c b/general/toaster/umdf2/func/featured/toaster.c index c25eebd4..157c1843 100644 --- a/general/toaster/umdf2/func/featured/toaster.c +++ b/general/toaster/umdf2/func/featured/toaster.c @@ -75,7 +75,7 @@ Return Value: KdPrint(("WDF Toaster Function Driver Sample - Featured version\n")); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If you create any resources // in the DriverEntry and want to be cleaned in driver unload, diff --git a/general/toaster/umdf2/func/simple/toaster.c b/general/toaster/umdf2/func/simple/toaster.c index 6ed215db..7b117240 100644 --- a/general/toaster/umdf2/func/simple/toaster.c +++ b/general/toaster/umdf2/func/simple/toaster.c @@ -72,7 +72,7 @@ Return Value: KdPrint(("Toaster Function Driver Sample - Driver Framework Edition.\n")); // - // Initiialize driver config to control the attributes that + // Initialize driver config to control the attributes that // are global to the driver. Note that framework by default // provides a driver unload routine. If DriverEntry creates any resources // that require clean-up in driver unload, diff --git a/general/tracing/SystemTraceControl/README.md b/general/tracing/SystemTraceControl/README.md index bf94caa7..4a4335f4 100644 --- a/general/tracing/SystemTraceControl/README.md +++ b/general/tracing/SystemTraceControl/README.md @@ -5,23 +5,15 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: System Trace Control - platform: Application - language: cpp - category: General Tracing - description: Demonstrates how to use event tracing control APIs to collect events from the system trace provider. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617725 ----> - # SystemTraceProvider This sample application demonstrates how to use event tracing control APIs to collect events from the system trace provider. -The sample code provided shows how to start an [Event Tracing](http://msdn.microsoft.com/en-us/library/windows/hardware/bb968803) for Windows trace session and how to enable system events with stacks. When you build and run the application, it collects the trace data for 30 seconds and then stops. The sample application writes the results to a file, Systemtrace.etl. For more information, see [Tools for Software Tracing](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552961). +The sample code provided shows how to start an [Event Tracing](https://docs.microsoft.com/windows/win32/etw/event-tracing-portal) for Windows trace session and how to enable system events with stacks. When you build and run the application, it collects the trace data for 30 seconds and then stops. The sample application writes the results to a file, Systemtrace.etl. For more information, see [Tools for Software Tracing](https://docs.microsoft.com/windows-hardware/drivers/devtest/tools-for-software-tracing). -You can process the Systemtrace.etl file using Tracerpt.exe, a command-line trace tool included in Windows that formats trace events. It also analyzes the events and generates summary reports. For more information about how to use this tool, see [Tracerpt](http://go.microsoft.com/fwlink/p/?linkid=179389) topic on the TechNet website. +You can process the Systemtrace.etl file using Tracerpt.exe, a command-line trace tool included in Windows that formats trace events. It also analyzes the events and generates summary reports. For more information about how to use this tool, see [Tracerpt](https://docs.microsoft.com/windows-server/administration/windows-commands/tracerpt_1). -You can also process the file using the [Windows Performance Toolkit](http://go.microsoft.com/fwlink/p/?linkid=250774) (WPT), which is available in the SDK. +You can also process the file using the [Windows Performance Toolkit](https://docs.microsoft.com/windows-hardware/test/wpt/) (WPT), which is available in the SDK. diff --git a/general/tracing/evntdrv/README.md b/general/tracing/evntdrv/README.md index 588e7894..cf2d5f06 100644 --- a/general/tracing/evntdrv/README.md +++ b/general/tracing/evntdrv/README.md @@ -5,36 +5,28 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Eventdrv - platform: Application - language: cpp - category: General Tracing - description: Demonstrates the use of the Event Tracing for Windows (ETW) API in a driver. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617724 ----> - # Eventdrv -Eventdrv is a sample kernel-mode trace provider and driver. The driver does not control any hardware; it simply generates trace events. It is designed to demonstrate the use of the [Event Tracing for Windows (ETW)](http://msdn.microsoft.com/en-us/library/windows/hardware/ff545699) API in a driver. +Eventdrv is a sample kernel-mode trace provider and driver. The driver does not control any hardware; it simply generates trace events. It is designed to demonstrate the use of the [Event Tracing for Windows (ETW)](https://docs.microsoft.com/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-) API in a driver. -Evntdrv registers as a provider by calling the [**EtwRegister**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff545603) API. If the registration is successful, it logs a StartEvent with the device's name, the length of the name, and the status code. Then, when the sample receives a DeviceIOControl call, it logs a SampleEventA event. Finally, when the driver gets unloaded, it logs an UnloadEvent event with a pointer to the device object +Evntdrv registers as a provider by calling the [**EtwRegister**](https://docs.microsoft.com/windows-hardware/drivers/ddi/content/wdm/nf-wdm-etwregister) API. If the registration is successful, it logs a StartEvent with the device's name, the length of the name, and the status code. Then, when the sample receives a DeviceIOControl call, it logs a SampleEventA event. Finally, when the driver gets unloaded, it logs an UnloadEvent event with a pointer to the device object -**Note** The Windows Pre-Processor (WPP) Tracing tools such as TraceView.exe cannot be used to start, stop, or view traces. +> [!NOTE] +> The Windows Pre-Processor (WPP) Tracing tools such as TraceView.exe cannot be used to start, stop, or view traces. ## Run the sample 1. Install the manifest (Evntdrv.xml), which is located in the Evntdrv\\Eventdrv folder. Open a Visual Studio Command window (Run as administrator) and use the following command: - ``` - wevtutil im evntdrv.xml - ``` + `wevtutil im evntdrv.xml` + + Installing the manifest creates registry keys that enable tools to find the resource and message files that contain event provider information. For further details, see [wevtutil](https://docs.microsoft.com/windows-server/administration/windows-commands/wevtutil). - Installing the manifest creates registry keys that enable tools to find the resource and message files that contain event provider information. For further details about the WevtUtil.exe tool, see the MSDN Library. - - **Note** Using a Visual Studio Command windows sets up the environment variables you need to run the tracing tools for this sample. + > [!NOTE] + > Using a Visual Studio Command windows sets up the environment variables you need to run the tracing tools for this sample. 1. Make a folder in the system directory called ETWDriverSample (for example, C:\\ETWDriverSample). @@ -44,32 +36,24 @@ Evntdrv registers as a provider by calling the [**EtwRegister**](http://msdn.mic 1. Use Tracelog to start a trace session that is called "TestEventdrv." The following command starts the trace session and creates a trace log file, Eventdrv.etl, in the local directory. - ``` - Tracelog -start TestEventdrv -guid #b5a0bda9-50fe-4d0e-a83d-bae3f58c94d6 -f Eventdrv.etl - ``` + `tracelog -start TestEventdrv -guid #b5a0bda9-50fe-4d0e-a83d-bae3f58c94d6 -f Eventdrv.etl` 1. To generate trace messages, run Evntctrl.exe. Each time you type a character other than **Q** or **q**, Evntctrl sends an IOCTL to the driver that signals it to generate trace messages. To stop Evntctrl, type **Q** or **q**. 1. To stop the trace session, run the following command: - ``` - tracelog -stop TestEventdrv - ``` + `tracelog -stop TestEventdrv` 1. To display the traces collected in the Tracedrv.etl file, run the following command: - ``` - tracerpt Eventdrv.etl - ``` + `tracerpt Eventdrv.etl` This command creates two files: Summary.txt and Dumpfile.xml. Dumpfile.xml will contain the event information in an XML format. 1. To uninstall the manifest, run the following command: - ``` - wevtutil um evntdrv.xml - ``` + `wevtutil um evntdrv.xml` ## Notes -If you are building the Eventdrv sample to test on a 64-bit version of Windows, you need to sign the driver. All 64-bit versions of Windows require driver code to have a digital signature for the driver to load. See [Signing a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554809) and [Signing a Driver During Development and Testing](http://msdn.microsoft.com/en-us/library/windows/hardware/hh967733). You might also need to configure the test computer so that it can load test-signed kernel mode code, see [The TESTSIGNING Boot Configuration Option](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553484) and [**BCDEdit /set**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff542202). +If you are building the Eventdrv sample to test on a 64-bit version of Windows, you need to sign the driver. All 64-bit versions of Windows require driver code to have a digital signature for the driver to load. See [Signing a Driver](https://docs.microsoft.com/windows-hardware/drivers/develop/signing-a-driver) and [Signing a Driver During Development and Testing](https://docs.microsoft.com/windows-hardware/drivers/install/signing-drivers-during-development-and-test). You might also need to configure the test computer so that it can load test-signed kernel mode code, see [The TESTSIGNING Boot Configuration Option](https://docs.microsoft.com/windows-hardware/drivers/install/the-testsigning-boot-configuration-option) and [**BCDEdit /set**](https://docs.microsoft.com/windows-hardware/drivers/devtest/bcdedit--set). diff --git a/general/tracing/tracedriver/README.md b/general/tracing/tracedriver/README.md index c050eedf..3d32e0b6 100644 --- a/general/tracing/tracedriver/README.md +++ b/general/tracing/tracedriver/README.md @@ -5,33 +5,26 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: Tracedrv - platform: Application - language: cpp - category: General Tracing - description: A sample driver instrumented for software tracing. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617726 ----> - # Tracedrv Tracedrv is a sample driver instrumented for software tracing. The driver does not control any hardware; it simply generates trace messages. It is designed to show how to use WPP software tracing macros in a driver. Tracedrv initializes tracing (by using WPP\_INIT\_TRACING) and, when it receives a DeviceIOControl call, it starts a thread that logs 100 trace messages. The WPP software tracing directives, calls, and macros in the code are accompanied by comments that explain their purpose -While examining Tracedrv, read the [WPP Software Tracing](http://msdn.microsoft.com/en-us/library/windows/hardware/ff556204) in the Windows Driver Kit (WDK). This section includes a reference section that describes the directives, macros, and calls required for WPP software tracing. +While examining Tracedrv, read the [WPP Software Tracing](https://docs.microsoft.com/windows-hardware/drivers/devtest/wpp-software-tracing) in the Windows Driver Kit (WDK). This section includes a reference section that describes the directives, macros, and calls required for WPP software tracing. ## Run the sample To test the Tracedrv event tracing provider, use the following procedure. 1. Copy the Tracectl.exe file that was created when you built the Tracedrv solution from the Tracectl directory (for example, \\Documents\\Visual Studio 2015\\Projects\\tracedrv\\tracectl\\*platform*) to the Tracedrv directory (for example, \\Documents\\Visual Studio 2015\\Projects\\tracedrv\\tracedrv\\*platform*). + 1. Use Tracepdb to create a trace message format (TMF) file and a trace message control (TMC) file from the Tracedrv.pdb file. Tracepdb is located in the C:\\Program Files (x86)\\Windows Kits\\10\\bin\\*platform* directory. The PDB file that is used in this command is created when you the build the solution. Open a Visual Studio Command prompt window and navigate to the target build platform and configuration directory. Type the following command: - **tracepdb -f tracedrv.pdb** + `tracepdb -f tracedrv.pdb` 1. In the same Tracedrv target build directory, create a control GUID file for Tracedrv by opening a text file, adding the following content, and saving the file as Tracedrv.ctl. @@ -41,26 +34,22 @@ To test the Tracedrv event tracing provider, use the following procedure. 1. Use Tracelog to start a trace session that is called *TestTracedrv*. Tracelog is located in the C:\\Program Files (x86)\\Windows Kits\\10\\bin\\*platform* directory. The Tracedrv.ctl file that is used in this command was created in the previous step. The following command starts a trace session and creates a trace log file, tracedrv.etl, in the local directory. - ``` - tracelog -start TestTracedrv -guid tracedrv.ctl -f tracedrv.etl -flag 1 - ``` + `tracelog -start TestTracedrv -guid tracedrv.ctl -f tracedrv.etl -flag 1` - **Note** Without the -flag parameter, Tracedrv will not generate any trace messages. + > [!NOTE] + > Without the -flag parameter, Tracedrv will not generate any trace messages. 1. To generate trace messages, run Tracectl.exe. This executable file is built when you build the solution. Each time you type a character, other than **Q** or **q**, Tracectl sends an IOCTL to the driver that signals it to generate trace messages. To stop Tracectl, type **Q** or **q**. + 1. To stop the trace session, use the following Tracelog command. - ``` - tracelog -stop TestTracedrv - ``` + `tracelog -stop TestTracedrv` 1. To display the trace messages in the Tracedrv.etl file, use Tracefmt.exe. Tracefmt.exe is located in the C:\\Program Files (x86)\\Windows Kits\\10\\bin\\*platform*. The TMF file used in this command was created by Tracepdb.exe in step 2. The **-p** option specifies the directory of the TMF file. In this case, the TMF file is in the current directory. Type the following command: - ``` - tracefmt tracedrv.etl -p . -o Tracedrv.out - ``` + `tracefmt tracedrv.etl -p . -o Tracedrv.out` -The resulting Tracedrv.out file is a human-readable text file of the Tracedrv trace messages. To interpret the trace messages, in the Tracedrv.c file, search for the [**DoTraceMessage**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544918) macros. +The resulting Tracedrv.out file is a human-readable text file of the Tracedrv trace messages. To interpret the trace messages, in the Tracedrv.c file, search for the [**DoTraceMessage**](https://docs.microsoft.com/previous-versions/windows/hardware/previsioning-framework/ff544918(v=vs.85)) macros. ## Notes @@ -68,6 +57,6 @@ This sample driver should not be used in a production environment. Also, because it is not a Plug and Play driver, Tracedrv does not demonstrate tracing in a Plug and Play environment. -Tracedrv demonstrates the basic elements required for software tracing. It does not demonstrate more advanced tracing techniques, such as writing customized tracing calls (variations of [**DoTraceMessage**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544918)), or the use of WMI calls for software tracing. +Tracedrv demonstrates the basic elements required for software tracing. It does not demonstrate more advanced tracing techniques, such as writing customized tracing calls (variations of [**DoTraceMessage**](https://docs.microsoft.com/previous-versions/windows/hardware/previsioning-framework/ff544918(v=vs.85))), or the use of WMI calls for software tracing. -If you are building the Tracedrv sample to test on a 64-bit version of Windows, you need to sign the driver. All 64-bit versions of Windows require driver code to have a digital signature for the driver to load. See [Signing a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554809) and [Signing a Driver During Development and Testing](http://msdn.microsoft.com/en-us/library/windows/hardware/hh967733). You might also need to configure the test computer so that it can load test-signed kernel mode code, see [The TESTSIGNING Boot Configuration Option](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553484) and [**BCDEdit /set**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff542202). +If you are building the Tracedrv sample to test on a 64-bit version of Windows, you need to sign the driver. All 64-bit versions of Windows require driver code to have a digital signature for the driver to load. See [Signing a Driver](https://docs.microsoft.com/windows-hardware/drivers/develop/signing-a-driver) and [Signing a Driver During Development and Testing](https://docs.microsoft.com/windows-hardware/drivers/install/signing-drivers-during-development-and-test). You might also need to configure the test computer so that it can load test-signed kernel mode code, see [The TESTSIGNING Boot Configuration Option](https://docs.microsoft.com/windows-hardware/drivers/install/the-testsigning-boot-configuration-option) and [**BCDEdit /set**](https://docs.microsoft.com/windows-hardware/drivers/devtest/bcdedit--set). diff --git a/general/umdfSkeleton/README.md b/general/umdfSkeleton/README.md index 05cc5cb6..59a5f25b 100644 --- a/general/umdfSkeleton/README.md +++ b/general/umdfSkeleton/README.md @@ -5,17 +5,9 @@ languages: - cpp products: - windows +- windows-wdk --- -<!--- - name: UMDF Driver Skeleton Sample (UMDF version 1) - platform: UMDF1 - language: cpp - category: General WDF - description: Demonstrates how to use UDMF to write a minimal driver. - samplefwlink: http://go.microsoft.com/fwlink/p/?LinkId=617727 ----> - # UMDF Driver Skeleton Sample (UMDF Version 1) This sample demonstrates how to use version 1 of the User-Mode Driver Framework to write a minimal driver. |
