readpol.vbs (c) 2005-2007 martin underscore binder at gmx dot de

Reads and writes (!) registry.pol files used by Windows group policy.

Enables administrators in conjunction with gpmc scripting to fully automate the process of creating group policy objects. Additionally, it provides an easy way to get rid of "additional registry settings" (orphaned keys in a group policy, resulting from missing administrative template entries) which otherwise only can be removed through either recreating the whole policy or writing a custom ADM file containing the registry keys in question - silly thing... And you may easily deploy a setting without having to create a template - just add it to the file used to create the policy.

If you want to create registry.pol files, be sure to take a close look at the TxtFile format used to create them - it looks something strange, so the easiest way to create and maintain your own Txtfile is to read a given registry.pol and then examine the result - see explanatinons below. This is because there are some data values that are really hard - software restriction policies e.g. use REG_QWORD (REALLY! ;-)).


The script is based on information about the registry.pol file format found at http://msdn2.microsoft.com/en-us/library/aa374407.aspx and on additional information about registry based group policy and adminstrative templates found at http://go.microsoft.com/fwlink/?linkid=31057. Gpmc scripting information may be found through browsing to Microsoft and searching for "scripting group policy tasks using gpmc". Additionally, the part of reading a policy file is based on an unknown author's earlier work i found somewhere in the net.


You should have a good understanding of policy and registry concepts and basic knowledge on administrative templates. Be sure to read this entire document at least once, then get ready and set and start using the script ;-)

For testing purposes, I strongly recommend using a group policy object in Active Directory which is not linked to any OU and - to be on the safe side - has a DACL which denies applying rights to the "Everyone" group. Do NOT test with your local policy - you may find yourself suddenly being locked out your machine during background group policy processing.

To approve you did everything right when creating policy files, I recommend you edit a copy of the policy file through gpmc/gpedit (simply change a single setting), then create a new text file from this policy file and create a new policy file from the new text file. Then do a binary compare on the original policy file and the new policy file. They shold match.


Feel free to use the whole script or parts of it in your own work - but don't blame me if it does NOT do what you want it to do ;-) And please refer to the original author - me.


The following command line parameters are available. Optional parameters (or parts of them) use [brackets].

Basic parameters:
*****************

/PolFile:registry.pol
   Always required!

[/TxtFile:registry.txt]
   When reading, specify TxtFile to create TxtFile from PolFile (otherwise you only get screen output)
   When creating, both TxtFile and PolFile must be specified

[/Mode:R|C]
   Read PolFile (default) or create PolFile from TxtFile
   !!! Take care - existing files are overwritten without notice !!!

Customization parameters for TxtFile (1) - all of these are optional:
*********************************************************************
(See explanation of TxtFile format below.)

/NullChar:"MyNull" Default: "<00>"
    Null chars are unprintable and even do not show up in ascii notation, so they have to be escaped to something readable. Of course, they may also occur in REG_BINARY, although this data type is not supportet by administrative templates (but it occurs in windows settings).

/MultiSep:"MySep"  Default: "<0D0A>"
    CrLf may be present in REG_MULTI_SZ or REG_SZ and has to be escaped.

/SameAsValue:"t"   Default: "<SameAsValue>"
    When used as data, replaces data with value name, see examples below. Useful when creating policies for firewall exceptions - you have to enter your exception rule only once.

/BinMarker:"u"     Default: "0b"
    Prefix for binary data (REG_DWORD only), use this if you want to specify a bit mask instead of dec/hex values

/HexMarker:"v"     Default: "0x"
    Prefix for hex data, use this if you want to specify a nice readable hex value instead of meaningless decimal data. 

Customization parameters for TxtFile (2) - all of these are optional:
*********************************************************************
(See explanation of TxtFile format below.)

/KeySep:"w"        Default: ":"
   This character separates the registry key and value names. Use this if either your key path or your value name contains a colon.
/ValueSep:"x"      Default: "="
   This character separates the registy value name and data type. Use this if your value name contains an equal sign.
