O R G A N I C / F E R T I L I Z E R: sms: decoding advertflags for "asap"

Jan 2, 2008

sms: decoding advertflags for "asap"

before i start writing this, let me give some credit to robert mahle for getting me some information confirming stuff in this post. we've been working a bit (har har, no pun intended) trying to figure out how to decode the value of "asap" from the sms admin console into a spreadsheet. before i move too far ahead, some background for you...

in this previous post about displaying advertisement info via a script, we ran into some confusion trying to decode the advertflags value. trying to get "asap" to show up just wasn't happening. the real confusion about this is "asap" is not treated like other schedule data that you'd find by looking for the sms_scheduletoken data type. usually it's held under assignedschedule. despite the fact that "asap" shows up in the sms admin console as a schedule, it's held under advertflags. the sdk confirms this:

AdvertFlags
  Data type: uint32
  Access type: Read/write
  Qualifiers: Bits
  When to announce the advertisement to the user. These bit flags must be coordinated with the
  bit flags specified in the ProgramFlags property of the advertised program. For example, if
  you set ONUSERLOGOFF, the NOUSERLOGGEDIN flag in the program must be set. If the flag
  settings do not match, the program will not be advertised.
 
  The default value is 0.
 
  Bit flags are as follows:
 
  IMMEDIATE (bit 5)
  ONSYSTEMSTARTUP (bit 8)
  ONUSERLOGON (bit 9)
  ONUSERLOGOFF (bit 10)
  NO_DISPLAY (bit 25)
  ONSLOWNET (bit 26)

in order to decode advertflags, you have to have a little bit of understanding regarding how bit flags work. don't worry; we'll get into all that in a second. you know, as long as we're covering "asap" stuff, i suppose we'll use that in our example.

alright, the first thing to do would be to create a little script that will dump out all of your advertisements that are set to "asap." don't sweat it. no coding required. here's a little something you can use. it's from the book sms 2003 recipes: a problem-solution approach. i modified it a little bit for the decoding work we'll be doing.

strSMSServer = "mySMSServer"

Set objLoc =  CreateObject("WbemScripting.SWbemLocator")
Set objSMS= objLoc.ConnectServer(strSMSServer, "root\sms")
Set Results = objSMS.ExecQuery("SELECT * From SMS_ProviderLocation WHERE ProviderForLocalSite = true")
For each Loc in Results
 If Loc.ProviderForLocalSite = True Then
     Set objSMS = objLoc.ConnectServer(Loc.Machine, "root\sms\site_" & Loc.SiteCode)
         strSMSSiteCode = Loc.Sitecode
 End If
Next

Set colAdverts = objSMS.ExecQuery("Select * From SMS_Advertisement order by AdvertisementName")
For Each objAdvert In colAdverts
 if (objadvert.advertflags AND 2^5) then
     wscript.echo objAdvert.AdvertisementName & " ------- " & objAdvert.AdvertFlags
 end if
Next

if i run this script in my environment, i'd get output like the following... (i've changed the names around in case you thought we ran apps from a company called some).

C:\temp>cscript smsadvertisement.vbs
Microsoft (R) Windows Script Host Version 5.7
Copyright (C) Microsoft Corporation. All rights reserved.

Some Custom Screensaver ------- 33554464
Some Antivirus App ------- 33554464
Some Email Disaster Recovery Analyzer ------- 33554464
Some Monitoring Agent ------- 33554464
Some Zip Utility 9.0 ------- 33554464
Some Webby App ------- 33554464

the value following the ------- is the value of advertflags. in my environment, all of these advertisements contain the same value for me (may not be the case for you). i'm going to use the first one called "some custom screensaver." the value, obviously for this one is 33554464. as a reminder...

bit 1bit 2result
000
100
010
111

when using AND as a bitwise operator, this is basically what occurs: as you can see, anything with both comparison bits set to 1 will result in 1. otherwise, you get 0. hold on to that... if you look at the script above, we perform a bitwise AND operation. it happens right here:

if (objadvert.advertflags AND 2^5) then
  wscript.echo objAdvert.AdvertisementName & " ------- " & objAdvert.AdvertFlags
end if

okay, real quick math lesson: 2 to the 5th is ... ? that's right, 32. keep that magic value in your head. it's easier to do it this way because in the sdk, it specifies it's the 5th value. instead of multiplying 2*2*2*2*2, we just raise it to the power of the 5. the 5th bit is "immediate" otherwise known as "asap". take the value you're working with and put it in your calculator as a decimal value. now, click the "bin" radio button. you'll see that the value of 33554464 is converted to 10000000000000000000100000. now, do the same thing for 32 (or 2^5). you'll get 100000. just to make it easier to understand visually, i added leading zeroes, getting this: 00000000000000000000100000. now stack them together:

10000000000000000000100000
00000000000000000000100000
--------------------------
00000000000000000000100000

remember above when i told you that both comparison bits have to be 1 in order for the result bit to be 1? well, look at that. we only have a single place that it occurs.

ANDing the values together gives you a value of 32. (if you don't believe me, paste 100000 into your calculator as a hex value and convert it to dec.) the if/then script statement above is doing this for you.by the way, since you're only checking for one value, the result being greater than 0 is a successful return. technically you could write it as:
if (objadvert.advertflags AND 2^5) > 0 then
  wscript.echo objAdvert.AdvertisementName & " ------- " & objAdvert.AdvertFlags
end if
but you get the idea. since we know the value we return is 32, which is greater than 0, then it successfully found the 5th bit to be turned on. you could also set it to = 2^5 instead.