You get a bonus - 1 coin for daily activity. Now you have 1 coin

Creating your own Group Policies for Windows Server 2003

Practice



So, we have a task - to create our own set of properties for Group Policy. The so-called Administrative template, which can be imported from an ADM file into the list of already existing group policies, and which can likewise be used to manage registry values just like with the built-in properties.

Let's first figure out what group policies actually do. A group policy changes a certain set of registry values on a group of computers (defined by certain conditions). So, if we want to tell all computers in the group to use a specific home page for Internet Explorer, we simply instruct Windows to change, for all computers in the group, the registry parameter responsible for the home page to the corresponding value.

In the end, group policies are a set of instructions specifying which registry parameters need to be changed or applied to which values, for the specified group of computers.

So, by creating our own template (Administrative Template), we're creating pointers to certain registry keys that we want to change. We can specify all types of registry values except the following two:

a) REG_MULTI_SZ
b) REG_BINARY

that is, we cannot apply binary data sets (REG_BINARY) or multi-line sets (REG_MULTI_SZ) through group policies.

Next. Group policies are divided into "User" and "Computer" policies. Accordingly, the former are applied at the user level (i.e., on one computer, different users will get different group policies), while the latter are applied at the computer level (i.e., on one computer, the same group policy will be applied for all users).

Now let's connect this to the registry. User policies only concern the:
HKEY_CURRENT_USER
hive, while computer policies concern:
HKEY_LOCAL_MACHINE


Structure of an ADM file

An ADM file is a plain text file. You can edit it in Notepad or any other text editor (not Word, of course, and not Libre/Open Office - we need a pure text format).

We simply write the file (yes, even in FAR) and save it with the .adm extension at the path:
c:\windows\inf\
with whatever name you need. For example:
c:\windows\inf\mypolicy.adm


The file has the following structure:

; remark
CLASS xxx
CATEGORY "xxx"
KEYNAME "xxx"
POLICY "xxx"
VALUENAME xxx
END POLICY
END CATEGORY

So, let's start with the explanations.

The ";" character (semicolon), if placed at the beginning of a line, means that everything after it, to the end of the line, is a comment.


CLASS. We've established that group policies can apply to users and computers. CLASS is precisely the pointer indicating where to go to apply the parameters - to HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE. Accordingly, its value can be "CLASS USER" or "CLASS MACHINE":

CLASS USER

or

CLASS MACHINE


CATEGORY. This specifies the category name. For example, something like "Windows Update" or "Windows Installer". That is, this exact name is what we'll see in the left-hand pane of the group policy window when looking for it.

Example:

CATEGORY "My Policy"


KEYNAME. This specifies the name of the registry key that we'll be changing. This value isn't visible from the group policy management console. The key is specified together with its path, starting right after the HKEY_xxx class. That is, you don't need to write HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER, but everything that comes right after them - that's what goes here.

Example:
KEYNAME "Software\Microsoft\Office\12.0\Outlook\Preferences"


POLICY. This is the name of the group policy itself. That is, exactly the name we see in the right-hand pane of the group policy window. One category can contain several policies.

POLICY "This is first policy"


VALUENAME. This is the name of the registry value that we want to change at the KEYNAME location. That is, by changing the policy, you'll be applying the value to precisely this value name.

VALUENAME mySoftwareParam


END POLICY and END CATEGORY will, respectively, close out the set of parameters for a policy and the set of policies within a category.


Let's give the simplest possible example of such a file:

CLASS USER
CATEGORY "Моя политика"
KEYNAME "Software\MySoftware\Parameters"
POLICY "Параметр 1"
VALUENAME myparam1
END POLICY
POLICY "Параметр 2"
VALUENAME myparam2
END POLICY
END CATEGORY



Nested categories

In fact, we can see that the categories that come built into Windows are most often nested. How do we do the same thing?

It's all simple. Here's an example from which everything might already be clear right away:

CATEGORY "Parent"
CATEGORY "Child"
...
END CATEGORY
END CATEGORY

That is, we simply nest categories within each other. A more complex example - 2 categories nested inside a parent one:

CATEGORY "Parent"
CATEGORY "Child1"
...
END CATEGORY
CATEGORY "Child2"
...
END CATEGORY
END CATEGORY



Placeholders and strings