/TypeSep:"y"       Default: ":"
   This character separates the registry data type and data value. Use this if your data value contains a colon.
/DataSep:"z"       Default: " "
   This character separates the data value hex and data value ascii output. Use this if your ascii data value contains spaces.
/NoHex
   Use this to suppress value data hex output. Hex output in general is only useful if your value data contains unprintable characters.

Misc parameters - all of these are optional:
********************************************

[/L[A|O][:Logfile]] [/H:C|W] [/W[:0|1]] [/MaxLog:x]

/L: Enable logfile, /LA: append (default), /LO: overwrite
   You know what to do with this, don't you? If you omit a file name, <ScriptName>_%computername%.log is used.
/H: Specify WSH host environment (CScript or WScript) (default: current)
   Use this to force a given scripting host when automating. (When running in WScript, readpol uses IE for screen output.)
/W: Enable/disable screen output (default: enabled)
   Better use //B if you want to suppress output
/Maxlog: Size of logfile (default: 100.000 bytes). When exceeded, existing logfile is renamed to .bak.


Usage Examples:
***************

readpol.vbs /PolFile:%systemroot%\system32\grouppolicy\machine\registry.pol
Simply read local machine group policy to console/IE window

readpol.vbs /PolFile:registry.pol /TxtFile:registry.txt /NoHex
Read a policy and write contents to a text file. Suppress hexadecimal output of data values.

readpol.vbs /PolFile:registry.pol /TxtFile:registry.txt /Mode:C /Nullchar:#
Read a text file where the separator for REG_MULTI_SZ is "#" instead <00> and create a policy file



Text file explanation - read with care
**************************************
**************************************

Following are some sample lines from a real local machine group policy. They also contain software restriction settings (rasphone.exe), which is NOT recommended for production environments when creating policy files - settings that are not in the scope of the administrative templates node are not documented! Also, please note that any REG_SZ values always have to have <00> (nul) as last byte.


Example 1: Basic usage
**********************

Software\Policies\Microsoft\Windows\NetCache:Enabled=REG_DWORD:0x0000 (0)

This entry shows the easiest type of policy. The registry key is "Software\Policies\Microsoft\Windows\NetCache", the value name is "Enabled", and the value data is a REG_DWORD set to zero (this setting would disable Offline Files). Take note of the notation format after REG_DWORD: The first value that follows is the hex value data prefixed with "0x", the second one in braces is the decimal value data.


Example 2: Rare value types
***************************

Software\Policies\Microsoft\Windows\Safer\CodeIdentifiers\0\Hashes\{c35184c6-96c2-4e72-a2b0-46893ba147c3}:LastModified=REG_QWORD:0xF2C0C4C9 (4072719561)

This is a software restriction policy (you know this because of the key "Safer"). I do NOT recommend to use entries like this one to create policy files! No, I don't! NO! I just provided it to prove the existence (and usage) of REG_QWORD data types. 
One reason not to use entries like this: There are no references about available entries and allowed values and notations. For entries in administrative templates, on the other hand, you can always reference to the aministrative template itself.

Another more severe reason: The script doesn't handle REG_QWORD correctly. The reason for this is, that in registry.pol every byte of data is followed by a nul byte - with the only exception of REG_QWORD, where things are mixed up: If the QWord value is less than 2^32, it is padded with nul bytes. If it is MORE than 2^32, it is NOT padded (thx MS! - it seems they had a fixed data length of 8 byte for any type of numeric value). I thought about how to handle this, and I dropped it because the scope of the script is administrative templates, which do not deal with Qwords. The script just ignores the extra bytes, and this is the reason the QWord in the sample above is only 4 bytes long instead of 8 bytes.


Example 3: Different notations
******************************

Software\Policies\Microsoft\Windows\System:ProfileErrorAction=REG_DWORD:0x0001 (1)

