Avoiding Conflicts When Running Windows 95 Applications on Windows NT 4.0


Microsoft Corporation

November 1996

Summary: In general, most applications developed and tested on the Microsoft® Windows® 95 operating system will run without modification on the Microsoft Windows NT® Workstation 4.0 and Microsoft Windows NT Server 4.0 operating systems. Many Windows 95–based applications will also run on Windows NT version 3.51. However, a much higher percentage of applications written for Windows 95 will work on Windows NT 4.0 because this version of Windows NT includes the Windows 95 user interface (UI).

Some applications developed for Windows 95 may not perform as expected when run on Windows NT. A few common coding errors cause most of these problems. Developers can ensure that their applications work on all Microsoft 32-bit operating systems by following API calling conventions, avoiding legacy algorithms and code written for 16-bit environments, and using the guidelines in this paper.


Following 32-Bit API Conventions
Interpreting the Operating System Version
Hard-Coded Paths
Common Issues: Long File and Printer Names
Common Issues: DLLs
Common Issues: Large Drives
Common Issues: Coding Practices
Differences Between Windows 95 and Windows NT
For More Information


Microsoft Windows 95, Windows NT Workstation 4.0, and Windows NT Server 4.0 are all 32-bit operating systems that use the same Win32® application programming interface (API). This API has changed and expanded to encompass new features, and code should in most cases work without modification on all three operating systems. However, developers sometimes find that a program that runs bug-free on Windows 95 has problems running on Windows NT.

Some of the problems are caused by failure to follow the API calling rules and conventions. Windows NT strictly enforces 32-bit handles, API parameters, and memory ownership among multiple threads. Windows 95 may be more tolerant of poor 32-bit coding practices because it must support legacy 16-bit driver code.

Misinterpreting the operating system platform causes some programs to make Windows 95–specific procedure calls when running on Windows NT. For example, hard-coded executable paths or registry keys that are not identical on Windows 95 and Windows NT have been known to cause problems.

Bugs in applications written for both systems have been reported, although circumstances tend to hide them on Windows 95. Some applications fail to deal properly with long file and printer names. Others fail to install required dynamic-link libraries (DLLs) or to replace system DLLs with files for the wrong platform. Developers may use poor coding practices that cause users problems on both Windows 95 and Windows NT.

There are some differences between Windows 95 and Windows NT that applications must accommodate to run successfully. For example, the user's permissions and rights are inherited by applications the user starts. The applications may not be able to perform expected tasks on Windows NT if the user has insufficient rights. As another example, Windows NT is a Unicode operating system, which means that programs designed only for Windows 95 may pass ANSI data when Windows NT expects Unicode or treat Unicode data as ANSI.

Following API conventions, using code reviews and debugging tools to eliminate legacy 16-bit-based code and algorithms, and specifying flexibility in application design that allows programs to adapt to the features of both Windows 95 and Windows NT will provide users with robust products that run well in all 32-bit Windows environments.

This paper was developed as a result of Microsoft's own internal experiences in testing a wide range of 32-bit applications during the development of the Windows NT 4.0 operating system.

Following 32-Bit API Conventions

32-Bit Handles

Windows 95 and Windows NT are 32-bit operating systems. Both use 32 bits for handles to resources. To accommodate legacy code, Windows 95 accepts 16-bit handles and generates all 32-bit handles with the high 16 bits set to zero.

Figure 1. Windows 95 accepts and generates 32-bit handles with all zeroes in the high 16 bits.

Windows NT 3.x uses all 32 bits for handles. To accommodate legacy code, Windows NT 3.x will accept a 16-bit handle and try to match it to the low 16 bits of all open handles. If a match is found on the low 16 bits, Windows NT 3.x uses that 32-bit handle in place of the 16-bit handle. To avoid duplicating an existing 32-bit handle with a truncated or 16-bit handle, Windows NT always creates handles with at least one high bit set.

Windows NT 4.0 requires full 32-bit handles. It will not accept 16-bit handles. All 32 bits are used to identify handles. Any code that does not correctly accept and return 32-bit handles will fail on Windows NT 4.0.

