Microsoft Windows 2000 Application Compatibility Kyle MarshMicrosoft Corporation
November 1999
Summary: Discussion Make the application in Microsoft (R) Windows (R) 2000 is not compatibility. Some of the following parts:
Introduction settings and installation issues Windows 2000 compatibility problem application stability problem Differences between Windows platforms
Introducing a few months, I have been working on a task, namely the application compatibility issue in the Windows 2000 operating system. What I really want to discuss here is that the application is incompatible with Windows 2000. No one truly cares about the reason why the application is compatible.
I have been working with the Windows 2000 test group, and they have tested hundreds of applications in the past few months. We have discussed the application for normal or abnormal operations on Windows 2000. The issues we found can be classified as four categories:
Applications that cannot be installed on Windows 2000. This is the biggest problem we have found so far. Applications are not particularly installed on Windows 2000; the problem is that these applications do not allow themselves to install them into this new version of the operating system.
We do what the operating system is made and affect the application running. Whenever the Microsoft Windows NT (R) development group faces the choice, it is to make the system more stable or more powerful, or to ensure the compatibility of the application, they always sacrificed the latter and taking stability. A main goal of Windows 2000 development work is to make the system more stable as a platform. Unfortunately, some changes that must be performed in order to achieve this, the application has caused the application to be incompatible on Windows 2000. Changes we have made to the operating system do not affect the compatibility of the application, but it will interrupt some applications. Applications that depend on the Windows 9x platform. When we develop Windows 2000, we take into account many Windows 9x users to upgrade, so the Windows 9x applications are tested, and they are ported to Windows 2000. We find that some applications are too dependent on Windows 9x. Setting and installation issues We have to discuss the first type of problem is setting and installation issues; the most common problem is undoubtedly unable to install an application on Windows 2000. In fact, a most common reason that cannot be installed in the application is that Windows 2000 is a version 5.0 version of Windows NT. Test group tests the application in a variety of ways. They install the application in Windows 2000-based systems, or install the application in Windows NT 4.0 or Windows 95, and then upgrade the system to Windows 2000 for testing. After we take a machine that does not have any operating system, we install Windows 2000, then install the application, compared with the above upgrades, the former has much less compatibility. Version Check that the application cannot be installed on Windows 2000, which cannot handle the version number correctly. We have found that many applications do the operations made by the following sample code. They call GetversionEx during operation, then write a "if" statement, the statement specifies: "If the system is version 3, because there is no new shell, I can't run normally, so I may not be installed. If the system is version 4, I can install and set up. " The problem is that if the system is version 5, this "if" statement is not below. Because the version number is 5.0, these applications cannot be installed due to their own reasons, so we found a series of such problems. IF (Osvi.dwmajorversion == 3) {// please do this} else if (Osvi.dwmajorversion == 4) {// Please do the} Test Group Continue to find a solution and blind many of these applications. In early compilation, we can take steps to change the return value of GetVersionex. We can change its return value, deceive the app, tell it that version number is 4.0, and then the program will continue to install and run normally. But some application ideas are not installed on Windows 2000. For viral scanners or other low-level utilities, it is understood to be understood by an operating system. However, these applications displays the message to illustrate this. What we look for is those that cannot be installed or unable to run, and there is no application that does not know the user. How can I correctly check the version number? In Windows 2000 we will add a new API: VerifyVersionInfo, this API will check the primary version number, secondary version, and service pack in turn. If there is a new version of the operating system, the application can still install and run on it.
There are still many options and ways to apply VerifyVersionInfo, but if you just check "If the operating system is upgraded, how do you handle this, you only need to call these three signs, then check the primary version number, Version number and service pack. You can define the following statement: "My program needs to run on Windows NT 4.0, SP2", then ask VerifyVersionInfo "whether I am running this standard?", The API will return true value or false value. VerifyVersionInfo (& OSVI, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, DWLCONDITMASK); use this way to check the version, you can comply with Windows 2000 applications specification, its basic idea is "as long as there is a new version of the operating system, you must do it on the new version. Installation. "One problem with VerifyVersionInfo is currently the current API can only run on the Windows 2000 platform. In order to check the version of the old platforms such as Windows 95, you must apply GetversionEx. You can find that its function is basically the same as VerifyVersionInfo: check the primary version number, secondary version number, and service pack in turn.
BOOL bIsWindowsVersionOK (DWORD dwMajor, DWORD dwMinor, DWORD dwSPMajor) {OSVERSIONINFO osvi; // initialize OSVERSIONINFO structure // ZeroMemory (& osvi, sizeof (OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); GetVersionEx ((OSVERSIONINFO *) & osvi) ; // First, main version if (Osvi.dwmajorversion> dwmajor) return true; else if (Osvi.dwmajorversion == dwmajor) {///////ww (Osvi.dwminorversion> dwminor) Return True; Else IF (OSVI) .dwMinorVersion == dwMinor) {// right, better check Service Pack if (dwSPMajor && osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) {HKEY hKey; DWORD dwCSDVersion; DWORD dwSize; BOOL fMeetsSPRequirement = FALSE; if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, " System // CurrentControlset // Control // Windows ", 0, Key_Query_Value, & HKey) == Error_Success) {dwsize = si zeof (dwCSDVersion); if (RegQueryValueEx (hKey, "CSDVersion", NULL, NULL, (unsigned char *) & dwCSDVersion, & dwSize) == ERROR_SUCCESS) {fMeetsSPRequirement = (LOWORD (dwCSDVersion)> = dwSPMajor);} RegCloseKey (hKey) ;} return fMeetsSPRequirement;} return TRUE;}} return FALSE;} //// this example applies to Windows 2000 and later versions // BOOL bIsWindowsVersionOK (DWORD dwMajor, DWORD dwMinor, DWORD dwSPMajor) {OSVERSIONINFOEX osvi;
ZeroMemory (& osvi, sizeof (OSVERSIONINFOEX)); osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); osvi.dwMajorVersion = dwMajor; osvi.dwMinorVersion = dwMinor; osvi.wServicePackMajor = dwSPMajor; // set the conditional mask. VER_SET_CONDITION (dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); VER_SET_CONDITION (dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); VER_SET_CONDITION (dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); // execute the test. Return VerifyVersionInfo (& OSVI, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, DWLCONDitionMask);} First, you need to check the primary version number. If the primary version number of the current operating system is higher than the required primary version number, no check is required, run down directly. If the primary version number is equal, check the second version in the same way. Finally check the service package number. When we get a version of the release, you can say "It doesn't matter, we don't care whether service pack 3, 4 or 5". If the primary version number or the secondary version number has increased, the system can also be handled. We find all applications to check the version information, find that they will check each component separately. They will say "Hey, the main version number is 5, I only ask 4, good. The second number is .0, very good, but service pack is 0, I need 3". Obviously, Windows 2000 has not launched SP3, so this method of checking version information is wrong. Check the following details when checking the version number of Windows NT: Checking the version number and service pack information. The first is to get the return value of getVersionex and check the "Szcsdversion" string. The actual service pack number is embedded in a certain location of the string. Analysis This string character is really cumbersome, and you must always keep in mind whether it has been localized, it is difficult to do. This is not the best way. If the system is running Windows NT 4.0, you only need to check the following registration key value, where there is a number of service package numbers. Extract this number and make a "equal" or "greater than" comparison: HCLM / System / CurrentControlSet / Control / Windows / CSDVERSION If you run Windows 2000 or higher, you can still use GetversionEx, but you need Transfer it to the OsversionInfoEx structure, not the OsVersionInfo structure being used. Considering the size of the operator member, Windows 2000 will treat it as a larger structure and give a new field (service package, main version, subset) as an integer used in comparison. If you still use VerifyVersionInfo, you will find this is the most convenient way.
DLL version check In the case of checking the Windows version, we also discovered another question related to the version, that is, the user does not check the version of the DLL. Whether the DLL is Microsoft DLL in the system directory, or your own DLL, you must have a version check before copying it to the system. The purpose of the inspection is to prevent the old version of the DLL from being copied to the new version. Version information must be confirmed in the user's own DLL to check. It is important to do this, it can avoid a variety of trouble. Do not try to change the DLL in the system directory, do not consider upgrading the system DLL, or override the same DLL. The system DLL is a DLL submitted by Windows 2000 in a CD or a service package, located in the system directory. If you intend to prepare new Windows 2000 applications, you need to use Windows Installer, which can check the version of the DLL. As long as you explain that you need to place a particular DLL in a specific directory, you can find that Windows Installer is checked for you. You don't need to process this small piece of code. Dll Hell If the DLL version is not checked correctly, the result is no doubt that a DLL Hell will occur. I definitely not explain what DLL Hell is to explain to you, you must spend a lot of time on this. Because I originally participated in the development of CTL3D.dll, the same thing as familiar with my neighbors. We spent a few years, trying to break through obstacles that affect the normal work of DLL, and we finally determine that application developers cannot keep backward compatibility. Everyone is working hard in this regard, this goal is great, but it can't be realized. In fact, the DLL cannot keep backward compatibility. The result is: If an application is to end properly, it must depend on a specific version of a DLL, and another application depends on another version of the DLL, because these two applications are in this share of components. (Ie, shared DLL) has a conflict, resulting in the same system that cannot be coemented in the same system. So far, we still think that for Windows applications, DLL sharing features is a very good and important part. We also think that DLL can provide you with the features of you or very valuable. The problem is if you do not test the version of the DLL, and the cross-care program will bring a lot of problems with the DLL global sharing. Parallel DLL In Windows 2000, we have begun to implement some content called parallel DLLs. We hope that your application has also begun to close to parallel versions. In Windows 2000, we have taken some preventive measures to reduce DLL Hell. The first thing we have to consider is to ensure that the system is in protected state, and maintain its integrity. Then we will discuss Windows file protection. Another thing we have to do is in parallel to implement components, and I hope that the application vendor will do this. We are targeting Microsoft components; as for your own components, we also recommend that you do this. We will use a parallel version of the component, and we also hope that you can use a parallel version of the component for your own partial shared components. Another job that the System Stability Windows NT Group is working hard is to ensure that the system maintains a long time. Microsoft allows all functions to Windows NT in the form of division service packages, which is a problem. Customers who have installed Windows NT and companies are very vigilant when selecting a service package, because these things are not just some problems. Usually it will make some corrections, then say "Hey, we add this feature here, add that function there", these things make the system unable to reach the expected stability.
According to routine strategies, the service pack can only contain corrections to errors, and there is no other content. If we think that the operating system needs to add some important features and features, we will launch the .x version of Windows 2000. You will get such content similar to Windows NT 5.1, 5.2, and there are also three different versions of service packages for Windows NT. We will continue to work hard to maintain the integrity of each platform function, which even relate to QFE, error checking, and hot fix. The new version of the operating system will be issued each time with new features or new features. The last job we conducted in Microsoft is to ensure that what components have been released with the same product, we strongly recommend that you will follow. We are doing the most likely to reduce the number of components released in different products. If a particular component needs to work with another specific component, we will try to publish these two components together. For all these components that can be re-distributed, we will set out the released structure sequence. Parallel DLL If you need to change the components by global sharing components or DLLs to new parallel DLLs, you need to change some changes to the DLL. This change to DLL itself is necessary. You must declare: "The components I have designed will allow multiple versions to run at the same time." In order to make a component become a real parallel component, first need to rename the DLL, and change may exist in the OCX control, COM object All GUIDs. This renamed job can guarantee a new DLL running in parallel, which will no longer be global sharing. After the DLL is renamed, the application installs it into the autonomous directory without being installed. In this way, the application developers can say: "I have fully tested a specific version of this DLL, and I also confirm that this DLL will not upgrade before I will test again." Just give your developer enough confidence: Anyone cannot use shared components to disturb your app, causing the system to crash and bring us back to DLL Hell. If you are using these components as a user, you can register a relative path in your own directory (instead of the system directory). This will load a local version falling somewhere in the system, not a global copy. We modify the loadLibrary function to ensure that if the application registers a component with a relative path, we always complete the load in a relative path, regardless of this component is in the system directory, or is running else. This makes it possible to ensure that you get the copy of the application to test the application. Isolated Applications We also modified the LoadLibrary code to support DLL redirection. This administrator can redirect the DLL load process to a certain location and load the DLL by the local directory. After this process, your DLL can be in an isolated state. Suppose someone of a large unit is to test whether they can use your app, they have another application, and then test whether the two work together. They found that the result is not, the administrator starts to find where the two applications are conflicted on which component has occurred. After finding this component, the administrator considers the perspective of employees using these two programs, extracts the DLL (or contains OCX to the object) and places it in the directory where the application is located. Then the administrator created a file called foo.exe, and then added .local. If you call LoadLibrary, LoadLibrary finds that there is a foo.exe.local file here, which will first load the file in the application directory without considering the application for the application for the LoadLibrary call itself. This approach helps people distinguish between multiple applications that require the same component, so that all of these applications are running in the same system.
Windows file protection To ensure that the system's stability and platform reliability, the first step is to ensure that the system will not encounter any DLL HELL problem. We hope that no matter what happens, the system is still able to run, can boot, ie, users can have sufficient confidence in the stability of the system. With Windows File Protection (WFP), if the application tries to change a system file, Windows 2000 will restore it. For some features, the application will be installed and said: "Hey, I need this DLL new version ..." to implement a function, or at all this is a wrong application that does not correctly execute the version check function. Windows 2000 will check this and find that the file has been changed. If Windows 2000 found this is a system file, and declare "I don't allow this file", it will restore the file. If you want to upgrade files that have been locked by the system, you can only use several file replacement mechanisms issued by the Windows NT team: service pack, QFE or Hot FIX. They enable alternatives to system files, while other applications cannot be. For example, mfc42.dll is a file we locked. The DLL will not be upgraded through the language group, and only the Windows NT team can change this file in the system. If the C programmer needs to upgrade their DLL (and assume that they want to upgrade before the next version of Windows NT released after Windows 2000), only the parallel component version feature can only be used. Most * .sys, *. Dll, *. Exe and * .ocx files and several font files are in the protection. There are still several compatibility issues. First, the anti-virus program must recognize and correctly handle the Windows file protection, and then make the application's backup and recovery; these files cannot be copied, backed up, and recovered. Because you don't have a file replacement mechanism supported by your system, if you do this, you will cancel the Windows file protection. In order to prevent such operations, we added a few APIs in the system. The first API of the WFP API is SfcgetNextProtacectedFile. A list of all protected or protected files can be obtained. You can reply to this API at an null value to get a list of protected files.
BOOL WINAPI SfcGetNextProtectedFile (IN HANDLE RpcHandle, IN PPROTECTED_FILE_DATA ProtFileData); //// This will list protected file // void ListProtectedFiles (HWND hWnd) {HWND hwndList; PROTECTED_FILE_DATA pfd; int iCount; char szFileName [260]; int Ilen; Rect = getWindow (hwnd, gw_child); if (hwndlist == null) {getClientRect (hwnd, & rt); // Create a "list" control hwndlist = CreateWindow ("ListBox", NULL, WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_NOINTEGRALHEIGHT | LBS_USETABSTOPS, 0,20, rt.right, rt.bottom-40, hWnd, NULL, hInst, NULL);} else SendMessage (hwndList, LB_RESETCONTENT, 0, 0); ZeroMemory (& pfd, sizeof (Protected_file_data); iCount = 0; While (g_pfnsfcgetnextprotectedfile (null, & pfd)! = 0) {// For this "ANSI application" converts WCHAR to ANSI Ilen = WideChartubyte (CP_ACP, NULL , Pfd.FileName, WCSLEN (Pfd.FileName), SZFileName, 260, Null, NULL); SZFileName [Ilen] = '/ 0'; SendMessage (hwndlist, lb_addstring, 0, (lparam) szFileName); ICOUNT ;}} A more direct API is SFCISfileProtacected. The API can be more convenient to call most applications, and answer the following questions: "Take a look at this file, is it protected?" But remember that it needs to point to the full path to this file. You cannot just simply specify NTS.sys, but you need to give the path to the position where NTS.sys is located. If you pass this file to the API, it will say: "Yes, this file is protected", or "This is not a protected file." This API needs to be used when you do any backup or recovery operation. You can call this API if you want any installation settings or may update a system file. If you want to place a target file in the system directory, you need to call this API before doing this, to avoid cancel the Windows file protection.