Roberts Blog

The House of SCCM and Intune on System Center Street

Tag: PatchMaster (Page 1 of 2)

DP_Locality flags or bitmask in SMS_UpdatesAssignment

I recently had to figure out how to properly set the DP_Locality property in the WMI SMS_UpdatesAssignment server SMS Provider class, as part of some work being done on PatchMaster, which automates the deployment of patches.

Eventually I figured it out, but at first I couldn’t quite grasp what was going on. I had to query the PG to verify my thinking (Thank you Hugo!), and in this post I’m going to go over as much detail as possible so as to spam the bejesus out of the subject.

To frame things better, every time you create a new Software Updates deployment in SCCM, a new SMS_UpdatesAssignment instance is created in WMI on the Site server to represent it.

Here’s a shot of the property sheet of a deployment, note the Neighbour DP and fall-back DP panels at the top and middle, and the WUMU\Metering panel at the bottom:

This is what it looks like behind the wizards curtain, using WBEMTEST to take a peek, DPLocality is an unsigned 32-bit integer:

* Note that you can do the same with PowerShell: get-wmiobject -namespace “root\sms\site_<YOUR SITES SITE CODE>” -query “select * from SMS_UpdateGroupAssign
ment where AssignmentID = <DeploymentID>” | Format-List -Property DPLocality

The DPLocality properties value shows 786512 (0xC0050). We’ll decode this in a moment.

That integer actually represents a bit mask, or a set of flags. This is noted in the documentation under qualifiers for that property as bits.

When I set about to decode DPLocality, I came up short. The documentation on Microsoft Docs doesn’t quite explain the bit positions properly, we’ll go over this now.

Firstly, the information you need is spread across two pages, shown below is the class, and then the class that class is inherited from:

SMS_UpdatesAssignment Server WMI Class

The property we’re looking for is DPLocality:

As is shown above, this class is actually derived from the SMS_CIAssignmentBaseClass.

Deeper into the doc for the SMS_UpdatesAssignment class we get some information on the property we want to set, DPLocality:

First note that Qualifiers calls out that this is an integer formed using a bitmask (bits), concocted using flags.

Qualifiers: [not_null, bits]

It is also noted that the DPLocality property defaults to the flag combination DP_DOWNLOAD_FROM_LOCAL | DP_DOWNLOAD_FROM_REMOTE (0x50).

We have an assertion here, it states that when these two flags are combined they weigh in at 0x50 (hex), or 80 in decimal.


So we know that DP_DOWNLOAD_FROM_LOCAL and DP_DOWNLOAD_FROM_REMOTE are both set by default, and if we build ourselves a bit-table in excel, which I do a little bit further into this post, we can essentially figure out those two flags bit positions.

When these two flags are set the following radio button switches to “Download…”:

This panel defines whether the local DP or a neighbour DP can be used by clients for this deployment.

If you remove the DP_DOWNLOAD_FROM_REMOTE flag, the “Do not…” radio button is enabled instead.

That’s LOCAL or REMOTE DP defined, now let’s quickly look at the fall-back DP option and return to it in more detail further into the post:

To toggle the fall-back DP radio control we need to set another flag called DP_NO_FALLBACK_UNPROTECTED (detailed in the SMS_CIAssignmentBaseClass doc) so as to disable the fall-back DP option, or remove the flag to enable the option as highlighted in the shot above.

There isn’t much more noted for this class in this doc page, but we are told to go visit the base class that this one was inherited from, there is more for us there, so let’s go take a look.

SMS_CIAssignmentBaseClass Server WMI Class

Nothing worthy of note here but I include a shot of the properties for this base class:

Let’s cut straight to the chase, no need to dilly dally, roll down until you find the DPLocality property:

We know this is a bit-mask, and here we have all 5 flags and their bit positions listed for us.

Yes those are bit positions and consequently starts at 0.

With these flags and bit positions (adjusted in just a moment) that’s all we need to construct and deconstruct the DPLocality value.

As I hint, actually three of the bit positions are noted incorrectly, we’ll take a ganders at that in a moment.

With this information I put together a bit-mask table in excel for easy reference, so as to figure out what the values should be, this gives me the decimal and hex value represented by the bit positions.

Here’s the bit-mask lookup table as a shot:

So armed with that initial assertion of the value 0x50 (decimal 80) from the two DP_DOWNLOAD flags being turned on, we can see that decimal 16 and 64 are added together to yield 80 (hex 0x50), that verifies bit positions 4 and 6 nicely..

So, we’re told that bit positions 4 and 6 are for the DP_DOWNLOAD flags, and bit positions 17, 18 and 19 are for the other three flags.

The problem with this is that the references to flags starts out using the bit position (bit column in table above) starting from 0 (DP_DOWNLOAD flags), and then starting from 1 (as sequence column in table above) for the other three flags, giving incorrect bit positions..

