Allow administrators to mandate application policy defaults

Allow administrators to mandate application policy defaults

Benefits

Description

While allowing users to set options is generally a good thing, it can lead to problems caused by incorrect configurations. Often this requires a helpdesk call, or on site intervention by support staff. Providing Administrators with a way to set mandated program defaults via policy, allows administrators to set a baseline configuration that works “out of the box”. Unlike default policy settings, users cannot change their mandated settings.

Providing mandated policy gives administrators and support staff the ability to configure your program the way they want, and then stop users making changes. Because users cannot override mandated policies, internal documentation and support becomes easier as support staff know exactly how the desktop is configured.

The best way to implement mandated (and default) policy is to create three separate registry keys/values:

Then read each key/value, as follows:

  1. Mandated Setting, first. If a non-NULL value, use it.
  2. Otherwise, read User Setting. If a non-NULL value, use it.
  3. Otherwise, read Administrator’s Default Setting. If a non-NULL value, use it.
  4. Otherwise, read the application’s default from the application.

Following this procedure allows the administrator to set Default and Mandated policy while allowing users to have their settings saved separately. The application can then revert back to the user’s (or default) setting after a mandated policy setting is removed. If there’s an active mandated policy setting, then the UI which allows a user to change that setting should be disabled, or read-only.

Code Sample

This is a code fragment from the CAppSettings sample class. It uses a member function hrReadReg to read the settings, and defined key names.

    // Sanity check passed in values
    // ...

    ccbTemp = *lpccbSize;

    // Try to Read Mandated Setting
    hr = hrReadReg(m_hKeyMandated, tszSettingName, tszSetting, lpccbSize, TRUE);

    // If tszSetting is not > 1 the setting is empty,so we need to try again
    if ( (S_OK == lResult) && (_tcslen(tszSetting) > 1) )
    {
        // Succesfully Read Mandated Setting
    }
    else // No Mandated Setting, try to read User Setting
    {
        // Reset the size of the buffer for this read
        *lpccbSize = ccbTemp;

        hr = hrReadReg(m_hKeyUser, tszSettingName, tszSetting, lpccbSize, TRUE);

        if ( (S_OK == lResult) && (_tcslen(tszSetting) > 1) )
        {	
            // Succesfully Read User Setting		
        }
        else // No User Setting, try to read Admin Setting
        {
            // Reset the size of the buffer for this read
            *lpccbSize = ccbTemp;	
		
            hr = hrReadReg(m_hKeyAdminDefault, tszSettingName, tszSetting, lpccbSize, TRUE);
			
            if ( (S_OK == lResult) && (_tcslen(tszSetting) > 1) )
            {	
                // Succesfully read Admin Setting
            }
            else 
            {	
                // No Admin Setting. Use the default that was passed in
                
                // Set the size of the buffer to the size of the default
                 *lpccbSize = (_tcslen(tszDefaultSetting) * sizeof(TCHAR));

                // Make sure that the buffer is big enough to hold the default
                if (ccbTemp >= *lpccbSize)
                {
                    // copy the default that was passed in into 
                    // the buffer
                    _tcscpy(tszSetting,tszDefaultSetting);

                }
                else
                {
                    // oops. The bufer was too small for the default
                    hr = E_INVALIDARG;
                    goto __end;
                }
            }
        }
    }

__end:
    return hr;
}

Considerations

A method worth considering when performance is paramount would be to create these three registry keys:

The first two values are paired, and the second has an appended “_Z” for its value. This allows them to reside in a sequential location in the registry, allowing faster access. Processing these keys/values is as follows: First, read the toggle. If set to “Mandated,” read and use the data from the admin setting. If the toggle is set to default, read the user setting, and if non-NULL, use it. Otherwise, use the admin setting.

See Also

Administrative Template File Format, Allow administrators to set application policy defaults, MMC Snap-in extensions, Registry Overview