If the application casts a Windows NT 4.0–supplied handle to 16 bits, Windows NT 4.0 will not carry out any API calls using the truncated handle. Some programs truncate a handle-to-device context (hDC) to 16 bits and then use it to open a Print dialog box. On Windows NT 4.0, the dialog box never appears, so the user is unable to print anything. In other cases, a window may remain on top of the application work area because the handle passed to Windows NT 4.0 with the WM_DESTROY message is truncated. Windows NT 4.0 cannot identify the window to destroy because the handle is invalid. Some developers noted that the high 16 bits of all handles were always set to zero while developing programs on Windows 95. Thinking that was expected on all platforms, they added code to check for all handles to have zeroes in the high 16 bits. These programs fail when run on Windows NT 4.0, where all handles have at least one nonzero in the high 16 bits.

Incorrectly using 16-bit handles in a 32-bit operating system is often caused by porting legacy algorithms or using libraries intended for 16-bit environments. Algorithms should be subjected to careful code review to remove any 16-bit-specific implementations. As part of debugging tests, all handles should be validated as true 32-bit handles. When code is tested on Windows NT 4.0, all handles will have at least one of the high 16 bits set to a nonzero.

API Parameters

Windows NT includes functionality that is not available on Windows 95. Win32 APIs invoking those functions require parameters for the Windows NT features, even when run on Windows 95. Windows 95 ignores the parameters it can't use. Code tested only on Windows 95 can pass invalid values for the parameters used by Windows NT, which may cause the code to fail when run on Windows NT.

For example, calling the ChangeDisplaySettings function changes the driver refresh rate on Windows NT, a functionality that is not supported on Windows 95 drivers. Some applications change display settings and cache the current settings to be restored when the application is closed. If the application does not read and cache the refresh rate, an invalid value is passed to the function call when the display is reset on Windows NT. The driver then defaults to its lowest refresh rate when given an illegal value. Unless the user has, by coincidence, selected the lowest refresh rate, the display will be a different size than the user expected and will probably appear offset on the monitor.

To avoid these types of problems, it is important to test all code that makes function calls and holds returned parameters for later use to verify that all parameters passed from the call are read and cached, even parameters not used by the code or the operating system. Test all parameters passed from the application to function calls to make sure they hold legal values.

Memory Management

Windows NT strictly enforces memory management to maintain security and prevent processes and threads from interfering with each other. Allocated memory and resources may persist after the process or thread terminates, unless the memory or resource is specifically freed.

For (hFile = FindFirstFile(szBuffer, &FileInfo);
      hFile != INVALID_HANDLE_VALUE && bReturnValue;
   bReturnValue = FindNextFile(hFile, &FileInfo))
bReturn = RemoveDirectory(install_directory);

The RemoveDirectory call works as expected on Windows 95, but fails to remove the installation directory on Windows NT.

The preceding sample code is from an installation program. The program creates install_directory, expands temporary files into it, and uses the files to install the application. This fragment removes all temporary files and install_directory from the system. It loops using the FindNextFile function to delete the installation files from install_directory. Then it tries to remove install_directory. The directory is removed as expected on Windows 95. When the same code is run on Windows NT, the call returns ERROR_SHARING_VIOLATION, and the directory is not removed.

Even though FindNextFile returns a null handle when all files have been deleted, the hFile handle is still allocated in memory. Unless FindClose is called to close the handle, it remains open and Windows NT will not allow any process or thread to remove the folder associated with that handle. Windows NT protects all resources from arbitrary deletion by other processes and threads and requires developers to specifically free all resources they allocate.

Interpreting the Operating System Version

Background: GetVersion and GetVersionEx

Applications determine operating system platform, version, and build information by calling GetVersion or GetVersionEx. The GetVersion function returns information in a double word and GetVersionEx returns enumerated constants in a structure.

Figure 2. GetVersion returns platform, build number, and version coded in a DWORD.

Reading GetVersion Returns