If we purely use bit position, the flags actually reside in positions 4, 6, 16, 17 and 18, and not 4, 6, 17, 18, 19. It’s an easy amendment to the docs which I’ll try to submit soon.

Worth noting that you just need to add these flag’s decimal value together to produce a valid integer.

There are four combinations for the Neighbour and fall-back DP, these are:

  • Neighbour No – Fall-back DP Yes = DP_DOWNLOAD_FROM_LOCAL

To handle WUMU and Metering just add their decimal value in once you’ve calculated the Remote\Local\Fall-back DP options.

And that’s about all you need to handle DPLocality.

Since I was handling this for a C# project, I might as well pass on what I wrote, I’m sure it can be done better, this is enabling code not the high of perfection code.

Below I show a method used to encode the bitmask based on some .Net controls ‘state’, I.e. a checkbox is checked or unchecked:

private int handledplocalityBitmask()


if (!globalObjects.GlobalClass.disableProcessing)


int tosendInt = 80;

if (cb_deployment_downloadNeighbour.Checked && cb_deployment_defaultFallback.Checked) tosendInt = 80;

if (cb_deployment_downloadNeighbour.Checked && !cb_deployment_defaultFallback.Checked) tosendInt = 131152;

if (!cb_deployment_downloadNeighbour.Checked && cb_deployment_defaultFallback.Checked) tosendInt = 16;

if (!cb_deployment_downloadNeighbour.Checked && !cb_deployment_defaultFallback.Checked) tosendInt = 131088;

if (cb_deployment_usemsUpdates.Checked) tosendInt = tosendInt + 262144 ;

if (cb_deployment_allowMetered.Checked) tosendInt = tosendInt + 524288 ;

return tosendInt;


return 0;


The four variations on Default and Neighbour are covered, and WUMU and Metering are added in at the end.

To decode the bitmask requires some more interesting coding.

First define some flags and respective decimal values that can be referenced later on:

public enum DPLocalityBitMask
     DP_ALLOW_WUMU = 262144,

And here is the code sitting in a method that does the decoding:

// Handle DPLocality Bitmask Combinations (expect Metering and WUMU)

var DPLocalityMask = (DPLocalityBitMask)adeploymentProperty.DPLocality;

var decodedDPLocality = new List<DPLocalityBitMask>();

foreach (DPLocalityBitMask DPLocalityBit in Enum.GetValues(typeof(DPLocalityBitMask)))

    if (DPLocalityMask.HasFlag(DPLocalityBit))

// Neighbour, Fallback

if (decodedDPLocality.Contains(DPLocalityBitMask.DP_DOWNLOAD_FROM_LOCAL) && decodedDPLocality.Contains(DPLocalityBitMask.DP_DOWNLOAD_FROM_REMOTE))
     cb_deployment_downloadNeighbour.Checked = true;                       

if (decodedDPLocality.Contains(DPLocalityBitMask.DP_DOWNLOAD_FROM_LOCAL) && !decodedDPLocality.Contains(DPLocalityBitMask.DP_DOWNLOAD_FROM_REMOTE))
     cb_deployment_downloadNeighbour.Checked = false;

if (decodedDPLocality.Contains(DPLocalityBitMask.DP_NO_FALLBACK_UNPROTECTED))
     cb_deployment_defaultFallback.Checked = false;
     cb_deployment_defaultFallback.Checked = true;
// Metered network

if (decodedDPLocality.Contains(DPLocalityBitMask.DP_ALLOW_METERED_NETWORK))
     cb_deployment_allowMetered.Checked = true;
     cb_deployment_allowMetered.Checked = false;

// Use WUMU

if (decodedDPLocality.Contains(DPLocalityBitMask.DP_ALLOW_WUMU))
     cb_deployment_usemsUpdates.Checked = true;
     cb_deployment_usemsUpdates.Checked = false;


PatchMaster Source Code now On Github

I’ve created a repository on GitHub for PatchMaster here.

The entire Visual Studio 2015 authored C# code base seems to be published AOK:


I reserve no rights on this code, feel free to use however you see fit. Obviously a release of an out and out clone with no enhancements will be frowned upon.

I’ll continue to maintain this code branch,which is actually the source code for the next release V1.6. There’s only one or two changes made to the V1.5 code yielding V1.6. I’ll need to have several more changes put in place before I release V1.6.

I’m sure the source code will really help any of you out there that are trying to do something similar or along the same lines, automation of patching.


ConfigMgr PatchMaster 1.5 released

Slow in blogging, tweet is my primary source for announcements.

So PatchMaster 1.5 landed, and in time for Patch Tuesday for some of you!

The updates to the tool, I hope they help, let me know on twitter @robmvp or comments on this blog if you have any feature requests or issues.

Download from the TechNet Gallery here and let me know how you get on with it. I wrote it for you Smile For us Smile


