NOTE: This entry only focuses on the Windows Vista version of the FDCC and desktop applications.
Since its infancy, common themes have emerged which have delayed or prevented enterprise customers from deploying the FDCC. By the 80/20 rule, the two most common problems, in order, are:
1. Data and Settings Management
2. Application Installation
Customers have encountered other, smaller issues. But these two will cover 80% of the problems faced by applications when implementing the FDCC.
This entry will discuss the background of these items and how to best develop your application for the FDCC. It is primarily intended for developers, but system administrators can benefit too because some features of Windows will be discussed that can make your life easier.
This entry does not discuss UAC Virtualization. It assumes you are developing applications that will function entirely as a normal user.
Before we dive in, let’s discuss a little background and the purpose of the FDCC.
The spirit of the FDCC is to provide a standard operating system image and settings, a common set of applications, and firewall for a non-privileged user community. This is the best way to secure an enterprise and ensure fundamental system integrity while reducing costs.
Users cannot be allowed unrestricted access to a system. There is no technical or business reason users should have elevated privileges to browse the internet, check email, or create and modify documents. Doing so provides an easy opportunity for malware to steal, destroy, or falsify data.
The foundation of the FDCC is Microsoft Windows Vista with NTFS. This is great news for those who have invested time and effort learning how to develop on the Windows platform. If you have developed on Windows in the private sector/commercial world, then developing on the FDCC will be an easy transition.
The FDCC, and Windows in general, is a system designed for multiple users and to isolate the actions of multiple users. Non-elevated users can only write to their own profile. They are not allowed to:
· Make system-wide changes
· View or modify another user’s profile
· Write or modify directories owned by the operating system containing binaries such as EXE’s or DLL’s
This helps keep any unintentional and/or malicious activity by one user from affecting other users of a system and spreading across the enterprise.
Unfortunately, MCS has worked with many applications that modify the default permissions and leave a machine more vulnerable to attack. Security can be completely undone by one application making a seemingly minor change.
Your job as a developer is to make sure you follow these best practices to maintain this default security.
The target audience for FDCC applications is no longer the workgroup. Gone are the days when you could assume a system administrator could physically visit the machines of your user community and install and configure application. Developers must make every effort to make sure their application can be deployed and configured in an enterprise environment with hundreds, thousands, or myriads of users.
Administrators are users too and first impressions last forever. Often the first experiences administrators have with applications are when they install the software on client machines. This experience can either be a good one or bad. The requirements put forth in this document ensure that administrators have all of the tools they need to do their job.
Windows Vista provides the infrastructure to separate user data, user settings, and computer settings. Applications that use this infrastructure correctly offer the following benefits:
· Applications do not fail when run by non-privileged users
· Administrators or users can easily back up data and settings without needing to backup application or operating system files
· Multiple users can share a single computer, each with his or her own preferences and settings
· System administrators can enable Folder Redirection
· Applications are less likely to prevent Fast User Switching from operating correctly and efficiently
· Administrators can easily migrate user data when users get a new computer
Many applications make assumptions that their users would have administrative privileges and thus often try to write to protected areas of the operating system. Most commonly, these protected areas are the Program Files folder or HKLM. More generally, these areas include any resource in which normal users did not have write/modify access. Thus, on Windows XP many applications reported “access denied” error messages. Windows Vista introduced UAC Virtualization, but users often have no idea where the target redirection occurred. What’s more is that UAC Virtualization may be turned off in some organizations. If this occurs, applications commonly report “access denied” error messages just as they would were they running on Windows XP.
Several organizations maintained separate, logical drives for applications and data. Thus, it was common to find all application binaries installed on the C: drive and then a folder would be set up on the D: drive for user-created data. The idea was that the data would be safe on the D: drive if the C: drive ever crashed.
Also commonly found, were applications that installed custom directories on the root of the C: drive that contained application binaries and user-created data. The argument in favor of this practice was that applications and data could easily be migrated to new machines simply by backing up the directory on the old machine, and restoring it on the new on.
All of these scenarios remove flexibility from the system administrators and make network management more difficult. They raise the total cost of ownership for enterprises because:
1. Tools like the User State Migration Tool migrate user-created data, but it takes time and resources to develop and test each of these extensions. Often, several trial-and-error attempts must be made before it’s considered ready for production. Inevitably, something gets missed.
2. Administrators no longer have the flexibility to us folder redirection for user-created data.
3. While having the application isolate data into its own custom directory enabled users to share data, the negative is that this approach is a one-way street. It becomes difficult to separate data so that only certain users had access to it. It also makes using the application inside Terminal Services sessions practically impossible without major re-writing.
The following requirements will ensure that administrators have maximum flexibility and will help reduce their workload and allow them to administer by exception.
User-created data is anything a user can store or retrieve at a later time. Obvious examples are Word, Excel, or PowerPoint documents. User-create files must be stored in the Documents folder or subfolder. The default Documents folder location for a typical Vista installation is C:\Users\<username>\Documents, but paths should never be hard-coded. Calling the Common Item Dialog will default to the Documents folder. Windows Vista also provides direct access to the Documents folder using the SHGetKnownFolderPath function passing in FOLDERID_Documents. For example:
PWSTR pszDocFolder; SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &pszDocFolder); CoTaskMemFree(pszDocFolder);
On a typical installation of Windows Vista pszDocFolder would contain the string “C:\Users\<username>\Documents”.
Note: .NET Framework developers should use the System.Environment.GetFolderPath method with the Environment.SpecialFolder.MyDocuments parameter.
The benefits of using the Documents folder as the default location for data storage are:
· All users (including those with restricted account types) have write access to this location
· Users have one familiar place to organize and store all their data
· Data sharing is facilitated between applications because all applications using Common Item Dialog can easily access the Documents folder
· The Documents folder is an abstracted location and can be redirected to the network transparently by an administrator
· The Documents folder is available on the Start menu
Application-created data is used by the application to store application state, user preference, and temp files, etc. This type of data is typically hidden from users.
By storing this application-specific data in one of the several valid locations, you make it possible for multiple people to use the same computer without corrupting or improperly modifying each other’s data. The specification provides several valid locations and you are free to choose the location that works best for your needs.
A clear benefit to the developer is that can actually result in fewer lines of code. SHGetKnownFolderPath enables you to determine the correct location in which to store the user’s data and the user-specific application data.
Classifying and storing application data according to the guidelines in this requirement provides these benefits:
· It enables multiple users to share a computer and helps enable Fast User Switching.
· It enables business-related operations such as roaming, off-line storage, and allowing the operating system and its applications to be secured.
· It ensures a consistent and abstracted location for user data, enforces per-user separation of application data.
· It is one of the key factors in enabling remote use of the application.
This section identifies the valid file folders and the valid registry locations that applications must use for this data, and gives guidance on how to choose which of these locations are best used in different circumstances. The choice of valid locations to use is left to the software developer.
Classify application data into the following categories:
· Per user, roaming
· Per user, non-roaming
· Per computer (non-user specific and non-roaming)
NOTE There may be more than one category for the different application data stored by your application.
It is best to use application data file folders rather than the registry for storing application data in excess of 64K. The registry is an acceptable choice for small amounts of data. At installation time, try to store less than a total of 128K across HKEY_CURRENT_USER (HKCU) and HKEY_LOCAL_MACHINE (HKLM).
To comply with this specification, store application data files appropriately as either common or per-user. That is:
· In a subfolder of either the common application folder (identified by FOLDERID_ProgramData), or
· In the user profile folders: application data (FOLDERID_RoamingAppData) or local application data (FOLDERID_LocalAppData).
The subfolder to create to store user data files in is: [company name]\[product name]\[version].
Applications may also use the registry to store read/write application and configuration data.
· The HKCU registry hive is appropriate for storing small amounts of data (approximately 64K) and for policy settings that are per user.
· Avoid writing to HKLM during runtime, because limited users have read-only access to the entire HKLM tree by default. In addition, HKLM does not support roaming.
· Larger, file-based data should be placed in an application data folder. For example, Internet Explorer’s Temporary Internet Cache is stored within the file system of the user’s profile and not in the registry.
· At installation time, the application should not store more than a total of 128K across HKCU and HKLM. Note that HKEY_CLASSES_ROOT is excluded.
Once you have decided how to classify your data, you can use SHGetKnownFolderPath to retrieve the corresponding folder locations.
The KNOWNFOLDERID values described here provide a consistent, unified way to access the physical paths to the desired folder locations, independent of the operating system. The preferred API is SHGetKnownFolderPath. To access the path for application data, applications should call SHGetKnownFolderPath with the appropriate KNOWNFOLDERID and then append [company name]\[product name]\[version] to the returned path. Specifically:
PWSTR pszAppData; SHGetKnownFolderPath( FOLDERID_RoamingAppData, 0, NULL, & pszAppData); CoTaskMemFree(pszAppData);
On a typical installation of Windows Vista pszAppData would contain the string “C:\Users\<username>\AppData\Roaming”.
Note: .NET Framework developers should use the System.Environment.GetFolderPath method with the Environment.SpecialFolder.ApplicationData parameter.
When storing application data in the user profile, applications must use the following hierarchy under the Application Data file structure:
FOLDERID_RoamingAppData\ [Company or Organization Name]\ [Product Name]\ [Version]\ [File or Folder]
Per user, roaming
Per user, non-roaming
Per computer (non-user specific and non-roaming)
To comply with this specification, applications must classify and store data appropriately as either common or per-user. That is, either FOLDER_ProgramData or one of the user profiles: FOLDERID_RoamingAppData or FOLDERID_LocalAppData.
This folder will be enabled for roaming with the user profile. Use this folder to store all user-specific application preferences. For example, if a user can specify a custom dictionary to be used in the application, you would store it here. That way, if a user roams from computer to computer, the dictionary will roam with him or her. This also allows other users to have their own custom dictionaries.
This folder is for application data that does not roam. As it is still part of the User profile, this is still per-user information. Application data that is computer-dependent, such as user-specified monitor resolution, must be stored here.
This data must not roam because different computers are likely to have different monitors. In addition, large blocks of data that can easily be recreated and temporary files must be placed here to minimize download time that is incurred when roaming.
EXAMPLE Internet Explorer keeps its cache of downloaded .html/.gif pages here so that they don’t roam with the user. However, the smaller cookie and history lists are stored in FOLDERID_RoamingAppData so that they do roam.
This folder should be used for application data that is not user specific. Note that a limited user will only have read privilege for files in this folder, except for the files that user created. If users need to have write access to the common files, then during installation the application must create a sub-folder of FOLDERID_ProgramData with “Modify” privilege for appropriate user groups.
EXAMPLE An application may store a spell-check dictionary, a database of clip art or a log file in the FOLDERID_ProgramData folder. This information will not roam and is available to anyone using the computer.
· Files may be shared in the application data (FOLDERID_LocalAppData, FOLDERID_LocalAppDataLow or FOLDERID_RoamingAppData) folders. Multiple computers may use them simultaneously with different instances of the application. The data may also be used by multiple applications, for example, applications in a productivity suite. Applications should get a write exclusive on the file only when absolutely necessary. For example, applications using CreateFile should only specify GENERIC_WRITE when a write is required, but they should always set FILE_SHARE_READ.
· Paths returned by SHGetFolderPath are valid Win32 file system names that may contain spaces and may be in the universal naming convention (UNC) format.
· PathAppend() and PathCombine() APIs can be used to concatenate the relative path information onto the paths returned by SHGetFolderPath. For example: PathAppend(szAppData, "Company\Product\File.txt")
· By default, all users can write to the Users\Public\Documents location (FOLDERID_PublicDocuments).
The best way to package applications is using the Windows Installer format. Windows Installer is the native application installation engine in Windows Vista. It provides the following benefits:
· Applications can be inventoried using Windows Installer
· System administrators can selectively change how and which features will be installed
· Applications have the ability to self-heal
· It enables applications to separate per-user and per-machine installation tasks
· Applications can provide silent or unattended capabilities often with little effort on the developers part
· It enables system administrators to easily choose how the app is deployed (Group Policy Installation or Configuration Manager installation)
· A properly formatted MSI package is transactional. It either completely installs or completely fails. It never leaves the system in an unknown state.
· It automatically supports UAC
· There is already a large ecosystem of applications packaged in the Windows Installer format. Thus, the learning curve is minimal or non-existent for most system administrators.
See the following links for more information on Windows Installer:
· Overview of the Windows Installer Technology
· Developer Story Windows Installer
Once upon a time, it was common to find organizations with administrators running around the office from machine to machine, installing and configuring applications. Many lines of business (LOB) applications were limited to a finite set of known users and so it was understandable to train a few people how to administer them. They were built with enough functionality to meet the needs of the end user, but the burden of installing and configuring the applications was largely left to the administrators by following a long series of manual steps on each user’s desktop. The unfortunate reality is that creating a solid installation package was mostly an afterthought for many application developers.
The worst offenders had no installation package or the installation package was nothing more than a scripted xcopy. Administrators were instructed to create a directory, copy EXE’s and DLL’s, create registry keys and shortcuts before the application could be used. Any missed step or instruction not followed perfectly lead to a partially functioning application or, worse, a non-functioning application. Repeatability of the application installation was low and configuration management became more difficult. But even if an administrator got an application installed properly, there were often other difficulties running the apps.
Many applications stored user-created data and application data in the same directory as the application directory. If these applications were installed to Program Files, normal users were denied write and modify access. Thus, even if users weren’t responsible for installing and/or configuring their applications, they were still often granted elevated privileges because some applications simply would not run otherwise. But because users had full control over their PC’s, it created an unmanaged situation and administrators often had no idea how each machine was configured. Worst of all, users can easily download – without even realizing it—malware. This is an invitation to hackers and has historically been the cause of several security breaches in enterprise networks.
Many applications are also commonly installed to non-standard locations on the root of the hard drive, such as C:\AccountingApp. This was thought to solve the problem of giving users administrative privileges because users were able to read/write/modify. Plus some developers argued that it made migration from one machine to the next easier because a single directory could be copied from the source machine to the target machine. But it presented other problems.
Any user with write/modify access to the application folder would be able to replace the application binaries. But remember – Windows and the FDCC are designed to isolate multiple users and their actions. Thus, allowing users write/modify permissions to binaries shared by multiple users could allow someone with malicious intent to view or modify another user’s profile or make system-wide changes. More details and consequences of which can be found in the Changing access control on folders vs. files post.
In addition to being a security vulnerability, this approach also made it more difficult when users were upgraded to a new machine and data had to be migrated. Many development teams reasoned that application data is all stored in one place so it’s easy for an administrator to a folder from one machine to the next. True, but only if the administrator has to do it one time. And it completely ignores the security aspect. But security aside for the moment: what happens when there are hundreds or even thousands of machines and/or users? Administrators must rely on tools to help them migrate data like this.
Tools like the User State Migration Tool automatically migrate data for several hundreds of applications. And it is extensible so that administrators can migrate LOB apps. But it takes a lot of resources to configure USMT correctly. So what happens when there are hundreds or even thousands of applications?
Applications must always target the Program Files folder by default. Applications that install to a subdirectory of this folder inherit the restricted permissions from the parent by default. Normal users are given read and execute permissions to application binaries. But they are not allowed write or modify permissions.