--- title: Windows declared configuration extensibility description: Learn more about Windows declared configuration extensibility through native WMI providers. ms.date: 09/12/2024 ms.topic: how-to --- # Declared configuration extensibility The Windows declared configuration (WinDC) enrollment offers extensibility through native WMI providers. This feature instantiates and interfaces with a Windows Management Instrumentation (WMI) provider that implements a management infrastructure (MI) interface. The interface must implement GetTargetResource, TestTargetResource, and SetTargetResource methods, and can implement any number of string properties. > [!NOTE] > Only string properties are currently supported by extensibility providers. ```mof [static, Description ("Get resource state based on input configuration file." )] uint32 GetTargetResource( [in, EmbeddedInstance ("MSFT_FileDirectoryConfiguration"), Description ("Configuration document that is to be applied.")] string InputResource, [in, Description ("Flags passed to the provider. Reserved for future use." )] uint32 Flags, [out, EmbeddedInstance ("MSFT_FileDirectoryConfiguration"), Description ("The current state of the specified configuration resources." )] string OutputResource ); [static, Description ("Test resource state based on input configuration file." )] uint32 TestTargetResource( [in, EmbeddedInstance("MSFT_FileDirectoryConfiguration"), Description ("Configuration document to be applied." )] string InputResource, [in, Description ("Flags passed to the provider. reserved for future use." )] uint32 Flags, [out, Description ("True if identical. False otherwise." )] boolean Result, [out, Description ("Context information the provider can use to optimize the set. This is optional." )] uint64 ProviderContext ); [static, Description ("Set resource state based on input configuration file." )] uint32 SetTargetResource( [in, EmbeddedInstance ("MSFT_FileDirectoryConfiguration"), Description ("Configuration document to be applied." )] string InputResource, [in, Description ("Context information the provider can use to optimize the set from SetTargetResource. This is optional." )] uint64 ProviderContext, [in, Description ("Flags passed to the provider. reserved for future use." )] uint32 Flags ); ``` ## Author desired state configuration resources To create a native WMI provider, follow the steps outlined in [How to implement an MI provider](/previous-versions/windows/desktop/wmi_v2/how-to-implement-an-mi-provider). These steps include how to generate the source code for an MI interface using the `Convert-MofToProvider.exe` tool to generate the DLL and prepare it for placement. 1. Create a Managed Object Format (MOF) file that defines the schema for the desired state configuration resource including parameters and methods. This file includes the required parameters for the resource. 2. Copy the schema MOF file along with any required files into the provider tools directory, for example: ProviderGenerationTool. 3. Edit the required files and include the correct file names and class names. 4. Invoke the provider generator tool to generate the provider's project files. 5. Copy the generated files into the provider's project folder. 6. Start the development process. ## Example MI provider This example provides more details about each step to demonstrate how to implement a sample native resource named `MSFT_FileDirectoryConfiguration`. ### Step 1: Create the resource schema MOF file Create a sample schema MOF file used to generate the initial source code for the `MSFT_FileDirectoryConfiguration` native resource. Place it in the project directory named `MSFT_FileDirectoryConfiguration`. ```mof #pragma include ("cim_schema_2.26.0.mof") #pragma include ("OMI_BaseResource.mof") #pragma include ("MSFT_Credential.mof") [ClassVersion("1.0.0"), Description("The configuration provider for files and directories.")] class MSFT_FileDirectoryConfiguration : OMI_BaseResource { [Key, Description("File name and path on target node to copy or create.")] string DestinationPath; [Write, Description("The name and path of the file to copy from.")] string SourcePath; [Write, Description("Contains a string that represents the contents of the file. To create an empty file, the string must be empty. The contents will be written and compared using UTF-8 character encoding.")] string Contents; [static, Description ("Get resource states based on input configuration file." )] uint32 GetTargetResource( [in, EmbeddedInstance ("MSFT_FileDirectoryConfiguration"), Description ("Configuration document that is to be applied." )] string InputResource, [in,Description ("Flags passed to the providers. Reserved for future use." )] uint32 Flags, [out, EmbeddedInstance ("MSFT_FileDirectoryConfiguration"), Description ("The current state of the specified configuration resources." )] string OutputResource ); [static, Description ("Test resource states based on input configuration file." )] uint32 TestTargetResource( [in, EmbeddedInstance("MSFT_FileDirectoryConfiguration"), Description ("Configuration document that to be applied." )] string InputResource, [in, Description ("Flags passed to the providers. reserved for future use." )] uint32 Flags, [out, Description ("True if identical. False otherwise." )] boolean Result, [out, Description ("Context information that the provider can use to optimize the set, This is optional." )] uint64 ProviderContext ); [static, Description ("Set resource states based on input configuration file." )] uint32 SetTargetResource( [in, EmbeddedInstance ("MSFT_FileDirectoryConfiguration"), Description ("Configuration document that to be applied." )] string InputResource, [in, Description ("Context information that the provider can use to optimize the set from TestTargetResource, This is optional." )] uint64 ProviderContext, [in, Description ("Flags passed to the providers. reserved for future use." )] uint32 Flags ); }; ``` > [!NOTE] > > - The class name and DLL file name should be the same, as defined in the `Provider.DEF` file. > - The type qualifier `[Key]` on a property indicates that it uniquely identifies the resource instance. At least one `[Key]` property is required. > - The `[Required]` qualifier indicates that the property is required. In other words, a value must be specified in any configuration script that uses this resource. > - The `[write]` qualifier indicates that the property is optional when using the custom resource in a configuration script. The `[read]` qualifier indicates that a property can't be set by a configuration, and is for reporting purposes only. > - The `[Values]` qualifier restricts the values that can be assigned to the property. Define the list of allowed values in `[ValueMap]`. For more information, see [ValueMap and value qualifiers](/windows/win32/wmisdk/value-map). > - Any new MOF file should include the following lines at the top of the file: > > ```mof > #pragma include ("cim_schema_2.26.0.mof") > #pragma include ("OMI_BaseResource.mof") > #pragma include ("MSFT_Credential.mof") > ``` > > - Method names and its parameters should be same for every resource. Change `MSFT_FileDirectoryConfiguration` from EmbeddedInstance value to the class name of the desired provider. There should be only one provider per MOF file. ### Step 2: Copy the schema MOF files Copy these required files and folders to the project directory you created in step 1: - `CIM-2.26.0` - `codegen.cmd` - `Convert-MofToProvider.exe` - `MSFT_Credential.mof` - `MSFT_DSCResource.mof` - `OMI_BaseResource.mof` - `OMI_Errors.mof` - `Provider.DEF` - `wmicodegen.dll` For more information on how to obtain the required files, see [How to implement an MI provider](/previous-versions/windows/desktop/wmi_v2/how-to-implement-an-mi-provider). ### Step 3: Edit the required files Modify the following files in the project directory: - `MSFT_FileDirectoryConfiguration.mof`: You created this file in step 1. - `Provider.DEF`: This file contains the DLL name, for example, `MSFT_FileDirectoryConfiguration.dll`. - `codegen.cmd`: This file contains the command to invoke `convert-moftoprovider.exe`. ```cmd "convert-moftoprovider.exe" ^ -MofFile MSFT_FileDirectoryConfiguration.mof ^ MSFT_DSCResource.mof ^ OMI_Errors.mof ^ -ClassList MSFT_FileDirectoryConfiguration ^ -IncludePath CIM-2.26.0 ^ -ExtraClass OMI_Error ^ MSFT_DSCResource ^ -OutPath temp ``` ### Step 4: Run the provider generator tool Run `codegen.cmd`, which runs the `convert-moftoprovider.exe` command. Alternatively, you can run the command directly. ### Step 5: Copy the generated source files The command in step 3 specifies the `-OutPath` parameter, which in this example is a folder named `temp`. When you run the tool in step 4, it creates new files in this folder. Copy the generated files from this `temp` folder to the project directory. You created the project directory in step 1, which in this example is `MSFT_FileDirectoryConfiguration`. > [!NOTE] > Any time you update the schema MOF file, run the `codegen.cmd` script to regenerate the source files. Rerunning the generator tool overwrites any existing the source files. To prevent this behavior, this example uses a temporary folder. Minimize updates to the schema MOF file since the main implementation should be merged with the most recent auto-generated source files. ### About the `MSFT_FileDirectoryConfiguration` resource After you run the provider generator tool, it creates several source and header files: - `MSFT_FileDirectoryConfiguration.c` - `MSFT_FileDirectoryConfiguration.h` - `module.c` - `schema.c` - `WMIAdapter.c` From this list, you only need to modify `MSFT_FileDirectoryConfiguration.c` and `MSFT_FileDirectoryConfiguration.h`. You can also change the extension for the source files from `.c` to `.cpp`, which is the case for this resource. The business logic for this resource is implemented in `MSFT_FileDirectoryConfigurationImp.cpp` and `MSFT_FileDirectoryConfigurationImp.h`. These new files are added to the `MSFT_FileDirectoryConfiguration` project directory after you run the provider generator tool. For a native desired state configuration resource, you have to implement three autogenerated functions in `MSFT_FileDirectoryConfiguration.cpp`: - `MSFT_FileDirectoryConfiguration_Invoke_GetTargetResource` - `MSFT_FileDirectoryConfiguration_Invoke_TestTargetResource` - `MSFT_FileDirectoryConfiguration_Invoke_SetTargetResource` From these three functions, only `MSFT_FileDirectoryConfiguration_Invoke_GetTargetResource` is required for a Get scenario. `MSFT_FileDirectoryConfiguration_Invoke_TestTargetResource` and `MSFT_FileDirectoryConfiguration_Invoke_SetTargetResource` are used when remediation is needed. There are several other autogenerated functions in `MSFT_FileDirectoryConfiguration.cpp` that don't need implementation for a native desired state configuration resource. You don't need to modify the following functions: - `MSFT_FileDirectoryConfiguration_Load` - `MSFT_FileDirectoryConfiguration_Unload` - `MSFT_FileDirectoryConfiguration_EnumerateInstances` - `MSFT_FileDirectoryConfiguration_GetInstance` - `MSFT_FileDirectoryConfiguration_CreateInstance` - `MSFT_FileDirectoryConfiguration_ModifyInstance` - `MSFT_FileDirectoryConfiguration_DeleteInstance` ### About `MSFT_FileDirectoryConfiguration_Invoke_GetTargetResource` The `MSFT_FileDirectoryConfiguration_Invoke_GetTargetResource` function does the following steps to complete its task: 1. Validate the input resource. 1. Ensure the keys and required parameters are present. 1. Create a resource instance that is used as the output of the Get method. This instance is of type `MSFT_FileDirectoryConfiguration`, which is derived from `MI_Instance`. 1. Create the output resource instance from the modified resource instance and return it to the MI client by calling these functions: - `MSFT_FileDirectoryConfiguration_GetTargetResource_Construct` - `MSFT_FileDirectoryConfiguration_GetTargetResource_SetPtr_OutputResource` - `MSFT_FileDirectoryConfiguration_GetTargetResource_Set_MIReturn` - `MSFT_FileDirectoryConfiguration_GetTargetResource_Post` - `MSFT_FileDirectoryConfiguration_GetTargetResource_Destruct` 1. Clean up resources, for example, free allocated memory. ## WinDC document > [!IMPORTANT] > The target of the scenario settings can only be device wide for extensibility. The CSP **scope** defined in `` and WinDC **context** must be `Device`. The value of the `Document` leaf node in the [DeclaredConfiguration CSP](mdm/declaredconfiguration-csp.md) is an XML document that describes the request. Here's a sample WinDC document with the configuration data specified for extensibility. ```xml c:\data\test\bin\ut_extensibility.tmp TestFileContent1 ``` Only supported values for `osdefinedscenario` can be used. Unsupported values result in an error message similar to `Invalid scenario name`. | osdefinedscenario | Description | |--------------------------------------|----------------------------------------------| | MSFTExtensibilityMIProviderConfig | Used to configure MI provider settings. | | MSFTExtensibilityMIProviderInventory | Used to retrieve MI provider setting values. | Both `MSFTExtensibilityMIProviderConfig` and `MSFTExtensibilityMIProviderInventory` scenarios that require the same tags and attributes. - The `` XML tag describes the targeted WMI provider expressed by a namespace and class name along with the values either to be applied to the device or queried by the MI provider. This tag has the following attributes: | Attribute | Description | |--|--| | `namespace` | Specifies the targeted MI provider namespace. | | `classname` | The targeted MI provider. | - The `` XML tag describes the required parameter name and value. It only needs a value for configuration. The name is an attribute and the value is `` content. This tag has the following attributes: | Attribute | Description | |--|--| | `name` | Specifies the name of an MI provider parameter. | - The `` XML tag describes the optional parameter name and value. It only needs a value for configuration. The name is an attribute and the value is `` content. This tag has the following attributes: | Attribute | Description | |--|--| | `name` | Specifies the name of an MI provider parameter. | ## SyncML examples The standard OMA-DM SyncML syntax is used to specify the DeclaredConfiguration CSP operations such as **Replace**, **Add**, and **Delete**. The payload of the SyncML's `` element must be XML-encoded. For this XML encoding, there are various online encoders that you can use. To avoid encoding the payload, you can use [CDATA Section](https://www.w3.org/TR/REC-xml/#sec-cdata-sect) as shown in the following SyncML examples. ### Configuration request This example demonstrates how to send a configuration request using the `MSFT_FileDirectoryConfiguration` MI provider with the `MSFTExtensibilityMIProviderConfig` scenario. ```xml 14 ./Device/Vendor/MSFT/DeclaredConfiguration/Host/Complete/Documents/27FEA311-68B9-4320-9FC4-296F6FDFAFE2/Document c:\data\test\bin\ut_extensibility.tmp TestFileContent1 ]]> ``` ### Inventory request This example demonstrates how to send an inventory request using the MSFT_FileDirectoryConfiguration MI provider with the MSFTExtensibilityMIProviderInventory scenario. ```xml 15 ./Device/Vendor/MSFT/DeclaredConfiguration/Host/Inventory/Documents/12345678-1234-1234-1234-123456789012/Document c:\data\test\bin\ut_extensibility.tmp ]]> ``` ### Retrieve results This example retrieves the results of a configuration or inventory request: **Request**: ```xml 2 chr text/plain ./Device/Vendor/MSFT/DeclaredConfiguration/Host/Complete/Results/27FEA311-68B9-4320-9FC4-296F6FDFAFE2/Document ``` **Response**: ```xml 2 1 2 Get 200 3 1 2 ./Device/Vendor/MSFT/DeclaredConfiguration/Host/Complete/Results/27FEA311-68B9-4320-9FC4-296F6FDFAFE2/Document ``` ## MI implementation references - [Management infrastructure (MI) API](/archive/blogs/wmi/introducing-new-management-infrastructure-mi-api) - [MI provider (1) - Overview](/archive/blogs/wmi/implementing-mi-provider-1-overview) - [MI provider (2) - Define schema](/archive/blogs/wmi/implementing-mi-provider-2-define-schema) - [MI provider (3) - Generate code](/archive/blogs/wmi/implementing-mi-provider-3-generate-code) - [MI provider (4) - Generate code (continue)](/archive/blogs/wmi/implementing-mi-provider-4-generate-code-continute) - [MI provider (5) - Implement](/archive/blogs/wmi/implementing-mi-provider-5-implement) - [MI provider (6) - Build, register, and debug](/archive/blogs/wmi/implementing-mi-provider-6-build-register-and-debug) - [MI interfaces](/previous-versions/windows/desktop/wmi_v2/mi-interfaces) - [MI datatypes](/previous-versions/windows/desktop/wmi_v2/mi-datatypes) - [MI structures and unions](/previous-versions/windows/desktop/wmi_v2/mi-structures-and-unions) - [MI_Result enumeration (mi.h)](/windows/win32/api/mi/ne-mi-mi_result) - [MI_Type enumeration (mi.h)](/windows/win32/api/mi/ne-mi-mi_type)