PatchMaster V1.5 draws closer to release

I’m at the tail-end of the development of PatchMaster to bring it up to version 1.5.

The driver for this code release was silent running mode, headless mode. And instead of releasing once done, I kept the project back longer than I normally do, several weeks in fact, so that I can return to the code here and there to tweak, finesse and add in more features. It has worked out quite well, things I would have tutted over post-release are getting handled.

Here’s what is already coded and fully working:

  • Full
    logging to CMTrace log format (log in same folder as PM process)

  • Silent
    running – Automation is here! Scheduled Task this puppy and it’s a reoccurring
    background task that only needs to be monitored via its log – This was a real time sink, because I had to rework a vast amount of code to allow silent running, and lots of test runs

  • Reuse
    already downloaded content (share content between hierarchies, download
    just the once) – Content can be downloaded once then copied to another hierarchy where PM can be run to stave off another first-run or monthly iteration of content download

  • Tweaks to the UI datagrids
  • Build prerequisite checker – Checks if a Device Group has deployments and security scopes defined, aborts the build if not
  • Tons of enhancements under the hood, optimisations and general code clean up

And I’m just finishing up with this:

  • Product version branding to control registry key changes going forwards – All the way up to 1.4 you’ve had to clean the registry manually, as I was bad-ass lazy about it, was needed due to modifying the structure of the content in existing registry keys across product versions which can lead to funky results. Version 1.5 will reuse 1.4’s registry settings and tweak whatever it needs
  • Using Distribution Point Groups instead of Distribution Points – I started but didn’t figure it out. This is low down on the TODO list, selecting your DP’s the one time isn’t that painful, most likely will get it done for 1.6
  • Reporting
    rollup SUGs for All Client, All Server and All Office to supplement the
    product rollup SUGs (rolls up all classification SUGs for a product into
    one SUG for specific product compliance reporting, now report higher up,
    for all client/server/office SUG’s)


July mentioned because I’m testing … it is June’s content

Some great suggestions from Philipp Buchwald on my blog for PM, thanks a lot Philipp you rock! While out in the USA for MMS 2018 I met Josh, who also rocks, and uses PM like a boss!

I know there are quite a few of you out there using this tool, almost all of my active customers are using PM, it doesn’t have to be all of you, some of you already have scripted solutions, or rely on ADR’s and manually handle the out of cycle releases which are frequent not infrequent.

With PM patching goes from a chore to a button click, matters not if it is patch Tuesday, taco Tuesday or titanic Thursday, when patches are released PM introduces them into your environment seamlessly, all you need to do is raise a change control to track them going through your system, as it should be, and then kick back and monitor the show using the provided reporting Software Update Groups. With PM, you can liberate lots of back-end time, and project it forwards to the client-end, troubleshoot them, bring compliance up.

PatchMaster V1.4 released

Managed to get a new version of PatchMaster ready for shipping, as version 1.4.

You can download it here on TechNet Gallery.

This one has several enhancements, that should make it more universally adoptable.

I realise that it will be nigh-on-difficult, to make PatchMaster an all-singing-all-dancing highly configurable tool that’ll meet everyone’s requirements; But I can get PatchMaster to meet most requirements, while going some way towards meeting in the middle for the more exotic needs out there.

We’ll go over what’s new using shots.

The Time Machine now has a cool picture that changes when you activate the Time Machine!

The Naming Bar has had some attention, you can now remove the Product button, but Classification has to stay on, or the total patches found and total patches processed will differ.

Rules can now be created that Include then Exclude. This is comma-delimited, so you can build up a long list of things you want to be processed, then begin excluding the wheat from the chaff such as Itanium, ARM64 et al. If you leave Include blank, the Include rule becomes unfiltered and everything is processed just as in V1.3 (Exclude was called Ignore Build in V1.3 and below).

The Available Patches tab has a new checkbox, which allows you to include SUM Maintenance automatically after a Build has completed. Disable so that you can run SUM Maintenance manually, or enable so that it is done for you whenever you perform a build.

And here we are, I’ve wanted to put in SUM clean up since day one, but time limits what I can do.

We now have SUM Maintenance, which removes ANY superseded update from SUG and Software Update Packages (SUPs, collides with Software Update Point, if you  see me say SUPs in reference to PatchMaster, it’ll be the Package not the Point). If a SUG is left empty it will be deleted whether it is a Reporting or Deployment SUG. Content is removed from SUPs but the SUP is not deleted, I will do this in a later version, for now you’ll have to manually delete the Package’s from the SCCM Console after several months of usage.

SUM Maintenance can be triggered post-build using the checkbox on the Available Patches tab.

To run SUM Maintenance manually select Find Superseded Patches, if any show click Remove Superseded Patches and monitor the Log tab (it should switch you there automatically).

SUM Maintenance will log to the Log tab (I will pour this into a log file soon …).