Deep Dive – ADMX Ingestion on Windows 10

As I have solved the issue on ingesting the Office16.admx, I thought I would review the whole ingestion process to help understand how it works under the hood and how to manage it.

Since Windows 10 1703, ADMX can be ingested and processed by the MDM layer via the policy CSP with the URI

./Device/Vendor/MSFT/Policy/ConfigOperations/ADMXInstall/

For this article, I will use ADMX files that I have created for each situation. The name of the example application is CamilleApp and published by DebayCorp company.

ADMX Ingestion

The ADMXInstall URI

The ADMX Install URI has 3 configurable settings:

.../ConfigOperation/ADMXInstall/{AppName}/{Area}/{UniqueID}

AppName: Name of the Application targeted by this ADMX. Depending what you are targeting it should be unique to the application in case to cater for multiple version of the same application.
Operation supported : Add, Get, Delete
Example: Office 2016 and Office 2013 should be Office2016 and Office2013

ADMX Area: There are 2 areas which ADMX ingestion covers; which are Policy and Preference.
Policy is for usual GPO
Preference is for preference GPO
Operation supported : Add, Get, Delete

UniqueID: This parameter is unique to the ADMX installation, it is only used at the installation. Policy Manager uses it for versioning in case of update, more detail below.
Operation supported : Add, Get

The ADMX Install URI, follows LocURI format, you should stick to alphanumeric characters (a-z, A-Z,0-9) and may use underscore(_), I would advise against any other characters which can be used in URI, as this may be used in some other scenario.

Limitation

Finally, as described in my previous article on Office, there are some limitations on the ingestion process. I’ve coded a PS script to validate the ADMX against these limitations.
ADMXValidation Script

the ingested policies are not allowed to write to locations within the SystemSoftware\Microsoft, and Software\Policies\Microsoft keys, except for the following locations:

  • Software\Policies\Microsoft\Office\
  • Software\Microsoft\Office\
  • Software\Microsoft\Windows\CurrentVersion\Explorer\
  • Software\Microsoft\Internet Explorer\
  • software\policies\microsoft\shared tools\proofing tools\
  • software\policies\microsoft\imejp\
  • software\policies\microsoft\ime\shared\
  • software\policies\microsoft\shared tools\graphics filters\
  • software\policies\microsoft\windows\currentversion\explorer\
  • software\policies\microsoft\softwareprotectionplatform\
  • software\policies\microsoft\officesoftwareprotectionplatform\
  • software\policies\microsoft\windows\windows search\preferences\
  • software\policies\microsoft\exchange\
  • software\microsoft\shared tools\proofing tools\
  • software\microsoft\shared tools\graphics filters\
  • software\microsoft\windows\windows search\preferences\
  • software\microsoft\exchange\
  • software\policies\microsoft\vba\security\
  • software\microsoft\onedrive
  • software\Microsoft\Edge
  • Software\Microsoft\EdgeUpdate\

Import Process

Admin process

The import process require 2 steps.

Step 1 – Create the URI

The URI must be created for each ADMX you want to import.
My application name is CamilleApp and the ADMX target Policy.
For the uniqueID, we can use any value for now as this is unique to this installation. I’m going to use Version1 for this example.

.../ConfigOperation/ADMXInstall/CamilleApp/Policy/Version1

Step 2 – Build the SyncML

The SyncML is a standard SyncML with the ADMX escaped to avoid any interference between the ADMX format and the SyncML format.
It uses the Add operation.

Note: Anything before policydefinition need to be removed before adding it to the SyncML

Generic SyncML:

<Add>
    <CmdID>2</CmdID>
    <Item>
        <Target>
            <LocURI>./Device/Vendor/MSFT/Policy/ConfigOperations/ADMXInstall/CamilleApp/Policy/Version2</LocURI>
        </Target>
        <Data>{ADMX escaped from < > to &lt; &gt; }></Data>
    </Item>
</Add>

Validation

To validate that the ingestion has processed correctly, you can have a look in the Windows Event Viewer at Applications and Services Logs > Microsoft > Windows > Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider > Admin
The ingestion process only logs when there are errors, it will tell which ADMX failed and where in the ADMX there is an issue.

ADMX-Ingestion-Error-what
Which ADMX is failing
ADMX-Ingestion-Error-where
Where it is failing

Behind the scenes

Policy Manager is responsible for ingesting the ADMX sent over SyncML. There are 2 places where Policy Manager stores the information, the registry and locally.

Registry

Policy Manager store in AdmxDefault and AdmxInstalled, the registry keys are located in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\

ADMX-Ingestion-Location-Registry
Registry

AdmxDefault: Contains the settings from the ADMX itself, with where each settings apply on which registry key, take note of the SourceAdmxFile with the value.

AdmxInstalled: Contain the URI received by Policy Manager from SyncML sent by the MDM server.

Local Files

ADMX files, once ingested, are stored in the Policy Manager folder located in C:\Windows\System32\config\systemprofile\AppData\Local\PolicyManager\, we can see that the name of the file is the unique ID specified in the URI initially.

ADMX-Ingestion-Location-Files
Local Files

Update ADMX

An ADMX is specific to an application or a set of applications; should these applications get new features, there may be a requirement to extend or update.
In the GPO world, you would replace the ADMX by the new one.
For AMDX Ingestion, you install a new version on top of the previous one.

