diff options
Diffstat (limited to 'setup')
| -rw-r--r-- | setup/DIFxAPI/AppDrv/AppDrv.vcxproj | 187 | ||||
| -rw-r--r-- | setup/DIFxAPI/AppDrv/AppDrv.vcxproj.Filters | 22 | ||||
| -rw-r--r-- | setup/DIFxAPI/AppDrv/AppDrvDepend.c | 147 | ||||
| -rw-r--r-- | setup/DIFxAPI/AppDrv/readme.htm | 109 | ||||
| -rw-r--r-- | setup/DIFxAPI/DIFxAPI.sln | 46 | ||||
| -rw-r--r-- | setup/DIFxAPI/DIFxCmd/DIFxCmd.vcxproj | 187 | ||||
| -rw-r--r-- | setup/DIFxAPI/DIFxCmd/DIFxCmd.vcxproj.Filters | 22 | ||||
| -rw-r--r-- | setup/DIFxAPI/DIFxCmd/difxcmd.c | 218 | ||||
| -rw-r--r-- | setup/DIFxAPI/DIFxCmd/readme.htm | 59 | ||||
| -rw-r--r-- | setup/DIFxAPI/ReadMe.md | 5 | ||||
| -rw-r--r-- | setup/devcon/ReadMe.md | 111 | ||||
| -rw-r--r-- | setup/devcon/cmds.cpp | 2408 | ||||
| -rw-r--r-- | setup/devcon/devcon.cpp | 1162 | ||||
| -rw-r--r-- | setup/devcon/devcon.h | 133 | ||||
| -rw-r--r-- | setup/devcon/devcon.rc | 37 | ||||
| -rw-r--r-- | setup/devcon/devcon.sln | 28 | ||||
| -rw-r--r-- | setup/devcon/devcon.vcxproj | 183 | ||||
| -rw-r--r-- | setup/devcon/devcon.vcxproj.Filters | 33 | ||||
| -rw-r--r-- | setup/devcon/dump.cpp | 1328 | ||||
| -rw-r--r-- | setup/devcon/msg.mc | 987 | ||||
| -rw-r--r-- | setup/devcon/rc_ids.h | 28 |
21 files changed, 7440 insertions, 0 deletions
diff --git a/setup/DIFxAPI/AppDrv/AppDrv.vcxproj b/setup/DIFxAPI/AppDrv/AppDrv.vcxproj new file mode 100644 index 00000000..c82e3348 --- /dev/null +++ b/setup/DIFxAPI/AppDrv/AppDrv.vcxproj @@ -0,0 +1,187 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{51E48BC7-B82C-4F02-8C66-9A94C32E8DE4}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{2431EBAC-383A-407F-B131-FDA52CCA3DFF}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>AppDrv</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>AppDrv</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>AppDrv</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>AppDrv</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);difxapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);difxapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);difxapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);difxapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="AppDrvDepend.c" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/setup/DIFxAPI/AppDrv/AppDrv.vcxproj.Filters b/setup/DIFxAPI/AppDrv/AppDrv.vcxproj.Filters new file mode 100644 index 00000000..7c8e3101 --- /dev/null +++ b/setup/DIFxAPI/AppDrv/AppDrv.vcxproj.Filters @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{9481CE08-D6B5-4535-BEB1-2150D2E62176}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{FCEAD7F6-88BE-4D1B-B2DB-3C93C6E8D318}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{78BA1C9C-DC6C-4ED4-8B64-78677A62B0A0}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="AppDrvDepend.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/setup/DIFxAPI/AppDrv/AppDrvDepend.c b/setup/DIFxAPI/AppDrv/AppDrvDepend.c new file mode 100644 index 00000000..27180f00 --- /dev/null +++ b/setup/DIFxAPI/AppDrv/AppDrvDepend.c @@ -0,0 +1,147 @@ +/*++ + +Copyright (c) Microsoft Corporation + + +Description: + +This sample demonstrates how to use the application-to-driver dependency +feature of the Driver Install Frameworks (DIFx) API. The DriverPackageInstall +and the DriverPackageUninstall APIs allow the calling application to register +and remove dependencies on a driver package. In order to register or remove +a dependency on a driver package, the calling application needs to populate +the fields of an INSTALLERINFO structure with information about itself. It +then needs to pass in this structure as a parameter to the DIFx APIs, as +shown in this sample. + +--*/ +#include <windows.h> +#include <stdio.h> +#include <difxapi.h> + +int __cdecl +wmain( int argc, WCHAR* argv[] ) +{ + WCHAR *InfPath = NULL; + INSTALLERINFO AppInfo; + BOOL Result; + BOOL NeedReboot; + + if (argc < 7) { + wprintf( TEXT("USAGE: AppDrv.exe <option> <full path to the inf file> <Application ID> <Product display name> <Product name> <Manufacturer name>\n") ); + wprintf( TEXT("<option> can be one of the following -\n") ); + wprintf( TEXT("/i - Install the driver\n") ); + wprintf( TEXT("/u - Uninstall the driver\n") ); + return 0; + } + + // + // Initialization + // + NeedReboot = FALSE; + + // + // Get the path to the INF file + // + InfPath = argv[2]; + + // + // Fill in the fields of the INSTALLERINFO structure with information about + // the application performing the install. + // + + // + // The application ID should be some random string unique to this + // application. + // + AppInfo.pApplicationId = argv[3]; + AppInfo.pDisplayName = argv[4]; + AppInfo.pProductName = argv[5]; + AppInfo.pMfgName = argv[6]; + + // + // The option parameter should be present and be exactly two characters. + // + if ((argv[1] == NULL) || + (argv[1][0] == TEXT('\0')) || + (argv[1][1] == TEXT('\0')) || + (argv[1][2] != TEXT('\0'))) { + wprintf( TEXT("ERROR: An invalid command line option %ws was passed in!\n"), argv[1] ); + goto clean0; + } + + if ((argv[1][0] == TEXT('/')) && + ((argv[1][1] == TEXT('i')) || + (argv[1][1] == TEXT('I')))) { + // + // Install the driver package, passing in the INSTALLERINFO structure with + // information about the application performing the install. By passing in + // this structure, the "MySoftware" application is expressing a dependency + // on the driver being installed. + // + wprintf( TEXT("INFO: Attempting to install the driver package %ws.\n"), InfPath ); + + Result = DriverPackageInstall(InfPath, + 0, // flags + &AppInfo, // dependency information + &NeedReboot); + + if (ERROR_SUCCESS == Result) { + wprintf( TEXT("SUCCESS: installed driver package %ws.\n"), InfPath ); + } else if (ERROR_NO_MORE_ITEMS == Result) { + wprintf( TEXT("INFO: the driver package %ws was successfully staged on the machine.\n"), InfPath ); + wprintf( TEXT("INFO: All devices found already have a better driver than what is contained in the specified inf file.\n")); + } else if (ERROR_NO_SUCH_DEVINST == Result) { + wprintf( TEXT("INFO: the driver package %ws was successfully staged on the machine.\n"), InfPath ); + wprintf( TEXT("INFO: There aren't any live devnodes with the device ID contained in the INF.\n")); + } else if (ERROR_NO_DEVICE_ID == Result) { + wprintf( TEXT("INFO: the driver package %ws was successfully staged on the machine.\n"), InfPath ); + wprintf( TEXT("INFO: No device IDs found in INF '%ws' for current platform.\n"), InfPath); + } else { + wprintf( TEXT("ERROR: An error occurred while installing driver package %ws. Error code - 0x%X.\n"), InfPath, Result); + goto clean0; + } + + if (NeedReboot){ + wprintf( TEXT("INFO: Machine will have to be rebooted to complete install.\n")); + } + + } else if ((argv[1][0] == TEXT('/')) && + ((argv[1][1] == TEXT('u')) || + (argv[1][1] == TEXT('U')))) { + // + // Uninstall the driver package, passing in the INSTALLERINFO structure + // with information about the application performing the uninstall. By + // passing in this structure, the "MySoftware" application is removing + // its dependency on the driver. The driver will actually be + // uninstalled only if there are no other applications dependent on it. + // If there are other applications depending on the driver, then the call + // to DriverPackageUninstall will simply remove the dependency of the + // "MySoftware" application on the driver, and return + // ERROR_DEPENDENT_APPLICATIONS_EXIST. + // + wprintf( TEXT("INFO: Attempting to uninstall the driver package %ws.\n"), InfPath ); + + Result = DriverPackageUninstall(InfPath, + 0, // flags + &AppInfo, // dependency information + &NeedReboot); + if (ERROR_SUCCESS != Result) { + if (ERROR_DEPENDENT_APPLICATIONS_EXIST == Result) { + wprintf( TEXT("INFO: The driver package %ws was not uninstalled because there were some applications still depending on it.\n"), InfPath); + } else { + wprintf( TEXT("ERROR: An error occurred while uninstalling driver package %ws\n."), InfPath); + goto clean0; + } + } else { + wprintf( TEXT("SUCCESS: Uninstalled driver package %ws.\n"), InfPath ); + } + } else { + wprintf( TEXT("ERROR: An invalid command line option %ws was passed in!\n"), argv[1] ); + } + + clean0: + return 0; +} + + diff --git a/setup/DIFxAPI/AppDrv/readme.htm b/setup/DIFxAPI/AppDrv/readme.htm new file mode 100644 index 00000000..bffaefc3 --- /dev/null +++ b/setup/DIFxAPI/AppDrv/readme.htm @@ -0,0 +1,109 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML><HEAD><TITLE>DIFxAPI AppDrv</TITLE> +<META http-equiv=Content-Type content="text/html; charset=windows-1252"> +<META content="MSHTML 6.00.2900.2802" name=GENERATOR><!-- #BeginEditable "doctitle" --><!-- #EndEditable --></HEAD> +<BODY link=#0000FF><FONT face=Verdana size=5> +<H2>Driver Install Frameworks API (DIFx API) </H2></FONT><FONT +face=Verdana size=2> +<P style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><A +href="file:///C:/Documents%20and%20Settings/tstone/My%20Documents/DIFx%20Readmes/DPInst/readme.htm#Note">Note</A> + +<P style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><A +href="file:///C:/Documents%20and%20Settings/tstone/My%20Documents/DIFx%20Readmes/DPInst/readme.htm#Intro">Description</A> +<P style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><A +href="file:///C:/Documents%20and%20Settings/tstone/My%20Documents/DIFx%20Readmes/DPInst/readme.htm#Run">Building the Sample</A> +<P style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><A +href="file:///C:/Documents%20and%20Settings/tstone/My%20Documents/DIFx%20Readmes/DPInst/readme.htm#Plug">Running the Sample</A> +<H3><A name=Note></A>Note</H3> +<P>This sample works only on an x86 Windows operating system. However, the +techniques illustrated in this sample apply to Windows operating systems for +other architectures as well.<BR> +<H3><A name=Intro></A>Description</H3> +<P>This sample demonstrates the usage of the application to driver dependency feature of DIFx API. It provides an example of how the INSTALLERINFO structure is to be used in calls to DriverPackageInstall and DriverPackageUninstall functions. By passing the INSTALLERINFO structure as a parameter to the DriverPackageInstall function, an application expresses a dependency on the driver package. By passing the INSTALLERINFO structure as a parameter to the DriverPackageUninstall function, an application removes its dependency on the driver package. +</P> +<H3><A name=Run></A>Building the Sample</H3> +<P>Navigate to the src\setup\DIFxAPI\AppDrv directory and run the following command: + +<P> build -cZ + +<H3><A name=Plug></A>Running the Sample</H3> +<P>The usage of AppDrv.exe is as follows:</P> +<P>AppDrv.exe <option> <full path to the inf file> <Application ID> <Product +display name> <Product name> <Manufacturer name><br> + </P> +<P><option><option> <full path to the inf file> <Application ID> <Product display name> <Product name> <Manufacturer name> + +<option> can be one of the following:</P> +<P> /i - Install the driver + +</P> +<P> /u - Uninstall the driver + +<Application ID> + +</P> +<P><Application ID> is a unique identifier that denotes the application that is installing the driver</P> +<P><Product Display name> is a user-friendly display name for the application that is installing the driver +<Product name> + +</P> +<P><Product name> is the name of the application that is installing the driver</P> +<P><Manufacturer name> is the name of the company that is shipping that is installing the driver + +</P> +<P>In order to understand the application to driver dependency feature of DIFx +API, try the following:</P> +<P>1) Run the command</P> +<P> AppDrv.exe /i <Path to some INF> <Path to INF> abc123 "My first application" "App 1" "Good Company, Inc." + +<Path to INF> + +</P> +<P> <Path to INF> should be the full path to the INF file for some driver package. + +</P> +<P>For example, you can use one of the sample driver packages that are provided in the directory src\setup\DIFxSampleDriverPackages in the DDK. + +At this point DIFx API will install the driver and it will register that an application with application ID "abc123" is dependent on the driver. + +</P> +<P>2) Run the command:</P> +<P> AppDrv.exe /i <Path to the same INF> <Path to the same INF> xyz456 "My second application" "App 2" "Good Company, Inc." + +<Path to the same INF> + +</P> +<P> <Path to the same INF> should be the path to the same INF that was used in step 1. + +</P> +<P>At this point DIFx API will register that two applications, with application IDs "abc123" and "xyz456" are dependent on the driver. + +</P> +<P>3) Run the command:</P> +<P> AppDrv.exe /u <Path to the same INF> <Path to the same INF> abc123 "My first application" "App 1" "Good Company, Inc." + +<Path to the same INF> + +</P> +<P> <Path to the same INF> should be the path to the same INF that was used in step 1. + +</P> +<P>At this point, DIFx API will remove the dependency of the application with application ID "abc123" from the driver. However, it will not uninstall the driver, because the application with application ID "xyz456" is still dependent on it. + +</P> +<P>4) Run the command:</P> +<P> AppDrv.exe /u <Path to the same INF> <Path to the same INF> xyz456 "My second application" "App 2" "Good Company, Inc." + +<Path to the same INF> +</P> +<P> <Path to the same INF> should be the path to the same INF that was used in step 1. + +</P> +<P>At this point, DIFx API will remove the dependency of the application with application ID "xyz456" from the driver. Since no other applications are dependent on the driver, DIFx API will also uninstall the driver. +</P> + +<P align=center><A +href="file:///C:/Documents%20and%20Settings/tstone/My%20Documents/DIFx%20Readmes/DPInst/readme.htm#top"><FONT +face=Verdana size=2>Top of page</FONT></A><FONT face=Verdana size=2> +</P></FONT><FONT face="MS Sans Serif" size=1> +<P>� Microsoft Corporation 2002</FONT> </FONT></P></BODY></HTML> diff --git a/setup/DIFxAPI/DIFxAPI.sln b/setup/DIFxAPI/DIFxAPI.sln new file mode 100644 index 00000000..c7fc6244 --- /dev/null +++ b/setup/DIFxAPI/DIFxAPI.sln @@ -0,0 +1,46 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AppDrv", "AppDrv", "{B11F7E40-EE73-4682-AB3B-064469A819E1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DIFxCmd", "DIFxCmd", "{2B03F68A-553F-4311-89F2-C8FFC7525379}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppDrv", "AppDrv\AppDrv.vcxproj", "{51E48BC7-B82C-4F02-8C66-9A94C32E8DE4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DIFxCmd", "DIFxCmd\DIFxCmd.vcxproj", "{C368C716-AC0A-4165-861B-42D55AD9FB99}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {51E48BC7-B82C-4F02-8C66-9A94C32E8DE4}.Debug|Win32.ActiveCfg = Debug|Win32 + {51E48BC7-B82C-4F02-8C66-9A94C32E8DE4}.Debug|Win32.Build.0 = Debug|Win32 + {51E48BC7-B82C-4F02-8C66-9A94C32E8DE4}.Release|Win32.ActiveCfg = Release|Win32 + {51E48BC7-B82C-4F02-8C66-9A94C32E8DE4}.Release|Win32.Build.0 = Release|Win32 + {51E48BC7-B82C-4F02-8C66-9A94C32E8DE4}.Debug|x64.ActiveCfg = Debug|x64 + {51E48BC7-B82C-4F02-8C66-9A94C32E8DE4}.Debug|x64.Build.0 = Debug|x64 + {51E48BC7-B82C-4F02-8C66-9A94C32E8DE4}.Release|x64.ActiveCfg = Release|x64 + {51E48BC7-B82C-4F02-8C66-9A94C32E8DE4}.Release|x64.Build.0 = Release|x64 + {C368C716-AC0A-4165-861B-42D55AD9FB99}.Debug|Win32.ActiveCfg = Debug|Win32 + {C368C716-AC0A-4165-861B-42D55AD9FB99}.Debug|Win32.Build.0 = Debug|Win32 + {C368C716-AC0A-4165-861B-42D55AD9FB99}.Release|Win32.ActiveCfg = Release|Win32 + {C368C716-AC0A-4165-861B-42D55AD9FB99}.Release|Win32.Build.0 = Release|Win32 + {C368C716-AC0A-4165-861B-42D55AD9FB99}.Debug|x64.ActiveCfg = Debug|x64 + {C368C716-AC0A-4165-861B-42D55AD9FB99}.Debug|x64.Build.0 = Debug|x64 + {C368C716-AC0A-4165-861B-42D55AD9FB99}.Release|x64.ActiveCfg = Release|x64 + {C368C716-AC0A-4165-861B-42D55AD9FB99}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {51E48BC7-B82C-4F02-8C66-9A94C32E8DE4} = {B11F7E40-EE73-4682-AB3B-064469A819E1} + {C368C716-AC0A-4165-861B-42D55AD9FB99} = {2B03F68A-553F-4311-89F2-C8FFC7525379} + EndGlobalSection +EndGlobal diff --git a/setup/DIFxAPI/DIFxCmd/DIFxCmd.vcxproj b/setup/DIFxAPI/DIFxCmd/DIFxCmd.vcxproj new file mode 100644 index 00000000..65d9c57b --- /dev/null +++ b/setup/DIFxAPI/DIFxCmd/DIFxCmd.vcxproj @@ -0,0 +1,187 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{C368C716-AC0A-4165-861B-42D55AD9FB99}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{EB4A0E3E-31D0-4D1E-9415-453DC8D122F6}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + </ItemDefinitionGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>DIFxCmd</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>DIFxCmd</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>DIFxCmd</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>DIFxCmd</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);difxapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);difxapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);difxapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);difxapi.lib</AdditionalDependencies> + </Link> + <ClCompile> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="difxcmd.c" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/setup/DIFxAPI/DIFxCmd/DIFxCmd.vcxproj.Filters b/setup/DIFxAPI/DIFxCmd/DIFxCmd.vcxproj.Filters new file mode 100644 index 00000000..6657863f --- /dev/null +++ b/setup/DIFxAPI/DIFxCmd/DIFxCmd.vcxproj.Filters @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{EB72BAFA-7E87-4214-8F90-7AB380D50C9E}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{E9A405A6-0CA8-4171-A852-CA5C44A9B6BA}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{784DA48C-700C-4454-974B-0DA8644295CB}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="difxcmd.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/setup/DIFxAPI/DIFxCmd/difxcmd.c b/setup/DIFxAPI/DIFxCmd/difxcmd.c new file mode 100644 index 00000000..7cc64b95 --- /dev/null +++ b/setup/DIFxAPI/DIFxCmd/difxcmd.c @@ -0,0 +1,218 @@ +/*++ + +Copyright (c) Microsoft Corporation + + +Description: + + Command line program that demonstrates how to use DIFxAPI. + + Link with either DIFXAPI.LIB and have DIFXAPI.DLL on the path. + + This sample demonstrates how to use DIFXAPI to preinstall, install and uninstall + a driver package. It also allows to retrieve the path to an already preinstalled + or installed driver package. It further shows how to capture logging information + and print it out. +--*/ + +#include <windows.h> +#include <tchar.h> +#include <stdlib.h> +#include <stdio.h> +#include <difxapi.h> + +static VOID __cdecl +LogCallback( + DIFXAPI_LOG Event, + DWORD Error, + const TCHAR * pEventDescription, + PVOID CallbackContext + ); + + +int __cdecl +_tmain( + int argc, + TCHAR* argv[] + ) +{ + TCHAR DestPath[MAX_PATH]; + ULONG Size = MAX_PATH; + TCHAR * InfPath = NULL; + TCHAR DriverPackageInfPath[MAX_PATH]; + DWORD Ret; + TCHAR Option; + BOOL NeedReboot = FALSE; + DWORD Flags = 0; + LPTSTR lpFilePart; + int i; + DWORD dw; + Size = MAX_PATH; + + + _tprintf( TEXT("DIFxAPI Sample Program\n") ); + if( argc < 3 ) + { + _tprintf( TEXT("USAGE: test /p /i /u /g <inf-filename> [Flag(s)]\n") ); + _tprintf( TEXT("\nOptions:\n")); + _tprintf( TEXT("/p : preinstall driver package.\n") ); + _tprintf( TEXT("/i : install driver package.\n") ); + _tprintf( TEXT("/u : uninstall driver package.\n") ); + _tprintf( TEXT("/g : get driver package path.\n") ); + + _tprintf( TEXT("\n<inf-filename> : has to be in the current directory.\n") ); + _tprintf( TEXT("\nFlags:\n")); + _tprintf( TEXT("DRIVER_PACKAGE_REPAIR: 0x00000001 ( 1)\n")); + _tprintf( TEXT("DRIVER_PACKAGE_SILENT: 0x00000002 ( 2)\n")); + _tprintf( TEXT("DRIVER_PACKAGE_FORCE: 0x00000004 ( 4)\n")); + _tprintf( TEXT("DRIVER_PACKAGE_ONLY_IF_DEVICE_PRESENT: 0x00000008 ( 8)\n")); + _tprintf( TEXT("DRIVER_PACKAGE_LEGACY: 0x00000010 (16)\n")); + _tprintf( TEXT("DRIVER_PACKAGE_DELETE_FILES: 0x00000020 (32)\n")); + + return 0; + } + + // + // Get command line choices + // + + // + // The code suppresses the warning 28193 for the call to _totlower. + // This suppression is done because that function has a check return + // annotation on it. However, it doesn't return an error code + // and the check return annotation is really being used to indicate + // that the return value of the function should be looked at and/or + // assigned to a variable. The check return annotation means the return + // value should always be checked in all code paths. The return value is + // assigned to a variable, but the return in the for loop could cause + // this function to exit before Option is ever examined. For that case, + // the code doesn't need to check the value of Option so the warning + // is being suppressed + // +#pragma warning( suppress: 28193) + Option = (TCHAR)_totlower(argv[1][1]); + InfPath = argv[2]; + + for ( i = 3; i<argc; i++ ){ + dw = _ttol( argv[i] ); + // + // Either an error occurred during conversion of a flags parameter + // into a long or a flag of 0 was specified. Either way, + // this is invalid input. + // + if (0 == dw) + { + _tprintf( TEXT("An invalid flag was specified.") ); + + return 0; + } + + Flags |= dw; + } + + + GetFullPathName( InfPath, MAX_PATH, DriverPackageInfPath, &lpFilePart); + + _tprintf( TEXT("INFO: Option \"/%c\"\n"), Option ); + _tprintf( TEXT("INFO: Input file \"%s\"\n"), DriverPackageInfPath ); + _tprintf( TEXT("INFO: Flags 0x%X (%u)\n\n"), Flags, Flags ); + + + DIFXAPISetLogCallback( LogCallback, (PVOID)NULL ); + + Ret = ERROR_SUCCESS; + + if ( TEXT('p') == Option ) + { + _tprintf( TEXT("TEST: preinstalling driver package.\n")); + Ret = DriverPackagePreinstall( DriverPackageInfPath, Flags ); + if( ERROR_SUCCESS == Ret ){ + _tprintf( TEXT("INFO: preinstalled package.\n") ); + } else if (ERROR_ALREADY_EXISTS == Ret){ + _tprintf( TEXT("INFO: package was already in store.\n") ); + } else { + _tprintf( TEXT("ERROR: failed with error code 0x%X\n"), Ret ); + } + } + else if ( TEXT('i') == Option ) + { + _tprintf( TEXT("TEST: installing driver package.\n")); + + Ret = DriverPackageInstall( + DriverPackageInfPath, + Flags, + NULL, + &NeedReboot ); + + if( ERROR_SUCCESS == Ret ){ + _tprintf( TEXT("SUCCESS: installed package %s.\n"), DriverPackageInfPath ); + } else if (ERROR_NO_MORE_ITEMS == Ret){ + _tprintf( TEXT("INFO: All devices found already have a better driver than what is contained in the specified inf file. To force an install, use the ForceIfNotBetter flag.\n")); + } else if (ERROR_NO_SUCH_DEVINST == Ret){ + _tprintf( TEXT("INFO: There aren't any live devnodes with the DeviceId contained in the INF.\n")); + } + else{ + _tprintf( TEXT("ERROR: failed with error code 0x%X\n"), Ret ); + } + + if (NeedReboot){ + _tprintf( TEXT("INFO: Machine will have to be rebooted to complete install.") ); + } + + } + else if ( TEXT('u') == Option ) + { + _tprintf( TEXT("TEST: uninstalling driver package.\n")); + + Ret = DriverPackageUninstall( + DriverPackageInfPath, + Flags, + NULL, + &NeedReboot ); + + if( ERROR_SUCCESS == Ret ){ + _tprintf( TEXT("SUCCESS: uninstalled driver package %s.\n"), DriverPackageInfPath ); + } else { + _tprintf( TEXT("ERROR: failed with error code 0x%X\n"), Ret ); + } + + if (NeedReboot) { + _tprintf( TEXT("INFO: Machine will have to be rebooted to complete uninstall.") ); + } + + } + else if ( TEXT('g') == Option ) + { + _tprintf( TEXT("TEST: getting driver package path.\n")); + Ret = DriverPackageGetPath( DriverPackageInfPath, DestPath, &Size ); + if ( ERROR_SUCCESS==Ret ){ + _tprintf( TEXT("INFO: INF path is %s\n"), DestPath ); + } else { + _tprintf( TEXT("ERROR: failed with error code 0x%X\n"), Ret ); + } + } else { + _tprintf( TEXT("ERROR: invalid command line option /%c.\n"), Option ); + } + + DIFXAPISetLogCallback( NULL, (PVOID)NULL ); + + return 1; +} + + + +VOID __cdecl +LogCallback( + DIFXAPI_LOG Event, + DWORD Error, + const TCHAR * pEventDescription, + PVOID CallbackContext + ) +{ + UNREFERENCED_PARAMETER(CallbackContext); + if (0==Error){ + _tprintf( TEXT("LOG Event: %u, %s\n"), Event, pEventDescription ); + } else { + _tprintf( TEXT("LOG Event: %u, Error = %u, %s\n"), Event, Error, pEventDescription); + } +} diff --git a/setup/DIFxAPI/DIFxCmd/readme.htm b/setup/DIFxAPI/DIFxCmd/readme.htm new file mode 100644 index 00000000..a369e56e --- /dev/null +++ b/setup/DIFxAPI/DIFxCmd/readme.htm @@ -0,0 +1,59 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML><HEAD><TITLE>DIFxAPI AppDrv</TITLE> +<META http-equiv=Content-Type content="text/html; charset=iso-8859-1"> +<META content="MSHTML 6.00.2900.2802" name=GENERATOR><!-- #BeginEditable "doctitle" --><!-- #EndEditable --></HEAD> +<BODY link=#0000ff><FONT face=Verdana size=5> +<H2>Driver Install Frameworks API (DIFx API) </H2></FONT><FONT face=Verdana +size=2> + +<P style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><a href="#Intro">Description</a> + +<P style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><a href="#Build">Building +the Sample </a> +<P style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><a href="#Run">Running +the Sample</a> +<P style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"><a href="#Usage">Usage of the +DIFXAPI Sample Program</a><P style="MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px"> <H3><A name=Intro></A>Description</H3> +<P>This sample demonstrates how to use DIFx API. It shows how to preinstall, +install and uninstall driver packages. It also shows how to retrieve the path to +an already preinstalled or installed driver package. It furthers shows how to +capture logging information that the APIs create during installs and uninstalls. </P> +<H3><a name="Build"></a>Building the Sample</H3> +<P>Navigate to the src\setup\DIFxAPI\DIFXCMD directory and run the following +command: +<P> build -cZ +<H3><a name="Run"></a>Running the Sample</H3> +<P>Once the sample is built, run the following commands. Before running the +command, copy a complete driver package into the same directory:</P> +<P>difxcmd.exe to print out how to use the command line tool + +</P> +<P>difxcmd.exe /p my.inf , to preinstall my.inf </P> +<P>difxcmd.exe /i my.inf , to install my.inf </P> +<P>difxcmd.exe /i my.inf 16, to install my.inf in legacy mode (accepting unsigned drivers) +</P> +<P>difxcmd.exe /p my.inf , to obtain the path to the installed my.inf </P> +<P>difxcmd.exe /u my.inf , to uninstall my.inf </P> +<H3><a name="Usage"></a>Usage of the DIFXAPI Sample Program </H3> +<p>difxapi /p /i /u /g <inf-filename> [Flag(s)]<br> +<br> +Options:<br> +/p : preinstall driver package.<br> +/i : install driver package.<br> +/u : uninstall driver package.<br> +/g : get driver package path.<br> +<br> +<inf-filename> : has to be in the current directory.<br> +<br> +Flags:<br> +DRIVER_PACKAGE_REPAIR: 0x00000001 ( 1)<br> +DRIVER_PACKAGE_SILENT: 0x00000002 ( 2)<br> +DRIVER_PACKAGE_FORCE: 0x00000004 ( 4)<br> +DRIVER_PACKAGE_ONLY_IF_DEVICE_PRESENT: 0x00000008 ( 8)<br> +DRIVER_PACKAGE_LEGACY: 0x00000010 (16)<br> +DRIVER_PACKAGE_DELETE_FILES: 0x00000020 (32)</p> +<P align=center><A +href="file:///C:/Documents%20and%20Settings/tstone/My%20Documents/DIFx%20Readmes/DPInst/readme.htm#top"><FONT +face=Verdana size=2>Top of page</FONT></A><FONT face=Verdana size=2> +</P></FONT><FONT face="MS Sans Serif" size=1> +<P>� Microsoft Corporation 2002</FONT> </FONT></P></BODY></HTML> diff --git a/setup/DIFxAPI/ReadMe.md b/setup/DIFxAPI/ReadMe.md new file mode 100644 index 00000000..cbbea926 --- /dev/null +++ b/setup/DIFxAPI/ReadMe.md @@ -0,0 +1,5 @@ +Driver Install Frameworks API (DIFxAPI) Sample +============================================== + +[Driver Install Frameworks API (DIFxAPI)](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544834) Sample. + diff --git a/setup/devcon/ReadMe.md b/setup/devcon/ReadMe.md new file mode 100644 index 00000000..fbea8dca --- /dev/null +++ b/setup/devcon/ReadMe.md @@ -0,0 +1,111 @@ +Device Console (DevCon) Tool +============================ + +[DevCon](http://msdn.microsoft.com/en-us/library/windows/hardware/ff544707) is a command-line tool that displays detailed information about devices, and lets you search for and manipulate devices from the command line. DevCon enables, disables, installs, configures, and removes devices on the local computer and displays detailed information about devices on local and remote computers. DevCon is included in the WDK. + +This document explains the DevCon design, and how to use the SetupAPI and device installation functions to enumerate devices and perform device operations in a console application. For a complete description of DevCon features and instructions for using them, see the DevCon help file included with the WDK documentation in Driver Development Tools/Tools for Testing Drivers/DevCon. + +DevCon is provided in ready-to-run form in tools\\devcon. For usage, refer to the document provided with devcon.exe. DevCon is a command line utility with built-in documentation available by typing "devcon help". + +Download and extract the sample +------------------------------- + +Download the C++ sample from this page, and extract its contents. For example, you could extract to c:\\DevConSample. + +Starting in the Visual Studio 2013 WDK, you can build the sample in two ways: using the Visual Studio Integrated Development Environment (IDE) or from the command line using the Visual Studio Command Prompt window and the Microsoft Build Engine (MSBuild.exe). + +**Building the sample using Visual Studio** + +1. Open Visual Studio. From the **File** menu, select **Open Project/Solution**. Within your WDK installation, navigate to the folder where you extracted DevCon. For example c:\\DevConSample\\C++ and open the devcon.sln project file. +2. Right-click the solution in the **Solution Explorer** and select **Configuration Manager**. +3. From the **Configuration Manager**, select the **Active Solution Configuration** (for example, Windows 8.1 Debug or Windows 8.1 Release) and the **Active Solution Platform** (for example, Win32) that correspond to the type of build you are interested in. +4. From the **Build** menu, click **Build Solution** (Ctrl+Shift+B). + +Previous versions of the WDK used the Windows Build utility (Build.exe) and provided separate build environment windows for each of the supported build configurations. Starting in the Visual Studio 2013 WDK, you can use the Visual Studio Command Prompt window for all build configurations. + +**Building the sample using the command line (MSBuild)** + +1. Open a Visual Studio Command Prompt window. Click **Start** and search for **Developer Command Prompt**. If your project is under %PROGRAMFILES%, you need to open the command prompt window using elevated permissions (**Run as administrator**). From this window you can use MsBuild.exe to build any Visual Studio project by specifying the project (.VcxProj) or solutions (.Sln) file. +2. Navigate to the project directory and enter the **MSbuild** command for your target. For example, to perform a clean build of a Visual Studio driver project called devcon.vcxproj, navigate to the project directory and enter the following MSBuild command: **msbuild /t:clean /t:build .\\devcon.vcxproj**. +3. If the build succeeds, you will find the tools (devcon.exe) in the binary output directory corresponding to the target platform, for example samples\\setup\\devcon\\Windows 8.1 Debug. + +Run the sample +-------------- + +Type "devcon find \*" to list device instances of all present devices on the local machine. + +Type "devcon status @root\\rdp\_mou\\0000" to list status of the terminal server mouse driver. + +Type "devcon status \*PNP05\*" to list status of all COM ports. + +How DevCon works: + +Running "devcon help" will provide a list of commands along with short descriptions of what each command does. "devcon help \<command\>" will give more detailed help on that command. The interpretation of each command is done via a dispatch table "DispatchTable" that is at the bottom of "cmds.cpp". Some of the commands make use of a generic device enumerator "EnumerateDevices". A few of these commands will work when given a remote target computer, and will also work if using the 32-bit devcon on Wow64. A description of some of the more interesting functions and the APIs they use follows: + +cmdClasses +This command demonstrates the use of [**SetupDiBuildClassInfoListEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550911) to enumerate all device class GUID's. The function [**SetupDiClassNameFromGuidEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550950) and [**SetupDiGetClassDescriptionEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551058) are used to obtain more information about each device class. + +cmdListClass +This command demonstrates the use of [**SetupDiClassGuidsFromNameEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550941) to enumerate one or more class GUID's that match the class name. This command also demonstrates the use of [**SetupDiGetClassDevsEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551072) to list all the devices for each class GUID. + +cmdFind cmdFindAll cmdStatus +A simple use of *EnumerateDevices* (explained below) to list devices and display different levels of information about each device. Note that all but *cmdFindAll* use DIGCF\_PRESENT to only list information about devices that are currently present. The main functionality for these and related devices is done inside *FindCallback.* + +cmdEnable cmdDisable cmdRestart +These commands show how to issue DIF\_PROPERTYCHANGE to enable a device, disable a device, or restart a device. The main functionality for each of these commands is done inside *ControlCallback*. These operations cannot be done on a remote machine or in the context of Wow64. CFGMGR32 API's should not be used as they skip class and co-installers. + +cmdUpdate +This command shows how to use [**UpdateDriverForPlugAndPlayDevices**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff553534) to update the driver for all devices to a specific driver. Normally INSTALLFLAG\_FORCE would not be specified allowing **UpdateDriverForPlugAndPlayDevices** to determine if there is a better match already known. It's specified in DevCon to allow DevCon to be used more effectively as a debugging/testing tool. This cannot be done on a remote machine or in the context of Wow64. + +cmdInstall +A variation of *cmdUpdate* to install a driver when there is no associated hardware. It creates a new root-enumerated device instance and associates it with a made up hardware ID specified on the command line (which should correspond to a hardware ID in the INF). This cannot be done on a remote machine or in the context of Wow64. + +cmdRemove +A command to remove devices. Plug & Play devices that are removed will reappear in response to *cmdRescan*. The main functionality of this command is in *RemoveCallback* that demonstrates the use of DIF\_REMOVE. This cannot be done on a remote machine or in the context of Wow64. CFGMGR32 API's should not be used as they skip class and co-installers. + +cmdRescan +This command shows the correct way to rescan for all Plug & Play devices that may have previously been removed, or that otherwise require a rescan to detect them. + +cmdDPAdd +This command allows you to add a Driver Package to the machine. The main functionality of this command demonstrates the use of [**SetupCopyOEMInf**](http://msdn.microsoft.com/en-us/library/windows/hardware/). Adding a Driver Package to the machine doesn’t mean the drivers are installed on devices, it simply means the drivers are available automatically when a new device is plugged in or a existing device is updated. + +cmdDPDelete +This command allows you to uninstall a Driver Package from the machine. The main functionality of this command demonstrates the use of [**SetupUninstallOEMInf**](http://msdn.microsoft.com/en-us/library/windows/hardware/). Removing a Driver Package from the machine does not uninstall the drivers associated with a device. If you want to accomplish both then use *cmdRemove* on all the devices using a given Driver Package and then *cmdDPDelete* to remove the Driver Package itself from the machine. + +cmdDPEnum +This command allows you to enumerate all of the 3rd party Driver Packages currently installed on the machine and also shows you how to get some common properties from a Driver Package (Provider, Class description, DriverVer date and version). + +cmdDPEnumLegacy +This command shows you how to enumerate 3rd party Driver Packages on Windows Server 2003 and earlier operating systems. + +Reboot +This function shows how to correctly reboot the machine from a hardware install program. In particular it passes flags to **ExitWindowsEx** that cause the reboot to be associated with hardware installation. You should never reboot the machine unnecessarily. + +EnumerateDevices +Demonstrates the use of [**SetupDiGetClassDevsEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551072) to enumerate all devices or all present devices, either globally or limited to a specific setup class. Demonstrates the use of [**SetupDiCreateDeviceInfoListEx**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550958) to create a blank list associated with a class or not (for most cases, a blank list need not be associated with a class). Demonstrates the use of [**SetupDiOpenDeviceInfo**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552071) to add a device instance into a device info list. These last two API's are ideal to obtain a [SP\_DEVINFO\_DATA](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552344) structure from a device instance and machine name when mixing CFGMGR32 API's with SETUPAPI API's. [**SetupDiGetDeviceInfoListDetail**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551103) is called to obtain a remote machine handle that may be passed into CFGMGR32 API's. [**SetupDiEnumDeviceInfo**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551010) is called to enumerate each and every device that is in the device info list (either explicitly added, or determined by the call to **SetupDiGetClassDevsEx**). The instance ID is obtained by calling [**CM\_Get\_Device\_ID\_Ex**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff538411), using information in devInfo (obtained from **SetupDiEnumerateDeviceInfo**) and devInfoListDetail (obtained from **SetupDiGetDeviceInfoListDetail**). *GetHwIds* is called to obtain a list of hardware and compatible ID's (explained below). Once an interesting device has been determined (typically by checking hardware ID's) then the callback is called to operate on that individual device. + +GetHwIds +Shows how to get the complete list of hardware ID's or compatible ID's for a device using [**SetupDiGetDeviceRegistryProperty**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551967). + +GetDeviceDescription +Shows how to obtain descriptive information about a device. The friendly name is used if it exists, otherwise the device description is used. + +DumpDeviceWithInfo +Shows how to obtain an instance ID (or use any CFGMGR32 API) given HDEVINFO (device info list) and [PSP\_DEVINFO\_DATA](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552344) (device info data). + +DumpDeviceStatus +Shows how to interpret the information returned by [**CM\_Get\_DevNode\_Status\_Ex**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff538517). Refer to *cfg.h* for information returned by this API. + +DumpDeviceResources +Shows how to obtain information about resources used by a device. + +DumpDeviceDriverFiles +Provided as a debugging aid, obtains information about the files apparently being used for a device. It uses [**SetupDiBuildDriverInfoList**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550917) to obtain information about the driver being used for the specified device. The driver list associated with a device may be enumerated by calling [**SetupDiEnumDriverInfo**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff551018). In this case, there will be no more than one driver listed. This function proceeds to obtain a list of files that would normally be copied for this driver using DIF\_INSTALLDEVICEFILES. [**SetupScanFileQueue**](http://msdn.microsoft.com/en-us/library/windows/hardware/) is used to enumerate the file queue to display the list of files that are associated with the driver. + +DumpDeviceDriverNodes +Provided as a debugging aid, this function determines the list of compatible drivers for a device. It uses [**SetupDiBuildDriverInfoList**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff550917) to obtain the list of compatible drivers. In this case, all drivers are enumerated, however typically DIF\_SELECTBESTCOMPATDRV and [**SetupDiGetSelectedDriver**](http://msdn.microsoft.com/en-us/library/windows/hardware/ff552013) would be used together to find which driver the OS would consider to be the best. + +DumpDeviceStack +This function determines class and device upper and lower filters. + + diff --git a/setup/devcon/cmds.cpp b/setup/devcon/cmds.cpp new file mode 100644 index 00000000..590decdd --- /dev/null +++ b/setup/devcon/cmds.cpp @@ -0,0 +1,2408 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + devcon.cpp + +Abstract: + + Device Console + command-line interface for managing devices + +--*/ + +#include "devcon.h" + +struct GenericContext { + DWORD count; + DWORD control; + BOOL reboot; + LPCTSTR strSuccess; + LPCTSTR strReboot; + LPCTSTR strFail; +}; + +#define FIND_DEVICE 0x00000001 // display device +#define FIND_STATUS 0x00000002 // display status of device +#define FIND_RESOURCES 0x00000004 // display resources of device +#define FIND_DRIVERFILES 0x00000008 // display drivers used by device +#define FIND_HWIDS 0x00000010 // display hw/compat id's used by device +#define FIND_DRIVERNODES 0x00000020 // display driver nodes for a device. +#define FIND_CLASS 0x00000040 // display device's setup class +#define FIND_STACK 0x00000080 // display device's driver-stack + +struct SetHwidContext { + int argc_right; + LPTSTR * argv_right; + DWORD prop; + int skipped; + int modified; +}; + +int cmdHelp(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + HELP command + allow HELP or HELP <command> + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine (ignored) + argc/argv - remaining parameters + +Return Value: + + EXIT_xxxx + +--*/ +{ + DWORD helptext = 0; + int dispIndex; + LPCTSTR cmd = NULL; + BOOL unknown = FALSE; + + UNREFERENCED_PARAMETER(Machine); + UNREFERENCED_PARAMETER(Flags); + + if(argc) { + // + // user passed in a command for help on... long help + // + for(dispIndex = 0;DispatchTable[dispIndex].cmd;dispIndex++) { + if(_tcsicmp(argv[0],DispatchTable[dispIndex].cmd)==0) { + cmd = DispatchTable[dispIndex].cmd; + helptext = DispatchTable[dispIndex].longHelp; + break; + } + } + if(!cmd) { + unknown = TRUE; + cmd = argv[0]; + } + } + + if(helptext) { + // + // long help + // + FormatToStream(stdout,helptext,BaseName,cmd); + } else { + // + // help help + // + FormatToStream(stdout,unknown ? MSG_HELP_OTHER : MSG_HELP_LONG,BaseName,cmd); + // + // enumerate through each command and display short help for each + // + for(dispIndex = 0;DispatchTable[dispIndex].cmd;dispIndex++) { + if(DispatchTable[dispIndex].shortHelp) { + FormatToStream(stdout,DispatchTable[dispIndex].shortHelp,DispatchTable[dispIndex].cmd); + fputs("\n",stdout); + } + } + } + return EXIT_OK; +} + +int cmdClasses(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + CLASSES command + lists classes on (optionally) specified machine + format as <name>: <destination> + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - ignored + +Return Value: + + EXIT_xxxx + +--*/ +{ + DWORD reqGuids = 128; + DWORD numGuids; + LPGUID guids = NULL; + DWORD index; + int failcode = EXIT_FAIL; + + UNREFERENCED_PARAMETER(BaseName); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + guids = new GUID[reqGuids]; + if(!guids) { + goto final; + } + if(!SetupDiBuildClassInfoListEx(0,guids,reqGuids,&numGuids,Machine,NULL)) { + do { + if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + goto final; + } + delete [] guids; + reqGuids = numGuids; + guids = new GUID[reqGuids]; + if(!guids) { + goto final; + } + } while(!SetupDiBuildClassInfoListEx(0,guids,reqGuids,&numGuids,Machine,NULL)); + } + FormatToStream(stdout,Machine?MSG_CLASSES_HEADER:MSG_CLASSES_HEADER_LOCAL,numGuids,Machine); + for(index=0;index<numGuids;index++) { + TCHAR className[MAX_CLASS_NAME_LEN]; + TCHAR classDesc[LINE_LEN]; + if(!SetupDiClassNameFromGuidEx(&guids[index],className,MAX_CLASS_NAME_LEN,NULL,Machine,NULL)) { + if (FAILED(StringCchCopy(className,MAX_CLASS_NAME_LEN,TEXT("?")))) { + goto final; + } + } + if(!SetupDiGetClassDescriptionEx(&guids[index],classDesc,LINE_LEN,NULL,Machine,NULL)) { + if (FAILED(StringCchCopy(classDesc,LINE_LEN,className))) { + goto final; + } + } + _tprintf(TEXT("%-20s: %s\n"),className,classDesc); + } + + failcode = EXIT_OK; + +final: + + if(guids) { + delete [] guids; + } + return failcode; +} + +int cmdListClass(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + LISTCLASS <name>.... + lists all devices for each specified class + there can be more than one physical class for a class name (shouldn't be + though) in such cases, list each class + if machine given, list devices for that machine + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - list of class names + +Return Value: + + EXIT_xxxx + +--*/ +{ + DWORD reqGuids = 16; + int argIndex; + int failcode = EXIT_FAIL; + LPGUID guids = NULL; + HDEVINFO devs = INVALID_HANDLE_VALUE; + + UNREFERENCED_PARAMETER(BaseName); + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + return EXIT_USAGE; + } + + guids = new GUID[reqGuids]; + if(!guids) { + goto final; + } + + for(argIndex = 0;argIndex<argc;argIndex++) { + DWORD numGuids; + DWORD index; + + if(!(argv[argIndex] && argv[argIndex][0])) { + continue; + } + + // + // there could be one to many name to GUID mapping + // + while(!SetupDiClassGuidsFromNameEx(argv[argIndex],guids,reqGuids,&numGuids,Machine,NULL)) { + if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + goto final; + } + delete [] guids; + reqGuids = numGuids; + guids = new GUID[reqGuids]; + if(!guids) { + goto final; + } + } + if(numGuids == 0) { + FormatToStream(stdout,Machine?MSG_LISTCLASS_NOCLASS:MSG_LISTCLASS_NOCLASS_LOCAL,argv[argIndex],Machine); + continue; + } + for(index = 0;index<numGuids;index++) { + TCHAR className[MAX_CLASS_NAME_LEN]; + TCHAR classDesc[LINE_LEN]; + DWORD devCount = 0; + SP_DEVINFO_DATA devInfo; + DWORD devIndex; + + devs = SetupDiGetClassDevsEx(&guids[index],NULL,NULL,DIGCF_PRESENT,NULL,Machine,NULL); + if(devs != INVALID_HANDLE_VALUE) { + // + // count number of devices + // + devInfo.cbSize = sizeof(devInfo); + while(SetupDiEnumDeviceInfo(devs,devCount,&devInfo)) { + devCount++; + } + } + + if(!SetupDiClassNameFromGuidEx(&guids[index],className,MAX_CLASS_NAME_LEN,NULL,Machine,NULL)) { + if (FAILED(StringCchCopy(className,MAX_CLASS_NAME_LEN,TEXT("?")))) { + goto final; + } + } + if(!SetupDiGetClassDescriptionEx(&guids[index],classDesc,LINE_LEN,NULL,Machine,NULL)) { + if (FAILED(StringCchCopy(classDesc,LINE_LEN,className))) { + goto final; + } + } + + // + // how many devices? + // + if (!devCount) { + FormatToStream(stdout,Machine?MSG_LISTCLASS_HEADER_NONE:MSG_LISTCLASS_HEADER_NONE_LOCAL,className,classDesc,Machine); + } else { + FormatToStream(stdout,Machine?MSG_LISTCLASS_HEADER:MSG_LISTCLASS_HEADER_LOCAL,devCount,className,classDesc,Machine); + for(devIndex=0;SetupDiEnumDeviceInfo(devs,devIndex,&devInfo);devIndex++) { + DumpDevice(devs,&devInfo); + } + } + if(devs != INVALID_HANDLE_VALUE) { + SetupDiDestroyDeviceInfoList(devs); + devs = INVALID_HANDLE_VALUE; + } + } + } + + failcode = 0; + +final: + + if(guids) { + delete [] guids; + } + + if(devs != INVALID_HANDLE_VALUE) { + SetupDiDestroyDeviceInfoList(devs); + } + + return failcode; +} + +int FindCallback(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Index, _In_ LPVOID Context) +/*++ + +Routine Description: + + Callback for use by Find/FindAll + just simply display the device + +Arguments: + + Devs )_ uniquely identify the device + DevInfo ) + Index - index of device + Context - GenericContext + +Return Value: + + EXIT_xxxx + +--*/ +{ + GenericContext *pFindContext = (GenericContext*)Context; + + UNREFERENCED_PARAMETER(Index); + + if(!pFindContext->control) { + DumpDevice(Devs,DevInfo); + pFindContext->count++; + return EXIT_OK; + } + if(!DumpDeviceWithInfo(Devs,DevInfo,NULL)) { + return EXIT_OK; + } + if(pFindContext->control&FIND_DEVICE) { + DumpDeviceDescr(Devs,DevInfo); + } + if(pFindContext->control&FIND_CLASS) { + DumpDeviceClass(Devs,DevInfo); + } + if(pFindContext->control&FIND_STATUS) { + DumpDeviceStatus(Devs,DevInfo); + } + if(pFindContext->control&FIND_RESOURCES) { + DumpDeviceResources(Devs,DevInfo); + } + if(pFindContext->control&FIND_DRIVERFILES) { + DumpDeviceDriverFiles(Devs,DevInfo); + } + if(pFindContext->control&FIND_STACK) { + DumpDeviceStack(Devs,DevInfo); + } + if(pFindContext->control&FIND_HWIDS) { + DumpDeviceHwIds(Devs,DevInfo); + } + if (pFindContext->control&FIND_DRIVERNODES) { + DumpDeviceDriverNodes(Devs,DevInfo); + } + pFindContext->count++; + return EXIT_OK; +} + +int cmdFind(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + FIND <id> ... + use EnumerateDevices to do hardwareID matching + for each match, dump to stdout + note that we only enumerate present devices + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx + +--*/ +{ + GenericContext context; + int failcode; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + return EXIT_USAGE; + } + + context.count = 0; + context.control = 0; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,FindCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,Machine?MSG_FIND_TAIL_NONE:MSG_FIND_TAIL_NONE_LOCAL,Machine); + } else { + FormatToStream(stdout,Machine?MSG_FIND_TAIL:MSG_FIND_TAIL_LOCAL,context.count,Machine); + } + } + return failcode; +} + +int cmdFindAll(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + FINDALL <id> ... + use EnumerateDevices to do hardwareID matching + for each match, dump to stdout + like find, but also show not-present devices + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx + +--*/ +{ + GenericContext context; + int failcode; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + return EXIT_USAGE; + } + + context.count = 0; + context.control = 0; + failcode = EnumerateDevices(BaseName,Machine,0,argc,argv,FindCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,Machine?MSG_FIND_TAIL_NONE:MSG_FIND_TAIL_NONE_LOCAL,Machine); + } else { + FormatToStream(stdout,Machine?MSG_FIND_TAIL:MSG_FIND_TAIL_LOCAL,context.count,Machine); + } + } + return failcode; +} + +int cmdStatus(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + STATUS <id> ... + use EnumerateDevices to do hardwareID matching + for each match, dump status to stdout + note that we only enumerate present devices + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx + +--*/ +{ + GenericContext context; + int failcode; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + return EXIT_USAGE; + } + + context.count = 0; + context.control = FIND_DEVICE | FIND_STATUS; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,FindCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,Machine?MSG_FIND_TAIL_NONE:MSG_FIND_TAIL_NONE_LOCAL,Machine); + } else { + FormatToStream(stdout,Machine?MSG_FIND_TAIL:MSG_FIND_TAIL_LOCAL,context.count,Machine); + } + } + return failcode; +} + + +int cmdResources(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + RESOURCES <id> ... + use EnumerateDevices to do hardwareID matching + for each match, dump resources to stdout + note that we only enumerate present devices + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx + +--*/ +{ + GenericContext context; + int failcode; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + return EXIT_USAGE; + } + + context.count = 0; + context.control = FIND_DEVICE | FIND_RESOURCES; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,FindCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,Machine?MSG_FIND_TAIL_NONE:MSG_FIND_TAIL_NONE_LOCAL,Machine); + } else { + FormatToStream(stdout,Machine?MSG_FIND_TAIL:MSG_FIND_TAIL_LOCAL,context.count,Machine); + } + } + return failcode; +} + + +int cmdDriverFiles(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + STATUS <id> ... + use EnumerateDevices to do hardwareID matching + for each match, dump driver files to stdout + note that we only enumerate present devices + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx + +--*/ +{ + GenericContext context; + int failcode; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + return EXIT_USAGE; + } + if(Machine) { + // + // must be local machine as we need to involve class/co installers (FIND_DRIVERFILES) + // + return EXIT_USAGE; + } + + context.count = 0; + context.control = FIND_DEVICE | FIND_DRIVERFILES; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,FindCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,Machine?MSG_FIND_TAIL_NONE:MSG_FIND_TAIL_NONE_LOCAL,Machine); + } else { + FormatToStream(stdout,Machine?MSG_FIND_TAIL:MSG_FIND_TAIL_LOCAL,context.count,Machine); + } + } + return failcode; +} + +int cmdDriverNodes(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + STATUS <id> ... + use EnumerateDevices to do hardwareID matching + for each match, dump drivernodes to stdout + note that we only enumerate present devices + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx + +--*/ +{ + GenericContext context; + int failcode; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + return EXIT_USAGE; + } + if(Machine) { + // + // must be local machine as we need to involve class/co installers (FIND_DRIVERNODES) + // + return EXIT_USAGE; + } + + context.count = 0; + context.control = FIND_DEVICE | FIND_DRIVERNODES; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,FindCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,Machine?MSG_FIND_TAIL_NONE:MSG_FIND_TAIL_NONE_LOCAL,Machine); + } else { + FormatToStream(stdout,Machine?MSG_FIND_TAIL:MSG_FIND_TAIL_LOCAL,context.count,Machine); + } + } + return failcode; +} + +int cmdHwIds(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + HWIDS <id> ... + use EnumerateDevices to do hardwareID matching + for each match, dump hw/compat id's to stdout + note that we only enumerate present devices + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx + +--*/ +{ + GenericContext context; + int failcode; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + return EXIT_USAGE; + } + + context.count = 0; + context.control = FIND_DEVICE | FIND_HWIDS; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,FindCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,Machine?MSG_FIND_TAIL_NONE:MSG_FIND_TAIL_NONE_LOCAL,Machine); + } else { + FormatToStream(stdout,Machine?MSG_FIND_TAIL:MSG_FIND_TAIL_LOCAL,context.count,Machine); + } + } + return failcode; +} + +int cmdStack(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + STACK <id> ... + use EnumerateDevices to do hardwareID matching + for each match, dump device class and stack to stdout + note that we only enumerate present devices + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx + +--*/ +{ + GenericContext context; + int failcode; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + return EXIT_USAGE; + } + + context.count = 0; + context.control = FIND_DEVICE | FIND_CLASS | FIND_STACK; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,FindCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,Machine?MSG_FIND_TAIL_NONE:MSG_FIND_TAIL_NONE_LOCAL,Machine); + } else { + FormatToStream(stdout,Machine?MSG_FIND_TAIL:MSG_FIND_TAIL_LOCAL,context.count,Machine); + } + } + return failcode; +} + + + + +int ControlCallback(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Index, _In_ LPVOID Context) +/*++ + +Routine Description: + + Callback for use by Enable/Disable/Restart + Invokes DIF_PROPERTYCHANGE with correct parameters + uses SetupDiCallClassInstaller so cannot be done for remote devices + Don't use CM_xxx API's, they bypass class/co-installers and this is bad. + + In Enable case, we try global first, and if still disabled, enable local + +Arguments: + + Devs )_ uniquely identify the device + DevInfo ) + Index - index of device + Context - GenericContext + +Return Value: + + EXIT_xxxx + +--*/ +{ + SP_PROPCHANGE_PARAMS pcp; + GenericContext *pControlContext = (GenericContext*)Context; + SP_DEVINSTALL_PARAMS devParams; + + UNREFERENCED_PARAMETER(Index); + + switch(pControlContext->control) { + case DICS_ENABLE: + // + // enable both on global and config-specific profile + // do global first and see if that succeeded in enabling the device + // (global enable doesn't mark reboot required if device is still + // disabled on current config whereas vice-versa isn't true) + // + pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); + pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; + pcp.StateChange = pControlContext->control; + pcp.Scope = DICS_FLAG_GLOBAL; + pcp.HwProfile = 0; + // + // don't worry if this fails, we'll get an error when we try config- + // specific. + if(SetupDiSetClassInstallParams(Devs,DevInfo,&pcp.ClassInstallHeader,sizeof(pcp))) { + SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,Devs,DevInfo); + } + // + // now enable on config-specific + // + pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); + pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; + pcp.StateChange = pControlContext->control; + pcp.Scope = DICS_FLAG_CONFIGSPECIFIC; + pcp.HwProfile = 0; + break; + + default: + // + // operate on config-specific profile + // + pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); + pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; + pcp.StateChange = pControlContext->control; + pcp.Scope = DICS_FLAG_CONFIGSPECIFIC; + pcp.HwProfile = 0; + break; + + } + + if(!SetupDiSetClassInstallParams(Devs,DevInfo,&pcp.ClassInstallHeader,sizeof(pcp)) || + !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,Devs,DevInfo)) { + // + // failed to invoke DIF_PROPERTYCHANGE + // + DumpDeviceWithInfo(Devs,DevInfo,pControlContext->strFail); + } else { + // + // see if device needs reboot + // + devParams.cbSize = sizeof(devParams); + if(SetupDiGetDeviceInstallParams(Devs,DevInfo,&devParams) && (devParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT))) { + DumpDeviceWithInfo(Devs,DevInfo,pControlContext->strReboot); + pControlContext->reboot = TRUE; + } else { + // + // appears to have succeeded + // + DumpDeviceWithInfo(Devs,DevInfo,pControlContext->strSuccess); + } + pControlContext->count++; + } + return EXIT_OK; +} + +int cmdEnable(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + ENABLE <id> ... + use EnumerateDevices to do hardwareID matching + for each match, attempt to enable global, and if needed, config specific + +Arguments: + + BaseName - name of executable + Machine - must be NULL (local machine only) + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx (EXIT_REBOOT if reboot is required) + +--*/ +{ + GenericContext context; + TCHAR strEnable[80]; + TCHAR strReboot[80]; + TCHAR strFail[80]; + int failcode = EXIT_FAIL; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + // + // arguments required + // + return EXIT_USAGE; + } + if(Machine) { + // + // must be local machine as we need to involve class/co installers + // + return EXIT_USAGE; + } + if(!LoadString(NULL,IDS_ENABLED,strEnable,ARRAYSIZE(strEnable))) { + return EXIT_FAIL; + } + if(!LoadString(NULL,IDS_ENABLED_REBOOT,strReboot,ARRAYSIZE(strReboot))) { + return EXIT_FAIL; + } + if(!LoadString(NULL,IDS_ENABLE_FAILED,strFail,ARRAYSIZE(strFail))) { + return EXIT_FAIL; + } + + context.control = DICS_ENABLE; // DICS_PROPCHANGE DICS_ENABLE DICS_DISABLE + context.reboot = FALSE; + context.count = 0; + context.strReboot = strReboot; + context.strSuccess = strEnable; + context.strFail = strFail; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,ControlCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,MSG_FIND_TAIL_NONE_LOCAL); + } else if(!context.reboot) { + FormatToStream(stdout,MSG_ENABLE_TAIL,context.count); + } else { + FormatToStream(stdout,MSG_ENABLE_TAIL_REBOOT,context.count); + failcode = EXIT_REBOOT; + } + } + return failcode; +} + +int cmdDisable(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + DISABLE <id> ... + use EnumerateDevices to do hardwareID matching + for each match, attempt to disable global + +Arguments: + + BaseName - name of executable + Machine - must be NULL (local machine only) + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx (EXIT_REBOOT if reboot is required) + +--*/ +{ + GenericContext context; + TCHAR strDisable[80]; + TCHAR strReboot[80]; + TCHAR strFail[80]; + int failcode = EXIT_FAIL; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + // + // arguments required + // + return EXIT_USAGE; + } + if(Machine) { + // + // must be local machine as we need to involve class/co installers + // + return EXIT_USAGE; + } + if(!LoadString(NULL,IDS_DISABLED,strDisable,ARRAYSIZE(strDisable))) { + return EXIT_FAIL; + } + if(!LoadString(NULL,IDS_DISABLED_REBOOT,strReboot,ARRAYSIZE(strReboot))) { + return EXIT_FAIL; + } + if(!LoadString(NULL,IDS_DISABLE_FAILED,strFail,ARRAYSIZE(strFail))) { + return EXIT_FAIL; + } + + context.control = DICS_DISABLE; // DICS_PROPCHANGE DICS_ENABLE DICS_DISABLE + context.reboot = FALSE; + context.count = 0; + context.strReboot = strReboot; + context.strSuccess = strDisable; + context.strFail = strFail; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,ControlCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,MSG_FIND_TAIL_NONE_LOCAL); + } else if(!context.reboot) { + FormatToStream(stdout,MSG_DISABLE_TAIL,context.count); + } else { + FormatToStream(stdout,MSG_DISABLE_TAIL_REBOOT,context.count); + failcode = EXIT_REBOOT; + } + } + return failcode; +} + +int cmdRestart(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + RESTART <id> ... + use EnumerateDevices to do hardwareID matching + for each match, attempt to restart by issueing a PROPCHANGE + +Arguments: + + BaseName - name of executable + Machine - must be NULL (local machine only) + argc/argv - remaining parameters - passed into EnumerateDevices + +Return Value: + + EXIT_xxxx (EXIT_REBOOT if reboot is required) + +--*/ +{ + GenericContext context; + TCHAR strRestarted[80]; + TCHAR strReboot[80]; + TCHAR strFail[80]; + int failcode = EXIT_FAIL; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + // + // arguments required + // + return EXIT_USAGE; + } + if(Machine) { + // + // must be local machine as we need to involve class/co installers + // + return EXIT_USAGE; + } + if(!LoadString(NULL,IDS_RESTARTED,strRestarted,ARRAYSIZE(strRestarted))) { + return EXIT_FAIL; + } + if(!LoadString(NULL,IDS_REQUIRES_REBOOT,strReboot,ARRAYSIZE(strReboot))) { + return EXIT_FAIL; + } + if(!LoadString(NULL,IDS_RESTART_FAILED,strFail,ARRAYSIZE(strFail))) { + return EXIT_FAIL; + } + + context.control = DICS_PROPCHANGE; + context.reboot = FALSE; + context.count = 0; + context.strReboot = strReboot; + context.strSuccess = strRestarted; + context.strFail = strFail; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,ControlCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,MSG_FIND_TAIL_NONE_LOCAL); + } else if(!context.reboot) { + FormatToStream(stdout,MSG_RESTART_TAIL,context.count); + } else { + FormatToStream(stdout,MSG_RESTART_TAIL_REBOOT,context.count); + failcode = EXIT_REBOOT; + } + } + return failcode; +} + +int cmdReboot(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + REBOOT + reboot local machine + +Arguments: + + BaseName - name of executable + Machine - must be NULL (local machine only) + argc/argv - remaining parameters - ignored + +Return Value: + + EXIT_xxxx + +--*/ +{ + UNREFERENCED_PARAMETER(BaseName); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + if(Machine) { + // + // must be local machine + // + return EXIT_USAGE; + } + FormatToStream(stdout,MSG_REBOOT); + return Reboot() ? EXIT_OK : EXIT_FAIL; +} + + +int cmdUpdate(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + UPDATE + update driver for existing device(s) + +Arguments: + + BaseName - name of executable + Machine - machine name, must be NULL + argc/argv - remaining parameters + +Return Value: + + EXIT_xxxx + +--*/ +{ + HMODULE newdevMod = NULL; + int failcode = EXIT_FAIL; + UpdateDriverForPlugAndPlayDevicesProto UpdateFn; + BOOL reboot = FALSE; + LPCTSTR hwid = NULL; + LPCTSTR inf = NULL; + DWORD flags = 0; + DWORD res; + TCHAR InfPath[MAX_PATH]; + + UNREFERENCED_PARAMETER(BaseName); + UNREFERENCED_PARAMETER(Flags); + + if(Machine) { + // + // must be local machine + // + return EXIT_USAGE; + } + if(argc<2) { + // + // at least HWID required + // + return EXIT_USAGE; + } + inf = argv[0]; + if(!inf[0]) { + return EXIT_USAGE; + } + + hwid = argv[1]; + if(!hwid[0]) { + return EXIT_USAGE; + } + // + // Inf must be a full pathname + // + res = GetFullPathName(inf,MAX_PATH,InfPath,NULL); + if((res >= MAX_PATH) || (res == 0)) { + // + // inf pathname too long + // + return EXIT_FAIL; + } + if(GetFileAttributes(InfPath)==(DWORD)(-1)) { + // + // inf doesn't exist + // + return EXIT_FAIL; + } + inf = InfPath; + flags |= INSTALLFLAG_FORCE; + + // + // make use of UpdateDriverForPlugAndPlayDevices + // + newdevMod = LoadLibrary(TEXT("newdev.dll")); + if(!newdevMod) { + goto final; + } + UpdateFn = (UpdateDriverForPlugAndPlayDevicesProto)GetProcAddress(newdevMod,UPDATEDRIVERFORPLUGANDPLAYDEVICES); + if(!UpdateFn) + { + goto final; + } + + FormatToStream(stdout,inf ? MSG_UPDATE_INF : MSG_UPDATE,hwid,inf); + + if(!UpdateFn(NULL,hwid,inf,flags,&reboot)) { + goto final; + } + + FormatToStream(stdout,MSG_UPDATE_OK); + + failcode = reboot ? EXIT_REBOOT : EXIT_OK; + +final: + + if(newdevMod) { + FreeLibrary(newdevMod); + } + + return failcode; +} + +int cmdInstall(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + CREATE + Creates a root enumerated devnode and installs drivers on it + +Arguments: + + BaseName - name of executable + Machine - machine name, must be NULL + argc/argv - remaining parameters + +Return Value: + + EXIT_xxxx + +--*/ +{ + HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE; + SP_DEVINFO_DATA DeviceInfoData; + GUID ClassGUID; + TCHAR ClassName[MAX_CLASS_NAME_LEN]; + TCHAR hwIdList[LINE_LEN+4]; + TCHAR InfPath[MAX_PATH]; + int failcode = EXIT_FAIL; + LPCTSTR hwid = NULL; + LPCTSTR inf = NULL; + + if(Machine) { + // + // must be local machine + // + return EXIT_USAGE; + } + if(argc<2) { + // + // at least HWID required + // + return EXIT_USAGE; + } + inf = argv[0]; + if(!inf[0]) { + return EXIT_USAGE; + } + + hwid = argv[1]; + if(!hwid[0]) { + return EXIT_USAGE; + } + + // + // Inf must be a full pathname + // + if(GetFullPathName(inf,MAX_PATH,InfPath,NULL) >= MAX_PATH) { + // + // inf pathname too long + // + return EXIT_FAIL; + } + + // + // List of hardware ID's must be double zero-terminated + // + ZeroMemory(hwIdList,sizeof(hwIdList)); + if (FAILED(StringCchCopy(hwIdList,LINE_LEN,hwid))) { + goto final; + } + + // + // Use the INF File to extract the Class GUID. + // + if (!SetupDiGetINFClass(InfPath,&ClassGUID,ClassName,sizeof(ClassName)/sizeof(ClassName[0]),0)) + { + goto final; + } + + // + // Create the container for the to-be-created Device Information Element. + // + DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID,0); + if(DeviceInfoSet == INVALID_HANDLE_VALUE) + { + goto final; + } + + // + // Now create the element. + // Use the Class GUID and Name from the INF file. + // + DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + if (!SetupDiCreateDeviceInfo(DeviceInfoSet, + ClassName, + &ClassGUID, + NULL, + 0, + DICD_GENERATE_ID, + &DeviceInfoData)) + { + goto final; + } + + // + // Add the HardwareID to the Device's HardwareID property. + // + if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, + &DeviceInfoData, + SPDRP_HARDWAREID, + (LPBYTE)hwIdList, + (lstrlen(hwIdList)+1+1)*sizeof(TCHAR))) + { + goto final; + } + + // + // Transform the registry element into an actual devnode + // in the PnP HW tree. + // + if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, + DeviceInfoSet, + &DeviceInfoData)) + { + goto final; + } + + FormatToStream(stdout,MSG_INSTALL_UPDATE); + // + // update the driver for the device we just created + // + failcode = cmdUpdate(BaseName,Machine,Flags,argc,argv); + +final: + + if (DeviceInfoSet != INVALID_HANDLE_VALUE) { + SetupDiDestroyDeviceInfoList(DeviceInfoSet); + } + + return failcode; +} + +int cmdUpdateNI(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + UPDATE (non interactive version) + update driver for existing device(s) + +Arguments: + + BaseName - name of executable + Machine - machine name, must be NULL + argc/argv - remaining parameters + +Return Value: + + EXIT_xxxx + +--*/ +{ + // + // turn off interactive mode while doing the update + // + HMODULE setupapiMod = NULL; + SetupSetNonInteractiveModeProto SetNIFn; + int res; + BOOL prev; + + setupapiMod = LoadLibrary(TEXT("setupapi.dll")); + if(!setupapiMod) { + return cmdUpdate(BaseName,Machine,Flags,argc,argv); + } + SetNIFn = (SetupSetNonInteractiveModeProto)GetProcAddress(setupapiMod,SETUPSETNONINTERACTIVEMODE); + if(!SetNIFn) + { + FreeLibrary(setupapiMod); + return cmdUpdate(BaseName,Machine,Flags,argc,argv); + } + prev = SetNIFn(TRUE); + res = cmdUpdate(BaseName,Machine,Flags,argc,argv); + SetNIFn(prev); + FreeLibrary(setupapiMod); + return res; +} + +int RemoveCallback(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Index, _In_ LPVOID Context) +/*++ + +Routine Description: + + Callback for use by Remove + Invokes DIF_REMOVE + uses SetupDiCallClassInstaller so cannot be done for remote devices + Don't use CM_xxx API's, they bypass class/co-installers and this is bad. + +Arguments: + + Devs )_ uniquely identify the device + DevInfo ) + Index - index of device + Context - GenericContext + +Return Value: + + EXIT_xxxx + +--*/ +{ + SP_REMOVEDEVICE_PARAMS rmdParams; + GenericContext *pControlContext = (GenericContext*)Context; + SP_DEVINSTALL_PARAMS devParams; + LPCTSTR action = NULL; + // + // need hardware ID before trying to remove, as we wont have it after + // + TCHAR devID[MAX_DEVICE_ID_LEN]; + SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; + + UNREFERENCED_PARAMETER(Index); + + devInfoListDetail.cbSize = sizeof(devInfoListDetail); + if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) || + (CM_Get_Device_ID_Ex(DevInfo->DevInst,devID,MAX_DEVICE_ID_LEN,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) { + // + // skip this + // + return EXIT_OK; + } + + rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); + rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE; + rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL; + rmdParams.HwProfile = 0; + if(!SetupDiSetClassInstallParams(Devs,DevInfo,&rmdParams.ClassInstallHeader,sizeof(rmdParams)) || + !SetupDiCallClassInstaller(DIF_REMOVE,Devs,DevInfo)) { + // + // failed to invoke DIF_REMOVE + // + action = pControlContext->strFail; + } else { + // + // see if device needs reboot + // + devParams.cbSize = sizeof(devParams); + if(SetupDiGetDeviceInstallParams(Devs,DevInfo,&devParams) && (devParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT))) { + // + // reboot required + // + action = pControlContext->strReboot; + pControlContext->reboot = TRUE; + } else { + // + // appears to have succeeded + // + action = pControlContext->strSuccess; + } + pControlContext->count++; + } + _tprintf(TEXT("%-60s: %s\n"),devID,action); + + return EXIT_OK; +} + +int cmdRemove(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + REMOVE + remove devices + +Arguments: + + BaseName - name of executable + Machine - machine name, must be NULL + argc/argv - remaining parameters + +Return Value: + + EXIT_xxxx + +--*/ +{ + GenericContext context; + TCHAR strRemove[80]; + TCHAR strReboot[80]; + TCHAR strFail[80]; + int failcode = EXIT_FAIL; + + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + // + // arguments required + // + return EXIT_USAGE; + } + if(Machine) { + // + // must be local machine as we need to involve class/co installers + // + return EXIT_USAGE; + } + if(!LoadString(NULL,IDS_REMOVED,strRemove,ARRAYSIZE(strRemove))) { + return EXIT_FAIL; + } + if(!LoadString(NULL,IDS_REMOVED_REBOOT,strReboot,ARRAYSIZE(strReboot))) { + return EXIT_FAIL; + } + if(!LoadString(NULL,IDS_REMOVE_FAILED,strFail,ARRAYSIZE(strFail))) { + return EXIT_FAIL; + } + + context.reboot = FALSE; + context.count = 0; + context.strReboot = strReboot; + context.strSuccess = strRemove; + context.strFail = strFail; + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,RemoveCallback,&context); + + if(failcode == EXIT_OK) { + + if(!context.count) { + FormatToStream(stdout,MSG_REMOVE_TAIL_NONE); + } else if(!context.reboot) { + FormatToStream(stdout,MSG_REMOVE_TAIL,context.count); + } else { + FormatToStream(stdout,MSG_REMOVE_TAIL_REBOOT,context.count); + failcode = EXIT_REBOOT; + } + } + return failcode; +} + +int cmdRescan(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + RESCAN + rescan for new devices + +Arguments: + + BaseName - name of executable + Machine - machine name, must be NULL + argc/argv - remaining parameters + +Return Value: + + EXIT_xxxx + +--*/ +{ + + // + // reenumerate from the root of the devnode tree + // totally CM based + // + int failcode = EXIT_FAIL; + HMACHINE machineHandle = NULL; + DEVINST devRoot; + + UNREFERENCED_PARAMETER(BaseName); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + if(Machine) { + if(CM_Connect_Machine(Machine,&machineHandle) != CR_SUCCESS) { + return failcode; + } + } + + if(CM_Locate_DevNode_Ex(&devRoot,NULL,CM_LOCATE_DEVNODE_NORMAL,machineHandle) != CR_SUCCESS) { + goto final; + } + + FormatToStream(stdout,Machine ? MSG_RESCAN : MSG_RESCAN_LOCAL); + + if(CM_Reenumerate_DevNode_Ex(devRoot, 0, machineHandle) != CR_SUCCESS) { + goto final; + } + + FormatToStream(stdout,MSG_RESCAN_OK); + + failcode = EXIT_OK; + +final: + if(machineHandle) { + CM_Disconnect_Machine(machineHandle); + } + + return failcode; +} + +int cmdClassFilter(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + CLASSFILTER <name> <type> <subcmds> + Allows tweaking of class filters + Useful for filter driver development and for Product Support + + <subcmds> is a list of the following: + @service - sets 'after' to the first match of service after 'after' + (reset to -1 after any other command) + !service - deletes first match of 'service' after 'after' + -service - insert new service directly prior to 'after', or at start + +service - insert new service directly after 'after', or at end + + if no <subcmds> given, list the services + +Arguments: + + BaseName - name of executable + Machine - if non-NULL, remote machine + argc/argv - remaining parameters - list of class names + +Return Value: + + EXIT_xxxx + +--*/ +{ + int failcode = EXIT_FAIL; + int argIndex; + DWORD numGuids = 0; + GUID guid; + LPTSTR regval = NULL; + HKEY hk = (HKEY)INVALID_HANDLE_VALUE; + LPTSTR * multiVal = NULL; + int after; + bool modified = false; + int span; + SC_HANDLE SCMHandle = NULL; + SC_HANDLE ServHandle = NULL; + + UNREFERENCED_PARAMETER(BaseName); + UNREFERENCED_PARAMETER(Flags); + + if((argc<2) || !argv[0][0]) { + return EXIT_USAGE; + } + + // + // just take the first guid for the name + // + if(!SetupDiClassGuidsFromNameEx(argv[0],&guid,1,&numGuids,Machine,NULL)) { + if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + goto final; + } + } + if(numGuids == 0) { + goto final; + } + if(_tcsicmp(argv[1],TEXT("upper"))==0) { + regval = REGSTR_VAL_UPPERFILTERS; + } else if(_tcsicmp(argv[1],TEXT("lower"))==0) { + regval = REGSTR_VAL_LOWERFILTERS; + } else { + failcode = EXIT_USAGE; + goto final; + } + + hk = SetupDiOpenClassRegKeyEx(&guid, + KEY_READ | (argc>2 ? KEY_WRITE : 0), + DIOCR_INSTALLER, + Machine, + NULL + ); + if(hk == INVALID_HANDLE_VALUE) { + goto final; + } + multiVal = GetRegMultiSz(hk,regval); + + if(argc<=2) { + // + // just display + // + FormatToStream(stdout,MSG_CLASSFILTER_UNCHANGED); + DumpArray(1,multiVal); + failcode = EXIT_OK; + goto final; + } + after = -1; // for the @service expressions + span = 1; + + if(!multiVal) { + multiVal = CopyMultiSz(NULL); + if(!multiVal) { + goto final; + } + } + + for(argIndex=2;argIndex<argc;argIndex++) { + if((argv[argIndex] == NULL) || + (!argv[argIndex])) { + failcode = EXIT_USAGE; + break; + } + + int op = argv[argIndex][0]; + LPTSTR serv = argv[argIndex]+1; + int mark = 0; + int cnt; + int ent; + LPTSTR * tmpArray; + + if(op == TEXT('=')) { + after = -1; + span = 1; + op = serv[0]; + if(!op) { + continue; + } + serv++; + } + + if(!serv[0]) { + failcode = EXIT_USAGE; + goto final; + } + + if((op == TEXT('@')) || (op == TEXT('!'))) { + // + // need to find specified service in list + // + for(after+=span;multiVal[after];after++) { + if(_tcsicmp(multiVal[after],serv)==0) { + break; + } + } + if(!multiVal[after]) { + goto final; + } + if(op == TEXT('@')) { + // + // all we needed to do for '@' + // + span = 1; // span of 1 + continue; + } + // + // we're modifying + // + int c; + for(c = after;multiVal[c];c++) { + multiVal[c] = multiVal[c+1]; + } + LPTSTR * newArray = CopyMultiSz(multiVal); + if(!newArray) { + goto final; + } + DelMultiSz(multiVal); + multiVal = newArray; + span = 0; // span of 0 (deleted) + modified = true; + continue; + } + + if(op == '+') { + // + // insert after + // + if(after<0) { + int c; + for(c = 0;multiVal[c];c++) { + // nothing + } + mark = c; + } + else { + mark = after+span; + } + } else if(op == '-') { + // + // insert before + // + if(after<0) { + mark = 0; + } else { + mark = after; + } + } else { + // + // not valid + // + failcode = EXIT_USAGE; + goto final; + } + // + // sanity - see if service exists + // + SCMHandle = OpenSCManager(Machine, NULL, GENERIC_READ); + if(!SCMHandle) { + goto final; + } + ServHandle = OpenService(SCMHandle,serv,GENERIC_READ); + if(ServHandle) { + CloseServiceHandle(ServHandle); + } + CloseServiceHandle(SCMHandle); + if(!ServHandle) { + goto final; + } + + // + // need an array a little bigger + // + for(cnt = 0;multiVal[cnt];cnt++) { + // nothing + } + + tmpArray = new LPTSTR[cnt+2]; + if(!tmpArray) { + goto final; + } + _Analysis_assume_(mark < cnt); + for(ent=0;ent<mark;ent++) { + tmpArray[ent] = multiVal[ent]; + } + tmpArray[ent] = serv; + for(;ent<cnt;ent++) { + tmpArray[ent+1] = multiVal[ent]; + } + tmpArray[ent+1] = NULL; + LPTSTR * newArray = CopyMultiSz(tmpArray); + delete [] tmpArray; + if(!newArray) { + goto final; + } + DelMultiSz(multiVal); + multiVal = newArray; + modified = true; + span = 1; + after = mark; + } + + if(modified) { + if(multiVal[0]) { + size_t len = 0; + LPTSTR multiSz = multiVal[-1]; + LPTSTR p = multiSz; + while(*p) { + p+=lstrlen(p)+1; + } + p++; // skip past null + len = (p-multiSz)*sizeof(TCHAR); + if(len > DWORD_MAX) { + goto final; + } + LONG err = RegSetValueEx(hk,regval,0,REG_MULTI_SZ,(LPBYTE)multiSz,(DWORD)len); + if(err==NO_ERROR) { + FormatToStream(stdout,MSG_CLASSFILTER_CHANGED); + DumpArray(1,multiVal); + failcode = EXIT_REBOOT; + } + } else { + LONG err = RegDeleteValue(hk,regval); + if((err == NO_ERROR) || (err == ERROR_FILE_NOT_FOUND)) { + FormatToStream(stdout,MSG_CLASSFILTER_CHANGED); + failcode = EXIT_REBOOT; + } + } + } else { + FormatToStream(stdout,MSG_CLASSFILTER_UNCHANGED); + DumpArray(1,multiVal); + failcode = EXIT_OK; + } + +final: + + if(multiVal) { + DelMultiSz(multiVal); + } + if(hk != (HKEY)INVALID_HANDLE_VALUE) { + RegCloseKey(hk); + } + + return failcode; +} + +int SetHwidCallback(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Index, _In_ LPVOID Context) +/*++ + +Routine Description: + + Callback for use by SetHwid + +Arguments: + + Devs )_ uniquely identify the device + DevInfo ) + Index - index of device + Context - SetHwidContext + +Return Value: + + EXIT_xxxx + +--*/ +{ + SetHwidContext *pControlContext = (SetHwidContext*)Context; + ULONG status; + ULONG problem; + LPTSTR * hwlist = NULL; + bool modified = false; + int result = EXIT_FAIL; + + // + // processes the sub-commands on each callback + // not most efficient way of doing things, but perf isn't important + // + TCHAR devID[MAX_DEVICE_ID_LEN]; + SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; + + UNREFERENCED_PARAMETER(Index); + + devInfoListDetail.cbSize = sizeof(devInfoListDetail); + if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) || + (CM_Get_Device_ID_Ex(DevInfo->DevInst,devID,MAX_DEVICE_ID_LEN,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS) || + (CM_Get_DevNode_Status_Ex(&status,&problem,DevInfo->DevInst,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) { + // + // skip this + // + return EXIT_OK; + } + // + // this is how to verify it's root enumerated + // + if(!(status & DN_ROOT_ENUMERATED)) { + _tprintf(TEXT("%-60s: "),devID); + FormatToStream(stdout,MSG_SETHWID_NOTROOT); + pControlContext->skipped++; + return EXIT_OK; + } + hwlist = GetDevMultiSz(Devs,DevInfo,pControlContext->prop); + if(hwlist == NULL) { + hwlist = CopyMultiSz(NULL); + if(hwlist == NULL) { + return EXIT_FAIL; + } + } + + // + // modify hwid list (only relevent for root-enumerated devices) + // + int i; + int mark = -1; + + for(i=0;i<pControlContext->argc_right;i++) { + LPTSTR op = pControlContext->argv_right[i]; + if(op[0] == TEXT('=')) { + // + // clear the hwid list first + // + hwlist[0] = NULL; + mark = 0; + op++; + } else if(op[0] == TEXT('+')) { + // + // insert as better match + // + mark = 0; + op++; + } else if(op[0] == TEXT('-')) { + // + // insert as worse match + // + mark = -1; + op++; + } else if(op[0] == TEXT('!')) { + // + // delete + // + mark = -2; + op++; + } else { + // + // treat as a hardware id + // + } + if(!*op) { + result = EXIT_USAGE; + goto final; + } + int cnt; + for(cnt = 0;hwlist[cnt];cnt++) { + // nothing + } + if((mark == -1) || (mark>cnt)) { + mark = cnt; + } + LPTSTR * tmpArray = new LPTSTR[cnt+2]; + if(!tmpArray) { + goto final; + } + int dst = 0; + int ent; + for(ent=0;ent<mark;ent++) { + if(_tcsicmp(hwlist[ent],op)==0) { + continue; + } + tmpArray[dst++] = hwlist[ent]; + } + if(mark>=0) { + tmpArray[dst++] = op; + } + for(;ent<cnt;ent++) { + if(_tcsicmp(hwlist[ent],op)==0) { + continue; + } + tmpArray[dst++] = hwlist[ent]; + } + tmpArray[dst] = NULL; + LPTSTR * newArray = CopyMultiSz(tmpArray); + delete [] tmpArray; + if(!newArray) { + goto final; + } + DelMultiSz(hwlist); + hwlist = newArray; + modified = true; + mark++; + } + + // + // re-set the hwid list + // + if(modified) { + if(hwlist[0]) { + size_t len = 0; + LPTSTR multiSz = hwlist[-1]; + LPTSTR p = multiSz; + while(*p) { + p+=lstrlen(p)+1; + } + p++; // skip past final null + len = (p-multiSz)*sizeof(TCHAR); + if(len > DWORD_MAX) { + result = EXIT_FAIL; + goto final; + } + if(!SetupDiSetDeviceRegistryProperty(Devs, + DevInfo, + pControlContext->prop, + (LPBYTE)multiSz, + (DWORD)len)) { + result = EXIT_FAIL; + goto final; + } + } else { + // + // delete list + // + if(!SetupDiSetDeviceRegistryProperty(Devs, + DevInfo, + pControlContext->prop, + NULL, + 0)) { + result = EXIT_FAIL; + goto final; + } + } + } + result = EXIT_OK; + pControlContext->modified++; + _tprintf(TEXT("%-60s: "),devID); + for(mark=0;hwlist[mark];mark++) { + if(mark > 0) { + _tprintf(TEXT(",")); + } + _tprintf(TEXT("%s"),hwlist[mark]); + } + _tprintf(TEXT("\n")); + + // + // cleanup + // + + final: + + if(hwlist) { + DelMultiSz(hwlist); + } + + return result; +} + +int cmdSetHwid(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + + SETHWID + changes the hardware ID's of the listed root-enumerated devices + This demonstrates how to differentiate between root-enumerated and + non root-enumerated devices. + It also demonstrates how to get/set hardware ID's of root-enumerated + devices. + +Arguments: + + BaseName - name of executable + Machine - machine name, must be NULL + argc/argv - remaining parameters + +Return Value: + + EXIT_xxxx + +--*/ +{ + SetHwidContext context; + int failcode = EXIT_FAIL; + + UNREFERENCED_PARAMETER(Flags); + + if(!SplitCommandLine(argc,argv,context.argc_right,context.argv_right) + || (argc == 0) + || (context.argc_right == 0)) { + // + // arguments required both left and right of ':=' + // + return EXIT_USAGE; + } + context.skipped = 0; + context.modified = 0; + context.prop = SPDRP_HARDWAREID; + + failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,SetHwidCallback,&context); + + if(failcode == EXIT_OK) { + + if(context.skipped) { + FormatToStream(stdout,MSG_SETHWID_TAIL_SKIPPED,context.skipped,context.modified); + } else if(context.modified) { + FormatToStream(stdout,MSG_SETHWID_TAIL_MODIFIED,context.modified); + } else { + FormatToStream(stdout,MSG_SETHWID_TAIL_NONE); + } + } + return failcode; +} + +int cmdDPAdd(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + dp_add + Add a driver package to the machine. + +Arguments: + + BaseName - name of executable + Machine - machine name, must be NULL + argc/argv - remaining parameters + +Return Value: + + EXIT_xxxx + +--*/ +{ + int failcode = EXIT_FAIL; + DWORD res; + TCHAR SourceInfFileName[MAX_PATH]; + TCHAR DestinationInfFileName[MAX_PATH]; + PTSTR DestinationInfFileNameComponent = NULL; + PTSTR FilePart = NULL; + + UNREFERENCED_PARAMETER(BaseName); + UNREFERENCED_PARAMETER(Machine); + UNREFERENCED_PARAMETER(Flags); + + if(!argc) { + return EXIT_USAGE; + } + + res = GetFullPathName(argv[0], + ARRAYSIZE(SourceInfFileName), + SourceInfFileName, + &FilePart); + if ((!res) || (res >= ARRAYSIZE(SourceInfFileName))) { + FormatToStream(stdout,MSG_DPADD_INVALID_INF); + goto final; + } + + if (!SetupCopyOEMInf(SourceInfFileName, + NULL, + SPOST_PATH, + 0, + DestinationInfFileName, + ARRAYSIZE(DestinationInfFileName), + NULL, + &DestinationInfFileNameComponent)) { + FormatToStream(stdout,MSG_DPADD_FAILED); + goto final; + } + + // + // Successfully added the driver package to the machine. + // + FormatToStream(stdout,MSG_DPADD_SUCCESS,DestinationInfFileNameComponent); + failcode = EXIT_OK; + +final: + + return failcode; +} + +int cmdDPDelete(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + dp_delete + Deletes a driver package to the machine. + +Arguments: + + BaseName - name of executable + Machine - machine name, must be NULL + argc/argv - remaining parameters + +Return Value: + + EXIT_xxxx + +--*/ +{ + int failcode = EXIT_FAIL; + DWORD res; + TCHAR InfFileName[MAX_PATH]; + PTSTR FilePart = NULL; + HMODULE setupapiMod = NULL; + SetupUninstallOEMInfProto SUOIFn; + + UNREFERENCED_PARAMETER(BaseName); + UNREFERENCED_PARAMETER(Machine); + + if(!argc) { + return EXIT_USAGE; + } + + res = GetFullPathName(argv[0], + ARRAYSIZE(InfFileName), + InfFileName, + &FilePart); + if ((!res) || (!FilePart)) { + FormatToStream(stdout,MSG_DPADD_INVALID_INF); + goto final; + } + + setupapiMod = LoadLibrary(TEXT("setupapi.dll")); + if(!setupapiMod) { + goto final; + } + SUOIFn = (SetupUninstallOEMInfProto)GetProcAddress(setupapiMod,SETUPUNINSTALLOEMINF); + if(!SUOIFn) + { + goto final; + } + + if (!SUOIFn(FilePart, + ((Flags & DEVCON_FLAG_FORCE) ? 1 : 0), + NULL)) { + if (GetLastError() == ERROR_INF_IN_USE_BY_DEVICES) { + FormatToStream(stdout,MSG_DPDELETE_FAILED_IN_USE); + } else if (GetLastError() == ERROR_NOT_AN_INSTALLED_OEM_INF) { + FormatToStream(stdout,MSG_DPDELETE_FAILED_NOT_OEM_INF); + } else { + FormatToStream(stdout,MSG_DPDELETE_FAILED); + } + goto final; + } + + // + // Successfully added the driver package to the machine. + // + FormatToStream(stdout,MSG_DPDELETE_SUCCESS,FilePart); + failcode = EXIT_OK; + +final: + if (setupapiMod) { + FreeLibrary(setupapiMod); + } + + return failcode; +} + +int cmdDPEnumLegacy(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PTSTR argv[]) +/*++ + +Routine Description: + dp_enumLegacy + Enumerates installed Driver Packages on the machine pre Windows Longhorn + +Arguments: + + BaseName - name of executable + Machine - machine name, must be NULL + argc/argv - remaining parameters + +Return Value: + + EXIT_xxxx + +--*/ +{ + int failcode = EXIT_FAIL; + TCHAR FindName[MAX_PATH]; + HANDLE hFind = INVALID_HANDLE_VALUE; + WIN32_FIND_DATA wfd; + + UNREFERENCED_PARAMETER(BaseName); + UNREFERENCED_PARAMETER(Machine); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(argv); + + if(argc) { + return EXIT_USAGE; + } + + if (!GetWindowsDirectory(FindName, ARRAYSIZE(FindName)) || + FAILED(StringCchCat(FindName, ARRAYSIZE(FindName), TEXT("\\INF\\OEM*.INF")))) { + goto final; + } + + hFind = FindFirstFile(FindName, &wfd); + if (hFind == INVALID_HANDLE_VALUE) { + // + // No OEM driver packages on this machine. + // + FormatToStream(stdout,MSG_DPENUM_NO_OEM_INF); + failcode = EXIT_OK; + goto final; + } + + FormatToStream(stdout,MSG_DPENUM_LIST_HEADER); + + do { + FormatToStream(stdout,MSG_DPENUM_LIST_ENTRY,wfd.cFileName); + DumpDriverPackageData(wfd.cFileName); + } while (FindNextFile(hFind, &wfd)); + + FindClose(hFind); + + failcode = EXIT_OK; + +final: + + return failcode; +} + + +DispatchEntry DispatchTable[] = { + { TEXT("classfilter"), cmdClassFilter, MSG_CLASSFILTER_SHORT, MSG_CLASSFILTER_LONG }, + { TEXT("classes"), cmdClasses, MSG_CLASSES_SHORT, MSG_CLASSES_LONG }, + { TEXT("disable"), cmdDisable, MSG_DISABLE_SHORT, MSG_DISABLE_LONG }, + { TEXT("driverfiles"), cmdDriverFiles, MSG_DRIVERFILES_SHORT, MSG_DRIVERFILES_LONG }, + { TEXT("drivernodes"), cmdDriverNodes, MSG_DRIVERNODES_SHORT, MSG_DRIVERNODES_LONG }, + { TEXT("enable"), cmdEnable, MSG_ENABLE_SHORT, MSG_ENABLE_LONG }, + { TEXT("find"), cmdFind, MSG_FIND_SHORT, MSG_FIND_LONG }, + { TEXT("findall"), cmdFindAll, MSG_FINDALL_SHORT, MSG_FINDALL_LONG }, + { TEXT("help"), cmdHelp, MSG_HELP_SHORT, 0 }, + { TEXT("hwids"), cmdHwIds, MSG_HWIDS_SHORT, MSG_HWIDS_LONG }, + { TEXT("install"), cmdInstall, MSG_INSTALL_SHORT, MSG_INSTALL_LONG }, + { TEXT("listclass"), cmdListClass, MSG_LISTCLASS_SHORT, MSG_LISTCLASS_LONG }, + { TEXT("reboot"), cmdReboot, MSG_REBOOT_SHORT, MSG_REBOOT_LONG }, + { TEXT("remove"), cmdRemove, MSG_REMOVE_SHORT, MSG_REMOVE_LONG }, + { TEXT("rescan"), cmdRescan, MSG_RESCAN_SHORT, MSG_RESCAN_LONG }, + { TEXT("resources"), cmdResources, MSG_RESOURCES_SHORT, MSG_RESOURCES_LONG }, + { TEXT("restart"), cmdRestart, MSG_RESTART_SHORT, MSG_RESTART_LONG }, + { TEXT("sethwid"), cmdSetHwid, MSG_SETHWID_SHORT, MSG_SETHWID_LONG }, + { TEXT("stack"), cmdStack, MSG_STACK_SHORT, MSG_STACK_LONG }, + { TEXT("status"), cmdStatus, MSG_STATUS_SHORT, MSG_STATUS_LONG }, + { TEXT("update"), cmdUpdate, MSG_UPDATE_SHORT, MSG_UPDATE_LONG }, + { TEXT("updateni"), cmdUpdateNI, MSG_UPDATENI_SHORT, MSG_UPDATENI_LONG }, + { TEXT("dp_add"), cmdDPAdd, MSG_DPADD_SHORT, MSG_DPADD_LONG }, + { TEXT("dp_delete"), cmdDPDelete, MSG_DPDELETE_SHORT, MSG_DPDELETE_LONG }, + { TEXT("dp_enum"), cmdDPEnumLegacy,MSG_DPENUM_SHORT, MSG_DPENUM_LONG }, + { TEXT("?"), cmdHelp, 0, 0 }, + { NULL,NULL } +}; + + + diff --git a/setup/devcon/devcon.cpp b/setup/devcon/devcon.cpp new file mode 100644 index 00000000..d501dc1e --- /dev/null +++ b/setup/devcon/devcon.cpp @@ -0,0 +1,1162 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + devcon.cpp + +Abstract: + + Device Console + command-line interface for managing devices + +--*/ + +#include "devcon.h" + +struct IdEntry { + LPCTSTR String; // string looking for + LPCTSTR Wild; // first wild character if any + BOOL InstanceId; +}; + +void FormatToStream(_In_ FILE * stream, _In_ DWORD fmt,...) +/*++ + +Routine Description: + + Format text to stream using a particular msg-id fmt + Used for displaying localizable messages + +Arguments: + + stream - file stream to output to, stdout or stderr + fmt - message id + ... - parameters %1... + +Return Value: + + none + +--*/ +{ + va_list arglist; + LPTSTR locbuffer = NULL; + DWORD count; + + va_start(arglist, fmt); + count = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + fmt, + 0, // LANGID + (LPTSTR) &locbuffer, + 0, // minimum size of buffer + &arglist); + + if(locbuffer) { + if(count) { + int c; + int back = 0; + // + // strip any trailing "\r\n"s and replace by a single "\n" + // + while(((c = *CharPrev(locbuffer,locbuffer+count)) == TEXT('\r')) || + (c == TEXT('\n'))) { + count--; + back++; + } + if(back) { + locbuffer[count++] = TEXT('\n'); + locbuffer[count] = TEXT('\0'); + } + // + // now write to apropriate stream + // + _fputts(locbuffer,stream); + } + LocalFree(locbuffer); + } +} + +void Padding(_In_ int pad) +/*++ + +Routine Description: + + Insert padding into line before text + +Arguments: + + pad - number of padding tabs to insert + +Return Value: + + none + +--*/ +{ + int c; + + for(c=0;c<pad;c++) { + fputs(" ",stdout); + } +} + + +void Usage(_In_ LPCTSTR BaseName) +/*++ + +Routine Description: + + Display simple usage text + +Arguments: + + BaseName - name of executable + +Return Value: + + none + +--*/ +{ + FormatToStream(stderr,MSG_USAGE,BaseName); +} + +void CommandUsage(_In_ LPCTSTR BaseName, _In_ LPCTSTR Cmd) +/*++ + +Routine Description: + + Invalid command usage + Display how to get help on command + +Arguments: + + BaseName - name of executable + +Return Value: + + none + +--*/ +{ + FormatToStream(stderr,MSG_COMMAND_USAGE,BaseName,Cmd); +} + +void Failure(_In_ LPCTSTR BaseName, _In_ LPCTSTR Cmd) +/*++ + +Routine Description: + + Display simple error text for general failure + +Arguments: + + BaseName - name of executable + +Return Value: + + none + +--*/ +{ + FormatToStream(stderr,MSG_FAILURE,BaseName,Cmd); +} + +BOOL Reboot() +/*++ + +Routine Description: + + Attempt to reboot computer + +Arguments: + + none + +Return Value: + + TRUE if API suceeded + +--*/ +{ + HANDLE Token; + TOKEN_PRIVILEGES NewPrivileges; + LUID Luid; + + // + // we need to "turn on" reboot privilege + // if any of this fails, try reboot anyway + // + if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&Token)) { + goto final; + } + + if(!LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&Luid)) { + CloseHandle(Token); + goto final; + } + + NewPrivileges.PrivilegeCount = 1; + NewPrivileges.Privileges[0].Luid = Luid; + NewPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + AdjustTokenPrivileges( + Token, + FALSE, + &NewPrivileges, + 0, + NULL, + NULL + ); + + CloseHandle(Token); + +final: + + // + // attempt reboot - inform system that this is planned hardware install + // + // warning 28159 is a warning to rearchitect to avoid rebooting. However, + // sometimes during device installation, a reboot is needed, so this warning + // is being suppressed for the call to InitiateSystemShutdownEx. + // +#pragma warning( suppress: 28159) + return InitiateSystemShutdownEx(NULL, + NULL, + 0, + FALSE, + TRUE, + REASON_PLANNED_FLAG | REASON_HWINSTALL); + +} + +LPTSTR GetDeviceStringProperty(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Prop) +/*++ + +Routine Description: + + Return a string property for a device, otherwise NULL + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + Prop - string property to obtain + +Return Value: + + string containing description + +--*/ +{ + LPTSTR buffer; + DWORD size; + DWORD reqSize; + DWORD dataType; + DWORD szChars; + + size = 1024; // initial guess + buffer = new TCHAR[(size/sizeof(TCHAR))+1]; + if(!buffer) { + return NULL; + } + while(!SetupDiGetDeviceRegistryProperty(Devs,DevInfo,Prop,&dataType,(LPBYTE)buffer,size,&reqSize)) { + if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + goto failed; + } + if(dataType != REG_SZ) { + goto failed; + } + size = reqSize; + delete [] buffer; + buffer = new TCHAR[(size/sizeof(TCHAR))+1]; + if(!buffer) { + goto failed; + } + } + szChars = reqSize/sizeof(TCHAR); + buffer[szChars] = TEXT('\0'); + return buffer; + +failed: + if(buffer) { + delete [] buffer; + } + return NULL; +} + +LPTSTR GetDeviceDescription(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) +/*++ + +Routine Description: + + Return a string containing a description of the device, otherwise NULL + Always try friendly name first + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + string containing description + +--*/ +{ + LPTSTR desc; + desc = GetDeviceStringProperty(Devs,DevInfo,SPDRP_FRIENDLYNAME); + if(!desc) { + desc = GetDeviceStringProperty(Devs,DevInfo,SPDRP_DEVICEDESC); + } + return desc; +} + +IdEntry GetIdType(_In_ LPCTSTR Id) +/*++ + +Routine Description: + + Determine if this is instance id or hardware id and if there's any wildcards + instance ID is prefixed by '@' + wildcards are '*' + + +Arguments: + + Id - ptr to string to check + +Return Value: + + IdEntry + +--*/ +{ + IdEntry Entry; + + Entry.InstanceId = FALSE; + Entry.Wild = NULL; + Entry.String = Id; + + if(Entry.String[0] == INSTANCEID_PREFIX_CHAR) { + Entry.InstanceId = TRUE; + Entry.String = CharNext(Entry.String); + } + if(Entry.String[0] == QUOTE_PREFIX_CHAR) { + // + // prefix to treat rest of string literally + // + Entry.String = CharNext(Entry.String); + } else { + // + // see if any wild characters exist + // + Entry.Wild = _tcschr(Entry.String,WILD_CHAR); + } + return Entry; +} + +__drv_allocatesMem(object) +LPTSTR * GetMultiSzIndexArray(_In_ __drv_aliasesMem LPTSTR MultiSz) +/*++ + +Routine Description: + + Get an index array pointing to the MultiSz passed in + +Arguments: + + MultiSz - well formed multi-sz string + +Return Value: + + array of strings. last entry+1 of array contains NULL + returns NULL on failure + +--*/ +{ + LPTSTR scan; + LPTSTR * array; + int elements; + + for(scan = MultiSz, elements = 0; scan[0] ;elements++) { + scan += lstrlen(scan)+1; + } + array = new LPTSTR[elements+2]; + if(!array) { + return NULL; + } + array[0] = MultiSz; + array++; + if(elements) { + for(scan = MultiSz, elements = 0; scan[0]; elements++) { + array[elements] = scan; + scan += lstrlen(scan)+1; + } + } + array[elements] = NULL; + return array; +} + +__drv_allocatesMem(object) +LPTSTR * CopyMultiSz(_In_opt_ PZPWSTR Array) +/*++ + +Routine Description: + + Creates a new array from old + old array need not have been allocated by GetMultiSzIndexArray + +Arguments: + + Array - array of strings, last entry is NULL + +Return Value: + + MultiSz array allocated by GetMultiSzIndexArray + +--*/ +{ + LPTSTR multiSz = NULL; + HRESULT hr; + int cchMultiSz = 0; + int c; + if(Array) { + for(c=0;Array[c];c++) { + cchMultiSz+=lstrlen(Array[c])+1; + } + } + cchMultiSz+=1; // final Null + multiSz = new TCHAR[cchMultiSz]; + if(!multiSz) { + return NULL; + } + int len = 0; + if(Array) { + for(c=0;Array[c];c++) { + hr = StringCchCopy(multiSz+len,cchMultiSz-len,Array[c]); + if(FAILED(hr)){ + if(multiSz) + delete [] multiSz; + return NULL; + } + +#pragma prefast(suppress:__WARNING_BUFFER_OVERFLOW, "ESP:732") + len+=lstrlen(multiSz+len)+1; + } + } + + if( len < cchMultiSz ){ + multiSz[len] = TEXT('\0'); + } else { + // This should never happen! + multiSz[cchMultiSz-1] = TEXT('\0'); + } + + LPTSTR * pRes = GetMultiSzIndexArray(multiSz); + if(pRes) { + return pRes; + } + delete [] multiSz; + + return NULL; +} + +void DelMultiSz(_In_opt_ __drv_freesMem(object) PZPWSTR Array) +/*++ + +Routine Description: + + Deletes the string array allocated by GetDevMultiSz/GetRegMultiSz/GetMultiSzIndexArray + +Arguments: + + Array - pointer returned by GetMultiSzIndexArray + +Return Value: + + None + +--*/ +{ + if(Array) { + Array--; + if(Array[0]) { + delete [] Array[0]; + } + delete [] Array; + } +} + +__drv_allocatesMem(object) +LPTSTR * GetDevMultiSz(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Prop) +/*++ + +Routine Description: + + Get a multi-sz device property + and return as an array of strings + +Arguments: + + Devs - HDEVINFO containing DevInfo + DevInfo - Specific device + Prop - SPDRP_HARDWAREID or SPDRP_COMPATIBLEIDS + +Return Value: + + array of strings. last entry+1 of array contains NULL + returns NULL on failure + +--*/ +{ + LPTSTR buffer; + DWORD size; + DWORD reqSize; + DWORD dataType; + LPTSTR * array; + DWORD szChars; + + size = 8192; // initial guess, nothing magic about this + buffer = new TCHAR[(size/sizeof(TCHAR))+2]; + if(!buffer) { + return NULL; + } + while(!SetupDiGetDeviceRegistryProperty(Devs,DevInfo,Prop,&dataType,(LPBYTE)buffer,size,&reqSize)) { + if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + goto failed; + } + if(dataType != REG_MULTI_SZ) { + goto failed; + } + size = reqSize; + delete [] buffer; + buffer = new TCHAR[(size/sizeof(TCHAR))+2]; + if(!buffer) { + goto failed; + } + } + szChars = reqSize/sizeof(TCHAR); + buffer[szChars] = TEXT('\0'); + buffer[szChars+1] = TEXT('\0'); + array = GetMultiSzIndexArray(buffer); + if(array) { + return array; + } + +failed: + if(buffer) { + delete [] buffer; + } + return NULL; +} + +__drv_allocatesMem(object) +LPTSTR * GetRegMultiSz(_In_ HKEY hKey, _In_ LPCTSTR Val) +/*++ + +Routine Description: + + Get a multi-sz from registry + and return as an array of strings + +Arguments: + + hKey - Registry Key + Val - Value to query + +Return Value: + + array of strings. last entry+1 of array contains NULL + returns NULL on failure + +--*/ +{ + LPTSTR buffer; + DWORD size; + DWORD reqSize; + DWORD dataType; + LPTSTR * array; + DWORD szChars; + LONG regErr; + + size = 8192; // initial guess, nothing magic about this + buffer = new TCHAR[(size/sizeof(TCHAR))+2]; + if(!buffer) { + return NULL; + } + reqSize = size; + regErr = RegQueryValueEx(hKey,Val,NULL,&dataType,(PBYTE)buffer,&reqSize); + while((regErr != NO_ERROR)) { + if(GetLastError() != ERROR_MORE_DATA) { + goto failed; + } + if(dataType != REG_MULTI_SZ) { + goto failed; + } + size = reqSize; + delete [] buffer; + buffer = new TCHAR[(size/sizeof(TCHAR))+2]; + if(!buffer) { + goto failed; + } + regErr = RegQueryValueEx(hKey,Val,NULL,&dataType,(PBYTE)buffer,&reqSize); + } + szChars = reqSize/sizeof(TCHAR); + buffer[szChars] = TEXT('\0'); + buffer[szChars+1] = TEXT('\0'); + + array = GetMultiSzIndexArray(buffer); + if(array) { + return array; + } + +failed: + if(buffer) { + delete [] buffer; + } + return NULL; +} + +BOOL WildCardMatch(_In_ LPCTSTR Item, _In_ const IdEntry & MatchEntry) +/*++ + +Routine Description: + + Compare a single item against wildcard + I'm sure there's better ways of implementing this + Other than a command-line management tools + it's a bad idea to use wildcards as it implies + assumptions about the hardware/instance ID + eg, it might be tempting to enumerate root\* to + find all root devices, however there is a CfgMgr + API to query status and determine if a device is + root enumerated, which doesn't rely on implementation + details. + +Arguments: + + Item - item to find match for eg a\abcd\c + MatchEntry - eg *\*bc*\* + +Return Value: + + TRUE if any match, otherwise FALSE + +--*/ +{ + LPCTSTR scanItem; + LPCTSTR wildMark; + LPCTSTR nextWild; + size_t matchlen; + + // + // before attempting anything else + // try and compare everything up to first wild + // + if(!MatchEntry.Wild) { + return _tcsicmp(Item,MatchEntry.String) ? FALSE : TRUE; + } + if(_tcsnicmp(Item,MatchEntry.String,MatchEntry.Wild-MatchEntry.String) != 0) { + return FALSE; + } + wildMark = MatchEntry.Wild; + scanItem = Item + (MatchEntry.Wild-MatchEntry.String); + + for(;wildMark[0];) { + // + // if we get here, we're either at or past a wildcard + // + if(wildMark[0] == WILD_CHAR) { + // + // so skip wild chars + // + wildMark = CharNext(wildMark); + continue; + } + // + // find next wild-card + // + nextWild = _tcschr(wildMark,WILD_CHAR); + if(nextWild) { + // + // substring + // + matchlen = nextWild-wildMark; + } else { + // + // last portion of match + // + size_t scanlen = lstrlen(scanItem); + matchlen = lstrlen(wildMark); + if(scanlen < matchlen) { + return FALSE; + } + return _tcsicmp(scanItem+scanlen-matchlen,wildMark) ? FALSE : TRUE; + } + if(_istalpha(wildMark[0])) { + // + // scan for either lower or uppercase version of first character + // + + // + // the code suppresses the warning 28193 for the calls to _totupper + // and _totlower. This suppression is done because those functions + // have a check return annotation on them. However, they don't return + // error codes and the check return annotation is really being used + // to indicate that the return value of the function should be looked + // at and/or assigned to a variable. The check return annotation means + // the return value should always be checked in all code paths. + // We assign the return values to variables but the while loop does not + // examine both values in all code paths (e.g. when scanItem[0] == 0, + // neither u nor l will be examined) and it doesn't need to examine + // the values in all code paths. + // +#pragma warning( suppress: 28193) + TCHAR u = _totupper(wildMark[0]); +#pragma warning( suppress: 28193) + TCHAR l = _totlower(wildMark[0]); + while(scanItem[0] && scanItem[0]!=u && scanItem[0]!=l) { + scanItem = CharNext(scanItem); + } + if(!scanItem[0]) { + // + // ran out of string + // + return FALSE; + } + } else { + // + // scan for first character (no case) + // + scanItem = _tcschr(scanItem,wildMark[0]); + if(!scanItem) { + // + // ran out of string + // + return FALSE; + } + } + // + // try and match the sub-string at wildMark against scanItem + // + if(_tcsnicmp(scanItem,wildMark,matchlen)!=0) { + // + // nope, try again + // + scanItem = CharNext(scanItem); + continue; + } + // + // substring matched + // + scanItem += matchlen; + wildMark += matchlen; + } + return (wildMark[0] ? FALSE : TRUE); +} + +BOOL WildCompareHwIds(_In_ PZPWSTR Array, _In_ const IdEntry & MatchEntry) +/*++ + +Routine Description: + + Compares all strings in Array against Id + Use WildCardMatch to do real compare + +Arguments: + + Array - pointer returned by GetDevMultiSz + MatchEntry - string to compare against + +Return Value: + + TRUE if any match, otherwise FALSE + +--*/ +{ + if(Array) { + while(Array[0]) { + if(WildCardMatch(Array[0],MatchEntry)) { + return TRUE; + } + Array++; + } + } + return FALSE; +} + +bool SplitCommandLine( + _In_ int & argc, + _In_reads_(argc) LPTSTR * & argv, + _Out_ int & argc_right, + _Outref_result_buffer_(argc_right) LPTSTR * & argv_right) +/*++ + +Routine Description: + + Splits a command line into left and right of := + this is used for some of the more complex commands + +Arguments: + + argc/argv - in/out + - in, specifies the existing argc/argv + - out, specifies the argc/argv to left of := + arc_right/argv_right - out + - specifies the argc/argv to right of := + +Return Value: + + true - ":=" appears in line, false otherwise + +--*/ +{ + int i; + for(i = 0;i<argc;i++) { + if(_tcsicmp(argv[i],SPLIT_COMMAND_SEP)==0) { + argc_right = argc-(i+1); + argv_right = argv+(i+1); + argc = i; + return true; + } + } + argc_right = 0; + argv_right = argv+argc; + return false; +} + +int EnumerateDevices(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PWSTR* argv, _In_ CallbackFunc Callback, _In_ LPVOID Context) +/*++ + +Routine Description: + + Generic enumerator for devices that will be passed the following arguments: + <id> [<id>...] + =<class> [<id>...] + where <id> can either be @instance-id, or hardware-id and may contain wildcards + <class> is a class name + +Arguments: + + BaseName - name of executable + Machine - name of machine to enumerate + Flags - extra enumeration flags (eg DIGCF_PRESENT) + argc/argv - remaining arguments on command line + Callback - function to call for each hit + Context - data to pass function for each hit + +Return Value: + + EXIT_xxxx + +--*/ +{ + HDEVINFO devs = INVALID_HANDLE_VALUE; + IdEntry * templ = NULL; + int failcode = EXIT_FAIL; + int retcode; + int argIndex; + DWORD devIndex; + SP_DEVINFO_DATA devInfo; + SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; + BOOL doSearch = FALSE; + BOOL match; + BOOL all = FALSE; + GUID cls; + DWORD numClass = 0; + int skip = 0; + + UNREFERENCED_PARAMETER(BaseName); + + if(!argc) { + return EXIT_USAGE; + } + + templ = new IdEntry[argc]; + if(!templ) { + goto final; + } + + // + // determine if a class is specified + // + if(argc>skip && argv[skip][0]==CLASS_PREFIX_CHAR && argv[skip][1]) { + if(!SetupDiClassGuidsFromNameEx(argv[skip]+1,&cls,1,&numClass,Machine,NULL) && + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + goto final; + } + if(!numClass) { + failcode = EXIT_OK; + goto final; + } + skip++; + } + if(argc>skip && argv[skip][0]==WILD_CHAR && !argv[skip][1]) { + // + // catch convinient case of specifying a single argument '*' + // + all = TRUE; + skip++; + } else if(argc<=skip) { + // + // at least one parameter, but no <id>'s + // + all = TRUE; + } + + // + // determine if any instance id's were specified + // + // note, if =<class> was specified with no id's + // we'll mark it as not doSearch + // but will go ahead and add them all + // + for(argIndex=skip;argIndex<argc;argIndex++) { + templ[argIndex] = GetIdType(argv[argIndex]); + if(templ[argIndex].Wild || !templ[argIndex].InstanceId) { + // + // anything other than simple InstanceId's require a search + // + doSearch = TRUE; + } + } + if(doSearch || all) { + // + // add all id's to list + // if there's a class, filter on specified class + // + devs = SetupDiGetClassDevsEx(numClass ? &cls : NULL, + NULL, + NULL, + (numClass ? 0 : DIGCF_ALLCLASSES) | Flags, + NULL, + Machine, + NULL); + + } else { + // + // blank list, we'll add instance id's by hand + // + devs = SetupDiCreateDeviceInfoListEx(numClass ? &cls : NULL, + NULL, + Machine, + NULL); + } + if(devs == INVALID_HANDLE_VALUE) { + goto final; + } + for(argIndex=skip;argIndex<argc;argIndex++) { + // + // add explicit instances to list (even if enumerated all, + // this gets around DIGCF_PRESENT) + // do this even if wildcards appear to be detected since they + // might actually be part of the instance ID of a non-present device + // + if(templ[argIndex].InstanceId) { + SetupDiOpenDeviceInfo(devs,templ[argIndex].String,NULL,0,NULL); + } + } + + devInfoListDetail.cbSize = sizeof(devInfoListDetail); + if(!SetupDiGetDeviceInfoListDetail(devs,&devInfoListDetail)) { + goto final; + } + + // + // now enumerate them + // + if(all) { + doSearch = FALSE; + } + + devInfo.cbSize = sizeof(devInfo); + for(devIndex=0;SetupDiEnumDeviceInfo(devs,devIndex,&devInfo);devIndex++) { + + if(doSearch) { + for(argIndex=skip,match=FALSE;(argIndex<argc) && !match;argIndex++) { + TCHAR devID[MAX_DEVICE_ID_LEN]; + LPTSTR *hwIds = NULL; + LPTSTR *compatIds = NULL; + // + // determine instance ID + // + if(CM_Get_Device_ID_Ex(devInfo.DevInst,devID,MAX_DEVICE_ID_LEN,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS) { + devID[0] = TEXT('\0'); + } + + if(templ[argIndex].InstanceId) { + // + // match on the instance ID + // + if(WildCardMatch(devID,templ[argIndex])) { + match = TRUE; + } + } else { + // + // determine hardware ID's + // and search for matches + // + hwIds = GetDevMultiSz(devs,&devInfo,SPDRP_HARDWAREID); + compatIds = GetDevMultiSz(devs,&devInfo,SPDRP_COMPATIBLEIDS); + + if(WildCompareHwIds(hwIds,templ[argIndex]) || + WildCompareHwIds(compatIds,templ[argIndex])) { + match = TRUE; + } + } + DelMultiSz(hwIds); + DelMultiSz(compatIds); + } + } else { + match = TRUE; + } + if(match) { + retcode = Callback(devs,&devInfo,devIndex,Context); + if(retcode) { + failcode = retcode; + goto final; + } + } + } + + failcode = EXIT_OK; + +final: + if(templ) { + delete [] templ; + } + if(devs != INVALID_HANDLE_VALUE) { + SetupDiDestroyDeviceInfoList(devs); + } + return failcode; + +} + +int +__cdecl +_tmain(_In_ int argc, _In_reads_(argc) PWSTR* argv) +/*++ + +Routine Description: + + Main entry point + interpret -m:<machine> + and hand off execution to command + +Arguments: + + argc/argv - parameters passed to executable + +Return Value: + + EXIT_xxxx + +--*/ +{ + LPCTSTR cmd; + LPCTSTR baseName; + LPCTSTR machine = NULL; + int dispIndex; + int firstArg = 1; + int retval = EXIT_USAGE; + BOOL autoReboot = FALSE; + DWORD flags = 0; + + // + // syntax: + // + // [options] [-]command [<arg> [<arg>]] + // + // options: + // -m:<machine> - remote + // -r - auto reboot + // -f - force operation + // + baseName = _tcsrchr(argv[0],TEXT('\\')); + if(!baseName) { + baseName = argv[0]; + } else { + baseName = CharNext(baseName); + } + while((argc > firstArg) && ((argv[firstArg][0] == TEXT('-')) || (argv[firstArg][0] == TEXT('/')))) { + if((argv[firstArg][1]==TEXT('m')) || (argv[firstArg][1]==TEXT('M'))) { + if((argv[firstArg][2]!=TEXT(':')) || (argv[firstArg][3]==TEXT('\0'))) { + // + // don't recognize this switch + // + break; + } + machine = argv[firstArg]+3; + } else if((argv[firstArg][1]==TEXT('r')) || (argv[firstArg][1]==TEXT('R'))) { + if((argv[firstArg][2]!=TEXT('\0')) ) { + // + // don't recognize this switch + // + break; + } else { + autoReboot = TRUE; + } + } else if((argv[firstArg][1]==TEXT('f')) || (argv[firstArg][1]==TEXT('F'))) { + if((argv[firstArg][2]!=TEXT('\0')) ) { + // + // don't recognize this switch + // + break; + } else { + flags |= DEVCON_FLAG_FORCE; + } + } else { + // + // don't recognize this switch + // + break; + } + firstArg++; + } + + if((argc-firstArg) < 1) { + // + // after switches, must at least be command + // + Usage(baseName); + return EXIT_USAGE; + } + cmd = argv[firstArg]; + if((cmd[0]==TEXT('-')) || (cmd[0]==TEXT('/'))) { + // + // command may begin '-' or '/' + // eg, people might do devcon -help + // + cmd = CharNext(cmd); + } + firstArg++; + for(dispIndex = 0;DispatchTable[dispIndex].cmd;dispIndex++) { + if(_tcsicmp(cmd,DispatchTable[dispIndex].cmd)==0) { + retval = DispatchTable[dispIndex].func(baseName,machine,flags,argc-firstArg,argv+firstArg); + switch(retval) { + case EXIT_USAGE: + CommandUsage(baseName,DispatchTable[dispIndex].cmd); + break; + case EXIT_REBOOT: + if(autoReboot) { + Reboot(); + } + break; + case EXIT_OK: + break; + default: + Failure(baseName,DispatchTable[dispIndex].cmd); + break; + } + return retval; + } + } + Usage(baseName); + return EXIT_USAGE; +} + + diff --git a/setup/devcon/devcon.h b/setup/devcon/devcon.h new file mode 100644 index 00000000..6dd1ba2f --- /dev/null +++ b/setup/devcon/devcon.h @@ -0,0 +1,133 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + devcon.h + +Abstract: + + Device Console header + +--*/ + +#include <windows.h> +#include <tchar.h> +#include <stdlib.h> +#include <stdio.h> +#include <setupapi.h> +#include <regstr.h> +#include <infstr.h> +#include <cfgmgr32.h> +#include <string.h> +#include <malloc.h> +#include <newdev.h> +#include <objbase.h> +#include <strsafe.h> + +#include "msg.h" +#include "rc_ids.h" + +#ifndef ARRAYSIZE +#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) +#endif + +typedef int (*DispatchFunc)(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_ LPTSTR argv[]); +typedef int (*CallbackFunc)(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Index, _In_ LPVOID Context); + +typedef struct { + LPCTSTR cmd; + DispatchFunc func; + DWORD shortHelp; + DWORD longHelp; +} DispatchEntry; + +extern DispatchEntry DispatchTable[]; + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) +#endif + +#define INSTANCEID_PREFIX_CHAR TEXT('@') // character used to prefix instance ID's +#define CLASS_PREFIX_CHAR TEXT('=') // character used to prefix class name +#define WILD_CHAR TEXT('*') // wild character +#define QUOTE_PREFIX_CHAR TEXT('\'') // prefix character to ignore wild characters +#define SPLIT_COMMAND_SEP TEXT(":=") // whole word, indicates end of id's + +// +// Devcon.exe command line flags +// +#define DEVCON_FLAG_FORCE 0x00000001 + +void FormatToStream(_In_ FILE * stream, _In_ DWORD fmt,...); +void Padding(_In_ int pad); +bool SplitCommandLine( + _In_ int & argc, + _In_reads_(argc) LPTSTR * & argv, + _Out_ int & argc_right, + _Outref_result_buffer_(argc_right) LPTSTR * & argv_right); +int EnumerateDevices(_In_ LPCTSTR BaseName, _In_opt_ LPCTSTR Machine, _In_ DWORD Flags, _In_ int argc, _In_reads_(argc) PWSTR* argv, _In_ CallbackFunc Callback, _In_ LPVOID Context); +LPTSTR GetDeviceStringProperty(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Prop); +LPTSTR GetDeviceDescription(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo); +__drv_allocatesMem(object) LPTSTR * GetDevMultiSz(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ DWORD Prop); +__drv_allocatesMem(object) LPTSTR * GetRegMultiSz(_In_ HKEY hKey, _In_ LPCTSTR Val); +__drv_allocatesMem(object) LPTSTR * GetMultiSzIndexArray(_In_ __drv_aliasesMem LPTSTR MultiSz); +void DelMultiSz(_In_opt_ __drv_freesMem(object) PZPWSTR Array); +__drv_allocatesMem(object) LPTSTR * CopyMultiSz(_In_opt_ PZPWSTR Array); + +BOOL DumpArray(_In_ int pad, _In_ PZPWSTR Array); +BOOL DumpDevice(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo); +BOOL DumpDeviceClass(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo); +BOOL DumpDeviceDescr(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo); +BOOL DumpDeviceStatus(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo); +BOOL DumpDeviceResources(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo); +BOOL DumpDeviceDriverFiles(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo); +BOOL DumpDeviceDriverNodes(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo); +BOOL DumpDeviceHwIds(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo); +BOOL DumpDeviceWithInfo(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_opt_ LPCTSTR Info); +BOOL DumpDeviceStack(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo); +BOOL DumpDriverPackageData(_In_ LPCTSTR InfName); +BOOL Reboot(); + + +// +// UpdateDriverForPlugAndPlayDevices +// +typedef BOOL (WINAPI *UpdateDriverForPlugAndPlayDevicesProto)(_In_opt_ HWND hwndParent, + _In_ LPCTSTR HardwareId, + _In_ LPCTSTR FullInfPath, + _In_ DWORD InstallFlags, + _Out_opt_ PBOOL bRebootRequired + ); +typedef BOOL (WINAPI *SetupSetNonInteractiveModeProto)(_In_ BOOL NonInteractiveFlag + ); +typedef BOOL (WINAPI *SetupUninstallOEMInfProto)(_In_ LPCTSTR InfFileName, + _In_ DWORD Flags, + _Reserved_ PVOID Reserved + ); + +#if _SETUPAPI_VER >= _WIN32_WINNT_WINXP +typedef BOOL (WINAPI *SetupVerifyInfFileProto)(_In_ LPCTSTR InfName, + _In_opt_ PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo, + _Inout_ PSP_INF_SIGNER_INFO InfSignerInfo ); +#endif + +#ifdef _UNICODE +#define UPDATEDRIVERFORPLUGANDPLAYDEVICES "UpdateDriverForPlugAndPlayDevicesW" +#define SETUPUNINSTALLOEMINF "SetupUninstallOEMInfW" +#else +#define UPDATEDRIVERFORPLUGANDPLAYDEVICES "UpdateDriverForPlugAndPlayDevicesA" +#define SETUPUNINSTALLOEMINF "SetupUninstallOEMInfA" +#endif +#define SETUPSETNONINTERACTIVEMODE "SetupSetNonInteractiveMode" +#define SETUPVERIFYINFFILE "SetupVerifyInfFile" + +// +// exit codes +// +#define EXIT_OK (0) +#define EXIT_REBOOT (1) +#define EXIT_FAIL (2) +#define EXIT_USAGE (3) + diff --git a/setup/devcon/devcon.rc b/setup/devcon/devcon.rc new file mode 100644 index 00000000..ead46f85 --- /dev/null +++ b/setup/devcon/devcon.rc @@ -0,0 +1,37 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include <windows.h> +#include <commctrl.h> +#include "rc_ids.h" + +STRINGTABLE DISCARDABLE +{ + IDS_ENABLED, "Enabled" + IDS_ENABLED_REBOOT, "Enabled on reboot" + IDS_ENABLE_FAILED, "Enable failed" + IDS_DISABLED, "Disabled" + IDS_DISABLED_REBOOT, "Disabled on reboot" + IDS_DISABLE_FAILED, "Disable failed" + IDS_RESTARTED, "Restarted" + IDS_REQUIRES_REBOOT, "Requires reboot" + IDS_RESTART_FAILED, "Restart failed" + IDS_REMOVED, "Removed" + IDS_REMOVED_REBOOT, "Removed on reboot" + IDS_REMOVE_FAILED, "Remove failed" +} + + +// +// Version resources +// +#include <ntverp.h> +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Windows Setup API" +#define VER_INTERNALNAME_STR "SETUPAPI.DLL" +#define VER_ORIGINALFILENAME_STR "SETUPAPI.DLL" +#include <common.ver> + +#include "msg.rc" diff --git a/setup/devcon/devcon.sln b/setup/devcon/devcon.sln new file mode 100644 index 00000000..cc5b6752 --- /dev/null +++ b/setup/devcon/devcon.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "devcon", "devcon.vcxproj", "{E3D0CF6A-32E9-4970-8BED-43CC8DF57A5D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E3D0CF6A-32E9-4970-8BED-43CC8DF57A5D}.Debug|Win32.ActiveCfg = Debug|Win32 + {E3D0CF6A-32E9-4970-8BED-43CC8DF57A5D}.Debug|Win32.Build.0 = Debug|Win32 + {E3D0CF6A-32E9-4970-8BED-43CC8DF57A5D}.Release|Win32.ActiveCfg = Release|Win32 + {E3D0CF6A-32E9-4970-8BED-43CC8DF57A5D}.Release|Win32.Build.0 = Release|Win32 + {E3D0CF6A-32E9-4970-8BED-43CC8DF57A5D}.Debug|x64.ActiveCfg = Debug|x64 + {E3D0CF6A-32E9-4970-8BED-43CC8DF57A5D}.Debug|x64.Build.0 = Debug|x64 + {E3D0CF6A-32E9-4970-8BED-43CC8DF57A5D}.Release|x64.ActiveCfg = Release|x64 + {E3D0CF6A-32E9-4970-8BED-43CC8DF57A5D}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/setup/devcon/devcon.vcxproj b/setup/devcon/devcon.vcxproj new file mode 100644 index 00000000..c674ef8a --- /dev/null +++ b/setup/devcon/devcon.vcxproj @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{E3D0CF6A-32E9-4970-8BED-43CC8DF57A5D}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{406B583C-3ECF-4696-B3DD-6F2E8B3C1ED5}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>devcon</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>devcon</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>devcon</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>devcon</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;kernel32.lib;ntdll.lib;ole32.lib;setupapi.lib;shell32.lib;user32.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;kernel32.lib;ntdll.lib;ole32.lib;setupapi.lib;shell32.lib;user32.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;kernel32.lib;ntdll.lib;ole32.lib;setupapi.lib;shell32.lib;user32.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);advapi32.lib;kernel32.lib;ntdll.lib;ole32.lib;setupapi.lib;shell32.lib;user32.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="cmds.cpp" /> + <ClCompile Include="devcon.cpp" /> + <ClCompile Include="dump.cpp" /> + <MessageCompile Include="msg.mc" /> + <ResourceCompile Include="devcon.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/setup/devcon/devcon.vcxproj.Filters b/setup/devcon/devcon.vcxproj.Filters new file mode 100644 index 00000000..803e16d8 --- /dev/null +++ b/setup/devcon/devcon.vcxproj.Filters @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{C14D27DB-E3A6-4543-A3C4-7EF046CD3D67}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{8837D39E-7F9A-4CCB-B352-F512532281A3}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{CCD87CAF-050E-44E6-B5BE-C919F85E854D}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="cmds.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="devcon.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="dump.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="devcon.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/setup/devcon/dump.cpp b/setup/devcon/dump.cpp new file mode 100644 index 00000000..fac6ee31 --- /dev/null +++ b/setup/devcon/dump.cpp @@ -0,0 +1,1328 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + dump.cpp + +Abstract: + + Device Console + dump information out about a particular device + +--*/ + +#include "devcon.h" + +BOOL DumpDeviceWithInfo(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_opt_ LPCTSTR Info) +/*++ + +Routine Description: + + Write device instance & info to stdout + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + none + +--*/ +{ + TCHAR devID[MAX_DEVICE_ID_LEN]; + BOOL b = TRUE; + SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; + + devInfoListDetail.cbSize = sizeof(devInfoListDetail); + if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) || + (CM_Get_Device_ID_Ex(DevInfo->DevInst,devID,MAX_DEVICE_ID_LEN,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) { + StringCchCopy(devID, ARRAYSIZE(devID), TEXT("?")); + b = FALSE; + } + + if(Info) { + _tprintf(TEXT("%-60s: %s\n"),devID,Info); + } else { + _tprintf(TEXT("%s\n"),devID); + } + return b; +} + +BOOL DumpDevice(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) +/*++ + +Routine Description: + + Write device instance & description to stdout + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + TRUE if success + +--*/ +{ + LPTSTR desc; + BOOL b; + + desc = GetDeviceDescription(Devs,DevInfo); + b = DumpDeviceWithInfo(Devs,DevInfo,desc); + if(desc) { + delete [] desc; + } + return b; +} + +BOOL DumpDeviceDescr(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) +/*++ + +Routine Description: + + Write device description to stdout + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + TRUE if success + +--*/ +{ + LPTSTR desc; + + desc = GetDeviceDescription(Devs,DevInfo); + if(!desc) { + return FALSE; + } + Padding(1); + FormatToStream(stdout,MSG_DUMP_DESCRIPTION,desc); + delete [] desc; + return TRUE; +} + +BOOL DumpDeviceClass(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) +/*++ + +Routine Description: + + Write device class information to stdout + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + TRUE if success + +--*/ +{ + LPTSTR cls; + LPTSTR guid; + + Padding(1); + cls = GetDeviceStringProperty(Devs,DevInfo,SPDRP_CLASS); + guid = GetDeviceStringProperty(Devs,DevInfo,SPDRP_CLASSGUID); + if(!cls && !guid) { + FormatToStream(stdout, + MSG_DUMP_NOSETUPCLASS + ); + } else { + FormatToStream(stdout, + MSG_DUMP_SETUPCLASS, + guid ? guid : TEXT("{}"), + cls ? cls : TEXT("(?)") + ); + } + + if(cls) { + delete [] cls; + } + if(guid) { + delete [] guid; + } + + return TRUE; +} + +BOOL DumpDeviceStatus(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) +/*++ + +Routine Description: + + Write device status to stdout + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + none + +--*/ +{ + SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; + ULONG status = 0; + ULONG problem = 0; + BOOL hasInfo = FALSE; + BOOL isPhantom = FALSE; + CONFIGRET cr = CR_SUCCESS; + + devInfoListDetail.cbSize = sizeof(devInfoListDetail); + if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) || + ((cr = CM_Get_DevNode_Status_Ex(&status,&problem,DevInfo->DevInst,0,devInfoListDetail.RemoteMachineHandle))!=CR_SUCCESS)) { + if ((cr == CR_NO_SUCH_DEVINST) || (cr == CR_NO_SUCH_VALUE)) { + isPhantom = TRUE; + } else { + Padding(1); + FormatToStream(stdout,MSG_DUMP_STATUS_ERROR); + return FALSE; + } + } + // + // handle off the status/problem codes + // + if (isPhantom) { + Padding(1); + FormatToStream(stdout,MSG_DUMP_PHANTOM); + return TRUE; + } + if((status & DN_HAS_PROBLEM) && problem == CM_PROB_DISABLED) { + hasInfo = TRUE; + Padding(1); + FormatToStream(stdout,MSG_DUMP_DISABLED); + return TRUE; + } + if(status & DN_HAS_PROBLEM) { + hasInfo = TRUE; + Padding(1); + FormatToStream(stdout,MSG_DUMP_PROBLEM,problem); + } + if(status & DN_PRIVATE_PROBLEM) { + hasInfo = TRUE; + Padding(1); + FormatToStream(stdout,MSG_DUMP_PRIVATE_PROBLEM); + } + if(status & DN_STARTED) { + Padding(1); + FormatToStream(stdout,MSG_DUMP_STARTED); + } else if (!hasInfo) { + Padding(1); + FormatToStream(stdout,MSG_DUMP_NOTSTARTED); + } + return TRUE; +} + +BOOL DumpDeviceResourcesOfType(_In_ DEVINST DevInst, _In_ HMACHINE MachineHandle, _In_ LOG_CONF Config, _In_ RESOURCEID ReqResId) +{ + RES_DES prevResDes = (RES_DES)Config; + RES_DES resDes = 0; + RESOURCEID resId = ReqResId; + ULONG dataSize; + PBYTE resDesData; + BOOL retval = FALSE; + + UNREFERENCED_PARAMETER(DevInst); + + while(CM_Get_Next_Res_Des_Ex(&resDes,prevResDes,ReqResId,&resId,0,MachineHandle)==CR_SUCCESS) { + if(prevResDes != Config) { + CM_Free_Res_Des_Handle(prevResDes); + } + prevResDes = resDes; + if(CM_Get_Res_Des_Data_Size_Ex(&dataSize,resDes,0,MachineHandle)!=CR_SUCCESS) { + continue; + } + resDesData = new BYTE[dataSize]; + if(!resDesData) { + continue; + } + if(CM_Get_Res_Des_Data_Ex(resDes,resDesData,dataSize,0,MachineHandle)!=CR_SUCCESS) { + delete [] resDesData; + continue; + } + switch(resId) { + case ResType_Mem: { + + PMEM_RESOURCE pMemData = (PMEM_RESOURCE)resDesData; + if(pMemData->MEM_Header.MD_Alloc_End-pMemData->MEM_Header.MD_Alloc_Base+1) { + Padding(2); + _tprintf(TEXT("MEM : %08I64x-%08I64x\n"),pMemData->MEM_Header.MD_Alloc_Base,pMemData->MEM_Header.MD_Alloc_End); + retval = TRUE; + } + break; + } + + case ResType_IO: { + + PIO_RESOURCE pIoData = (PIO_RESOURCE)resDesData; + if(pIoData->IO_Header.IOD_Alloc_End-pIoData->IO_Header.IOD_Alloc_Base+1) { + Padding(2); + _tprintf(TEXT("IO : %04I64x-%04I64x\n"),pIoData->IO_Header.IOD_Alloc_Base,pIoData->IO_Header.IOD_Alloc_End); + retval = TRUE; + } + break; + } + + case ResType_DMA: { + + PDMA_RESOURCE pDmaData = (PDMA_RESOURCE)resDesData; + Padding(2); + _tprintf(TEXT("DMA : %u\n"),pDmaData->DMA_Header.DD_Alloc_Chan); + retval = TRUE; + break; + } + + case ResType_IRQ: { + + PIRQ_RESOURCE pIrqData = (PIRQ_RESOURCE)resDesData; + + Padding(2); + _tprintf(TEXT("IRQ : %u\n"),pIrqData->IRQ_Header.IRQD_Alloc_Num); + retval = TRUE; + break; + } + } + delete [] resDesData; + } + if(prevResDes != Config) { + CM_Free_Res_Des_Handle(prevResDes); + } + return retval; +} + +BOOL DumpDeviceResources(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) +/*++ + +Routine Description: + + Dump Resources to stdout + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + none + +--*/ +{ + SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; + ULONG status = 0; + ULONG problem = 0; + LOG_CONF config = 0; + BOOL haveConfig = FALSE; + + // + // see what state the device is in + // + devInfoListDetail.cbSize = sizeof(devInfoListDetail); + if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) || + (CM_Get_DevNode_Status_Ex(&status,&problem,DevInfo->DevInst,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) { + return FALSE; + } + + // + // see if the device is running and what resources it might be using + // + if(!(status & DN_HAS_PROBLEM)) { + // + // If this device is running, does this devinst have a ALLOC log config? + // + if (CM_Get_First_Log_Conf_Ex(&config, + DevInfo->DevInst, + ALLOC_LOG_CONF, + devInfoListDetail.RemoteMachineHandle) == CR_SUCCESS) { + haveConfig = TRUE; + } + } + if(!haveConfig) { + // + // If no config so far, does it have a FORCED log config? + // (note that technically these resources might be used by another device + // but is useful info to show) + // + if (CM_Get_First_Log_Conf_Ex(&config, + DevInfo->DevInst, + FORCED_LOG_CONF, + devInfoListDetail.RemoteMachineHandle) == CR_SUCCESS) { + haveConfig = TRUE; + } + } + + if(!haveConfig) { + // + // if there's a hardware-disabled problem, boot-config isn't valid + // otherwise use this if we don't have anything else + // + if(!(status & DN_HAS_PROBLEM) || (problem != CM_PROB_HARDWARE_DISABLED)) { + // + // Does it have a BOOT log config? + // + if (CM_Get_First_Log_Conf_Ex(&config, + DevInfo->DevInst, + BOOT_LOG_CONF, + devInfoListDetail.RemoteMachineHandle) == CR_SUCCESS) { + haveConfig = TRUE; + } + } + } + + if(!haveConfig) { + // + // if we don't have any configuration, display an apropriate message + // + Padding(1); + FormatToStream(stdout,(status & DN_STARTED) ? MSG_DUMP_NO_RESOURCES : MSG_DUMP_NO_RESERVED_RESOURCES ); + return TRUE; + } + Padding(1); + FormatToStream(stdout,(status & DN_STARTED) ? MSG_DUMP_RESOURCES : MSG_DUMP_RESERVED_RESOURCES ); + + // + // dump resources + // + DumpDeviceResourcesOfType(DevInfo->DevInst,devInfoListDetail.RemoteMachineHandle,config,ResType_All); + + // + // release handle + // + CM_Free_Log_Conf_Handle(config); + + return TRUE; +} + + +UINT DumpDeviceDriversCallback(_In_ PVOID Context, _In_ UINT Notification, _In_ UINT_PTR Param1, _In_ UINT_PTR Param2) +/*++ + +Routine Description: + + if Context provided, Simply count + otherwise dump files indented 2 + +Arguments: + + Context - DWORD Count + Notification - SPFILENOTIFY_QUEUESCAN + Param1 - scan + +Return Value: + + none + +--*/ +{ + LPDWORD count = (LPDWORD)Context; + LPTSTR file = (LPTSTR)Param1; + + UNREFERENCED_PARAMETER(Notification); + UNREFERENCED_PARAMETER(Param2); + + if(count) { + count[0]++; + } else { + Padding(2); + _tprintf(TEXT("%s\n"),file); + } + + return NO_ERROR; +} + +BOOL FindCurrentDriver(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo, _In_ PSP_DRVINFO_DATA DriverInfoData) +/*++ + +Routine Description: + + Find the driver that is associated with the current device + We can do this either the quick way (available in WinXP) + or the long way that works in Win2k. + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + TRUE if we managed to determine and select current driver + +--*/ +{ + SP_DEVINSTALL_PARAMS deviceInstallParams; + WCHAR SectionName[LINE_LEN]; + WCHAR DrvDescription[LINE_LEN]; + WCHAR MfgName[LINE_LEN]; + WCHAR ProviderName[LINE_LEN]; + HKEY hKey = NULL; + DWORD RegDataLength; + DWORD RegDataType; + DWORD c; + BOOL match = FALSE; + long regerr; + + ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams)); + deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); + + if(!SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) { + return FALSE; + } + +#ifdef DI_FLAGSEX_INSTALLEDDRIVER + // + // Set the flags that tell SetupDiBuildDriverInfoList to just put the + // currently installed driver node in the list, and that it should allow + // excluded drivers. This flag introduced in WinXP. + // + deviceInstallParams.FlagsEx |= (DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS); + + if(SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) { + // + // we were able to specify this flag, so proceed the easy way + // we should get a list of no more than 1 driver + // + if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER)) { + return FALSE; + } + if (!SetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_CLASSDRIVER, + 0, DriverInfoData)) { + return FALSE; + } + // + // we've selected the current driver + // + return TRUE; + } + deviceInstallParams.FlagsEx &= ~(DI_FLAGSEX_INSTALLEDDRIVER | DI_FLAGSEX_ALLOWEXCLUDEDDRVS); +#endif + // + // The following method works in Win2k, but it's slow and painful. + // + // First, get driver key - if it doesn't exist, no driver + // + hKey = SetupDiOpenDevRegKey(Devs, + DevInfo, + DICS_FLAG_GLOBAL, + 0, + DIREG_DRV, + KEY_READ + ); + + if(hKey == INVALID_HANDLE_VALUE) { + // + // no such value exists, so there can't be an associated driver + // + RegCloseKey(hKey); + return FALSE; + } + + // + // obtain path of INF - we'll do a search on this specific INF + // + RegDataLength = sizeof(deviceInstallParams.DriverPath); // bytes!!! + regerr = RegQueryValueEx(hKey, + REGSTR_VAL_INFPATH, + NULL, + &RegDataType, + (PBYTE)deviceInstallParams.DriverPath, + &RegDataLength + ); + + if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) { + // + // no such value exists, so no associated driver + // + RegCloseKey(hKey); + return FALSE; + } + + // + // obtain name of Provider to fill into DriverInfoData + // + RegDataLength = sizeof(ProviderName); // bytes!!! + regerr = RegQueryValueEx(hKey, + REGSTR_VAL_PROVIDER_NAME, + NULL, + &RegDataType, + (PBYTE)ProviderName, + &RegDataLength + ); + + if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) { + // + // no such value exists, so we don't have a valid associated driver + // + RegCloseKey(hKey); + return FALSE; + } + + // + // obtain name of section - for final verification + // + RegDataLength = sizeof(SectionName); // bytes!!! + regerr = RegQueryValueEx(hKey, + REGSTR_VAL_INFSECTION, + NULL, + &RegDataType, + (PBYTE)SectionName, + &RegDataLength + ); + + if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) { + // + // no such value exists, so we don't have a valid associated driver + // + RegCloseKey(hKey); + return FALSE; + } + + // + // driver description (need not be same as device description) + // - for final verification + // + RegDataLength = sizeof(DrvDescription); // bytes!!! + regerr = RegQueryValueEx(hKey, + REGSTR_VAL_DRVDESC, + NULL, + &RegDataType, + (PBYTE)DrvDescription, + &RegDataLength + ); + + RegCloseKey(hKey); + + if((regerr != ERROR_SUCCESS) || (RegDataType != REG_SZ)) { + // + // no such value exists, so we don't have a valid associated driver + // + return FALSE; + } + + // + // Manufacturer (via SPDRP_MFG, don't access registry directly!) + // + + if(!SetupDiGetDeviceRegistryProperty(Devs, + DevInfo, + SPDRP_MFG, + NULL, // datatype is guaranteed to always be REG_SZ. + (PBYTE)MfgName, + sizeof(MfgName), // bytes!!! + NULL)) { + // + // no such value exists, so we don't have a valid associated driver + // + return FALSE; + } + + // + // now search for drivers listed in the INF + // + // + deviceInstallParams.Flags |= DI_ENUMSINGLEINF; + deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS; + + if(!SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) { + return FALSE; + } + if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_CLASSDRIVER)) { + return FALSE; + } + + // + // find the entry in the INF that was used to install the driver for + // this device + // + for(c=0;SetupDiEnumDriverInfo(Devs,DevInfo,SPDIT_CLASSDRIVER,c,DriverInfoData);c++) { + if((_tcscmp(DriverInfoData->MfgName,MfgName)==0) + &&(_tcscmp(DriverInfoData->ProviderName,ProviderName)==0)) { + // + // these two fields match, try more detailed info + // to ensure we have the exact driver entry used + // + SP_DRVINFO_DETAIL_DATA detail; + detail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); + if(!SetupDiGetDriverInfoDetail(Devs,DevInfo,DriverInfoData,&detail,sizeof(detail),NULL) + && (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { + continue; + } + if((_tcscmp(detail.SectionName,SectionName)==0) && + (_tcscmp(detail.DrvDescription,DrvDescription)==0)) { + match = TRUE; + break; + } + } + } + if(!match) { + SetupDiDestroyDriverInfoList(Devs,DevInfo,SPDIT_CLASSDRIVER); + } + return match; +} + +BOOL DumpDeviceDriverFiles(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) +/*++ + +Routine Description: + + Dump information about what files were installed for driver package + <tab>Installed using OEM123.INF section [abc.NT] + <tab><tab>file... + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + none + +--*/ +{ + // + // do this by 'searching' for the current driver + // mimmicing a copy-only install to our own file queue + // and then parsing that file queue + // + SP_DEVINSTALL_PARAMS deviceInstallParams; + SP_DRVINFO_DATA driverInfoData; + SP_DRVINFO_DETAIL_DATA driverInfoDetail; + HSPFILEQ queueHandle = INVALID_HANDLE_VALUE; + DWORD count; + DWORD scanResult; + BOOL success = FALSE; + + ZeroMemory(&driverInfoData,sizeof(driverInfoData)); + driverInfoData.cbSize = sizeof(driverInfoData); + + if(!FindCurrentDriver(Devs,DevInfo,&driverInfoData)) { + Padding(1); + FormatToStream(stdout, MSG_DUMP_NO_DRIVER); + return FALSE; + } + + // + // get useful driver information + // + driverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); + if(!SetupDiGetDriverInfoDetail(Devs,DevInfo,&driverInfoData,&driverInfoDetail,sizeof(SP_DRVINFO_DETAIL_DATA),NULL) && + GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + // + // no information about driver or section + // + goto final; + } + if(!driverInfoDetail.InfFileName[0] || !driverInfoDetail.SectionName[0]) { + goto final; + } + + // + // pretend to do the file-copy part of a driver install + // to determine what files are used + // the specified driver must be selected as the active driver + // + if(!SetupDiSetSelectedDriver(Devs, DevInfo, &driverInfoData)) { + goto final; + } + + // + // create a file queue so we can look at this queue later + // + queueHandle = SetupOpenFileQueue(); + + if ( queueHandle == (HSPFILEQ)INVALID_HANDLE_VALUE ) { + goto final; + } + + // + // modify flags to indicate we're providing our own queue + // + ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams)); + deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); + if ( !SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams) ) { + goto final; + } + + // + // we want to add the files to the file queue, not install them! + // + deviceInstallParams.FileQueue = queueHandle; + deviceInstallParams.Flags |= DI_NOVCP; + + if ( !SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams) ) { + goto final; + } + + // + // now fill queue with files that are to be installed + // this involves all class/co-installers + // + if ( !SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, Devs, DevInfo) ) { + goto final; + } + + // + // we now have a list of delete/rename/copy files + // iterate the copy queue twice - 1st time to get # of files + // 2nd time to get files + // (WinXP has API to get # of files, but we want this to work + // on Win2k too) + // + + count = 0; + scanResult = 0; + // + // call once to count + // + SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,&count,&scanResult); + Padding(1); + FormatToStream(stdout, count ? MSG_DUMP_DRIVER_FILES : MSG_DUMP_NO_DRIVER_FILES, count, driverInfoDetail.InfFileName, driverInfoDetail.SectionName); + // + // call again to dump the files + // + SetupScanFileQueue(queueHandle,SPQ_SCAN_USE_CALLBACK,NULL,DumpDeviceDriversCallback,NULL,&scanResult); + + success = TRUE; + +final: + + SetupDiDestroyDriverInfoList(Devs,DevInfo,SPDIT_CLASSDRIVER); + + if ( queueHandle != (HSPFILEQ)INVALID_HANDLE_VALUE ) { + SetupCloseFileQueue(queueHandle); + } + + if(!success) { + Padding(1); + FormatToStream(stdout, MSG_DUMP_NO_DRIVER); + } + + return success; + +} + +BOOL DumpArray(_In_ int pad, _In_ PZPWSTR Array) +/*++ + +Routine Description: + + Iterate array and dump entries to screen + +Arguments: + + pad - padding + Array - array to dump + +Return Value: + + none + +--*/ +{ + if(!Array || !Array[0]) { + return FALSE; + } + while(Array[0]) { + Padding(pad); + _tprintf(TEXT("%s\n"),Array[0]); + Array++; + } + return TRUE; +} + +BOOL DumpDeviceHwIds(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) +/*++ + +Routine Description: + + Write device instance & description to stdout + <tab>Hardware ID's + <tab><tab>ID + ... + <tab>Compatible ID's + <tab><tab>ID + ... + or + <tab>No Hardware ID's for device + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + none + +--*/ +{ + LPTSTR * hwIdArray = GetDevMultiSz(Devs,DevInfo,SPDRP_HARDWAREID); + LPTSTR * compatIdArray = GetDevMultiSz(Devs,DevInfo,SPDRP_COMPATIBLEIDS); + BOOL displayed = FALSE; + + if(hwIdArray && hwIdArray[0]) { + displayed = TRUE; + Padding(1); + FormatToStream(stdout, MSG_DUMP_HWIDS); + DumpArray(2,hwIdArray); + } + if(compatIdArray && compatIdArray[0]) { + displayed = TRUE; + Padding(1); + FormatToStream(stdout, MSG_DUMP_COMPATIDS); + DumpArray(2,compatIdArray); + } + if(!displayed) { + Padding(1); + FormatToStream(stdout, MSG_DUMP_NO_HWIDS); + } + + DelMultiSz(hwIdArray); + DelMultiSz(compatIdArray); + + return TRUE; +} + +BOOL DumpDeviceDriverNodes(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) +/*++ + +Routine Description: + + Write device instance & description to stdout + <tab>Installed using OEM123.INF section [abc.NT] + <tab><tab>file... + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + none + +--*/ +{ + BOOL success = FALSE; + SP_DEVINSTALL_PARAMS deviceInstallParams; + SP_DRVINFO_DATA driverInfoData; + SP_DRVINFO_DETAIL_DATA driverInfoDetail; + SP_DRVINSTALL_PARAMS driverInstallParams; + DWORD index; + SYSTEMTIME SystemTime; + ULARGE_INTEGER Version; + TCHAR Buffer[MAX_PATH]; + + ZeroMemory(&deviceInstallParams, sizeof(deviceInstallParams)); + ZeroMemory(&driverInfoData, sizeof(driverInfoData)); + + driverInfoData.cbSize = sizeof(SP_DRVINFO_DATA); + deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); + + if(!SetupDiGetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) { + return FALSE; + } + + // + // Set the flags that tell SetupDiBuildDriverInfoList to allow excluded drivers. + // + deviceInstallParams.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS; + + if(!SetupDiSetDeviceInstallParams(Devs, DevInfo, &deviceInstallParams)) { + return FALSE; + } + + // + // Now build a class driver list. + // + if(!SetupDiBuildDriverInfoList(Devs, DevInfo, SPDIT_COMPATDRIVER)) { + goto final2; + } + + // + // Enumerate all of the drivernodes. + // + index = 0; + while(SetupDiEnumDriverInfo(Devs, DevInfo, SPDIT_COMPATDRIVER, + index, &driverInfoData)) { + + success = TRUE; + + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_HEADER,index); + + // + // get useful driver information + // + driverInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); + if(SetupDiGetDriverInfoDetail(Devs,DevInfo,&driverInfoData,&driverInfoDetail,sizeof(SP_DRVINFO_DETAIL_DATA),NULL) || + GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + + Padding(1); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_INF,driverInfoDetail.InfFileName); + Padding(1); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_SECTION,driverInfoDetail.SectionName); + } + + Padding(1); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_DESCRIPTION,driverInfoData.Description); + Padding(1); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_MFGNAME,driverInfoData.MfgName); + Padding(1); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_PROVIDERNAME,driverInfoData.ProviderName); + + if (FileTimeToSystemTime(&driverInfoData.DriverDate, &SystemTime)) { + if (GetDateFormat(LOCALE_USER_DEFAULT, + DATE_SHORTDATE, + &SystemTime, + NULL, + Buffer, + sizeof(Buffer)/sizeof(TCHAR) + ) != 0) { + Padding(1); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_DRIVERDATE,Buffer); + } + } + + Version.QuadPart = driverInfoData.DriverVersion; + Padding(1); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_DRIVERVERSION, + HIWORD(Version.HighPart), + LOWORD(Version.HighPart), + HIWORD(Version.LowPart), + LOWORD(Version.LowPart) + ); + + driverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS); + if(SetupDiGetDriverInstallParams(Devs,DevInfo,&driverInfoData,&driverInstallParams)) { + Padding(1); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_RANK,driverInstallParams.Rank); + Padding(1); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS,driverInstallParams.Flags); + + // + // Interesting flags to dump + // + if (driverInstallParams.Flags & DNF_OLD_INET_DRIVER) { + Padding(2); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_OLD_INET_DRIVER); + } + if (driverInstallParams.Flags & DNF_BAD_DRIVER) { + Padding(2); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_BAD_DRIVER); + } +#if defined(DNF_INF_IS_SIGNED) + // + // DNF_INF_IS_SIGNED is only available since WinXP + // + if (driverInstallParams.Flags & DNF_INF_IS_SIGNED) { + Padding(2); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_INF_IS_SIGNED); + } +#endif +#if defined(DNF_OEM_F6_INF) + // + // DNF_OEM_F6_INF is only available since WinXP + // + if (driverInstallParams.Flags & DNF_OEM_F6_INF) { + Padding(2); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_OEM_F6_INF); + } +#endif +#if defined(DNF_BASIC_DRIVER) + // + // DNF_BASIC_DRIVER is only available since WinXP + // + if (driverInstallParams.Flags & DNF_BASIC_DRIVER) { + Padding(2); + FormatToStream(stdout,MSG_DUMP_DRIVERNODE_FLAGS_BASIC_DRIVER); + } +#endif + } + + index++; + } + + + SetupDiDestroyDriverInfoList(Devs,DevInfo,SPDIT_COMPATDRIVER); + + +final2: + + if(!success) { + Padding(1); + FormatToStream(stdout, MSG_DUMP_NO_DRIVERNODES); + } + + return success; + +} + +BOOL DumpDeviceStack(_In_ HDEVINFO Devs, _In_ PSP_DEVINFO_DATA DevInfo) +/*++ + +Routine Description: + + Write expected stack information to stdout + +Arguments: + + Devs )_ uniquely identify device + DevInfo ) + +Return Value: + + TRUE if success + +--*/ +{ + LPTSTR * filters; + LPTSTR service; + HKEY hClassKey = (HKEY)INVALID_HANDLE_VALUE; + SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; + + // + // we need machine information + // + devInfoListDetail.cbSize = sizeof(devInfoListDetail); + if(!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) { + return FALSE; + } + + // + // we need device setup class, we can use the GUID in DevInfo + // note that this GUID is a snapshot, but works fine + // if DevInfo isn't old + // + + // + // class upper/lower filters are in class registry + // + hClassKey = SetupDiOpenClassRegKeyEx(&DevInfo->ClassGuid, + KEY_READ, + DIOCR_INSTALLER, + devInfoListDetail.RemoteMachineName[0] ? devInfoListDetail.RemoteMachineName : NULL, + NULL); + + if(hClassKey != INVALID_HANDLE_VALUE) { + // + // dump upper class filters if available + // + filters = GetRegMultiSz(hClassKey,REGSTR_VAL_UPPERFILTERS); + if(filters) { + if(filters[0]) { + Padding(1); + FormatToStream(stdout,MSG_DUMP_DEVICESTACK_UPPERCLASSFILTERS); + DumpArray(2,filters); + } + DelMultiSz(filters); + } + } + filters = GetDevMultiSz(Devs,DevInfo,SPDRP_UPPERFILTERS); + if(filters) { + if(filters[0]) { + // + // dump upper device filters + // + Padding(1); + FormatToStream(stdout,MSG_DUMP_DEVICESTACK_UPPERFILTERS); + DumpArray(2,filters); + } + DelMultiSz(filters); + } + service = GetDeviceStringProperty(Devs,DevInfo,SPDRP_SERVICE); + Padding(1); + FormatToStream(stdout,MSG_DUMP_DEVICESTACK_SERVICE); + if(service && service[0]) { + // + // dump service + // + Padding(2); + _tprintf(TEXT("%s\n"),service); + } else { + // + // dump the fact that there's no service + // + Padding(2); + FormatToStream(stdout,MSG_DUMP_DEVICESTACK_NOSERVICE); + } + if(service) { + delete [] service; + } + if(hClassKey != INVALID_HANDLE_VALUE) { + filters = GetRegMultiSz(hClassKey,REGSTR_VAL_LOWERFILTERS); + if(filters) { + if(filters[0]) { + // + // lower class filters + // + Padding(1); + FormatToStream(stdout,MSG_DUMP_DEVICESTACK_LOWERCLASSFILTERS); + DumpArray(2,filters); + } + DelMultiSz(filters); + } + RegCloseKey(hClassKey); + } + filters = GetDevMultiSz(Devs,DevInfo,SPDRP_LOWERFILTERS); + if(filters) { + if(filters[0]) { + // + // lower device filters + // + Padding(1); + FormatToStream(stdout,MSG_DUMP_DEVICESTACK_LOWERFILTERS); + DumpArray(2,filters); + } + DelMultiSz(filters); + } + + return TRUE; +} + +BOOL DumpDriverPackageData(_In_ LPCTSTR InfName) +{ + DWORD Err = NO_ERROR; + HINF hInf = INVALID_HANDLE_VALUE; + UINT ErrorLine; + INFCONTEXT Context; + TCHAR InfData[MAX_INF_STRING_LENGTH]; + GUID ClassGuid; +#if _SETUPAPI_VER >= _WIN32_WINNT_WINXP + SetupVerifyInfFileProto SVIFFn; +#endif // _SETUPAPI_VER >= _WIN32_WINNT_WINXP + HMODULE setupapiMod = NULL; + +#if _SETUPAPI_VER >= _WIN32_WINNT_WINXP + SP_INF_SIGNER_INFO InfSignerInfo; +#endif // _SETUPAPI_VER >= _WIN32_WINNT_WINXP + + hInf = SetupOpenInfFile(InfName, + NULL, + INF_STYLE_WIN4, + &ErrorLine); + if (hInf == INVALID_HANDLE_VALUE) { + Err = GetLastError(); + goto failed; + } + + // + // Dump out the provider. + // + if (SetupFindFirstLine(hInf, + INFSTR_SECT_VERSION, + INFSTR_KEY_PROVIDER, + &Context) && + (SetupGetStringField(&Context, + 1, + InfData, + ARRAYSIZE(InfData), + NULL))) { + FormatToStream(stdout,MSG_DPENUM_DUMP_PROVIDER,InfData); + } else { + FormatToStream(stdout,MSG_DPENUM_DUMP_PROVIDER_UNKNOWN); + } + + // + // Dump out the class + // + if (SetupFindFirstLine(hInf, + INFSTR_SECT_VERSION, + INFSTR_KEY_HARDWARE_CLASSGUID, + &Context) && + (SetupGetStringField(&Context, + 1, + InfData, + ARRAYSIZE(InfData), + NULL)) && + (SUCCEEDED(CLSIDFromString(InfData, &ClassGuid))) && + SetupDiGetClassDescriptionEx(&ClassGuid,InfData,ARRAYSIZE(InfData),NULL,NULL,NULL)) { + FormatToStream(stdout,MSG_DPENUM_DUMP_CLASS,InfData); + } else { + FormatToStream(stdout,MSG_DPENUM_DUMP_CLASS_UNKNOWN); + } + +#if _SETUPAPI_VER >= _WIN32_WINNT_WINXP + // + // Dump out the digital signer + // + setupapiMod = LoadLibrary(TEXT("setupapi.dll")); + if(!setupapiMod){ + goto failed; + } + SVIFFn = (SetupVerifyInfFileProto)GetProcAddress(setupapiMod, SETUPVERIFYINFFILE); + if(!SVIFFn){ + goto failed; + } + + ZeroMemory(&InfSignerInfo, sizeof(InfSignerInfo)); + InfSignerInfo.cbSize = sizeof(InfSignerInfo); + if (SVIFFn(InfName, NULL, &InfSignerInfo) || + (GetLastError() == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) || + (GetLastError() == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)) { + FormatToStream(stdout,MSG_DPENUM_DUMP_SIGNER,InfSignerInfo.DigitalSigner); + } else { + FormatToStream(stdout,MSG_DPENUM_DUMP_SIGNER_UNKNOWN); + } +#endif // _SETUPAPI_VER >= _WIN32_WINNT_WINXP + + // + // Dump out the version and date + // + if (SetupFindFirstLine(hInf, + INFSTR_SECT_VERSION, + INFSTR_DRIVERVERSION_SECTION, + &Context)) { + if (SetupGetStringField(&Context, + 1, + InfData, + ARRAYSIZE(InfData), + NULL)) { + FormatToStream(stdout,MSG_DPENUM_DUMP_DATE,InfData); + } else { + FormatToStream(stdout,MSG_DPENUM_DUMP_DATE_UNKNOWN); + } + + if (SetupGetStringField(&Context, + 2, + InfData, + ARRAYSIZE(InfData), + NULL)) { + FormatToStream(stdout,MSG_DPENUM_DUMP_VERSION,InfData); + } else { + FormatToStream(stdout,MSG_DPENUM_DUMP_VERSION_UNKNOWN); + } + + } else { + FormatToStream(stdout,MSG_DPENUM_DUMP_DATE_UNKNOWN); + FormatToStream(stdout,MSG_DPENUM_DUMP_VERSION_UNKNOWN); + } + + +failed: + if (hInf != INVALID_HANDLE_VALUE) { + SetupCloseInfFile(hInf); + } + + if(setupapiMod){ + FreeLibrary(setupapiMod); + } + + return (Err == NO_ERROR); +} + + diff --git a/setup/devcon/msg.mc b/setup/devcon/msg.mc new file mode 100644 index 00000000..6e6ec557 --- /dev/null +++ b/setup/devcon/msg.mc @@ -0,0 +1,987 @@ +;// +;// Copyright (c) Microsoft Corporation. All rights reserved. +;// + +;// +;// General +;// +MessageId=60000 SymbolicName=MSG_USAGE +Language=English +%1 Usage: %1 [-r] [-m:\\<machine>] <command> [<arg>...] +For more information, type: %1 help +. +MessageId=60001 SymbolicName=MSG_FAILURE +Language=English +%1 failed. +. +MessageId=60002 SymbolicName=MSG_COMMAND_USAGE +Language=English +%1: Invalid use of %2. +For more information, type: %1 help %2 +. + +;// +;// HELP +;// +MessageId=60100 SymbolicName=MSG_HELP_LONG +Language=English +Device Console Help: +%1 [-r] [-m:\\<machine>] <command> [<arg>...] +-r Reboots the system only when a restart or reboot is required. +<machine> Specifies a remote computer. +<command> Specifies a Devcon command (see command list below). +<arg>... One or more arguments that modify a command. +For help with a specific command, type: %1 help <command> +. +MessageId=60101 SymbolicName=MSG_HELP_SHORT +Language=English +%1!-20s! Display Devcon help. +. +MessageId=60102 SymbolicName=MSG_HELP_OTHER +Language=English +Unknown command. +. + +;// +;// CLASSES +;// +MessageId=60200 SymbolicName=MSG_CLASSES_LONG +Language=English +Devcon Classes Command +Lists all device setup classes. Valid on local and remote computers. +%1 [-m:\\<machine>] %2 +<machine> Specifies a remote computer. +Class entries have the format <name>: <descr> +where <name> is the class name and <descr> is the class description. +. +MessageId=60201 SymbolicName=MSG_CLASSES_SHORT +Language=English +%1!-20s! List all device setup classes. +. +MessageId=60202 SymbolicName=MSG_CLASSES_HEADER +Language=English +Listing %1!u! setup classes on %2. +. +MessageId=60203 SymbolicName=MSG_CLASSES_HEADER_LOCAL +Language=English +Listing %1!u! setup classes. +. + +;// +;// LISTCLASS +;// +MessageId=60300 SymbolicName=MSG_LISTCLASS_LONG +Language=English +Devcon Listclass Command +Lists all devices in the specified setup classes. Valid on local and remote computers. +%1 [-m:\\<machine>] %2 <class> [<class>...] +<machine> Specifies a remote computer. +<class> Specifies a device setup class. +Device entries have the format <instance>: <descr> +where <instance> is a unique instance of the device and <descr> is the device description. +. +MessageId=60301 SymbolicName=MSG_LISTCLASS_SHORT +Language=English +%1!-20s! List all devices in a setup class. +. +MessageId=60302 SymbolicName=MSG_LISTCLASS_HEADER +Language=English +Listing %1!u! devices in setup class "%2" (%3) on %4. +. +MessageId=60303 SymbolicName=MSG_LISTCLASS_HEADER_LOCAL +Language=English +Listing %1!u! devices in setup class "%2" (%3). +. +MessageId=60304 SymbolicName=MSG_LISTCLASS_NOCLASS +Language=English +There is no "%1" setup class on %2. +. +MessageId=60305 SymbolicName=MSG_LISTCLASS_NOCLASS_LOCAL +Language=English +There is no "%1" setup class on the local machine. +. +MessageId=60306 SymbolicName=MSG_LISTCLASS_HEADER_NONE +Language=English +There are no devices in setup class "%1" (%2) on %3. +. +MessageId=60307 SymbolicName=MSG_LISTCLASS_HEADER_NONE_LOCAL +Language=English +There are no devices in setup class "%1" (%2). +. + +;// +;// FIND +;// +MessageId=60400 SymbolicName=MSG_FIND_LONG +Language=English +Devcon Find Command +Finds devices with the specified hardware or instance ID. Valid on local and remote computers. +%1 [-m:\\<machine>] %2 <id> [<id>...] +%1 [-m:\\<machine>] %2 =<class> [<id>...] +<machine> Specifies a remote computer. +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +Device entries have the format <instance>: <descr> +where <instance> is the unique instance of the device and <descr> is the device description. +. +MessageId=60401 SymbolicName=MSG_FIND_SHORT +Language=English +%1!-20s! Find devices. +. +MessageId=60402 SymbolicName=MSG_FIND_TAIL_NONE +Language=English +No matching devices found on %1. +. +MessageId=60403 SymbolicName=MSG_FIND_TAIL_NONE_LOCAL +Language=English +No matching devices found. +. +MessageId=60404 SymbolicName=MSG_FIND_TAIL +Language=English +%1!u! matching device(s) found on %2. +. +MessageId=60405 SymbolicName=MSG_FIND_TAIL_LOCAL +Language=English +%1!u! matching device(s) found. +. +MessageId=60406 SymbolicName=MSG_FINDALL_LONG +Language=English +Devcon Findall Command +Finds devices with the specified hardware or instance ID, including devices +that are not currently attached. Valid on local and remote computers. +%1 [-m:\\<machine>] %2 <id> [<id>...] +%1 [-m:\\<machine>] %2 =<class> [<id>...] +<machine> Specifies a remote computer. +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +Device entries have the format <instance>: <descr> +where <instance> is the unique instance of the device and <descr> is the description. +. +MessageId=60407 SymbolicName=MSG_FINDALL_SHORT +Language=English +%1!-20s! Find devices, including those that are not currently attached. +. +MessageId=60408 SymbolicName=MSG_STATUS_LONG +Language=English +Devcon Status Command +Lists the running status of devices with the specified hardware or instance ID. +Valid on local and remote computers. +%1 [-m:\\<machine>] %2 <id> [<id>...] +%1 [-m:\\<machine>] %2 =<class> [<id>...] +<machine> Specifies a remote computer. +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +. +MessageId=60409 SymbolicName=MSG_STATUS_SHORT +Language=English +%1!-20s! List running status of devices. +. +MessageId=60410 SymbolicName=MSG_DRIVERFILES_LONG +Language=English +Devcon Driverfiles Command +List installed driver files for devices with the specified hardware or +instance ID. Valid only on the local computer. +%1 %2 <id> [<id>...] +%1 %2 =<class> [<id>...] +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +. +MessageId=60411 SymbolicName=MSG_DRIVERFILES_SHORT +Language=English +%1!-20s! List installed driver files for devices. +. +MessageId=60412 SymbolicName=MSG_RESOURCES_LONG +Language=English +Devcon Resources Command +Lists hardware resources of devices with the specified hardware or instance ID. +Valid on local and remote computers. +%1 [-m:\\<machine>] %2 <id> [<id>...] +%1 [-m:\\<machine>] %2 =<class> [<id>...] +<machine> Specifies a remote computer. +<class> Specifies a device setup class. +Examples of <id>: +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +. +MessageId=60413 SymbolicName=MSG_RESOURCES_SHORT +Language=English +%1!-20s! List hardware resources for devices. +. +MessageId=60414 SymbolicName=MSG_HWIDS_LONG +Language=English +Devcon Hwids Command +Lists hardware IDs of all devices with the specified hardware or instance ID. +Valid on local and remote computers. +%1 [-m:\\<machine>] %2 <id> [<id>...] +%1 [-m:\\<machine>] %2 =<class> [<id>...] +<machine> Specifies a remote computer. +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +. +MessageId=60415 SymbolicName=MSG_HWIDS_SHORT +Language=English +%1!-20s! List hardware IDs of devices. +. +MessageId=60416 SymbolicName=MSG_STACK_LONG +Language=English +Devcon Stack Command +Lists the expected driver stack of devices with the specified hardware +or instance ID. PnP calls each driver's AddDevice routine when building +the device stack. Valid on local and remote computers. +%1 [-m:\\<machine>] %2 <id> [<id>...] +%1 [-m:\\<machine>] %2 =<class> [<id>...] +<machine> Specifies a remote computer. +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +. +MessageId=60417 SymbolicName=MSG_STACK_SHORT +Language=English +%1!-20s! List expected driver stack for devices. +. +;// +;// ENABLE +;// +MessageId=60500 SymbolicName=MSG_ENABLE_LONG +Language=English +Devcon Enable Command +Enables devices with the specified hardware or instance ID. Valid only on +the local computer. (To reboot when necessary, include -r.) +%1 [-r] %2 <id> [<id>...] +%1 [-r] %2 =<class> [<id>...] +-r Reboots the system only when a restart or reboot is required. +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +. +MessageId=60501 SymbolicName=MSG_ENABLE_SHORT +Language=English +%1!-20s! Enable devices. +. +MessageId=60502 SymbolicName=MSG_ENABLE_TAIL_NONE +Language=English +No devices were enabled, either because the devices were not found, +or because the devices could not be enabled. +. +MessageId=60503 SymbolicName=MSG_ENABLE_TAIL_REBOOT +Language=English +The %1!u! device(s) are ready to be enabled. To enable the devices, restart the devices or +reboot the system . +. +MessageId=60504 SymbolicName=MSG_ENABLE_TAIL +Language=English +%1!u! device(s) are enabled. +. + +;// +;// DISABLE +;// +MessageId=60600 SymbolicName=MSG_DISABLE_LONG +Language=English +Devcon Disable Command +Disables devices with the specified hardware or instance ID. +Valid only on the local computer. (To reboot when necesary, Include -r .) +%1 [-r] %2 <id> [<id>...] +%1 [-r] %2 =<class> [<id>...] +-r Reboots the system only when a restart or reboot is required. +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +. +MessageId=60601 SymbolicName=MSG_DISABLE_SHORT +Language=English +%1!-20s! Disable devices. +. +MessageId=60602 SymbolicName=MSG_DISABLE_TAIL_NONE +Language=English +No devices were disabled, either because the devices were not found, +or because the devices could not be disabled. +. +MessageId=60603 SymbolicName=MSG_DISABLE_TAIL_REBOOT +Language=English +The %1!u! device(s) are ready to be disabled. To disable the devices, restart the +devices or reboot the system . +. +MessageId=60604 SymbolicName=MSG_DISABLE_TAIL +Language=English +%1!u! device(s) disabled. +. + + +;// +;// RESTART +;// +MessageId=60700 SymbolicName=MSG_RESTART_LONG +Language=English +Devcon Restart Command +Restarts devices with the specified hardware or instance ID. +Valid only on the local computer. (To reboot when necesary, Include -r .) +%1 [-r] %2 <id> [<id>...] +%1 [-r] %2 =<class> [<id>...] +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +. +MessageId=60701 SymbolicName=MSG_RESTART_SHORT +Language=English +%1!-20s! Restart devices. +. +MessageId=60702 SymbolicName=MSG_RESTART_TAIL_NONE +Language=English +No devices were restarted, either because the devices were not found, +or because the devices could not be restarted. +. +MessageId=60703 SymbolicName=MSG_RESTART_TAIL_REBOOT +Language=English +The %1!u! device(s) are ready to be restarted. To restart the devices, reboot the system. +. +MessageId=60704 SymbolicName=MSG_RESTART_TAIL +Language=English +%1!u! device(s) restarted. +. + + +;// +;// REBOOT +;// +MessageId=60800 SymbolicName=MSG_REBOOT_LONG +Language=English +%1 %2 +Reboots the local computer as part of a planned hardware installation. +. +MessageId=60801 SymbolicName=MSG_REBOOT_SHORT +Language=English +%1!-20s! Reboot the local computer. +. +MessageId=60802 SymbolicName=MSG_REBOOT +Language=English +Rebooting the local computer. +. + +;// +;// DUMP +;// +MessageId=60904 SymbolicName=MSG_DUMP_PROBLEM +Language=English +The device has the following problem: %1!02u! +. +MessageId=60905 SymbolicName=MSG_DUMP_PRIVATE_PROBLEM +Language=English +The driver reported a problem with the device. +. +MessageId=60906 SymbolicName=MSG_DUMP_STARTED +Language=English +Driver is running. +. +MessageId=60907 SymbolicName=MSG_DUMP_DISABLED +Language=English +Device is disabled. +. +MessageId=60908 SymbolicName=MSG_DUMP_NOTSTARTED +Language=English +Device is currently stopped. +. +MessageId=60909 SymbolicName=MSG_DUMP_NO_RESOURCES +Language=English +Device is not using any resources. +. +MessageId=60910 SymbolicName=MSG_DUMP_NO_RESERVED_RESOURCES +Language=English +Device has no reserved resources. +. +MessageId=60911 SymbolicName=MSG_DUMP_RESOURCES +Language=English +Device is currently using the following resources: +. +MessageId=60912 SymbolicName=MSG_DUMP_RESERVED_RESOURCES +Language=English +Device has the following reserved resources: +. +MessageId=60913 SymbolicName=MSG_DUMP_DRIVER_FILES +Language=English +Driver installed from %2 [%3]. %1!u! file(s) used by driver: +. +MessageId=60914 SymbolicName=MSG_DUMP_NO_DRIVER_FILES +Language=English +Driver installed from %2 [%3]. The driver is not using any files. +. +MessageId=60915 SymbolicName=MSG_DUMP_NO_DRIVER +Language=English +No driver information available for the device. +. +MessageId=60916 SymbolicName=MSG_DUMP_HWIDS +Language=English +Hardware IDs: +. +MessageId=60917 SymbolicName=MSG_DUMP_COMPATIDS +Language=English +Compatible IDs: +. +MessageId=60918 SymbolicName=MSG_DUMP_NO_HWIDS +Language=English +No hardware/compatible IDs found for this device. +. +MessageId=60919 SymbolicName=MSG_DUMP_NO_DRIVERNODES +Language=English +No driver nodes found for this device. +. +MessageId=60920 SymbolicName=MSG_DUMP_DRIVERNODE_HEADER +Language=English +Driver node #%1!u!: +. +MessageId=60921 SymbolicName=MSG_DUMP_DRIVERNODE_INF +Language=English +Inf file is %1 +. +MessageId=60922 SymbolicName=MSG_DUMP_DRIVERNODE_SECTION +Language=English +Inf section is %1 +. +MessageId=60923 SymbolicName=MSG_DUMP_DRIVERNODE_DESCRIPTION +Language=English +Driver description is %1 +. +MessageId=60924 SymbolicName=MSG_DUMP_DRIVERNODE_MFGNAME +Language=English +Manufacturer name is %1 +. +MessageId=60925 SymbolicName=MSG_DUMP_DRIVERNODE_PROVIDERNAME +Language=English +Provider name is %1 +. +MessageId=60926 SymbolicName=MSG_DUMP_DRIVERNODE_DRIVERDATE +Language=English +Driver date is %1 +. +MessageId=60927 SymbolicName=MSG_DUMP_DRIVERNODE_DRIVERVERSION +Language=English +Driver version is %1!u!.%2!u!.%3!u!.%4!u! +. +MessageId=60928 SymbolicName=MSG_DUMP_DRIVERNODE_RANK +Language=English +Driver node rank is %1!u! +. +MessageId=60929 SymbolicName=MSG_DUMP_DRIVERNODE_FLAGS +Language=English +Driver node flags are %1!08X! +. +MessageId=60930 SymbolicName=MSG_DUMP_DRIVERNODE_FLAGS_OLD_INET_DRIVER +Language=English +Inf came from the Internet +. +MessageId=60931 SymbolicName=MSG_DUMP_DRIVERNODE_FLAGS_BAD_DRIVER +Language=English +Driver node is marked "BAD" +. +MessageId=60932 SymbolicName=MSG_DUMP_DRIVERNODE_FLAGS_INF_IS_SIGNED +Language=English +Inf is digitally signed +. +MessageId=60933 SymbolicName=MSG_DUMP_DRIVERNODE_FLAGS_OEM_F6_INF +Language=English +Inf was installed by using F6 during text mode setup +. +MessageId=60934 SymbolicName=MSG_DUMP_DRIVERNODE_FLAGS_BASIC_DRIVER +Language=English +Driver provides basic functionality when no signed driver is available. +. +MessageId=60935 SymbolicName=MSG_DUMP_DEVICESTACK_UPPERCLASSFILTERS +Language=English +Upper class filters: +. +MessageId=60936 SymbolicName=MSG_DUMP_DEVICESTACK_UPPERFILTERS +Language=English +Upper filters: +. +MessageId=60937 SymbolicName=MSG_DUMP_DEVICESTACK_SERVICE +Language=English +Controlling service: +. +MessageId=60938 SymbolicName=MSG_DUMP_DEVICESTACK_NOSERVICE +Language=English +(none) +. +MessageId=60939 SymbolicName=MSG_DUMP_DEVICESTACK_LOWERCLASSFILTERS +Language=English +Class lower filters: +. +MessageId=60940 SymbolicName=MSG_DUMP_DEVICESTACK_LOWERFILTERS +Language=English +Lower filters: +. +MessageId=60941 SymbolicName=MSG_DUMP_SETUPCLASS +Language=English +Setup Class: %1 %2 +. +MessageId=60942 SymbolicName=MSG_DUMP_NOSETUPCLASS +Language=English +Device is not set up. +. +MessageId=60943 SymbolicName=MSG_DUMP_DESCRIPTION +Language=English +Name: %1 +. +MessageId=60944 SymbolicName=MSG_DUMP_PHANTOM +Language=English +Device is not present. +. +MessageId=60945 SymbolicName=MSG_DUMP_STATUS_ERROR +Language=English +Error retrieving the device's status. +. + +;// +;// INSTALL +;// +MessageId=61000 SymbolicName=MSG_INSTALL_LONG +Language=English +Devcon Install Command +Installs the specified device manually. Valid only on the local computer. +(To reboot when necesary, Include -r .) +%1 [-r] %2 <inf> <hwid> +<inf> Specifies an INF file with installation information for the device. +<hwid> Specifies a hardware ID for the device. +-r Reboots the system only when a restart or reboot is required. +. +MessageId=61001 SymbolicName=MSG_INSTALL_SHORT +Language=English +%1!-20s! Install a device manually. +. +MessageId=61002 SymbolicName=MSG_INSTALL_UPDATE +Language=English +Device node created. Install is complete when drivers are installed... +. + +;// +;// UPDATE +;// +MessageId=61100 SymbolicName=MSG_UPDATE_LONG +Language=English +Devcon Update Command +Updates drivers for all devices with the specified hardware ID (<hwid>). +Valid only on the local computer. (To reboot when necesary, Include -r .) +%1 [-r] %2 <inf> <hwid> +-r Reboots the system only when a restart or reboot is required. +<inf> Specifies an INF file with installation information for the devices. +<hwid> Specifies the hardware ID of the devices. +. +MessageId=61101 SymbolicName=MSG_UPDATE_SHORT +Language=English +%1!-20s! Update a device manually. +. +MessageId=61102 SymbolicName=MSG_UPDATE_INF +Language=English +Updating drivers for %1 from %2. +. +MessageId=61103 SymbolicName=MSG_UPDATE +Language=English +Updating drivers for %1. +. +MessageId=61104 SymbolicName=MSG_UPDATENI_LONG +Language=English +%1 [-r] %2 <inf> <hwid> +Update drivers for devices (Non Interactive). +This command will only work for local machine. +Specify -r to reboot automatically if needed. +<inf> is an INF to use to install the device. +All devices that match <hwid> are updated. +Unsigned installs will fail. No UI will be +presented. +. +MessageId=61105 SymbolicName=MSG_UPDATENI_SHORT +Language=English +%1!-20s! Manually update a device (non interactive). +. +MessageId=61106 SymbolicName=MSG_UPDATE_OK +Language=English +Drivers installed successfully. +. +;// +;// Driver Package (add/remove/enum) +;// +MessageId=61107 SymbolicName=MSG_DPADD_LONG +Language=English +%1 %2 <inf> +Adds (installs) a third-party (OEM) driver package. +This command will only work on the local machine. +<inf> is a full path to the INF of the Driver +Package that will be installed on this machine. +. +MessageId=61108 SymbolicName=MSG_DPADD_SHORT +Language=English +%1!-20s! Adds (installs) a third-party (OEM) driver package. +. +MessageId=61109 SymbolicName=MSG_DPDELETE_LONG +Language=English +%1 [-f] %2 <inf> +Deletes a third-party (OEM) driver package. +This command will only work on the local machine. +[-f] will force delete the driver package, even +if it is in use by a device. +<inf> is the name of a published INF on the local +machine. This is the value returned from dp_add +and dp_enum. +. +MessageId=61110 SymbolicName=MSG_DPDELETE_SHORT +Language=English +%1!-20s! Deletes a third-party (OEM) driver package. +. +MessageId=61111 SymbolicName=MSG_DPENUM_LONG +Language=English +%1 %2 +Lists the third-party (OEM) driver packages installed on this machine. +This command will only work on the local machine. +Values returned from dp_enum can be sent to dp_delete +to be removed from the machine. +. +MessageId=61112 SymbolicName=MSG_DPENUM_SHORT +Language=English +%1!-20s! Lists the third-party (OEM) driver packages installed on this machine. +. +MessageId=61113 SymbolicName=MSG_DPADD_INVALID_INF +Language=English +The specified INF path is not valid. +. +MessageId=61114 SymbolicName=MSG_DPADD_FAILED +Language=English +Adding the specified driver package to the machine failed. +. +MessageId=61115 SymbolicName=MSG_DPADD_SUCCESS +Language=English +Driver package '%1' added. +. +MessageId=61116 SymbolicName=MSG_DPDELETE_FAILED +Language=English +Deleting the specified driver package from the machine failed. +. +MessageId=61117 SymbolicName=MSG_DPDELETE_FAILED_IN_USE +Language=English +Deleting the specified driver package from the machine failed +because it is in use by a device. +. +MessageId=61118 SymbolicName=MSG_DPDELETE_FAILED_NOT_OEM_INF +Language=English +Deleting the specified driver package from the machine failed +because it is not an third-party package. +. +MessageId=61119 SymbolicName=MSG_DPDELETE_SUCCESS +Language=English +Driver package '%1' deleted. +. +MessageId=61120 SymbolicName=MSG_DPENUM_NO_OEM_INF +Language=English +There are no third-party driver packages on this machine. +. +MessageId=61121 SymbolicName=MSG_DPENUM_LIST_HEADER +Language=English +The following third-party driver packages are installed on this computer: +. +MessageId=61122 SymbolicName=MSG_DPENUM_LIST_ENTRY +Language=English +%1 +. +MessageId=61123 SymbolicName=MSG_DPENUM_DUMP_PROVIDER +Language=English + Provider: %1 +. +MessageId=61124 SymbolicName=MSG_DPENUM_DUMP_PROVIDER_UNKNOWN +Language=English + Provider: unknown +. +MessageId=61125 SymbolicName=MSG_DPENUM_DUMP_CLASS +Language=English + Class: %1 +. +MessageId=61126 SymbolicName=MSG_DPENUM_DUMP_CLASS_UNKNOWN +Language=English + Class: unknown +. +MessageId=61127 SymbolicName=MSG_DPENUM_DUMP_VERSION +Language=English + Version: %1 +. +MessageId=61128 SymbolicName=MSG_DPENUM_DUMP_VERSION_UNKNOWN +Language=English + Version: unknown +. +MessageId=61129 SymbolicName=MSG_DPENUM_DUMP_DATE +Language=English + Date: %1 +. +MessageId=61130 SymbolicName=MSG_DPENUM_DUMP_DATE_UNKNOWN +Language=English + Date: unknown +. +MessageId=61131 SymbolicName=MSG_DPENUM_DUMP_SIGNER +Language=English + Signer: %1 +. +MessageId=61132 SymbolicName=MSG_DPENUM_DUMP_SIGNER_UNKNOWN +Language=English + Signer: unknown +. +;// +;// REMOVE +;// +MessageId=61200 SymbolicName=MSG_REMOVE_LONG +Language=English +Devcon Remove Command +Removes devices with the specified hardware or instance ID. Valid only on +the local computer. (To reboot when necesary, Include -r .) +%1 [-r] %2 <id> [<id>...] +%1 [-r] %2 =<class> [<id>...] +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +. +MessageId=61201 SymbolicName=MSG_REMOVE_SHORT +Language=English +%1!-20s! Remove devices. +. +MessageId=61202 SymbolicName=MSG_REMOVE_TAIL_NONE +Language=English +No devices were removed. +. +MessageId=61203 SymbolicName=MSG_REMOVE_TAIL_REBOOT +Language=English +The %1!u! device(s) are ready to be removed. To remove the devices, reboot the system. +. +MessageId=61204 SymbolicName=MSG_REMOVE_TAIL +Language=English +%1!u! device(s) were removed. +. + +;// +;// RESCAN +;// +MessageId=61300 SymbolicName=MSG_RESCAN_LONG +Language=English +Devcon Rescan Command +Directs Plug and Play to scan for new hardware. Valid on a local or remote computer. +%1 [-m:\\<machine>] +<machine> Specifies a remote computer. +. +MessageId=61301 SymbolicName=MSG_RESCAN_SHORT +Language=English +%1!-20s! Scan for new hardware. +. +MessageId=61302 SymbolicName=MSG_RESCAN_LOCAL +Language=English +Scanning for new hardware. +. +MessageId=61303 SymbolicName=MSG_RESCAN +Language=English +Scanning for new hardware on %1. +. +MessageId=61304 SymbolicName=MSG_RESCAN_OK +Language=English +Scanning completed. +. + +;// +;// DRIVERNODES +;// +MessageId=61400 SymbolicName=MSG_DRIVERNODES_LONG +Language=English +Devcon Drivernodes Command +Lists driver nodes for devices with the specified hardware or instance ID. +Valid only on the local computer. +%1 %2 <id> [<id>...] +%1 %2 =<class> [<id>...] +<class> Specifies a device setup class. +Examples of <id>: + * - All devices + ISAPNP\PNP0501 - Hardware ID + *PNP* - Hardware ID with wildcards (* matches anything) + @ISAPNP\*\* - Instance ID with wildcards (@ prefixes instance ID) + '*PNP0501 - Hardware ID with apostrophe (' prefixes literal match - matches exactly as typed, + including the asterisk.) +. +MessageId=61401 SymbolicName=MSG_DRIVERNODES_SHORT +Language=English +%1!-20s! List driver nodes of devices. +. + +;// +;// CLASSFILTER +;// +MessageId=61500 SymbolicName=MSG_CLASSFILTER_LONG +Language=English +Devcon Classfilter Command + +Lists, adds, deletes, and reorders upper and lower filter drivers for a device +setup class. Changes do not take effect until the affected devices are restarted +or the machine is rebooted. + +%1 %2 [-r] <class> {upper | lower} [<operator><filter> [<operator><filter>...]] +<class> Specifies a device setup class. +<operator> Specifies an operation (listed below). +<filter> Specifies a class filter driver. +upper Identifies an upper filter driver. +lower Identifies a lower filter driver. + +To list the upper/lower filter drivers for a class, +type: devcon classfilter <class> {upper | lower} + +The Devcon classfilter command uses subcommands, which consist of an +operator (=, @, -, +, !) and a filter driver name. + +The Devcon classfilter command uses a virtual cursor to move through +the list of filter drivers. The cursor starts at the beginning of the +list (before the first filter). Unless returned to the starting position, +the cursor always moves forward. + +Operators + = Move the cursor to the beginning of the filter driver list (before the + first filter driver). + + @ Position the cursor on the next instance of the specified filter. + + - Add before. Insert the specified filter before the filter on which the cursor + is positioned. If the cursor is not positioned on a filter, insert the + new filter at the beginning of the list. When the subcommand completes, the + cursor is positioned on the newly-added filter. + + + Add after. Insert the specified filter after the filter on which the cursor + is positioned. If the cursor is not positioned on a filter, Devcon inserts the + new filter at the end of the list. When the subcommand completes, the cursor + cursor is positioned on the newly-added filter. + + ! Deletes the next occurrence of the specified filter. When the subcommand + completes, the cursor occupies the position of the deleted filter. + Subsequent - or + subcommands insert a new filter at the cursor position. + + +Examples: +If the upper filters for setup class "foo" are A,B,C,B,D,B,E: +%1 %2 foo upper @D !B - deletes the third 'B'. +%1 %2 foo upper !B !B !B - deletes all three instances of 'B'. +%1 %2 foo upper =!B =!A - deletes the first 'B' and the first 'A'. +%1 %2 foo upper !C +CC - replaces 'C' with 'CC'. +%1 %2 foo upper @D -CC - inserts 'CC' before 'D'. +%1 %2 foo upper @D +CC - inserts 'CC' after 'D'. +%1 %2 foo upper -CC - inserts 'CC' before 'A'. +%1 %2 foo upper +CC - inserts 'CC' after 'E'. +%1 %2 foo upper @D +X +Y - inserts 'X' after 'D' and 'Y' after 'X'. +%1 %2 foo upper @D -X -Y - inserts 'X' before 'D' and 'Y' before 'X'. +%1 %2 foo upper @D -X +Y - inserts 'X' before 'D' and 'Y' between 'X' and 'D'. +. + +MessageId=61501 SymbolicName=MSG_CLASSFILTER_SHORT +Language=English +%1!-20s! Add, delete, and reorder class filters. +. +MessageId=61502 SymbolicName=MSG_CLASSFILTER_CHANGED +Language=English +Class filters changed. Restart the devices or reboot the system to make the change effective. +. +MessageId=61503 SymbolicName=MSG_CLASSFILTER_UNCHANGED +Language=English +Class filters unchanged. +. +;// +;// SETHWID +;// +MessageId=61600 SymbolicName=MSG_SETHWID_LONG +Language=English +%1 [-m:\\<machine>] %2 <id> [<id>...] := <subcmds> +%1 [-m:\\<machine>] %2 =<class> [<id>...] := <subcmds> +Modifies the hardware ID's of the listed devices. This command will only work for root-enumerated devices. +This command will work for a remote machine. +Examples of <id> are: +* - All devices (not recommended) +ISAPNP\PNP0601 - Hardware ID +*PNP* - Hardware ID with wildcards (* matches anything) +@ROOT\*\* - Instance ID with wildcards (@ prefixes instance ID) +<class> is a setup class name as obtained from the classes command. + +<subcmds> consists of one or more: +=hwid - Clear hardware ID list and set it to hwid. ++hwid - Add or move hardware ID to head of list (better match). +-hwid - Add or move hardware ID to end of list (worse match). +!hwid - Remove hardware ID from list. +hwid - each additional hardware id is inserted after the previous. +. +MessageId=61601 SymbolicName=MSG_SETHWID_SHORT +Language=English +%1!-20s! Modify Hardware ID's of listed root-enumerated devices. +. + +MessageId=61602 SymbolicName=MSG_SETHWID_TAIL_NONE +Language=English +No hardware ID's modified. +. +MessageId=61603 SymbolicName=MSG_SETHWID_TAIL_SKIPPED +Language=English +Skipped %1!u! non-root device(s), modified the hardware ID on %2!u! device(s). +. +MessageId=61604 SymbolicName=MSG_SETHWID_TAIL_MODIFIED +Language=English +Modified the Hardware ID on %1!u! device(s). +. +MessageId=61605 SymbolicName=MSG_SETHWID_NOTROOT +Language=English +Skipping (Not root-enumerated). +. + + diff --git a/setup/devcon/rc_ids.h b/setup/devcon/rc_ids.h new file mode 100644 index 00000000..f377a0b5 --- /dev/null +++ b/setup/devcon/rc_ids.h @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + rc_ids.h + +Abstract: + + Header for devcon resources + +--*/ + +#define IDS_ENABLED 3000 +#define IDS_ENABLED_REBOOT 3001 +#define IDS_ENABLE_FAILED 3002 +#define IDS_DISABLED 3003 +#define IDS_DISABLED_REBOOT 3004 +#define IDS_DISABLE_FAILED 3005 +#define IDS_RESTARTED 3006 +#define IDS_REQUIRES_REBOOT 3007 +#define IDS_RESTART_FAILED 3008 +#define IDS_REMOVED 3009 +#define IDS_REMOVED_REBOOT 3010 +#define IDS_REMOVE_FAILED 3011 + + |
