Migration Extension Interface Reference

Joseph Dadzie
Microsoft Corporation

October 1997

There are two sets of sample source code that accompany this article. The first, pview, migrates pview.exe from Windows 9x to Windows NT 5.0. The second, scrnsave, migrates the Windows 95 screen savers, such as Flying Windows and Marquee. Both packages include heavily commented source code for the Migration DLLs.

Click to view or copy the PVIEW sample source code that accompanies this article.

Click to view or copy the SCRNSAVE sample source code that accompanies this article.

Introduction

Many applications work identically under Miclrosoft®Windows® 9x and Windows NT® 5.0. Your application may operate differently under the different versions. If so, if your users decide to move from Windows 9x to Windows NT, they will be unable to use your application. To prevent this, Microsoft provides the Migration Extension Interface.

If applications do not work properly, users have to reinstall them. Individual reinstallation of applications is an irritation at any level. In corporate environments, where large-scale deployments are automated, reinstalling applications is prohibitive, since it increases deployment costs. For most non-corporate environments, users may not have the original installation media readily available to reinstall their applications.

The Migration Extension Interface is an extension to the Setup API that enables you to ensure that your application will operate correctly after Windows NT is installed over Windows 9x. To make use of the Migration Extension Interface, you must write a migration DLL (MIGRATE.DLL) that the Setup program can use to make the necessary changes that will enable your application to work correctly under the new operating system.

This reference is divided into the following major sections:

Overview

Most users expect that all their installed applications will function properly after they decide to upgrade from Windows 9x to Windows NT. However, it is almost impossible to guarantee that an existing application will work properly after Windows NT Setup completes installation of the new operating system. While Windows NT Setup attempts to adhere to the ideal behavior, there are certain problems with some applications that it cannot handle. These include problems caused by applications that:

As the developer of your application, you are the only one who can resolve these issues. You can use the Migration Extension Interface to interact with the upgrade process and correct inconsistencies like these before they become problems.

How the Migration Process Works

The Migration Extension Interface is designed to fit into the upgrade process as follows:

  1. A user installs your application on a Windows 9x–based system. You place your MIGRATE.DLL file (with your company’s digital certificate and other associated files) on your distribution media, on the Web site from which the user installed the application, or on the user’s hard disk. If the files are installed on the hard disk, you must write the following to the Windows 9x registry:
    HKLM\Software\Microsoft\Windows\CurrentVersion\Setup\Migration DLLs
    Value name: <ProductID string >
    Value: <path to MIGRATE.DLL>
    

Note   The ProductID must match the string returned by the QueryVersion function described later on in this document.

  1. Sometime later, the user runs the Windows NT 5.0 Setup program, which scans the Windows 9x registry and prompts the user for the location of other migration DLLs.

  2. Setup locates and activates your MIGRATE.DLL, passing it its MIGRATE.INF file.

  3. Your MIGRATE.DLL modifies the MIGRATE.INF file with the relevant information, and passes it back to Windows NT Setup.

  4. Windows NT Setup continues its installation process. When it begins the Windows NT portion of the installation, it again contacts your MIGRATE.DLL and passes it the MIGRATE.INF file.

  5. Your MIGRATE.DLL uses the information it wrote into the MIGRATE.INF file and takes the appropriate actions that will enable your application to run under Windows NT.

Note   Support for the digital certificate requirement and specification of the location of MIGRATE.DLL if installed on the user’s hard disk will be fully implemented for Windows NT 5.0 Beta 2.

About MIGRATE.DLL

The migration DLL is a standard Win32®-based DLL you create. It is called by Windows NT 5.0 Setup at different times during the upgrade process to perform a custom migration of your otherwise incompatible application. Setup relies on migration DLLs to identify unknown software components and to either migrate their settings to Windows NT, or to remove the components that will never work properly after an upgrade.

At a minimum, a migration DLL must have the following Setup-defined exported functions.

Your migration DLL can contain additional functions, as well. But if any of these seven functions is missing from a migration DLL, Setup will not load and process it, and your application will not migrate.

How Migration DLLs Are Processed

This section describes the order in which the functions in the migration DLL are called and a brief description of each function. Note that if any of the required seven functions is not present, Setup will skip your MIGRATE.DLL, and your application will not be migrated to the new system.

During the initial portion of Windows NT Setup (that is, while Windows 9x is still running), the following MIGRATE.DLL functions are called in their listed order.

Function Caller Reason for Call
DllMain (DLL_PROCESS_ATTACH) Windows 9x Standard call to load the migration DLL from the installation media.
QueryVersion Setup Obtain application identification information (such as the product ID and version number) and determine if further processing is necessary.

After successful processing, the relevant files are copied to the user’s hard disk.

DllMain (DLL_PROCESS_DETACH) Windows 9x The system unloads the migration DLL.
DllMain (DLL_PROCESS_ATTACH) Windows 9x The system loads the migration DLL from its new location on the local hard disk.
Initialize9x Setup MIGRATE.DLL prepares itself for the migration process. It detects its target application component locations. Then it provides the working and source directories to Windows NT Setup.
MigrateUser9x Setup Setup calls the MigrateUser9x function once for each Windows 9x user account on the computer being upgraded as well as for the Windows NT Administrator account (that is, the active user account becomes the NT Administrator account after migration). The migration DLL detects the users that have installed its target application.

Setup also calls MigrateUser9x for the default user account if necessary.

If the application is installed for the given user name, the DLL gathers user-specific application information to be used during the MigrateUserNT function call.

MigrateSystem9x Setup The DLL gathers system-wide information concerning its target application, and saves private data to be used during the MigrateSystemNT function call.
DllMain (DLL_PROCESS_DETACH) Windows 9x The system unloads the migration DLL.

During the second portion of Windows NT Setup (that is, when the newly installed Windows NT is running), the following MIGRATE.DLL functions are called in their listed order.

Function Caller Reason for Call
DllMain (DLL_PROCESS_ATTACH) Windows NT The system loads the migration DLL.
InitializeNT Setup Windows NT Setup provides the migration DLL with its working directory, specified during the earlier call to Initialize9x.
MigrateUserNT Setup Setup calls MigrateUserNT once per user. It enables the migration DLL to make changes to a user’s application settings.