ADMX Full update

In this example, the ADMX has been updated to add MachineSetting3 in the MachineSettings area. The ADMX still contains all the previous settings in it.

Admin Process

Step 1 – Create the URI

The inital URI used for the initial import the ADMX was

.../ConfigOperation/ADMXInstall/CamilleApp/Policy/Version1

The unique ID needs to be modified, again the unique ID can be anything, here I’m going to use Version2

.../ConfigOperation/ADMXInstall/CamilleApp/Policy/Version2

Step 2 – Build the SyncML

The SyncML is again using Add operation, as described before this is, with Get, the only operation allowed.

SyncML:

<Add>
    <CmdID>2</CmdID>
    <Item>
        <Target>
            <LocURI>./Device/Vendor/MSFT/Policy/ConfigOperations/ADMXInstall/CamilleApp/Policy/Version2</LocURI>
        </Target>
        <Data>{ADMX escaped from < > to &lt; &gt; }</Data>
    </Item>
</Add>

Behind the scenes

Registry

The registry was updated with the new setting MachineSetting3 and the SourceAdmxFile value has been also updated to Version2 for each setting.

ADMX-Ingestion-Update-Location-Registry
Registry shows Version2

Local Files

In terms of local files, Version2 has been added.

ADMX-Ingestion-Update-Location-Files
Local Files updated

Partial Update

Sometimes, it may happen that the ADMX is not complete and only contains some settings. Policy manager will still ingest but only update or create the corresponding settings.

In this example, the ADMX add MachineSetting4 in the MachineSettings area. The ADMX does not contain all the other settings in it.

Admin Process

Step 1 – Create the URI

The last URI used for the import the ADMX was

.../ConfigOperation/ADMXInstall/CamilleApp/Policy/Version2

The unique ID needs to be modified, again the unique ID can be anything, here I’m going to use Version3Partial

.../ConfigOperation/ADMXInstall/CamilleApp/Policy/Version3Partial

Step 2 – Build the SyncML

SyncML:

<Add>
    <CmdID>2</CmdID>
    <Item>
        <Target>
            <LocURI>./Device/Vendor/MSFT/Policy/ConfigOperations/ADMXInstall/CamilleApp/Policy/Version3Partial</LocURI>
        </Target>
        <Data>{ADMX escaped from < > to &lt; &gt; }</Data>
    </Item>
</Add>

Behind the scenes

Registry

The registry was updated with the new setting MachineSetting4 and SourceAdmxFile has Version3Partial for itsvalue. All other settings, SourceAdmxFile value remain Version2.

ADMX-Ingestion-PartialUpdate-Location-Registry-set1
MachineSetting1 remains on Version2
ADMX-Ingestion-PartialUpdate-Location-Registry-set4
MachineSetting4 is at Version3Partial

Local Files

ADMX-Ingestion-PartialUpdate-Location-Files
Local Files updated

Recap

Updating an ADMX is quite straight forward, the use of unique ID allows correct updates and helps Windows to map the settings against the correct ADMX, that’s why only Add operations are allowed on it and there is no Delete.

Delete ADMX

We understood that the node UniqueID is used for uniqueness of each setting, so it make sense to not have the Delete operation on it.
As part of the lifecycle, an ADMX might need to be deleted as the application is not used anymore or some parts are not required.

In the ADMX install URI, we have 2 nodes which allow Delete operation, AppName and Area and depending on what you are trying to achieve you target one or the other.

Remember that the area can be Policy or Preference. So you can delete either of them for each application.

The first things to know about deleting an ADMX from a machine, is that any settings applied have to be removed before trying to delete the ADMX. Policy manager will generate a 851 error in the logs (at Applications and Services Logs > Microsoft > Windows >Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider > Admin) to notify of this issue.

ADMX-Ingestion-Delete-Error-Settings

Admin Process

The same way we have proceed from Install and Update, this process is executed in 2 steps, agreeing that you have deleted the settings before hand. In this example, I’m going to delete the Policy part of the application.

Step 1 – Create the URI

.../ConfigOperations/ADMXInstall/CamilleApp/Policy

Step 2 – Build the SyncML

<Delete>
    <CmdID>1</CmdID>
    <Item>
        <Meta>
            <Format>chr</Format>
            <Type>text/plain</Type>
        </Meta>
        <Target>
            <LocURI>./Vendor/MSFT/Policy/ConfigOperations/ADMXInstall/CamilleApp/Policy</LocURI>
        </Target>
    </Item>
</Delete>

Behind the scenes

Registry

The registry shows the app as we only have deleted the Policy part of it, so if a Preference policy was defined, it would not be impacted and still be on the device.

ADMX-Ingestion-Delete-Location-Registry
CamilleApp is now empty

Local Files

Same as the registry, the application folder is still here but the Policy folder had been removed.

ADMX-Ingestion-Delete-Location-Files
Local folder is now empty

Conclusion

While Modern Management rely on CSPs for configuration. Third party applications still use ADMX files. ADMX ingestion provide a way of managing applications directly in CSP without no additional requirements. This provides an easy way for admins and enterprises to migrate GPOs and maintain these ADMX over the air.


Sources :