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 No – = DP_DOWNLOAD_FROM_LOCAL + DP_NO_FALLBACK_UNPROTECTED
- Neighbour Yes – Fall-back DP Yes = DP_DOWNLOAD_FROM_LOCAL + DP_DOWNLOAD_FROM_REMOTE
- Neighbour Yes – Fall-back DP No = DP_DOWNLOAD_FROM_LOCAL + DP_DOWNLOAD_FROM_REMOTE + DP_NO_FALLBACK_UNPROTECTED
- 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()
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 ;
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_DOWNLOAD_FROM_LOCAL = 16,
DP_DOWNLOAD_FROM_REMOTE = 64,
DP_NO_FALLBACK_UNPROTECTED = 131072,
DP_ALLOW_WUMU = 262144,
DP_ALLOW_METERED_NETWORK = 524288
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)))
// 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;
cb_deployment_defaultFallback.Checked = false;
cb_deployment_defaultFallback.Checked = true;
// Metered network
cb_deployment_allowMetered.Checked = true;
cb_deployment_allowMetered.Checked = false;
// Use WUMU
cb_deployment_usemsUpdates.Checked = true;
cb_deployment_usemsUpdates.Checked = false;