Once again - an easy entry ;-) This one means "immediately logoff when roaming profile fails". When creating a policy file from a text file, only the first value data after REG_DWORD: is used - the second one always is ignored. The space character between hex and decimal may be overridden by /DataSep. When creating policy files you may use either hex or decimal notation. The decision which format to use depends on the first two characters after REG_DWORD: - if these match the /HexSep ("0x" by default), then hex notation is assumed. You may also use binary notation by prefixing with "0b". So all of the following notations are valid and equal: "REG_DWORD:0x0012" or "REG_DWORD:18" or "REG_DWORD:0b00010010"


Example 4: <SameAsValue>
************************

SOFTWARE\Policies\Microsoft\WindowsFirewall\StandardProfile\GloballyOpenPorts\List:6502:udp:164.12.93.146/32,192.0.2.0/24:enabled:netop=REG_SZ:6502:udp:164.12.93.146/32,192.0.2.0/24:enabled:netop<00>

This is a firewall port exception. As you may notice, the value name and value data are identical. So, when creating a policy file from a text file, you may replace the part after the data type with <SameAsValue>. This dramatically improves readability of the text file. The required suffix <00> is appended by the script when using <SameAsValue>. You may wonder why this entry uses ":" as separator between key and value name - the value name itself contains colons!?! The reason is, only the first colon is used. The next separator (value name - value data) is the equal sign, so "List" is the key name, and the value name is up to the equal sign. Notation with <SameAsValue> is

SOFTWARE\Policies\Microsoft\WindowsFirewall\StandardProfile\GloballyOpenPorts\List:6502:udp:164.12.93.146/32,192.0.2.0/24:enabled:netop=REG_SZ:<SameAsValue>

Hint: When reading registry.pol files containing firewall rules, you should use /NoHex - the lines become almost unreadable if you don't...


Example 5: String values
************************

Software\Microsoft\Windows\CurrentVersion\Policies\System:Wallpaper=REG_SZ:0x633A5C77696E646F77735C7765625C77616C6C70617065725C666167206465736B746F702E626D7000 (c:\windows\web\wallpaper\desktop.bmp<00>)

This one sets the desktop background bitmap. It uses hex and ascii data value notation. In hex, a pair of hex numbers represents a single ascii character, therefore 0x633A5C resolves to decimal 99 - 58 - 92 which in turn means "c:\" - you get the picture?

I recommend not using hex notation - it's easier to maintain ascii notation: Wallpaper=REG_SZ:c:\windows\web\wallpaper\desktop.bmp<00>.

If your value data contains spaces, you may need to specify /DataSep:"Whateveryoulike" to use a different string, otherwise your value data will only contain the part before the first space.


Example 6: Action values
************************

Software\Microsoft\Windows\CurrentVersion\Policies\System:**del.IncludeRegInProQuota=REG_SZ:0x2000 ( <00>)

This is a policy set to "disabled", an existing value named "IncludeRegInProQuota" will be removed, resulting in the ntuser.dat not being included in calculation of roaming profile size. Whether a value gets deleted or not depends on the administrative template - you may specify the action "DELETE" for a policy setting instead of a data value. See the above mentioned Microsoft Web Sites for details. All action values have a value data of REG_SZ:0x2000 (space nul), although that doesn't really matter.


Example 7: Action values
************************

Software\Policies\Microsoft\Windows NT\Terminal Services\RAUnsolicit:**delvals.=REG_SZ:0x2000 ( <00>)

This policy configures "Remote Support", which is a policy that has additional options when enabled. When disabling this policy (forbid remote support), the action **delvals. deletes all registry values in the RAUnsolicit key.


Example 8: Custom registry values
*********************************

Software\Classes\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}:LocalizedString=REG_EXPAND_SZ:%USERNAME% on %COMPUTERNAME%<00>

This preference changes the name of "My Computer". You may notice that the key path does not contain "policy", and the "My Computer" icon can't be renamed through administrative templates provided by Microsoft. Of course, you could create a custom template. Or take the quick way, add this setting to your TxtFile and create registry.pol.