Note that the number of calls may be less than the number made to MigrateUser9x, since some user accounts may not migrate. For example, the default user account may not migrate if that account has never been accessed. As such, a DLL must store its private data on a per-user basis.

MigrateSystemNT Setup The migration DLL makes changes to the system’s application settings based on the information obtained during the call to MigrateSystem9x.
DllMain (DLL_PROCESS_DETACH) Windows NT The system unloads the migration DLL.

By the time the system calls the DllMain (DLL_PROCESS_ATTACH) function, Setup has done the following:

  1. Copied all 32-bit executables from %windir%\system to %windir%\system32.

  2. Adjusted the Windows 9x Registry key values within HKU\User\Software and HKLM\Software that contain full paths to files that exist in a new location on Windows NT.

  3. Migrated all system settings, including the registry, program menu items, desktop, recent documents, and other shell settings.

  4. Deleted Windows 9x-specific OLE system objects (not application objects).

  5. Migrated the user shell folders (such as c:\windows\desktop) to the Windows NT equivalent (i.e., c:\windows\profiles\<user>\desktop).

  6. Adjusted the paths in .STF files (part of ACME Setup) if necessary (for Beta 2).

  7. Adjusted links and PIFs that point to moved files.

Note   In the Windows NT phase of the upgrade process, each DLL function has 60 seconds to complete its processing. If it takes longer, Setup will terminate it.

Migration DLL Development Issues

Since a migration DLL is a standard Win32 DLL, writing one should be fairly straightforward. However, the following sections describe some specific development issues to consider.

Where to Place Migration DLLs

Migration Function Processing Order

Run Time DLLs Included with Windows NT 5.0

Manipulating a User’s Registry Settings

Check Network Availability

Avoid User Interfaces

Storing Private Data

Handling Special String Characters

Using the Setup Answer File

Deferring Application Migration

Logging Errors

Using the Win32 Profile APIs

Restarting Setup

Where to Place Migration DLLs

You can place your migration DLL in a network location, on a floppy disc, or on a compact disc.

Network Location of MIGRATE.DLL

A user may place migration DLLs on a network share and specify the location during Setup, or, if Setup is running in unattended mode, specify the location in the Setup answer file. Each migration DLL must be placed in its own subdirectory (along with any other files required for migrating the target application).

Note   If the Win95upg subdirectory exists before Setup runs, Setup will delete it and create a new one into which the specified files will be copied.

Floppy or Compact Disc-Based MIGRATE.DLL

Setup provides users with the option to supply a floppy or compact disc that contains migration DLLs for their target applications. Setup searches the provided media for MIGRATE.DLL files. For each DLL it finds, it copies the directory containing the DLL (as well as all other files and subdirectories in that directory) to a unique subdirectory.

Note   The Windows NT 5.0 compact disc also contains migration DLLs.

Migration Function Processing Order

There is no guaranteed processing order for migration DLLs. Therefore, do not allow one of your migration DLLs to be dependent on the migration DLL for another application.

Run-Time DLLs Included with Windows NT 5.0

Before running any migration extensions on the Windows 9x system, Setup will copy the following files from the Windows NT compact disc to the Windows 9x System directory:

For international environments, Setup copies the appropriate localized DLLs. For example, Setup copies MFC40JPN.DLL and MFC42JPN.DLL for a Japanese installation.

Debug versions of the run-time DLLs are not copied, nor can Setup guarantee that other run-time versions of an application will migrate correctly.

This list of files is not exhaustive. Setup may also install newer versions if they become available. However, if your migration extension needs a run-time DLL that is not installed by Windows NT, you must ship it with your migration DLL, and use the migration DLLs functionality to ensure the run-time DLL is installed.

Manipulating a User’s Registry Settings

Setup runs in a logged-on user context on Windows 9x, but does not run in a logged-on user context under Windows NT. Rather, it runs in the local system account context. As such, your migration DLL should not try to query or modify the HKEY_CURRENT_USER registry key directly. Instead, it should query the UserRegKey handles passed to it through the MigrateUser9x and MigrateUserNT functions.

Determining application registry differences

You can use SYSDIFF.EXE to determine registry entry differences between an application on a newly installed Windows NT 5.0 computer and an upgraded Windows 9x one. SYSDIFF.EXE is available from the Microsoft Windows NT 4.0 Workstation Resource Kit. This utility is useful when you are not familiar with the application registry differences between the two versions of your application.

To use SYSDIFF.EXE to determine the registry entries made by an application on a Windows NT computer:

  1. Install Windows NT 5.0 on a computer

  2. Log into the system under the administrator account

  3. Copy SYSDIFF.EXE and SYSDIFF.INF into a temporary directory

  4. Modify SYSDIFF.INF as necessary

  5. From the Command Prompt, run
    sysdiff /snap [/log:<logfile1>] <snap_file>
    

    logfile1 and snap_file are valid filenames. The /log parameter is optional. SYSDIFF.EXE will create both files.

  6. Install your application

    Note   SYSDIFF.EXE records all system changes. Install your application only.

  7. From the Command Prompt, run
    sysdiff /diff [/log:<logfile2>] <snap_file> <diff_file>
    

    logfile2 and diff_file are valid filenames. The /log parameter is optional. SYSDIFF.EXE will create both files. snap_file is the filename you specified in the previous call to SYSDIFF.EXE.

    From the Command Prompt, run

    sysdiff /dump <diff_file> <dump_file>
    

    dump_file is a valid filename. SYSDIFF.EXE will create it. diff_file is the filename you specified in the previous call to SYSDIFF.EXE.

    When SYSDIFF.EXE completes, dump_file is a plain text file containing a list of file, .INI file and registry changes made to the system by the target application. Now you are ready to get the upgrade registry entries.

To determine registry entry differences between an upgraded computer (from Windows 9x to Windows NT 5.0) and a newly installed Windows NT 5.0 computer:

  1. Install Windows 9x on a computer

  2. Install your application

  3. Upgrade the computer using WINNT32.EXE

  4. Log on to the Windows NT 5.0 computer

  5. Run REGEDIT32.EXE or REGEDIT.EXE

  6. Compare the registry values listed in dump_file obtained during the final call to SYSDIFF.EXE and those listed in the registry. The differences are those you will need to resolve.

