Noel Nyman
Microsoft Corporation
October 2, 1996
In general, most applications developed and tested on Microsoft® Windows® 95 will run without modification on Microsoft Windows NT® Workstation 4.0 and Microsoft Windows NT Server 4.0. 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 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 following guidelines.
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). Although the API has changed and expanded to encompass new features, code should in most cases work without modification on all three operating systems. (See "Introduction to the Win32 Application Programming Interface" [MSDN Library, Backgrounders].) Developers sometimes find that a program runs bug-free on Windows 95, but 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 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. A few developers hard-code executable paths or registry keys that are not identical on Windows 95 and Windows NT.
We see some common program bugs on both systems, although circumstances often hide them on Windows 95. Some applications fail to deal properly with long file and printer names. Others fail to install dynamic-link libraries (DLLs) that they require, or they 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. The user's permissions and rights are inherited by programs they start. The programs may not be able to perform expected tasks on Windows NT if the user has insufficient rights. Windows NT is a Unicode operating system. 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.
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.
0000000000000000 | 1010101010101010 |
High 16 bits | Low 16 bits |
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 will 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 doesn't 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 saw the high 16 bits of all handles 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 high 16 bit.
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 one.
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 could pass invalid values for the parameters that Windows NT uses. The invalid values may cause the code to fail when run on Windows NT.
For example, ChangeDisplaySettings can change the driver refresh rate on Windows NT. That functionality is not supported on Windows 95 drivers. Some applications change display settings and cache the current settings to be restored when the application ends. If the application does not read and cache the refresh rate, an invalid value will be passed to the API call when the display is reset on Windows NT. The driver uses its lowest refresh rate when given an illegal value. Unless the user has, by coincidence, selected that rate, the display will be a different size than the user expected and will probably appear offset on the monitor.
Test all code that makes API 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 API calls to make sure they hold legal value.
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.
SetCurrentDirectory(install_directory);
For (hFile = FindFirstFile(szBuffer, &FileInfo);
hFile != INVALID_HANDLE_VALUE && bReturnValue;
bReturnValue = FindNextFile(hFile, &FileInfo))
{
DeleteFile(FileInfo.FileName);
}
SetCurrentDirectory(initial_directory);
bReturn = RemoveDirectory(install_directory);
Figure 2. The RemoveDirectory call works as expected on Windows 95, but it fails to remove the installation directory on Windows NT.
The preceding code fragment is an example 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 FindNextFile to delete the installation files. 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 handle hFile is still allocated in memory. Unless FindClose is called to close the handle, 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.
Applications determine operating system platform, version, and build information by calling GetVersion or GetVersionEx. (See "To SUR, With Love: Important Stuff to Know About the Windows NT 4.0 Shell Update Release" at http://microsoft.com/win32dev/ui/ntsur.htm.) The GetVersion function returns information in a double word and GetVersionEx returns enumerated constants in a structure.
S |
9 |
bbbbbbbbbbbbbb |
iiiiiiii |
jjjjjjjj |
Win32s™ | 95 | build number | minor ver | major ver |
Figure 3. GetVersion returns platform, build number, and version coded in a DWORD.
Some of the Windows 95–based applications when run on Windows NT 4.0 have problems that are caused by their incorrect use of GetVersion. On Windows 95, the two high bits, labeled "S" and "9" in the preceding diagram, are set (not to zero). 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. Their developers assume 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 make Windows 95–specific calls into Kernel32.dll. These procedures are not available on Windows NT, and the calls will fail. Often, the applications will fail as well.
Other applications test only the platform bits. They correctly determine that they are running on Windows NT. 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 that require 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 tried to execute code they did not install.
Some applications that require a specific version, or higher, of Windows NT 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, making the critical Save function 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 GetVersion on Windows 95 or "950" as returned by GetVersionEx 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 Windows NT.
GetVersion 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.
Value | Platform |
VER_PLATFORM_WIN32s | Win32s on Windows 3.1 |
VER_PLATFORM_WIN32_WINDOWS | Win32 on Windows 95 |
VER_PLATFORM_WIN32_NT | Windows NT |
Figure 4. GetVersionEx returns platform as one of three constants in dwPlatformId.
The application must still get all the information it needs to determine operation system platform and version and use that information correctly.
The Imagecfg.exe tool is useful for verifying version problems in applications. Imagecfg adds information to the header of the application .exe or .dll that forces Windows NT to return "incorrect" information from GetVersion and GetVersionEx calls in place of the "real" operating system information. Parameters to Imagecfg tell Windows NT what "lie" to pass to the application. By specifying an earlier version of Windows NT or the version information associated with Windows 95, version problem applications may install or function as expected. Imagecfg will only write information to 32-bit headers.
C:>imagecfg -w c0000004 sample.exe
Figure 5. After using IMAGECFG with these parameters, Windows NT will return "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 can be found in the \support\debug\<platform> folder on the Windows NT compact disc. The command files "SetNT351.cmd" and "Setwin95.cmd" in the same folder will 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.
You can use Imagecfg to identify specific version 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
Figure 6. After using IMAGECFG, Windows NT will return "build 32, version 6.35 of Windows NT" to sample.exe when it calls GetVersion or GetVersionEx.
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 will give the user the greatest flexibility when upgrading the operating system.
The names and purposes of operating system executable files may change across versions or platforms. API function calls are available to start the executable files. Applications that avoid the API 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's 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.
Instead of using API calls, some developers search the Windows 95 registry for information they need. When they find it, they hard-code the path to the key. 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 API call GetProfileString returns the name of the default printer on all 32-bit operating systems. Using the API call will result in the proper application behavior. (See "Designing Your Installation Program" in Windows Interface Guidelines for Software Design in the MSDN Library.)
Both Windows 95 and Windows NT support file paths and printer names up to MAX_PATH characters long. (See "Making Room for Long Filenames.") 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 bugs are exposed on both Windows 95 and Windows NT if the same path and printer names are used.
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 they 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.
Several characters that are illegal in DOS file, folder, and printer names are accepted under Windows 95 and Windows NT. In addition to the space (ANSI 0032), these 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 7. 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, that use the system common dialog boxes allow semicolons in folder and file names.
Use the following guidelines to test your application for proper handling of long file and printer names (spaces are represented by the # character):
test
....test....
....####test####....
....####te..st####....
test....
....test
.test
test.
test#test#test#test
C:\test#1234567890[on to MAX_PATH total length]
\\folder#one\folder#two\folder#three\folder#four\file
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")
Neither Windows 95 nor Windows NT installs the MFC 30 (Microsoft Foundation Classes version 3.0) dynamic-link libraries (DLLs) on a minimum installation. 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. Since most Windows 95 users accept the default setup, which 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 will not find the DLLs on a Windows NT system.
Some Windows 95 applications need the MFC 30 DLLs, but fail to install them. The applications were tested by their developers on Windows 95. Since most Windows 95 installations have, by coincidence, the MFC 30 DLLs, the applications installed and performed as expected. The applications either fail to install or do not work properly on Windows NT because the required DLLs are not available.
Applications should verify the presence of all DLLs that they require and be prepared to install them if necessary. 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. (See "To SUR, With Love: Important Stuff to Know About the Windows NT 4.0 Shell Update Release" at http://microsoft.com/win32dev/ui/ntsur.htm.)
Some applications replace system DLLs, such as URL.dll, with newer versions. Applications that don't verify operating system platform and version correctly may install a new DLL for the wrong platform or version (see the preceding 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.
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 megabytes (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:
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.
Some applications either require the correct value for free drive space for 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 that 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 by users, since they do not often look at or rely on the information.
Because many existing applications failed on drives larger than 2 GB, a change has been made in the API function GetDiskFreeSpace. The function now returns a maximum value of 2 GB, even if the drive has more than 2 GB free. A new API 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.
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 clicks from the user to make selections.
Figure 8. In this 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 the system is set to use large fonts on the Settings tab in Display Properties, dialog boxes will resize to accommodate the large fonts. (See "Font and Size" at http://microsoft.com/win32dev/uiguide/uigui401.htm.) 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_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.
A few applications will not resize or change to full-screen mode properly if the "Show contents while dragging" option has been checked on the Plus! tab in Display Properties. 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.
Windows NT is a Unicode operating system. All of its internal routines use Unicode for character handling. (See "Unicode Support in Win32" [MSDN Library, Backgrounders].)
Code can be compiled specifically for the Unicode environment by defining Unicode to notify the preprocessor to expand generic function prototype macros, such as SetWindowText, to wide character versions. Code designed to run only in an ANSI environment, compiled with Unicode not defined, prototypes only the ANSI versions. Applications can also be written making mixed calls to both the ANSI and Unicode versions of text-oriented API calls; 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 API functions have no ANSI equivalents and required Unicode parameters.
Several applications designed for Windows 95 pass ANSI text when Windows NT expects Unicode. Autorun 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 9. 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:
Some API functions return Unicode strings on Windows NT. If an application processes only ANSI strings, it must use WideCharToMultiByte 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.
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.
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 they crash during operation.
Windows NT does not create Uninstall or SharedDLLs keys in the registry during installation. Applications should be prepared to create the keys during installation.
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 FAT drives. See also the preceding section "Common Issues – Large Drives."
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.
Windows NT supports MIPS R4000, DEC™ Alpha AXP™ and IBM® PowerPC™ processors. Users with those machines 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, is available for Windows NT 4.0 that allows users to run 32-bit Intel® code on RISC-based machines under software emulation. Windows x86 has been tested with many applications, and most work as expected. Some API 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. (See http://www.microsoft.com/ntworkstation/x86.htm for information on Windows x86.)
Even small memory leaks in applications may eventually degrade Windows NT performance for several reasons:
Applications should be tested for leaks on Windows 95 and Windows NT. Pmon.exe 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.
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. 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 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.