When some Windows 95–based applications are run on Windows NT 4.0, they have problems caused by the incorrect use of the GetVersion function. On Windows 95, the two high bits (labeled "S" and "9" in the preceding diagram) are set (bit=1). All versions of Windows NT return zero in these two bits. Both Windows 95 and Windows NT 4.0 return major version "4" and minor version "0." If an application makes installation or internal path decisions based on platform, it must evaluate the platform bits and the version number to make the correct determination of Windows 95 or Windows NT.

Many applications verify only the operating system version number. It is assumed that only Windows 95 returns "4" as a major version number. When these applications find major version "4" returned by Windows NT 4.0, they install code that makes Windows 95–specific calls into KERNEL32.DLL. Because these procedures are not available on Windows NT, the calls fail and the application often fails as well.

Other applications test only the platform bits. They correctly determine that they are running on Windows NT, but their developers assume the platform must be Windows NT 3.x and that Windows 95 features, such as TAPI and the Windows Explorer shell, are not present. The applications either do not install or do not activate their features requiring those Windows 95 functions. In most cases, Windows NT 4.0 supports the same features as Windows 95 and the applications would run successfully.

Some applications interpret the platform incorrectly during installation and install files for Windows 95 or an older version of Windows NT, then the applications use different code after they start that correctly identifies the platform. The applications fail when they try to execute code they did not install.

Other applications require a specific version, or higher, of Windows NT, but do not correctly evaluate the version information. They test only the minor version number, expecting a value equal to or greater than the minimum version the applications required. The "0" in minor version is less than the value expected, and the applications fail to install.

A few applications test the platform bits, detect Windows NT, and assume version 3.x, with Windows NT 3.x–style common dialog boxes. Later, the applications determine that the Windows Explorer is present and set the OFN_EXPLORER flag for calling common dialog boxes. When the applications try to create certain common dialog boxes, they pass both the old-style structure and the OFN_EXPLORER flag. Windows NT expects to receive the new-style structure based on the OFN_EXPLORER flag and cannot read the old-style structure. The common dialog box (often the Save As dialog box) is never created and the critical Save function is unavailable to the user.

Specific build number tests should be avoided in applications. Programs will fail if they test for build "0" (as returned by the GetVersion function on Windows 95) or "950" (as returned by the GetVersionEx function on Windows 95). Windows NT 4.0 returns build numbers between "1058" and "1381" for both calls. Note that the Win32 Software Development Kit (SDK) identifies the build number bits as reserved for Windows 95 on calls to GetVersion. Code that tests for any specific return value may fail on future versions of Windows 95 as well as on Windows NT.

Using GetVersionEx

The GetVersion function has been superseded by GetVersionEx, which is the preferred call for new applications. The data is returned in an OSVERSIONINFO structure that's less easily misinterpreted than the individual bits in DWORD from GetVersion. For example, the platform is returned as an enumerated constant.

Table 1. GetVersionEx returns platform as one of three constants in dwPlatformID

Value Platform
VER_PLATFORM_WIN32s Win32s on Windows 3.1
VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95

The application must still get all the information it needs to determine operation system platform and version and use that information correctly.

Using IMAGECFG.EXE to Verify Version Problems

The IMAGECFG.EXE tool is useful for verifying version problems in applications. IMAGECFG adds information to the header of the application's executable file or DLL responsible for forcing Windows NT to return "incorrect" information from GetVersion and GetVersionEx calls in place of the "real" operating system information. Parameters to IMAGECFG give Windows NT the "incorrect" information to pass to the application. By specifying an earlier version of Windows NT or the version information associated with Windows 95, applications with version problems may install or function as expected. IMAGECFG will only write information to 32-bit headers.

C:>imagecfg  -w  c0000004  sample.exe 

After using IMAGECFG with the parameters shown in the preceding sample code, Windows NT returns "version 4.0, Windows 95" to SAMPLE.EXE when it calls GetVersion or GetVersionEx. The "-w" flag indicates that the next parameter is the desired GetVersion DWORD in hexadecimal: Win32s and Windows 95 bits set, build number zero, minor version "0," and major version "4."