Note   This procedure is different because SYSDIFF does not work across platforms.

Check Network Availability

The network is not available to Setup during the Windows 9x phase of the upgrade process, but it will not be available during the Windows NT phase. Your migration DLL must not try to access the network during the Windows NT portion of the migration.

Avoid User Interfaces

Your migration DLL should not have a user interface. A parent window handle is provided only for the extreme case where a user interface is unavoidable. If Setup provides a NULL parent window handle, the DLL must never display any windows, dialogs, popups, or messages boxes. The migration DLL must never display a user interface on the Windows NT side of Setup.

This is extremely important when Setup is running in unattended mode. You can determine the Setup mode by testing the value of the ParentWnd parameter in either MigrateUser9x or MigrateSystem9x.

The installation process should be as hassle-free as possible. If the User Interface is required at any point during an attended installation, consider the usability implications when someone must load multiple migration DLLs.

Storing Private Data

Each migration DLL is copied to unique working directory. Your migration DLL may store private Windows 9x configuration information in this directory, as well as other run-time or data files required for the migration.

This directory is the only location to which your migration DLL should write when it is running on Windows 9x. Setup deletes this working directory after all migration DLLs have completed, and after Windows NT is successfully installed.

Handling Special String Characters

When writing messages, paths, and registry locations to an INF file, your migration DLL may need to pass certain characters that have special meanings to Setup and to the operating system. When writing messages or paths, the string must be enclosed in double-quotes if it contains any of the following:

"

%

,

;

[

]

In addition, embedded percent and double quote characters must be formatted properly before the string is written to the INF file. For example,

This "example" illustrates how to escape the percent (%) symbol

Must appear in an INF file as

"This ""example"" illustrates how to escape the percent (%%) symbol"

When writing registry locations to an INF file, you must replace the characters listed below as well as all characters with ASCII values greater than 127 (including double-byte characters) with their hexadecimal values enclosed in tilde (~).

Character Hex value
" 0x22
% 0x25
, 0x2C
; 0x3B
[ 0x5B
] 0x5D
~ 0x7E

For example, replace a semicolon (;) with the string ~3B~ .

Using the Setup Answer File

Setup passes the location of its answer file (UNATTEND.TXT) to your migration DLL in the MigrateUser9x, MigrateSystem9x, MigrateUserNT, and MigrateSystemNT functions.

Your migration DLL can modify this answer file during the Windows 9x portion of the upgrade process by using the Win32 profile APIs (such as WritePrivateProfileString). Your DLL is permitted to change standard answer file settings and create private sections for its own use. Note that it may not modify the following sections of the UNATTEND.TXT file.

[Unattended]]
[MassStorageDrivers]
[DisplayDrivers]
[KeyboardDrivers]
[PointingDeviceDrivers]
[OemBootFiles]
[OEM_Ads]
[GuiUnattended]
[UserData]
[LicenseFilePrintData]
[Display]
[Modem]

Note   This list will change before Beta 2. See the win95upg.inf (Answer File Restrictions) on the Windows NT CD.

For a detailed description of answer file parameters, search the Microsoft Knowledge Base database at http://www.microsoft.com/kb/.

If you require a private section, your DLL should build the section name from the working directory passed to it by the Initialize9x function. The private section name may only contain alphanumeric characters (A-Z and 0-9). Spaces and other characters are not permitted because they prevent Windows NT Setup from starting the text-only portion of the installation.

During the Windows NT portion of the upgrade, your migration DLL must treat the UNATTEND.TXT file as a read-only file. You must not modify the answer file in any way.

Windows 9x upgrade answer file parameters

To support the Migration Extension Interface, the Windows 9x Upgrade section has been added to the UNATTEND.TXT answer file. (Note that this is subject to change before Beta 2.)

Attended = [Yes|No]

Default value is Yes. Attended specifies if the upgrade is running in attended mode or not. When set to No, Setup assumes default values for the rest of the Windows 9x Upgrade section parameters:

MigrationDllPath = <path>

Specifies a local or UNC path to migration DLLs. Setup will search this directory and its subdirectories for migration DLLs.

ReportOnly = [No|Yes]

Default value is No. This parameter forces Setup to generate a compatibility report and then terminate without upgrading the computer.

SaveReportTo = <path>

Default is the local computer system drive (generally C:\). Specifies a local or UNC path (not a file name) to the desired location of Setup’s compatibility report files (HARDWARE.TXT and SOFTWARE.TXT). HARDWARE.TXT contains the hardware compatibility report. SOFTWARE.TXT contains the software compatibility report.

AppendComputerNameToPaths = [No|Yes]

Default value is No. This key is used to specify whether the computer name should be appended to the path to which the compatibility reports are to be saved. The directory is created if it does not already exist. For example, if SaveReportTo = C:\reports and the computer name is Testcomp, the reports would be saved to C:\reports\Testcomp.

Deferring Application Migration

If your application is network-based, it may not be practical for your migration DLL to copy your migration files from a network location to every local computer that has installed the Windows 9x version.

Instead, your migration DLL can redirect the application’s shell links to a new executable. This way, when a user launches the application, the new executable runs instead. This executable is responsible for completing the migration from the network location to that user's local machine in the user’s logged-on, network-accessible context on Windows NT. If you choose this approach, all your migration DLL needs to do is to copy the new executable to the local hard disk, and redirect all shell links from the original target application to this new executable. (You accomplish this through an entry in the [Moved] section of MIGRATE.INF).

The new executable must complete the migration when a user runs it on Windows NT. It must restore the original shell links, delete itself, and then run the newly migrated application. For more details on how to replace links, see the Shell Link documentation in the Win32 SDK.

See Also: [Moved] Section

Logging Errors

Windows NT Setup automatically logs errors returned by your migration DLL code. To log the errors your migration DLL detects, you must use the new Setup API function SetupLogError:

BOOL
SetupLogError (
   IN LPCTSTR MessageString,
   IN LogSeverity ErrorSeverity
   );

Parameters

MessageString

Error message string to be saved to Windows NT Setup’s action log (saved to %Windir%SETUPACT.LOG).

ErrorSeverity