Let's look at this variant:

CLASS USER
CATEGORY !!categoryMY
KEYNAME "Software\MySoftware\Parameters"
POLICY !!policy1
VALUENAME param1
END POLICY
POLICY !!policy2
VALUENAME param2
END POLICY
END CATEGORY

[strings]
categotyMY="Это моя категория"
policy1="Первый параметр"
policy2="Второй параметр"

What do we see here? Strange !! marks before the CATEGORY and POLICY values. These marks mean that what follows is merely the name of a string constant, while the actual strings themselves reside in a special [strings] section.

So, instead of displaying "!!categoryHOME," the policy management console will try to find a constant named "categoryHOME" in the "[strings]" section and will show the value of the constant "This is my category" instead.

This technique can somewhat improve the appearance of the ADM file by placing all the strings in one part of the file, and can also simplify localization - since now we won't have to hunt down every foreign-language word throughout the whole body of the document.

Such "pointers" can be applied to the "declarators" CATEGORY, POLICY, EXPLAIN and PART.



EXPLAIN (let's explain)

This keyword is used inside POLICY to display some explanatory text to the administrator when they open the group policy (the administrator can also read this explanation on the left, between the categories and policies panes, when they select a specific policy with the cursor).

Let's give an example:

CLASS USER
CATEGORY !!categoryMY
KEYNAME "Software\MySoftware\Parameters"
POLICY !!policy1
EXPLAIN !!policyEX1
VALUENAME param1
END POLICY
POLICY !!policy2
EXPLAIN !!policyEX2
VALUENAME param2
END POLICY
END CATEGORY

[strings]
categotyMY="Это моя категория"
policy1="Параметр 1"
policy2="Параметр 2"
policyEX1="Это объяснение параметра 1"
policyEX2="Это объяснение параметра 2"



SUPPORTED

If we open a group policy from Microsoft's built-in set, at the bottom we can see a line "Supported on: ...", which states which versions support this policy. We can do the same thing ourselves:

CLASS USER
CATEGORY !!categoryMY
KEYNAME "Software\MySoftware\Parameters"
POLICY !!policy1
SUPPORTED !!policy1s
EXPLAIN !!policyEX1
VALUENAME param1
END POLICY
POLICY !!policy2
SUPPORTED !!policy2s
EXPLAIN !!policyEX2
VALUENAME param2
END POLICY
END CATEGORY

[strings]
categotyMY="Это моя категория"
policy1="Параметр 1"
policy2="Параметр 2"
policyEX1="Это объяснение параметра 1"
policyEX2="Это объяснение параметра 2"
policy1s="Windows Server 2000, 2003, 2008"
policy2s="Windows XP, Vista, 7, Server 2003, 2008"



Drop-down lists

If you look into Windows' built-in group policies, you can often see drop-down lists with values. How do we create something like that? Several "declarators" are used for this together. Let's just start right away with an example:

CLASS USER
CATEGORY !!categoryMY
KEYNAME "Software\MySoftware\Parameters"

POLICY !!policyShowWelcome
PART "Показывать приветствие" DROPDOWNLIST
VALUENAME showWelcome
ITEMLIST
NAME "Показывать" VALUE "on"
NAME "Не показывать" VALUE "off"
NAME "Только в первый раз" VALUE "onlyfirst"
END ITEMLIST
END PART
END POLICY

END CATEGORY

[strings]
categotyMY="Это моя категория"
policyShowWelcome="Показывать приветствие?"

So what's new that we see here?

PART and END PART: these keywords let us mark off containers, inside which we declare "selectable" elements. More about containers will be written below.

DROPDOWNLIST: indicates that we need to create a drop-down list.

ITEMLIST and END ITEMLIST: inside this block we'll declare all the possible values that the administrator will be able to choose the one they need from.

NAME xxx VALUE xxx: After NAME, in quotes, we write the "human-readable" name of the value. After VALUE - what value to assign in the registry to the VALUENAME parameter.



Setting our own "enabled" and "disabled" values

By default, if we don't separately define values for "enabled," Windows will write a DWORD parameter to the registry with the value "1" for enabled, and will delete the VALUENAME parameter (entirely) when the policy becomes "disabled".

For example, we enabled the policy - the param value appears in the registry as a DWORD with the value "1".
We disabled it - the param value disappears.

In order to define your own values, there's a "VALUE" keyword:

KEYNAME "key"
VALUENAME "param"
VALUE "on"

We see that here, instead of "1," the value "on" of type REG_SZ will be written while the policy is enabled. But the "param" value will still simply be deleted if the policy is disabled.

KEYNAME "key"
VALUENAME "param"
VALUE NUMERIC 5

And here, when the policy is enabled, the number 5 of type DWORD will be written.

Now let's imagine a situation where we need the value to always be preserved. That is, so it isn't deleted when the policy is disabled, but instead transitions to another state - takes on a different value. The keywords "VALUEON" and "VALUEOFF" serve this purpose:

KEYNAME "key"
VALUENAME "param"
VALUEON "enabled"
VALUEOFF "disabled"

There's also a special parameter value "DELETE". For example, let's imagine the reverse situation: when the policy is enabled, we need the registry value to not exist, and when it's disabled, we need it to appear:

KEYNAME "key"
VALUENAME "param"
VALUEON DELETE
VALUEOFF "disabled"



Changing several registry keys at once

Let's imagine a situation: when the policy is enabled or disabled, we need to change several registry values at once (which happens fairly often). The keywords ACTIONLISTON and ACTIONLISTOFF serve this purpose:

KEYNAME "key"
VALUENAME "param"
ACTIONLISTON
VALUENAME "param1" VALUE "enabled"
VALUENAME "param2" VALUE "second on"
VALUENAME "param3" VALUE NUMERIC 5
END ACTIONLISTON
ACTIONLISTOFF
VALUENAME "param1" DELETE
VALUENAME "param2" VALUE "second off"
VALUENAME "param3" VALUE NUMERIC 0
END ACTIONLISTOFF

As the example shows, these lists work analogously to VALUEON and VALUEOFF. Inside the lists, sets of registry values are specified along with the values they need to be set to.


PART containers and other selector types

Above we learned how to create group policies. However, everything we've done so far is learn how to create policies with an "enabled/disabled" choice and, as a special case, with a drop-down list. However, in Microsoft's policies we see that it's also possible to make various selectors with checkboxes, to enter free text instead of choosing from suggested options, and so on.

The "declarator" PART serves to organize these capabilities. Along with it, certain qualifier keywords are used that tell the group policy management console exactly what kind of control we want.

The structure of PART is the same, and similar to other group policy blocks. The block begins with the keyword "PART", inside which comes some name or title for the parameter, followed by a description of the parameter's selector. And the final touch is the closing tag "END PART".

Let's go over the various "selectors".


TEXT

All this container does is display text. There's nothing to select or change in it - it's simply a text note for the administrator, perhaps with some information or an explanation of the meaning of the following parameters.

...
POLICY "My Policy"
KEYNAME "Software\Mysoft\Params"
PART "Это просто текстовое объяснение чего-то" TEXT
END PART
END POLICY
...


EDITTEXT

This selector allows entering an arbitrary set of characters (a text string) that will be saved as a registry value. The length of the entered text cannot exceed 255 characters.

...
POLICY "My Policy"
KEYNAME "Software\Mysoft\Params"
PART "Введите адрес" EDITTEXT REQUIRED
VALUENAME address
END PART
END POLICY
...

In this example, the text entered by the administrator will be saved in the address value of the registry key "Software\MySoft\Params".

The keyword REQUIRED is also used here, which means the text field cannot be left empty.

In addition, you can use the DEFAULT parameter to set a default value:

...
POLICY "My Policy"
KEYNAME "Software\Mysoft\Params"
PART "Введите адрес" EDITTEXT REQUIRED DEFAULT "какой-то адрес"
VALUENAME address
END PART
END POLICY
...

If you specify the MAXLEN keyword, the length of the entered text will be limited to the value you specify right after MAXLEN:

...
POLICY "My Policy"
KEYNAME "Software\Mysoft\Params"
PART "Введите адрес" EDITTEXT MAXLEN 50
VALUENAME address
END PART
END POLICY
...

And when the EXPANDABLETEXT keyword is specified, the entered value will be saved in the registry with the REG_EXPAND_SZ type.


DROPDOWNLIST

We've already talked about this selector above. It lets you create a drop-down list with predefined values.

...
POLICY "My Policy"
KEYNAME "Software\Mysoft\Params"
VALUENAME param
PART "Выберите значение" DROPDOWNLIST
ITEMLIST
NAME "Первый вариант" VALUE "first"
NAME "Второй вариант" VALUE "second"
NAME "Третий вариант" VALUE "third"
END ITEMLIST
END PART
END POLICY
...

In the ITEMLIST list, we specify a set of "name" = "value" pairs. The name will be displayed in the drop-down list for the administrator. The value will be set in the registry for the parameter specified in VALUENAME.

We can also additionally use the NOSORT keyword to prevent the group policy management console from automatically sorting the selector's names alphabetically.


NUMERIC

...
POLICY "My Policy"
KEYNAME "Software\Mysoft\Params"
PART "Введите число" NUMERIC REQUIRED SPIN 10
VALUENAME "MaxProfileSize"
DEFAULT 1000
MAX 10000
MIN 100
END PART
END POLICY
...

As the name suggests, it only allows entering numbers. It also provides "increase"-"decrease" buttons.

The SPIN parameter controls the increment step when it's pressed.
DEFAULT specifies the default value.
MAX and MIN are, respectively, the maximum and minimum values.

If you specify the TXTCONVERT modifier, then instead of writing the number as a DWORD, it will be converted to a string and written as REG_SZ.


CHECKBOX

The good old "checkbox". An enabled/disabled choice.

...
POLICY "My Policy"
KEYNAME "Software\Mysoft\Params"
PART "Включим это?" CHECKBOX
VALUENAME doWeEnable
VALUEON NUMERIC 1
VALUEOFF NUMERIC 0
END PART
END POLICY
...

Naturally, you don't have to use VALUEON/VALUEOFF - you can use the DELETE keyword and so on, i.e., everything discussed above.

If you specify the DEFCHECKED keyword, the selector will be checked (selected) by default.


COMBOBOX

Differs from DROPDOWNLIST in that here the administrator can not only choose some value from the drop-down list, but also enter their own.

...
POLICY "My Policy"
KEYNAME "Software\Mysoft\Params"
PART "Выберите или введите свое:" COMBOBOX
VALUENAME param
SUGGESTIONS
"alpha" "beta" "gamma" "another" "еще что-то"
END SUGGESTIONS
END PART
END POLICY
...

As we can see, we give the administrator a choice of values from the SUGGESTIONS list, but we don't forbid them from entering their own.

We can also use the NOSORT, MAXLEN, and DEFAULT modifiers here.


LISTBOX

Probably the most unusual type of selector. It doesn't let you set a VALUENAME or VALUE for it. All it does is display a "Show" button, clicking which lets the administrator see all the values under the specified registry key.

...
POLICY "My Policy"
KEYNAME "Software\Mysoft\Params"
PART "Параметры:" LISTBOX
END PART
END POLICY
...

We can use the EXPLICITVALUE modifier so that the list of value names is accompanied by a list of those values' data.


How to import your ADM file into the snap-in

As we already mentioned above - the file needs to be saved with the .adm extension. Use the path: c:\windows\inf

Now open the group policy snap-in (it doesn't matter whether it's GPMC or gpedit.msc) and right-click on "computer settings" or "user settings" ("Computer Configuration" or "User Configuration") on the "Administrative templates" item. A context menu should appear, one of whose items will be "Add/Remove administrative templates".

Select this item. A window will open through which you can "browse" for group policy files. Find yours and click "Open." If you've formatted your file correctly, it should import into the snap-in without a hitch, and you'll see your group policies in the categories panel.



If I still don't see my policies (but I do see my category)

It looks like you've created not a policy, but a "preference." These differ from policies in that they're not reversible (that is, if you turn off a policy, the registry values return to the state as if the policy had never been enabled at all; if you turn off a "preference," the registry values change to something else, but don't become the same as before it was enabled... a simple example is using VALUEOFF to set values for disabling the policy).

By default, such "preferences" are hidden from administrators' view. To see them, right-click on your category in the group policy management console and select "View-->Filtering" and uncheck both options in the window that opens, whose names begin with "Only show...".

Comments

To leave a comment

If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Lectures and tutorial on "Operating Systems and System Programming"

Terms: Operating Systems and System Programming