IMAGECFG is located in the \SUPPORT\DEBUG\<PLATFORM> folder on the Windows NT compact disc. The SETNT351.CMD and SETWIN95.CMD command files in the same folder execute IMAGECFG with the correct parameters for Windows NT 3.51 and Windows 95. For more information, run IMAGECFG with the "-?" switch from a command prompt.

Warning   IMAGECFG writes information into the headers of .EXE and .DLL files that may adversely affect performance of the files. The changes may not be reversible. The tool should only be used on copies of files, never originals. While IMAGECFG has been tested extensively, Microsoft will not be responsible for direct or consequential damages resulting from its use on any file.

Testing for Future OS Versions with IMAGECFG.EXE

You can use IMAGECFG to identify version-specific dependencies in new applications you develop. By using a small build number and a high version number, you can trap errors caused by testing specifically for the information today's operating systems return.

C:>imagecfg  -w  00202306  sample.exe 

After using IMAGECFG, Windows NT will return "build 32, version 6.35 of Windows NT" to SAMPLE.EXE when it calls the GetVersion or GetVersionEx function.

Testing for Features, Not Version

Many problems with applications on Windows NT 4.0 can be avoided by testing for the existence of features required rather than a specific operating system or version. As Windows 95 and Windows NT mature, they will have more features in common. Some features may be added as service packs or in OEM service releases. The version number may remain the same, even though new features are present in the system.

Testing for required features instead of just the version when installing or starting an application gives the user the greatest flexibility when upgrading the operating system.

Hard-Coded Paths

Paths to Executable Files

The names and purposes of operating system executable files may change across versions or platforms. Function calls are available to start the executable files. Applications that avoid the function calls in favor of hard-coding the executable file name or path risk failing on different versions and platforms.

For example, WINHELP.EXE in the Windows 3.x operating system displayed version 1.0 Help files. It was installed by default in the %windir% directory. On Windows 95, the executable file with that same name is a stub that starts the appropriate Help engine, depending on the Help file version. Some developers use a hard-coded path to WINHELP.EXE in 16-bit applications to open version 1.0 Help files. The same code works on Windows 95 from the 16-bit applications and from 32-bit versions of those applications, even though they use version 2.0 Help files. Using the hard-coded WINHELP.EXE name gave the developers portability on Windows 95 for both 16-bit and 32-bit applications.

On Windows NT 4.0, WINHELP.EXE is the version 1.0 Help file engine, just as it is on Windows 3.x. On Windows NT, it provides compatibility with legacy 16-bit applications. If it is started with a version 2.0 Help file, it displays an error dialog box because the file is an unknown format. 32-bit applications with WINHELP.EXE hard-coded fail to display version 2.0 Help files on Windows NT 4.0, even though they work as expected on Windows 95.

The .HLP extension is associated with the proper Help engine on all operating systems. Creating a process using the .HLP file will start the correct Help engine on Windows 95 or Windows NT. By hard-coding the Help engine name instead, developers limit their applications to one version on one platform. If Windows 95 changes its WINHELP.EXE implementation, the applications may no longer function on that platform either. Applications that don't rely on a hard-coded executable file name will survive the change.

Hard-Coded Registry Keys

Instead of using function calls, some developers search the Windows 95 registry for needed information. When this information is located, the path to the key is hard-coded. For example, Windows 95 stores printer information in subkeys of HKEY_LOCAL_MACHINE:System\CurrentControlSet\Control\Print\Printers.

Some applications look at that key and assume the absence of any subkeys means that there is no default printer. The applications usually failed to start if there was no default printer installed. Windows NT uses a different registry location to store printer information. When run on Windows NT, these applications will fail, even though a printer is installed.

The GetProfileString function call returns the name of the default printer on all 32-bit operating systems. Using the API call will result in the proper application behavior.

Common Issues: Long File and Printer Names

Long File Names with Previously Illegal Characters