Specifies the severity of the error to be logged. The error can have one of the following values, listed in increasing order of severity.

Remarks

If ErrorSeverity level is any one of LogSevWarning, LogSevError, or LogSevFatalError, a copy of the error message will also be saved to the %Windir%SETUPERR.LOG file.

Before logging an error, the log file must be opened using SetupOpenLog. SetupCloseLog must be used to close it after the error is written.

Note   Opening and closing a log file can be done in the DLLMain function of a migration DLL. See the sample source code for examples.

Using the Win32 Profile APIs

The Win32 Profile APIs (GetPrivateProfileString and WritePrivateProfileString) use a separate cache than the one used by SetupOpenInfFile. Therefore, if you open MIGRATE.INF using SetupOpenInfFile and then (before closing it) modify the file using WritePrivateProfileString, your changes will not appear in SetupOpenInfFile’s cache.

As such, care must be taken when using both the Win32 Profile APIs and the Setup APIs. Ideally, their use must be separated.

If you modify MIGRATE.INF using WritePrivateProfileString, you must call WritePrivateProfileString again with all NULL parameters to force the file to be written to disk before you open it again using SetupOpenInfFile.

If a file has already been opened with SetupOpenInfFile is already open, do not call WritePrivateProfileString to modify the same file.

Restarting Setup

The GUI-mode portion of Windows NT Setup may be restarted in case of a critical interruption (such as a power failure) during the upgrade. Your migration DLL should be prepared to handle this scenario. For example, before moving files, the DLL must check to see if the file has already been moved. Of course, this is standard programming practice, and the extent of your fail-safe functionality is mostly determined by the complexity of your migration process.

Testing a Migration DLL

Applications that do not survive migration from one version of Windows to another will not comply with Windows logo requirements. Your migration DLL can help to preserve your logo compliance.

The Setup program attempts to detect conflicts that arise from implementing your application under the new operating system. It may or may not succeed in identifying inconsistencies. Because of this, you should test your application extensively under various migration scenarios.

The migration functionality is provided to enable you to ensure that your customer base can use your application under the new operating system. You should test how your application behaves under different versions of Windows. Ideally, it behaves the same under different versions.

If conflicts exist, you have two options. You can either correct the intrinsic problem so that no problems occur during migration, or you can create a migration DLL. If you do not take advantage of the Migration Extension Interface, your customers will need to reinstall your application for it to run correctly under the newly installed system.

Migration DLLs must be thoroughly tested before being distributed to end users by means of the Web or other media. The following procedures outline the minimal process you should undertake during your test. Note that you should repeat the tests for multiple user account scenarios (default, roaming, workgroup, and domain users). The scenarios should also cover combinations of these user accounts.

To test your migration DLL under an attended upgrade:

  1. Install a version of Windows 9x on a computer.

  2. Install the target application on the computer.

  3. Start Windows NT Setup and select the Upgrade option on the Welcome page.

  4. Insert the media containing the migration DLL when prompted.

  5. Complete Windows NT Setup.

  6. Launch the migrated application on Windows NT.

  7. Run any test suites to determine if application is fully functional.

To test your migration DLL under an unattended upgrade:

  1. Install a version of Windows 9x on a computer.

  2. Install the target application on the computer.

  3. Place the migration DLL in a subdirectory of %windir%\setup\win95upg.

  4. Start Windows NT Setup in unattended mode with the “Win95Upgrade = Yes” key set in the answer file.

  5. Complete Windows NT Setup.

  6. Launch the migrated application on Windows NT.

  7. Run any test suites to determine if the application is fully functional.

Migration DLL Function Reference

QueryVersion

Setup uses QueryVersion to determine if further processing of the DLL is necessary.

LONG
CALLBACK 
QueryVersion (
   OUT LPCSTR *ProductID,
   OUT LPUINT DllVersion,
   OUT LPINT *CodePageArray,   OPTIONAL
   OUT LPCSTR *ExeNamesBuf,   OPTIONAL
   OUT PVENDORINFO *VendorInfo
   );

Parameters

*ProductID

Points to a string that identifies the DLL and its target application. To ensure uniqueness, the string must contain the name of the manufacturer, the product name, and the version number of the application the DLL will migrate. The length of the string must not exceed MAX_PATH bytes (as defined within your migration DLL). Setup ignores excess characters. The ProductID string is also used for error messages generated during DLL processing.

Note   Your migration DLL is responsible for allocating and freeing the ProductID string buffer.

DllVersion

Points to a non-zero unsigned integer that specifies the version number of your migration DLL. Setup looks for duplications by comparing ProductID strings from other migration DLLs. If two or more DLLs have identical ProductID strings, Setup uses the DLL with the highest DllVersion number and ignores the other duplicates.

Note   DllVersion is not intended to be the DLL’s binary version number.

CodePageArray

Points to an array of integers containing all the code pages supported by the migration DLL. The last element of the array must be -1. If your migration DLL does not support the system code page, Setup skips your migration DLL and your application will not migrate to the new operating system.

If this pointer is NULL, Setup processes all the required functions in the DLL regardless of the installed Windows 9x code pages. Set this pointer to NULL if the DLL has no language dependencies.

Note   Your DLL is responsible for the allocating and freeing memory used by this array.

ExeNamesBuf

Points to a multi-sz string buffer containing a list of filenames (not paths), that your migration DLL wants Setup to locate. Setup locates all instances of the listed files and returns the list of full file paths to your migration DLL via the MIGRATE.INF file. Paths to files located on network, substituted, or compressed drives will not be returned to the DLL, because Setup does not search those drives. Other directories on the computer not related to the active Windows 9x installation may also be excluded.

Set this parameter to NULL if you do not want Setup to search for any particular files.

Note   Your migration DLL is responsible for allocating and freeing the ExeNamesBuf string buffer.

VendorInfo

Points to a data structure that contains your company name, contact information (phone number), web address and instructions you want to provide to the user. Setup will display this information to the user in the migration report and in error cases. The VendorInfo data structure is of the form:

typedef struct {
CHAR    CompanyName[256];
CHAR    SupportNumber[256];
CHAR    SupportUrl[256];
CHAR    InstructionsToUser[1024];
} VENDORINFO, *PVENDORINFO; 

