Declared configuration extensibility providers

The declared configuration enrollment, which supports the declared configuration client stack, offers extensibility through native WMI providers. This feature instantiates and interfaces with a Windows Management Instrumentation (WMI) provider that has implemented a management infrastructure (MI) interface. The interface must implement GetTargetResource, TestTargetResource, and SetTargetResource methods, and may implement any number of string properties.

Note

Only string properties are currently supported by extensibility providers.

[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. 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 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

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.

#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.

  • Any new MOF file should include the following lines at the top of the file:

    #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.

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.

    "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.

  2. Ensure the keys and required parameters are present.

  3. 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.

  4. 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
  5. Clean up resources, for example, free allocated memory.

MI implementation references