Both Windows 95 and Windows NT support file paths and printer names up to MAX_PATH characters long. (See the article "Making Room for Long File Names".) Although coding errors regarding long names are exposed by both operating systems, Windows NT is often used in business environments where such names are most common. Testing on Windows 95 may be inadvertently limited to short path and printer names or names that do not use some characters that were illegal on DOS, but permitted in 32-bit operating systems. In all cases, the same errors are exposed on Windows 95 and Windows NT if the same path and printer names are used.

Legacy Algorithms: Length

DOS file names require an "8.3" format. DOS path length is limited to 128 characters. Some legacy algorithms and library routines still assume the DOS limitations.

Some applications correctly allow the path to be up to MAX_PATH characters, but restrict the name of each folder and file to the 8.3 format. They parse for the backslash ("\") separator, then truncate folder names longer than 8 characters to the next dot (".") or backslash. An additional three characters may be accepted following a dot. Existing files with names longer than the 8.3 format allows cannot be found. When new files are created, they appear in new folders based on the truncated names of existing folders.

Legacy Algorithms: Accepted Characters

Several characters that are not accepted in DOS file, folder, and printer names are accepted under Windows 95 and Windows NT. In addition to the space (ANSI 0032), the following characters are now legal in names:

+ , . ; = [ ]

Legacy algorithms may not allow one or more of these characters in names. If users create files, folders, or printers outside your application, they may not be able to access those resources from your application if your algorithms retain any of the DOS limitations. Some applications have no problems with names longer than 8.3, but will not accept spaces in the names of folders and files.

Some applications use existing controls for file handling that, by design, do not allow all the legal characters. Microsoft Office 95, for example, uses an edit box in Save As dialog boxes. Edit boxes treat a semicolon (;) as a text separator. When the user tries to type a document path with a folder name containing a semicolon in the Save As dialog box, the edit box assumes the semicolon is a delimiter between two document names and displays an error dialog box.

Figure 3. Office 95 Save As dialog boxes use the semicolon as a delimiter. An error dialog box appears if the user enters a folder name that contains a semicolon.

Other applications, such as WordPad, use the system common dialog boxes that allow semicolons in folder and file names.

Testing Long File and Printer Names

Use the following guidelines to test your application for proper handling of long file and printer names (spaces are represented by the # character):

  • Allow periods, plus signs, commas, semicolons, equal signs, and square brackets anywhere.
  • Don't save leading or trailing spaces.
  • Don't save question marks.
  • Support MAX_PATH characters (including the drive, path, and extension).
  • Save to a universal naming convention (UNC) path, such as \\Server\Directory\Filename.
  • If your application uses a default extension, it should add the default extension automatically. For example, "TEST." will save as "TEST..EXT".
    C:\test#1234567890[on to MAX_PATH total length]
    test (saved as "test.ext")
    ###test (saved as "test.ext")
    test### (saved as "test.ext")
    ###..test..## (saved as "..test...ext")
    test#;#+#,#=#[#] (saved as "test#;#+#,#=#[#].ext")
    ####....####test.test####....## (saved as "....####test.test####.....ext")

Common Issues: DLLs


Neither Windows 95 nor Windows NT installs the MFC 30 (Microsoft Foundation Classes version 3.0) DLLs on a minimum installation because neither operating system requires the MFC 30 DLLs for its core functionality. Many applications used with Windows 95, such as WordPad, are MFC 30 applications, and they will install the MFC 30 DLLs. Because most Windows 95 users accept the default setup that installs WordPad, they will find MFC 30 DLLs on their systems.

Windows NT WordPad does not use MFC 30 DLLs, nor does any other application that ships as part of Windows NT. Unless the user installs Office 95 or other applications that also install the MFC 30 DLLs, your application cannot expect to find the DLLs on a Windows NT system.

Some Windows 95 applications need the MFC 30 DLLs, but fail to install them. These particular applications were tested by their developers on Windows 95. Because most Windows 95 installations have the MFC 30 DLLs, the applications installed and performed as expected. The applications then either failed to install or did not work properly on Windows NT because the required DLLs are not available.

Applications should verify the presence of all required DLLs and install them if they are absent. Applications should warn the user with a clear and specific dialog box if they find what appears to be an older version of a required DLL. The user should be given the option to replace the older DLL or leave it in place. Applications should refcount DLLs they use that already exist on the system. When an application is removed, it should decrement the refcount on DLLs it uses. MFC and system DLLs should not be removed, even if the refcount is zero.

Replacing System DLLs

Some applications replace system DLLs with newer versions. One such example is URL.DLL. Applications that don't verify operating system platform and version correctly may install a new DLL for the wrong platform or version (see the section "Interpreting the Operating System Version"). Many applications that replace URL.DLL on Windows NT install a Windows 95–specific version. When that happens, any application that initializes URL.DLL will display an error dialog box. The Windows NT KERNEL32.DLL does not contain the entry point ReinitializeCriticalSection that a Windows 95–specific URL.DLL uses.

Applications must warn the user with a clear and specific dialog box if they intend to replace any system DLL. Applications should provide platform-specific DLLs if any calls are made from the DLL to other platform-specific functions.

Common Issues: Large Drives

Benign Installation Errors

The Windows 95 team tested many applications as part of FAT32 development. Some of those applications displayed incorrect drive size information during installation when drives had more than 2 gigabytes (GB) of free drive space.

Similar tests were run on Windows NT, which also has the ability to support single drives with more than 2 GB of free drive space. Using an 8 GB drive, 25 percent of the tested applications—including Windows NT–specific applications—underreported the free drive space available. Most of these applications reported free drive space between 1 GB and 430 MB. None of these bugs had been reported by Windows 95 users during earlier Microsoft testing, nor by Windows NT users. There are four likely reasons:

  • All installations succeeded. Even if the application found only 430 MB free, none of the applications required more than 430 MB for installation.
  • The free drive space information appeared only during installation when it could be easily overlooked or ignored by the user.
  • Until recently, the price per MB of hard disks made large drives uncommon. Most users installed applications on drives with less than 2 GB of free space.
  • Users with very large drives may have filled them with data or other applications, so less than 2 GB of free drive space remained when the underreporting applications were installed.

A few applications reported negative numbers for free drive space on drives over 2 GB. In all cases, the user could click an Ignore button, and then the installation proceeded normally.

Application Errors that Affect Users

Some applications require the correct value for free drive space as part of their functionality or display the value to the user. Most applications that perform disk operations, such as tape backup, use the correct free drive space values, even if they display a low value during installation.

One command shell application reports a size of 1 MB for an 8 GB drive from its "dir" and "free" commands. Most users consider this a serious bug. Other applications display free drive space as incidental information, usually in a system resources dialog box from their Help menus. Underreporting free drive space in those dialog boxes is not considered as serious a bug by users because they do not often look at or rely on the information.

API Changes to Accommodate Legacy Code

Because many existing applications failed on drives larger than 2 GB, a change has been made in the GetDiskFreeSpace function. It now returns a maximum value of 2 GB, even if the drive has more than 2 GB free. A new function, GetDiskFreeSpaceEx, will return the true free drive space. Applications running on Windows 95 or Windows NT that need the true free drive space should call GetDiskFreeSpaceEx.

Common Issues: Coding Practices

Large Fonts

Some applications use splash screens to let the user choose options. A bitmap with the options is displayed on a dialog box. Hidden controls under the bitmap receive mouse click messages as the user clicks the mouse over the bitmap to make selections.

Figure 4. Splash screen with user options

In the preceding simulated splash screen, the user can select User, Kernel, GDI, or close the dialog box by clicking the word Exit. The dialog box appears on a machine using the Large Fonts option. The bitmap image did not scale with the dialog box, and a gray background appears behind the bitmap on the resized dialog box.

If system is set to use large fonts on the Settings tab in Display Properties, dialog boxes will resize to accommodate the large fonts. Controls on the dialog boxes move along with the dialog box. The bitmap image does not resize. In this example, the control that should be under the word Exit is at the bottom of the resized dialog box. When the user clicks on the word Exit, the Kernel option will probably appear since that control has moved lower on the dialog box, relative to the bitmap. With no Close button on the dialog box and the hidden exit control buried in the gray border, the user is challenged to close the dialog box.

The problem can be avoided on Windows 95 and Windows NT by using a static window with SS_BITMAP and SS_the CENTERIMAGE flags instead of using a dialog box window to hold the bitmap.

In addition to splash screen bugs, clipping may occur in static controls and edit boxes. All applications should be tested with large fonts.

Full Drag

A few applications do not resize or change to full-screen mode properly if the "Show contents while dragging" option has been checked on the Plus! tab in the Display Properties dialog box. Windows NT 3.x called this option "Full Drag." The problems are most common in 16-bit applications. Some 32-bit applications ported from 16-bit code also display these bugs.

Differences Between Windows 95 and Windows NT

Passing ANSI Characters to Windows NT

Windows NT is a Unicode operating system. All of its internal routines use Unicode for character handling.

Code can be compiled specifically for the Unicode environment by defining UNICODE. With UNICODE defined, the preprocessor will expand generic function prototype macros, such as SetWindowText, to wide character versions. Code designed to run only in an ANSI environment can be compiled with UNICODE not defined and the preprocessor will prototype only the ANSI versions of the functions. Applications can also be written making mixed calls to both the ANSI and Unicode versions of text-oriented API calls, such as SetWindowTextA and SetWindowTextW, for example. The ANSI functions take ANSI text parameters (LPCSTR) and Unicode (or wide) functions take wide parameters (LPCWSTR). A few wide functions have no ANSI equivalents and required Unicode parameters.

Some applications designed for Windows 95 pass ANSI text when Windows NT expects Unicode. For example, the Autorun application on the Windows 95 compact disc passes the names of files to Windows NT using ANSI strings. Windows NT evaluates them as Unicode and cannot find any of the files on the compact disc. Windows NT assumes the wrong compact disc is in the drive and repeatedly prompts the user to reinsert the Windows 95 compact disc.

Figure 5. Applications can add Help verbs to the right-click menu in Windows Explorer with Help strings printed on the status bar.

Windows NT expects Unicode characters for the Windows Explorer right-click menu Help strings. Many Windows 95–based applications pass only ANSI strings, which display as garbage instead of text. Applications have several options for creating readable Help strings on both platforms:

  • Switch on Windows 95/Windows NT and use either the ANSI or wide function call as appropriate.
  • Switch on the uFlags parameter of IContextMenu::GetCommandString. Pass ANSI on GCS_HELPTEXT and Unicode on GCS_HELPTEXTW.
  • Pass a null string on the GCS_HELPTEXTW flag. Windows NT will attempt the call again with the GCS_HELPTEXT flag. The application can then pass an ANSI string and Windows NT will make the Unicode conversion.

Receiving Unicode Characters from Windows NT

Some functions return Unicode strings on Windows NT. If an application processes only ANSI strings, it must use the WideCharToMultiByte function to make its own conversions.

Some applications receiving Unicode strings use incorrect parameters when calling WideCharToMultiByte, so the conversion is unsuccessful. If the applications fail to trap the error code returned by Windows NT, they use whatever text (or garbage) was in the buffer before the call.

Common and Personal Program Groups

Windows 95 supports only one type of program group on the Start menu. Windows NT 3.x used two types of groups: Common and Personal. Beta 1 of Windows NT 4.0 used the Windows 95 program groups model to be compatible with the Windows 95 shell. Many Windows NT Beta 1 users requested the dual model used in earlier Windows NT versions.

Windows NT 4.0 now supports both Common and Personal groups on the Start menu. It implements logic that tries to "do the right thing" automatically when Windows 95–based applications are installed. You can ensure that the proper group is created by using the CSIDL_PROGRAMS or CSIDL_COMMON_PROGRAMS flags when calling SHGetSpecialFolderLocation.

Only users with Administrator rights can create Common groups. If your program needs to create a Common group, you should inform your user to install the program as an Administrator. Ideally, your application will verify the rights it has inherited from the user.

Test your application's uninstall routine to be certain it locates any program groups that it created. Remove all of them, as well as the icons they contain.

Rights and Privileges

Windows NT is a secure operating system. User rights and privileges maintain that security. As discussed in the preceding section, your application inherits the rights, permissions and limitations of the user running it. Your application may not have access to expected hardware, system, and file resources on some Windows NT–based systems. Some applications fail to install critical files or fail to write to the registry on Windows NT if the installing user is not an Administrator, but the applications give no warning to the user. The applications subsequently fail to start, or crash during operation.

Compressed NTFS

Windows NT supports the NT file system (NTFS). It supports compressed NTFS beginning with Windows NT version 3.51. Although NTFS compression should be transparent to applications, some programs will not create directories or files on compressed NTFS drives. Applications should be tested on NTFS and compressed NTFS as well as on FAT drives. See also the section "Common Issues: Large Drives."

Multiple Processors

Windows NT can support multiple processor (MP) machines. MP machines should be transparent to applications, but some applications have difficulties running on MP machines. Test applications on machines with more than one processor. Look in particular for incorrect window repainting.

RISC Platforms

Windows NT supports MIPS R4000, DEC Alpha AXP, and IBM PowerPC processors. Users with those computers may provide an additional lucrative market for your 32-bit applications. Programs run most effectively on RISC-based machines when compiled to native code.

A technology preview, Microsoft Windows x86, that allows users to run 32-bit Intel® code on RISC-based machines under software emulation is available for Windows NT 4.0. Windows x86 has been tested with many applications, and most work as expected. Some functions are not implemented in the Windows x86 technology preview. You may want to test your 32-bit Intel application on one or more RISC-based machines on Windows x86.

Memory Leaks

Even small memory leaks in applications may eventually degrade Windows NT performance for several reasons:

  • Windows NT is robust. Application problems can require rebooting a computer running Windows 3.x or Windows 95. On Windows NT, the process can be easily terminated without affecting the operating system or, in most cases, any other processes. Computers may run for months without rebooting Windows NT. If an application leaks memory or resources, and it is started several times a day, the leaks will accumulate over time to impact total system memory.
  • Even small leaks can affect the ability of Windows NT to provide the large contiguous blocks of memory required by some applications.
  • Memory or handles allocated to resources such as files and folders may prevent users from legitimately changing or removing them. See the section "Memory Management" earlier in this paper.

Applications should be tested for leaks on Windows 95 and Windows NT. PMON.EXE, located in the \support folder on the Windows NT compact disc, may be helpful in finding application leaks. Several commercial products are available to analyze source code and running programs for leaks, unused resource assignments, and other problems.

Autoexec.bat and Config.sys

New applications should use the registry instead of AUTOEXEC.BAT or CONFIG.SYS. Your new application may need to use those files to maintain compatibility with legacy 16-bit versions.

Because a few 16-bit applications fail to install if either AUTOEXEC.BAT or CONFIG.SYS is missing, Windows NT creates zero-byte-length files with those names in the root directory of the boot drive. Some applications fail when they try to use zero-byte-length files. If your application reads or writes to either AUTOEXEC.BAT or CONFIG.SYS, you should test it with zero-byte-length files to verify correct performance.


This white paper has presented common compatibility problems observed at Microsoft while testing applications developed for Windows 95 on Windows NT 4.0. In most cases, Windows 95 applications work as expected on Windows NT 4.0 because the operating systems share the same shell interface and have similar API functionality. Where differences exist between the two operating systems, special care should be taken to ensure that applications correctly detect the operating system platform and version. Applications should test for the presence of features they require rather than for a specific operating system version. Applications written to conform with Win32 API specifications have the best chance of working on new versions of both Windows 95 and Windows NT.

For More Information

For the latest information on Windows NT Workstation, check out our World Wide Web site at www.microsoft.com/NTWorkstation/default.asp or the Windows NT Server Forum on the Microsoft Network (GO WORD: MSNTS).


© 1996 Microsoft Corporation. All rights reserved.

The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication.

This White Paper is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS DOCUMENT.

Microsoft, Windows, Windows NT, Win32, Win32s, and the Windows logo are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

Other product or company names mentioned herein may be the trademarks of their respective owners.