Strings returned to Setup must be localized for the language version of Windows 9x running on the computer.

Note   The VendorInfo field will only be enforced for Beta 2 and beyond. A migration DLL written for Beta 2 will still run on Beta 1.

Return Values

All other return values (Win32 error values) are considered initialization errors. Setup will report the error to the user, clean up your migration DLL’s files, and ask the user to continue or cancel the Windows NT installation process.

An exception generated by a migration DLL causes Setup to report RPC error messages. Setup will provide more information in SETUPERR.LOG.

Remarks

Setup uses QueryVersion to determine if further processing of the DLL is necessary. During this call, your migration DLL (located on a floppy, compact disc, or network share) must provide Setup with the ProductID, DllVersion, CodePageArray and ExeNamesBuf information. At this point your migration DLL cannot make any changes to the system.

Your migration DLL should try to determine if the target application is installed on the computer, and then return the appropriate result from QueryVersion. The system unloads the migration DLL after QueryVersion returns. Setup copies it to the local hard disk and calls Initialize9x only if QueryVersion returns ERROR_SUCCESS.

During the call to QueryVersion, Setup finds all occurrences of files listed in the ExeNamesBuf string (if not NULL) and writes their locations to the [Migration Paths] section of MIGRATE.INF. These paths are then available to the other functions in your migration DLL.

Setup detects duplicate migration DLLs by comparing the ProductID strings of supplied DLLs. It only processes the DLL with the highest DLLVersion number. The user is not be notified of duplicates found.

Important: DllVersion number zero (0) is reserved for Windows NT Setup–provided migration DLLs. DLLs not supplied by Microsoft Windows NT with the Windows NT 5.0 compact disc must not use this value.

Initialize9x

Setup calls Initialize9x after relocating the migration DLL to the local hard disk.

LONG
CALLBACK 
Initialize9x (
   IN LPCSTR WorkingDirectory,
   IN LPCSTR SourceDirectories,
   LPVOID Reserved
   );

Parameters

WorkingDirectory

Points to the path of a Setup-supplied directory your migration DLL can use to store its private temporary data. This directory will contain MIGRATE.DLL and all associated files. Your migration DLL must write to this directory if it needs temporary data storage. Setup provides this directory again during the Windows NT phase of the upgrade process, and automatically deletes it after the upgrade is complete.

SourceDirectories

Points to the path of the Windows NT installation files. This path is a multi-sz string to enable you to specify multiple source directories. Normally, this directory is D:\I386 where D:\ is the CD-ROM drive on the computer.

Note   Compressed files on the Windows NT installation compact disc can be decompressed by using the Setup API functions SetupGetFileCompressionInfo and SetupDecompressOrCopyFile.

Reserved

Reserved for future use.

Return Values

All other return values (Win32 error values) are considered initialization errors. Setup reports the error to the user, cleans up your migration DLL’s files and asks the user to abort or continue the Windows NT installation process.

Exceptions generated by your migration DLL cause Setup to report RPC error messages. Setup provides more information in SETUPERR.LOG.

Remarks

Setup calls Initialize9x after relocating your migration DLL to the local hard disk. During this call, your DLL should try to detect its new installation. It should return ERROR_SUCCESS if it is ready to be called by Setup during the Windows NT portion of the upgrade. If the DLL returns ERROR_NOT_INSTALLED, Setup will stop processing it.

The current directory is set to the working directory and will not be changed by Setup during the processing of a migration DLL.

MigrateUser9x

Gathers information concerning the users, and saves private data to be used during the later call to MigrateUserNT.

LONG
CALLBACK 
MigrateUser9x (
   IN HWND ParentWnd, 
   IN LPCSTR AnswerFile,
   IN HKEY UserRegKey, 
   IN LPCSTR UserName, 
   LPVOID Reserved
   );

Parameters

ParentWnd

Specifies a handle to the parent window for any dialog boxes or windows that you may want your migration DLL to display.

Note   You should not display a user interface unless absolutely necessary.

If this parameter is NULL, Setup is running in an unattended mode and your DLL must not display user interface elements or prompt the user for input.

AnswerFile

Points to a copy of the Windows NT Setup answer file (typically UNATTEND.TXT) which is used to automate the installation of Windows NT. You can access this file using the Win32 profile APIs (for example, GetPrivateProfileString and WritePrivateProfileString). Some sections of this answer file cannot be modified by your DLL. For more information, see Using the Setup Answer File.

UserRegKey

Provides a registry handle to the user hive of the Windows 9x user specified in the UserName parameter. This user hive is equivalent to the user’s HKEY_CURRENT_USER (HKCU) when that user logs on. This handle is valid only within the scope of MigrateUser9x and is provided for user-specific information gathering purposes.

UserName

Provides the user name (e.g. “username”) for the Windows 9x user whose registry information is supplied through the UserRegKey parameter. A value of NULL refers to the default Windows 9x user account (the account used when a user accesses the system by skipping the logon process). UserName may also be “Administrator” even though Windows 9x does not have an administrator account. This allows a migration DLL to collect information for the Windows NT Administrator account to be created later.

Reserved

Reserved for future use.

Return Values

ERROR_SUCCESS if the target application is installed for the specified user. Also return ERROR_SUCCESS if your migration DLL needs further processing during the Windows NT phase.

ERROR_NOT_INSTALLED if your target application is not installed for the specified user account and that user’s registry does not require any processing. However, Setup will continue to call MigrateUser9x for the rest of the users, and MigrateSystem9x if this function returns ERROR_NOT_INSTALLED.

ERROR_CANCELLED if the user wants to exit Setup. You should specify this return value only if ParentWnd is not set to NULL.

All other return values (Win32 error values) are considered initialization errors. Setup reports the error to the user and prompts to abort or continue the upgrade.

Exceptions generated by your migration DLL cause Setup to report RPC error messages. Setup provides more information in SETUPERR.LOG.

Remarks

A DLL must always check for the value of ParentWnd in MigrateUser9x before proceeding since its value determines whether UI can be displayed to the user.

Do not use the MigrateUser9x function for user account modification. Use it only for information gathering about user accounts. To modify user-specific settings, save the data collected to your provided working directory and then use the MigrateUserNT function to perform the modifications.

