Allow administrators to mandate application policy defaults |
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:
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.
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;
}
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.
Administrative Template File Format, Allow administrators to set application policy defaults, MMC Snap-in extensions, Registry Overview