Recipe 4.12 Modifying a Bit-Flag Attribute

4.12.1 Problem

You want to modify an attribute that contains a bit flag.

4.12.2 Solution Using VBScript
' This code safely modifies a bit-flag attribute
strObject = "<ObjectDN>"       ' e.g. cn=jsmith,cn=users,dc=rallencorp,dc=com
strAttr = "<AttrName>"         ' e.g. rallencorp-UserProperties
boolEnableBit = <TRUEorFALSE>  ' e.g. FALSE 
intBit = <BitValue>            ' e.g. 16
' ------ END CONFIGURATION ---------

set objObject = GetObject("LDAP://" & strObject)
intBitsOrig = objObject.Get(strAttr)
intBitsCalc = CalcBit(intBitsOrig, intBit, boolEnableBit)

if intBitsOrig <> intBitsCalc then
   objObject.Put strAttr, intBitsCalc
   WScript.Echo "Changed " & strAttr & " from " & intBitsOrig & " to " & intBitsCalc
   WScript.Echo "Did not need to change " & strAttr & " (" & intBitsOrig & ")"
end if

Function CalcBit(intValue, intBit, boolEnable)

   CalcBit = intValue

   if boolEnable = TRUE then
      CalcBit = intValue Or intBit
      if intValue And intBit then
         CalcBit = intValue Xor intBit
      end if
   end if

End Function

4.12.3 Discussion

In Recipe 4.9, I described how to search against attributes that contain a bit flag, which are used to encode various settings about an object in a single attribute. As a quick recap, you need to use a logical OR operation to match any bits being searched against, and logical AND to match a specific set of bits. If you want to set an attribute that is a bit flag, you need to take special precautions to ensure you don't overwrite an existing bit. Let's consider an example. RAllenCorp wants to secretly store some non-politically correct information about its users, including things like whether the user is really old or has big feet. They don't want to create attributes such as rallencorp-UserHasBigFeet so they decide to encode the properties in a single bit flag attribute. They decide to call the attribute rallencorp-UserProperties with the following possible bit values:


User is overweight


User is very tall


User has big feet


User is very old

After they extend the schema to include the new attribute, they need to initially populate the attribute for all their users. To do so they can simply logically OR the values together that apply to each user. So if settings 4 and 8 apply to the jsmith user, his rallencorp-UserProperties would be set to 12 (4 OR 8). No big deal so far. The issue comes in when they need to modify the attribute in the future.

They later find out that the jsmith user was a former basketball player and is 6'8". They need to set the 2 bit (for being tall) in his rallencorp-UserProperties attribute. To set the 2 bit they need to first determine if it has already been set. If it has already been set, then there is nothing to do. If the 2 bit hasn't been set, they need to logical OR 2 with the existing value of jsmith's rallencorp-UserProperties attribute. If they simply set the attribute to 2, it would overwrite the 4 and 8 bits that had been set previously. In the VBScript solution, they could use the CalcBit function to determine the new value:

intBitsCalc = CalcBit(intBitsOrig, 2, TRUE)

The result would be 14 (12 OR 2).

The same logic applies if they want to remove a bit, except the XOR logical operator is used.

Active Directory contains numerous bit-flag attributes, most notably options (which is used on several different object classes) and userAccountControl (which is used on user objects). I do not recommended blindly setting those attributes unless you know what you are doing. It is preferable to use a script from this recipe so that it calculates the new value based on the existing value.

4.12.4 See Also

Recipe 4.9 for searching with a bit-wise filter

    Chapter 3. Domain Controllers, Global Catalogs, and FSMOs
    Chapter 6. Users
    Appendix A. Tool List