Use the DLL working directory provided by the Initialize9x WorkingDirectory parameter to store any user-specific configuration information you may want to keep track of. Remember to use the UserName parameter to differentiate the information about the various users.

MigrateSystem9x

Gathers system-wide information concerning the target application, and saves private data to be used during the later call to MigrateSystemNT.

LONG 
CALLBACK 
MigrateSystem9x (
   IN HWND ParentWnd, 
   IN LPCSTR AnswerFile,
   LPVOID Reserved
   );

Parameters

ParentWnd

Specifies a handle to the parent window for any dialog boxes or windows that your migration DLL may want to display.

Note   You should not display a user interface unless absolutely necessary.

If this parameter value is NULL, Setup is running in an unattended mode and your DLL must not prompt the user for input. Therefore, the ParentWnd value determines whether ERROR_CANCELLED can be returned from this function.

AnswerFile

Points to a copy of the Windows NT Setup answer file, UNATTEND.TXT. This file is used to automate the installation of Windows NT and can be accessed using the Win32 profile APIs, such as GetPrivateProfileString and WritePrivateProfileString. For more information, see Using the Setup Answer File.

Reserved

Reserved for future use.

Return Values

All other return values (Win32 error values) are considered initialization errors. Setup reports the error to the user and asks to abort or continue the upgrade.

Exceptions generated by your migration DLL cause Setup to report RPC error messages. Setup provides more information in SETUPERR.LOG.

Remarks

Your DLL must always check for the value in ParentWnd before proceeding, since its value determines whether user interface elements can be displayed to the user.

Do not use this function to modify the system. Use it for system-wide information gathering only. To modify system-wide settings, save any private data collected in your migration DLLs working directory (specified in an earlier call to Initialize9x). Use MigrateSystemNT to perform the modifications during the Windows NT portion of the upgrade.

InitializeNT

This function is called during Windows NT GUI Mode Setup when the Windows NT phase of the upgrade is ready to start.

LONG
CALLBACK 
InitializeNT (
   IN LPCWSTR WorkingDirectory,
   IN LPCWSTR SourceDirectories,
   LPVOID Reserved
   );

Parameters

WorkingDirectory

Points to the path of the Setup-supplied working directory. This value is the value that your migration DLL used for storing its private temporary data and files during the Windows 9x phase of the upgrade.

SourceDirectories

Points to the path of the Windows NT installation files. This path is a multi-sz because multiple source directories can be provided. Normally this directory is D:\I386 or C:\$WIN_NT$.~LS\I386 where D:\ is the CD-ROM drive on the computer and C:\$WIN_NT$.~LS\I386 is Setup’s temporary source directory.

Reserved

Reserved for future use.

Return Values

ERROR_SUCCESS if your migration DLL initializes properly within the Windows NT environment.

All other return values (Win32 error values) are considered critical errors. Setup reports the error to the user and then cancels processing your migration DLL. However, Setup will not continue the upgrade. Any errors or logs generated will include the ProductID string specified in QueryVersion to identify your DLL.

Exceptions generated by your migration DLL cause Setup to report RPC error messages. Setup provides more information in SETUPERR.LOG.

Remarks

InitializeNT is called during Windows NT GUI Mode Setup, when the Windows NT phase of application migration is ready to start. When this function is called, the current directory is set to the DLL’s working directory.

Your migration DLL must not display user messages in its InitializeNT function.

MigrateUserNT

Migrate the user accounts that port from Windows 9x to Windows NT.

LONG
CALLBACK 
MigrateUserNT ( 
   IN HINF AnswerFileHandle,
   IN HKEY UserRegKey,
   IN LPCWSTR UserName, 
   LPVOID Reserved
   );

Parameters

AnswerFileHandle

INF handle to the answer file being used for the upgrade process. This file contains settings generated by Setup, the attending user, and all migration DLLs. You can access the file referenced by this handle using the Setup functions. Do not close this handle at any time.

UserRegKey

A registry handle to the private registry settings of the Windows 9x user specified in UserName. This handle is equivalent to HKEY_CURRENT_USER (HKCU) when that user is logged on. The handle is only valid within the scope of MigrateUserNT. Do not close this handle at any time.

UserName

The user name for the user whose registry information is supplied through the UserRegKey parameter. If this value is NULL, Setup is referring to the Windows NT logon account. The Windows NT logon account is used for creating the desktop settings for the Windows NT logon prompt and as a template for creating new Windows NT users.

Reserved

Reserved for future use.

Return Value

Other error codes will terminate the processing of your migration DLL. However, Windows NT Setup will proceed. Ideally, only critical problems (such as a hardware failure) should generate terminating error codes.

Exceptions generated by your migration DLL cause Setup to report RPC error messages. Setup provides more information in SETUPERR.LOG.

Remarks

The order in which user names are passed to your migration DLL during the call to MigrateUserNT may be different than the order in which they were passed during the call to MigrateUser9x.

Setup may disable migration of one or more user accounts if errors occur. For this reason, the number of user names passed to MigrateUserNT may be less than the number passed to MigrateUser9x.

Your migration DLL is responsible for managing its private data created and stored during MigrateUser9x and processed during MigrateUserNT.

Your migration DLL must not display user messages within its MigrateUserNT function.

MigrateSystemNT

LONG
CALLBACK 
MigrateSystemNT ( 
   IN HINF AnswerFileHandle,
   LPVOID Reserved
   );

Parameter

AnswerFileHandle

INF handle to the answer file being used for the upgrade process. This file contains settings generated by Setup, the attending user, and all migration DLLs. You can access the file referenced by this handle using the Setup functions. Do not close this handle at any time.

Reserved

Reserved for future use.

Return Value

Other error codes will terminate the processing of your migration DLL. However, Windows NT Setup will proceed. Ideally, only critical problems (such as a hardware failure) should generate terminating error codes.

Exceptions generated by your migration DLL cause Setup to report RPC error messages. Setup provides more information in SETUPERR.LOG.

Remarks

Your migration DLL is responsible for managing its private data created and stored during MigrateSystem9x and processed during MigrateSystemNT.

Your migration DLL must not display user messages in its MigrateSystemNT function.

The MIGRATE.INF File

