Allow administrators to set application policy defaults

Allow administrators to set 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 program defaults via policy, allows administrators to set a baseline configuration that works “out of the box”. Users can then customize their settings if they wish, but if things go wrong, they can always remove their customizations and have the administrator-set defaults to fall back on.

Consider the things the administrator may want to set as defaults, and offer policies for them. Then, use these settings as a base for preferences, but allow users to change them. Settings that are defaulted during the install (from the .INF file) are obvious potential candidates, but others may be suitable. Don’t forget though, that an application should be able to run successfully without any registry settings.

The best way to implement default (and mandated) 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, MMC Snap-in extensions, Registry Overview