Desktop Deployment
Get A Move On: Migrate User Data With USMT
Michael Murgolo
At a Glance:
- Learn about state migration using USMT
- Decide which data and settings to migrate
- Configure migration rules
- Customize migration for applications
User State Migration Tool
BDD Solution Accelerator
Desktop migration projects pose a host of challenges and, if not done properly, can result in numerous angry calls to your helpdesk. Preparation is essential, whether migrating an entire
division’s computers, rolling out a new operating system, or just giving a single user new desktop hardware. Otherwise, users can lose important files, system settings, links to common resources, and so on. They will want to know where their "stuff" is. And this stuff—the personal data and settings known as the user state—is essential to keeping your users happy and productive during a system upgrade.
If a user receives a new desktop and little attention was paid to the files and settings on the old computer, they will likely have questions like "where are the Excel® spreadsheets I was working on?" or "where is the picture of my kids I had set as wallpaper?" At best, this will only lead to a loss of productivity as the user works on returning their work environment back to a familiar configuration. In a worse-case scenario, however, failing to maintain user state can lead to the loss of critical business data.
A migration of more than a few desktops requires automation. A variety of tools exist to automate state migration, including the User State Migration Tool (USMT) offered by Microsoft. This app will capture the user state from systems as far back as Windows® 95 when you’re migrating to Windows 2000 or Windows XP. USMT is a set of command-line tools that use .inf files to control what data gets migrated. There are a number of third-party tools that provide a graphical user interface for configuring migration parameters. These tools, in some cases, can migrate settings for more applications than USMT supports in its default configuration. However, USMT 2.6.1, which can be downloaded from the Microsoft Web site, will meet the migration needs of most large-scale desktop deployments once you’ve learned how to create and modify its configuration files.
In this article, I will not detail the use of USMT. Instead, I look more broadly at the need to migrate user data and settings, and USMT’s role in preserving this information. Sufficient coverage of this topic is provided in the help file included with USMT and in the User State Migration Feature Team Guide included with the Business Desktop Deployment Solution Accelerator (BDD).
If you want to learn more about BDD, take a look at the article, "A Guide to Pain-Free Desktop Deployment," by Steve Campbell and Michael Niehaus in this issue of TechNet Magazine.
An Overview of USMT
When installed to the default location, the binaries and configuration files are installed in C:\USMT\Bin, as shown in Figure 1. (The help file is installed in the C:\USMT folder.) The binaries can be copied to another location (another local folder or a network share) for execution. Just be sure to copy all the files in the C:\Bin folder to the new location.
Figure 1** Default USMT Files **
USMT consists of two command-line tools, Scanstate.exe and Loadstate.exe, as well as a number of supporting DLLs and configuration files. Scanstate is used to capture the user state on the old computer or operating system while Loadstate, as you can probably guess, is used to load the old state onto a new system or OS.
With the .inf files, you can specify migration rules that tell Scanstate what to capture on the source system (files, registry settings, and so on) and tell Loadstate where to restore them on the destination system. The Scanstate command line also specifies the location where state information—the data store—is temporarily held until it is loaded by Loadstate. The store can be placed on a network share, an external disk, or on the local disk in the case of an in-place operating system upgrade.
Keeping the data on the local disk during an OS wipe-and-load refresh can be a bit trickier. If there is not already a separate storage partition, you’ll need to use additional tools to resize the OS partition and create a second partition to store the state information while the OS partition is refreshed. However, when used with the Systems Management Server (SMS) Operating System Deployment Feature Pack (OSD), USMT can keep the store on the OS partition while it is nondestructively refreshed.
For more information on SMS, see Adam Gordon’s article "Zero Touch Windows Deployment With SMS" in this issue of TechNet Magazine.
Determining What to Migrate
Prior to version 2.6, USMT was limited by the fact that you had to run Scanstate while logged in as the user being migrated (in the user’s context), and you had to run Loadstate in a local administrator context before logging in as the user. This made the tool difficult to use in an automated migration process, and it required multiple scans and restores when migrating multiple users on one machine. Version 2.6, however, was enhanced with the ability to capture and restore the state of multiple users in a single pass while being run as an administrator or from a system context.
Just like earlier versions, Scanstate and Loadstate capture and restore the currently logged on user. However, through the use of the newly added /user and /all switches, or the [IncludeUsers] and [ExcludeUsers] sections in .inf files, you can now specify which users to include in the migration.
If this is the first time your organization has attempted a managed and automated migration of user data and settings, the task of determining what to migrate can seem quite daunting. With its default configuration files—Migapp.inf (which includes rules for migrating applications), Migsys.inf (which includes rules for migrating system components), Miguser.inf (which includes rules for migrating user-specific data), and ArchiveApp.inf (which includes rules for legacy applications)—USMT can migrate many items, including those listed in Figure 2. These .inf files will also gather various data files (based on file extension) from wherever they are found on the old hard disk and place them in the user’s My Documents folder on the new system.
Figure 2 Migrated User Items
- Desktop
- Start Menu settings
- Internet Explorer settings
- Internet Explorer Favorites
- My Pictures
- My Documents
- Quick Launch toolbar
- Accessibility setting
- Fonts
- Mouse and keyboard settings
- Regional settings
- Multimedia settings
- Outlook Express settings and data
- Display settings
- Screen saver settings
- Windows Explorer folder options
- TaskBar settings
- Classic interface preferences
- ODBC settings
- Command prompt settings
- Microsoft Office
- Adobe Acrobat Reader
- WinZip
Many of the default items are obviously worth migrating and, indeed, these default settings will often be sufficient for a basic migration. However, when considering what settings to migrate, give some thought as to what settings should be user configurable (hence migrated), and what settings should be standardized. Many organizations use a desktop migration as an opportunity to create and begin enforcing a better managed and more secure environment. Some of the settings that users can configure prior to the migration (on unmanaged computers) can be locked down on the new, managed computer. For example, a standard wallpaper, Microsoft® Internet Explorer security settings, and the Desktop configuration are some of the items you can manage to improve security and standardization.
Locating Where Settings Are Stored
Migrating files or settings with USMT involves specifying instructions (the rules we’ve been discussing) in an .inf file. These rules indicate what needs to be captured from the source computer and where to place it on the destination computer. Rules can define files, registry settings, .ini file settings, environment variables, and so on.
Migrating files is, for the most part, fairly straightforward since the source and destination are usually known. The more challenging task is determining how to migrate a Windows or application setting. Settings can be stored in the registry, .ini files, or some other type of text or binary files. Since you don’t necessarily know the storage mechanism or location of a given setting, it can be difficult to create rules to migrate the setting. To determine its location, start by checking the vendor’s documentation or Web site. (If the application was developed in-house, this is another good reason for making sure it’s been properly documented—so you don’t have to track down the original developer.)
If the location of a setting is not documented, you can use tools like Regmon and Filemon from Sysinternals or a third-party application packaging tool to try to uncover it. Regmon and Filemon monitor registry and file system activity, respectively. To try to capture where a setting is stored, simply start Regmon and Filemon monitoring and then change the setting. Once you’ve done this, look for registry and file system writes that occurred when you changed the setting and note where those writes are located.
Using an application packaging tool, you can generally take a before snapshot, make a setting change, and then take the after snapshot to see what has changed. I recommend doing your investigating on a computer that has only Windows installed (and the relevant application if you are checking on an application setting). Using a computer with antivirus software or other agents installed will result in a flood of file system and registry reads and writes, making it difficult to find the setting you’re looking for. Be sure to keep any unprotected computer like this isolated from the network.
What to Migrate
As I mentioned earlier, .inf files are used to specify what data and settings Scanstate should capture. Sysfiles.inf should always be used on the Scanstate command line because it tells Scanstate what files are part of the operating system and should not be migrated. There are other .inf files included with USMT besides Sysfiles.inf and the four rules files already mentioned. These .inf files must be present for USMT to operate, but they do not need to be specified on the command line. To capture files and settings not covered by these .inf files you must either modify the existing files or create new ones. The best way to learn how to do this is to study the aforementioned migration rule .inf files that come with USMT.
Each file has a [Version] section. If you create a new .inf file, I suggest copying the [Version] section from one of the existing files and then changing the DriverVer entry to your own date and version number.
The [Strings] section is used to create variables that represent longer strings elsewhere in the INF file.
Each .inf file has a master control (or component group) section that lists what sections (components) of the file to process. In Migapp.inf and ArchiveApp.inf this section is called [Applications], in Migsys.inf it is called [System Settings], and in Miguser.inf it is called [User Settings]. The USMT help file documents the syntax and purpose of each of these sections. Having a component group section allows each component to be easily disabled by simply placing a semicolon at the beginning of the component line. For example, to disable the migration of the Accessibility settings in Migsys.inf, place a semicolon at the beginning of the line that reads:
Accessibility, %accessibility%
Miguser.inf has an additional control section called [Copy This User State]. This section uses the syntax of .inf files from USMT 1.0, which did not support grouping items into components. This section is only used to find documents that may be on the source hard drive but are not located in known locations like My Documents, and to migrate them to a known location on the destination system (My Documents in most cases).
There are also additional control section types that are new for version 2.6, but that are not used in the standard .inf files. These are the [Administrator Scripts], the [Administrator User Scripts], and the [Files and Folders] sections. The use of these section types is documented in the help file.
The remaining sections constitute the individual components to be migrated. A component is a collection of sections that define what is to be migrated as a unit. Migsys.inf is a good one to study if you want to learn about building components since it has the greatest variety of syntax. Any section names that I refer to here as an example will be from Migsys.inf. I will go over the major component sections but not describe their syntax since that can be found in the help file. [Component.Detect] and [Component.Detect.n] sections are optional sections that allow you to control whether a section is processed based on any combination of detection criteria (for example, the existence of a file. [Component.Environment] sections are optional and allow you to define variables for a section based on a given object (a file or registry entry) and test criteria (whether the file exists or the registry entry matches a given value).
The next sections are for instructions. These sections list the rule sections containing the actual migration rules. There are several ways to define the instructions section. If there are [Component.Detect], [Component.Detect.n], or [Component.Environment] sections included, then the instructions section should be called [Component.Instructions]—for example, [Favorites.Instructions]. If these optional sections don’t exist, you can simply name the instructions section the name of the component (for example, [Accessibility]).
You can also filter the instructions list section based on operating system version. For example, the Fonts component has a [Fonts.9x] section for Windows 95, Windows 98, and Windows Me, and a [Fonts.NT] section for Windows NT®, Windows 2000, and Windows XP as shown in Figure 3. The Mouse and Keyboard component has three instructions sections: [Mouse and Keyboard] with instructions to be processed on any OS, [Mouse and Keyboard.9x], and [Mouse and Keyboard.NT]. (This operating system filtering can be very specific. See the topic titled "Operating system–specific section" in the USMT help file for details.) However they are named, the instruction sections specify which other sections contain the rules to migrate the data and settings relevant to the component.
Figure 3 Migsys.inf Excerpts
[version]
Signature=$Windows NT$
DriverVer=10/01/2002,5.2.3790.1807
[System Settings]
Accessibility, %accessibility%
Fonts,, dir, %csidl_fonts%
Mouse and Keyboard, %mouse_and_keyboard%
Browser, %internet_settings%
BrowserSecurity, %internet_security_settings%
International, %International%
Multimedia, %Multimedia%
Outlook Express, %outlook_express%
Display, %display%
ScreenSaver, %screensaver%
FolderOptions, %folderoptions%
TaskBar, %taskbar%
Classic, %classic%
ODBC, %ODBC%
CmdExe, %cmdexe%
[Common.Execute]
PreProcess = KillExplorer
Refresh = RefreshMetrics
Refresh = AskForLogOff
PostProcess = RestartExplorer
[Reboot.Execute]
Refresh = AskForReboot
[Fonts.9x]
RegFile=9xFonts.RegFile
ForceDestFile = Fonts.ForceDestFile
ForceDestReg = Fonts.ForceDestReg
Execute=Common.Execute
Execute=Fonts.Execute
[Fonts.NT]
RegFile=NtFonts.RegFile
ForceDestFile = Fonts.ForceDestFile
ForceDestReg = Fonts.ForceDestReg
Execute=Common.Execute
Execute=Fonts.Execute
Conversion = Fonts.Conversion
[9xFonts.RegFile]
HKLM\Software\Microsoft\Windows\CurrentVersion\
Fonts=HKLM\Software\Microsoft\Windows NT\
CurrentVersion\Fonts,,%csidl_fonts%
[NtFonts.RegFile]
HKLM\Software\Microsoft\Windows NT\
CurrentVersion\Fonts,,%csidl_fonts%
[Fonts.ForceDestFile]
dir=%csidl_fonts%
[Fonts.ForceDestReg]
HKLM\Software\Microsoft\Windows NT\
CurrentVersion\Fonts
[Fonts.Execute]
Refresh = RegisterFonts
[Fonts.Conversion]
HKLM\Software\Microsoft\Windows NT\
CurrentVersion\Fonts\*=\MigrateToNativeOnly
...
[Mouse and Keyboard]
DestDelReg = Mouse.DestDelReg
AddReg = Mouse.AddReg
RegFile = Mouse.RegFile
ForceDestFile = Mouse.ForceDestFile
ForceDestReg = Mouse.ForceDestReg
RestoreCallback = Mouse.Restore
Conversion = Mouse.Conversion
AddReg = Keyboard.AddReg
RenReg = Keyboard.RenReg
Execute=Common.Execute
ProcessSection=Mouse Cursor Scheme Name
ProcessSection=Mouse Cursor Scheme Reset
[Mouse and Keyboard.9X]
RenReg = MouseTrails9x.RenReg
RenReg = Mouse9x.RenReg
Conversion = Mouse9x.Conversion
[Mouse and Keyboard.NT]
AddReg = MouseTrailsNt.AddReg
[Mouse.DestDelReg]
HKR\Control Panel\Mouse [DoubleClickHeight]
HKR\Control Panel\Mouse [DoubleClickSpeed]
HKR\Control Panel\Mouse [DoubleClickWidth]
HKR\Control Panel\Mouse [MouseSensitivity]
HKR\Control Panel\Mouse [MouseSpeed]
HKR\Control Panel\Mouse [MouseThreshold1]
HKR\Control Panel\Mouse [MouseThreshold2]
HKR\Control Panel\Mouse [MouseTrails]
HKR\Control Panel\Mouse [SnapToDefaultButton]
HKR\Control Panel\Mouse [SwapMouseButtons]
HKR\Control Panel\Desktop [UserPreferencesMask]
HKR\Control Panel\Microsoft Input Devices\Mouse
...
[Mouse Cursor Scheme Name.Detect.1]
Registry, HKR\Control Panel\Cursors [], !MATCHES(Windows Default)
[Mouse Cursor Scheme Name.Detect.2]
Registry, HKR\Control Panel\Cursors [AppStarting]
[Mouse Cursor Scheme Name.Detect.3]
Registry, HKR\Control Panel\Cursors [Arrow]
[Mouse Cursor Scheme Name.Detect.4]
Registry, HKR\Control Panel\Cursors [Crosshair]
[Mouse Cursor Scheme Name.Detect.5]
Registry, HKR\Control Panel\Cursors [Hand]
[Mouse Cursor Scheme Name.Detect.6]
Registry, HKR\Control Panel\Cursors [Help]
[Mouse Cursor Scheme Name.Detect.7]
Registry, HKR\Control Panel\Cursors [IBeam]
[Mouse Cursor Scheme Name.Detect.8]
Registry, HKR\Control Panel\Cursors [No]
[Mouse Cursor Scheme Name.Detect.9]
Registry, HKR\Control Panel\Cursors [NWPen]
[Mouse Cursor Scheme Name.Detect.10]
Registry, HKR\Control Panel\Cursors [SizeAll]
[Mouse Cursor Scheme Name.Detect.11]
Registry, HKR\Control Panel\Cursors [SizeNESW]
[Mouse Cursor Scheme Name.Detect.12]
Registry, HKR\Control Panel\Cursors [SizeNS]
[Mouse Cursor Scheme Name.Detect.13]
Registry, HKR\Control Panel\Cursors [SizeNWSE]
[Mouse Cursor Scheme Name.Detect.14]
Registry, HKR\Control Panel\Cursors [SizeWE]
[Mouse Cursor Scheme Name.Detect.15]
Registry, HKR\Control Panel\Cursors [UpArrow]
[Mouse Cursor Scheme Name.Detect.16]
Registry, HKR\Control Panel\Cursors [Wait]
[Mouse Cursor Scheme Name.Instructions]
AddReg=Mouse Cursor Scheme Name.AddReg
[Mouse Cursor Scheme Name.AddReg]
HKR\Control Panel\Cursors []
[Mouse Cursor Scheme Reset.Detect]
Registry, HKR\Control Panel\Cursors [Scheme Source], MATCHES(0x00000000)
[Mouse Cursor Scheme Reset.Instructions]
DestDelReg=Mouse Cursor Scheme Reset.DestDelReg
[Mouse Cursor Scheme Reset.DestDelReg]
HKR\Control Panel\Cursors [Scheme Source]
HKR\Control Panel\Cursors [AppStarting]
HKR\Control Panel\Cursors [Arrow]
HKR\Control Panel\Cursors [Crosshair]
HKR\Control Panel\Cursors [Hand]
HKR\Control Panel\Cursors [Help]
HKR\Control Panel\Cursors [IBeam]
HKR\Control Panel\Cursors [No]
HKR\Control Panel\Cursors [NWPen]
HKR\Control Panel\Cursors [SizeAll]
HKR\Control Panel\Cursors [SizeNESW]
HKR\Control Panel\Cursors [SizeNS]
HKR\Control Panel\Cursors [SizeNWSE]
HKR\Control Panel\Cursors [SizeWE]
HKR\Control Panel\Cursors [UpArrow]
HKR\Control Panel\Cursors [Wait]
[Mouse.AddReg]
HKR\Control Panel\Mouse [DoubleClickHeight]
HKR\Control Panel\Mouse [DoubleClickSpeed]
HKR\Control Panel\Mouse [DoubleClickWidth]
HKR\Control Panel\Mouse [MouseSensitivity]
HKR\Control Panel\Mouse [MouseSpeed]
HKR\Control Panel\Mouse [MouseThreshold1]
HKR\Control Panel\Mouse [MouseThreshold2]
HKR\Control Panel\Mouse [SnapToDefaultButton]
HKR\Control Panel\Mouse [SwapMouseButtons]
HKR\Control Panel\Microsoft Input Devices\Mouse [TrayIcon]
HKR\Control Panel\Microsoft Input Devices\Mouse [Trails]
HKR\Control Panel\Microsoft Input Devices\Mouse [TrailLength]
HKR\Control Panel\Microsoft Input Devices\Mouse [PointerHide]
HKR\Control Panel\Microsoft Input Devices\Mouse [ClickLock]
HKR\Control Panel\Desktop [WheelScrollLines]
HKR\Control Panel\Desktop [UserPreferencesMask]
HKR\Control Panel\Cursors [Scheme Source]
[Mouse.RegFile]
HKR\Control Panel\Cursors [AppStarting]
HKR\Control Panel\Cursors [Arrow]
HKR\Control Panel\Cursors [Crosshair]
HKR\Control Panel\Cursors [Hand]
HKR\Control Panel\Cursors [Help]
HKR\Control Panel\Cursors [IBeam]
HKR\Control Panel\Cursors [No]
HKR\Control Panel\Cursors [NWPen]
HKR\Control Panel\Cursors [SizeAll]
HKR\Control Panel\Cursors [SizeNESW]
HKR\Control Panel\Cursors [SizeNS]
HKR\Control Panel\Cursors [SizeNWSE]
HKR\Control Panel\Cursors [SizeWE]
HKR\Control Panel\Cursors [UpArrow]
HKR\Control Panel\Cursors [Wait]
HKR\Control Panel\Cursors\Schemes
HKLM\Software\Microsoft\Windows\CurrentVersion\Control Panel\Cursors\Schemes
[Mouse.ForceDestFile]
%windir%\cursors\*.cur
%windir%\cursors\*.ani
[Mouse.ForceDestReg]
HKR\Control Panel\Cursor\Schemes
HKLM\Software\Microsoft\Windows\CurrentVersion\Control Panel\Cursors\Schemes
[Mouse.Restore]
HKR\Control Panel\Cursors\Schemes=\ExistsInHKLM, Software\Microsoft\Windows\CurrentVersion
[Mouse.Conversion]
HKR\Control Panel\Desktop [UserPreferencesMask]=\MigrateMouseUPM
HKLM\Software\Microsoft\Windows\CurrentVersion\Control Panel\Cursors\Schemes\*=\MigrateToNativeOnly
[MouseTrails9x.RenReg]
HKCC\Display\Settings [MouseTrails] = HKR\Control Panel\Mouse [MouseTrails]
[MouseTrailsNt.AddReg]
HKR\Control Panel\Mouse [MouseTrails]
[Mouse9x.Conversion]
HKR\Control Panel\Desktop [UserPreferenceMask]=\MigrateMouseUPM
[Mouse9x.RenReg]
HKR\Control Panel\Desktop [UserPreferenceMask] = HKR\Control Panel\Desktop [UserPreferencesMask]
[Keyboard.AddReg]
HKR\Control Panel\Desktop [CaretWidth]
HKR\Control Panel\Keyboard [InitialKeyboardIndicators]
HKR\Control Panel\Keyboard [KeyboardDelay]
HKR\Control Panel\Keyboard [KeyboardSpeed]
HKR\Control Panel\Desktop [CursorBlinkRate]
HKR\Control Panel\Input Method\*
[Keyboard.RenReg]
HKR\Keyboard Layout\Toggle []=[HotKey]
[Browser]
ProcessSection = Internet Explorer
ProcessSection = IE.CacheP.System,IE.Cache1.System,IE.Cache2.System
ProcessSection = IE.CacheP.User,IE.Cache1.User,IE.Cache2.User
ProcessSection = Favorites,Shared Favorites
ProcessSection = Telephony
ProcessSection = Ras Connections
Execute = Common.Execute
[Internet Explorer]
DestDelReg = IE.DestDelReg
AddReg = IE.AddReg
RenReg = IE.RenReg
DelReg = IE.DelReg
RegFile = IE.RegFile
RegFileEx = IE.RegFileEx
Conversion = IE.Conversion
You can nest components using the ProcessSection command. For example, the [Browser] section of Migsys.inf consists almost entirely of ProcessSection instructions that specify other components to run.
In summary, you can use the .inf files provided with USMT as models for any custom .inf files you may need to create. If you need to migrate user data files, model your custom .inf file on Miguser.inf. If you need to migrate operating system settings, model your .inf on Migsys.inf. And to migrate application settings, start with Migapp.inf.
Application Migration Considerations
Since USMT only migrates the setting for a small number of applications with its default .inf files, you will have to determine what needs to be migrated and how to migrate it for most of the commercial and internally developed desktop applications used by your organization. Migrating between computers with the same version of an application is usually a straightforward matter of determining what needs to be migrated and creating or modifying an .inf file to migrate it. This procedure may not be so straightforward when migrating from an older version of an application on the source computer to a newer version on the destination computer.
When capturing the settings for an application, Scanstate is capturing the settings for the old version. When the restore occurs, Loadstate can only put back what was captured, meaning the settings for the old version. One of three things can happen depending on the behavior of the new version of the application when it is run for the first time. The worst outcome will be that the new version ignores the settings of the old version. This is very difficult to overcome. You would have to create an .inf file to capture the old versions settings and write them to the location for the new version. If the settings have changed format between versions (maybe a text registry entry on the old version is now binary on the new version), you may have to script this transformation after Loadstate has run.
A better possible outcome is that the new version will use the settings of the old version as is. This makes migrating to the new version a straightforward task of identifying settings and moving them.
The final possible outcome is that the application sees the settings for the old version and upgrades them into the new version. For example, when migrating from one version of Microsoft® Office to a newer version, there are really two migrations going on. First, USMT only migrates settings for the source version of Office (per the rules in Migapp.inf). When the user starts an Office app for the first time on the destination machine, the new version of Office sees the older settings migrated by USMT and upgrades the settings it feels are appropriate to migrate. But as always, it’s a good idea to test your migration to determine how these applications will transfer.
Conclusion
This article should have given you some basic information about how USMT operates. Now you can move on to more specific topics that need to be considered when planning a state migration using USMT. These include such topics as changing user names or domain names; excluding data, settings, or users from the migration; and handling encrypted files, certificates, logging, and error handling.
Before using USMT or even planning a migration that will use it, make sure to read the USMT help file and the User State Migration Feature Team Guide in_cluded with the Business Desktop Deployment Solution Accelerator.
Michael Murgolo is a Senior Infrastructure Consultant for Microsoft Consulting Services. He is focused in the areas of operating systems, deployment, network services, active directory, systems management, automation, and patch management. He is a subject matter expert in the area of desktop deployment and migration.
© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.