During the Windows 9x phase of the upgrade, Windows NT Setup creates and uses MIGRATE.INF files to collect file information from all migration DLLs. During the Windows NT portion of the upgrade, Setup uses this same file to provide that information back to the submitting migration DLL.

Each working directory passed to a migration DLL has a MIGRATE.INF file in it. The sections are:

Section Description
[Version] This is a generic section required for every Windows 9x-style INF. It contains information about the version of Windows NT being used for the upgrade. Setup writes to this section.
[Migration Paths] This section contains a list of Win32 paths to files requested by your migration DLL through the QueryVersion function ExeNamesBuf parameter. Each line represents the full path to a file. Setup writes to this section.
[Excluded Paths] This section contains a list of paths not part of the active Windows 9x system configuration. Setup does not search through any of these paths or their subdirectories. Excluded paths include directories on the system drive used by other operating systems, network drives, and substituted or compressed drives. Setup writes to this section.
[Handled] You use this section to inform Windows NT Setup about files, directories and registry entries in the active Windows 9x installation you intend to migrate using your migration DLL.

Setup assumes that files, directories, and registry entries listed here are compatible with Windows NT 5.0. Therefore, users will not be warned about incompatibilities associated with these components. All file names, directories, and registry entries listed in this section must be valid on the active Windows 9x system.

You can use the WritePrivateProfileString function for adding lines to this section.

[Moved] You use this section to inform Windows NT Setup about files and directories you plan to move, rename, or delete during the migration. This enables Setup to adjust the relevant Windows NT Explorer shell links.

You can use the WritePrivateProfileString function for adding lines to this section.

[Incompatible Messages] You use this section to present messages to a user through the Setup incompatibility report (displayed during the Windows 9x phase of the upgrade process). The report is presented to the user before any changes are made to the computer, and is useful when you intend to change the behavior of an application, or when you plan to remove application components.
[<Message Object Section>] A message object section provides a mechanism for you to associate one or more message objects (file, directory, and registry location) with a message specified in the [Incompatible Messages] section.
[NT Disk Space Requirements] You use this section to specify the amount of disk space (on a per drive basis) your migration DLL requires during the Windows NT phase of the upgrade. Setup uses this information to calculate the total amount of space required for the upgrade. If sufficient space is unavailable, Setup informs the user accordingly during the Windows 9x phase of the upgrade.

[Version] Section

This is a generic section required for every Windows 9x-style INF. It contains information about the version of Windows NT being used for the upgrade. Your DLL cannot modify it.

Signature = <File Signature>

The signature of the file. For example, $Windows NT$. This is the default.

SetupOS = <OS Identifier>

OS Identifier specifies the operating system. For the upgrade, this value is Microsoft® Windows NT® Operating System.

SetupPlatform = <Platform Identifier>

Platform Identifier specifies the object Windows NT platform upgrade. The value can be either Workstation or Server.

SetupBuild = <Build Identifier>

Build Identifier specifies the object Windows NT build upgrade. This value will be 1382 or higher (depending on the build).

See the Win32 SDK for details on the non-migration information that may be contained in the [Version] section of Windows 9x-style INFs.

[Migration Paths] Section

This section contains a list of Win32 paths to files requested by your migration DLL through the QueryVersion function ExeNamesBuf parameter. Each line represents the full path to a file. Setup writes to this section.

Your migration DLL can read the file paths listed here using the Setup API functions SetupGetLineCount and SetupGetLineText.

If multiple copies of a particular file name are found (such as versions installed by other applications), multiple paths to the file name will be listed in this section. When this happens, it is up to your migration DLL to determine which executables are valid for migrating your application.

If a file is not found in the active Windows 9x system, it will not be listed.

[Excluded Paths] Section

This section contains a list of paths that are not part of the active Windows 9x system configuration. Setup does not search through any of these paths or their subdirectories. Excluded paths include directories on the system drive used by other operating systems, network drives, and substituted or compressed drives. Setup writes to this section.

If your application is installed in any one of the paths listed in this section, your DLL must consider the application as not installed and must return ERROR_NOT_INSTALLED when initializing.

Your migration DLL can read the paths listed in this section using the Setup API SetupGetLineCount and SetupGetLineText functions. You can then use string matching to determine if a path you need is excluded. Your DLL must never make changes to the directories listed in this section.

[Handled] Section

You use this section to inform Windows NT Setup about files, directories, and registry entries in the active Windows 9x installation you intend to migrate using your migration DLL.

Setup assumes that files, directories, and registry entries listed here are compatible with Windows NT 5.0. Therefore, it shall not warn users about incompatibilities associated with these components, nor will any processing be performed. For example, specifying a file path to a file in the system directory will cause it not to be moved to system32. Similarly, "handled" registry entries will not be copied to NT.

All file names, directories and registry entries listed in this section must be valid on the active Windows 9x system.

You can use the WritePrivateProfileString function to add lines to this section.

The syntax for lines in this section is:

<Identifier Object> = <Identifier Type>

where:

Identifier Object

Specifies the name or path to a Windows 9x file, directory or registry location. Files and directories are in long file name format. Registry paths are of the form:

<Root>\<SubKey>\<SubKey>\<…> [<Value Name>]

where:

Root

Specifies the registry root. It can be any one of HKEY_LOCAL_MACHINE, HKLM, HKEY_ROOT, or HKR (migration DLLs can only handle a registry key for ALL users, not for individual users).

SubKey

Specifies one or more registry keys separated by back slashes (\).

Value Name

(Optional) Specifies a registry value name enclosed in square brackets. An empty square bracket ([ ]) specifies the default value for the specified key name.

Registry keys or value names themselves may contain square brackets ([ ]), tildes (~) or characters with values greater than 127. You must enclose hexadecimal value for these characters in tildes (~) when writing them as registry values to the [Handled] section. For more information, see Handling Special String Characters.

Identifier Type

Identifies the type of <Identifier Object> to be handled. It must be one of the following three values:

File

The object specified refers to a long file name (including the full path to the file). This must be a full path, without environment variables, and without short versions of long file names.

Directory

The object specified refers to a directory (including the full path to the directory).

Registry

The object specified refers to a registry key (including the full path to that key).

[Moved] Section

Use this section to inform Windows NT Setup about files and directories you plan to move, rename, or delete during the migration. This enables Setup to adjust the relevant Windows NT Explorer shell links.

You can use the WritePrivateProfileString function for adding lines to this section. Listing a file here will keep it from being processed in any other way, just as it was in the [Handled] section.

The syntax for this section is:

<OldPath> = <NewPath>

where:

OldPath

Specifies the filename or path of a Windows 9x file or directory to be moved or deleted. Filenames and paths are in long file name format.

NewPath

Specifies the new filename or path, again in long file name format. If NewPath is empty or not specified, Setup will delete OldPath.

[Incompatible Messages] Section

Use this section to present messages to a user through the Setup incompatibility report (displayed during the Windows 9x phase of the upgrade process). The report is presented to the user before any changes are made to the computer, and is useful when you intend to change the behavior of an application, or when you plan to remove application components.

The syntax for this section is:

<Message Object Section> = <Message>

where:

Message Object Section

Specifies the name of a custom section (defined by your migration DLL) that contains a list of message objects, such as files, directories, and registry entries. The name may be any combination of uppercase and lower case letters, numbers, and spaces. It may not start or end with a space. By listing one or more message objects in a separate section, your DLL can associate several message objects with a single message. The value for Message Object Section is used as the component string in the compatibility report presented to the end user.

Message

A string describing the details of the incompatibility or message to be displayed to the user. The user will see the text in a multi-line, scrollable, read-only edit control.

For example, this incompatibility section may contain the following line:

MyAppMsg = "The DOS and Real-mode portions of Myapp.exe are not supported on Windows NT"

Where MyAppMsg refers to another section containing the list of files, directories and registry entries associated with the message string.

Notes

When you write an entry to the [Incompatible Messages] section, a Message Object Section must provide one or more objects associated with the message.

Your migration DLL is responsible for managing the code page and language dependencies of the messages listed in this section. In particular, the text in the [Incompatible Messages] section must be in the same language as the active Windows 9x system. Your DLL must not write messages to this section if it does not support the active operating system language.

The user has an option to view, print, or save the incompatibility report generated. This report will associate the ProductID with each Message.

[<Message Object Section>] Section

A message object section provides a mechanism for you to associate one or more message objects (file, directory, and registry location) with a message specified in the [Incompatible Messages] section. The [Handled] section describes how to specify a message object.

The section name is defined by your migration DLL. Each line has the following syntax:

<Message Object> = <Identifier Type>

where:

Message Object

Specifies a Windows 9x file, path or registry entry. A file or path must be specified in long filename format.

Identifier Type

Identifies the type of <Message Object>. It can only have one of the following three values:

File

The object specified refers to a long file name (including the full path to the file).

Directory

The object specified refers to a directory (including the full path to the directory).

Registry

The object specified refers to a registry key (including the full path to that key).

Notes

Setup uses the value for Message Object Section to develop a hierarchy for incompatibility messages. The use of the section name enables your migration DLL to organize multiple incompatibility messages in the same format that Setup uses. Setup processes the section name in one of two ways:

  1. If the name of the section matches ProductID, Setup displays the message at the root level of the incompatibility message tree. The ProductID itself is listed in a tree control, and when the user clicks on the root item, the incompatibility message is shown in an edit control.

  2. If the name of the section contains one or more backslashes, Setup separates the string at the backslashes to create the hierarchy. Setup limits the number of levels in the tree to 10. Optimally, you should organize your messages into three levels.

    Using the section name in this way achieves unique children for each migration DLL, organized under a single item at the root. Because ObjectSection is used for display purposes, your DLL must provide localized strings.

    Setup treats all objects in a section as a set. If every object in the set is found in any [Handled] section (including ones provided by other vendors), no incompatibility message will be displayed for the particular object, even if the message is listed in [Incompatible Messages]. If only some or none of the objects are handled, the message will be displayed.

[NT Disk Space Requirements] Section

You use this section to specify the amount of disk space (on a per-drive basis) your migration DLL requires during the Windows NT phase of the upgrade. Setup uses this information to calculate the total amount of space required for the upgrade. If insufficient space is available, Setup informs the user accordingly during the Windows 9x phase of the upgrade.

The syntax for this section is:

<DriveLetter> = <Space Required>

where:

DriveLetter

Specifies the drive/partition (single letter without a colon or backslash) in which a migration DLL requires space for its private data. Setup will ignore drives/partitions that are also listed in the [Excluded Paths] section.

Space Required

Is an integer that indicates the amount of disk space in (bytes) required by a migration DLL during the Windows NT phase of Setup. When calculating space requirements, the amount of space lost from directory and cluster use must be taken into account. The number does not include the files copied into the working directory during the Windows 9x phase.

If this section is not present, or if no drives or partitions are specified, Setup assumes that the migration DLL requires no additional hard disk space to migrate the target application.

Important: Be sure to specify the correct disk space requirement data. If you cannot calculate disk space requirements accurately, you should provide a liberal estimate of the space required.

Sample Migrate.inf file

;
; Sample migrate.inf file
;
[Version]
Signature = $Windows NT$
SetupOS = Microsoft(R) Windows NT(R) Operating System
SetupPlatform = Workstation
SetupBuild = 1610

[Migration Paths]
"c:\windows\foo.exe"
"c:\temp\foo.exe"
"C:\program files\foo\bar.exe"
"C:\foofiles\bar.exe"

[Excluded Paths]
"c:\winnt40"
"f:\"

[Handled]
"C:\windows\foo.exe"=File
"C:\windows\foo.dll"=File
"c:\Program Files\foo"=Path
"HKLM\Software\Foo-Bar, Inc."=Registry

[Moved]
;moved
"c:\dir\boo.exe"="c:\dir\nt\boo.exe"

;moved and replaced 
"c:\Windows\foo.exe"="c:\Windows\foo\foo_nt.exe" 

;deleted 
"c:\Windows\foo\Win9x"="" 

[Incompatible Messages]
;the message must be on one line, but can be long
Foo-Bar ="The application Foo-Bar does not support the DOS component 'boo' on Windows NT."

[Foo-Bar]
"C:\dir\boo.exe"=File
"C:\dir\boo.dll"=File

[NT Disk Space Requirements]
c=104096
d=16384