DOS Extender (Often Called a DOS Extender,Or Even Just an Extender) Is a Library That Assists in Running 32-Bit MS-DOS-Based Programs
Total Page:16
File Type:pdf, Size:1020Kb
Chen_Rev_Appendix B.qxp 12/6/06 10:54 AM Page 1 HOW TO ENSURE THAT YOUR PROGRAM DOES NOT RUN HUNDER WINDOWS 95 My primary focus for much of the Windows 95 project was MS-DOS application compatibility, specifically games. To help maintain my sanity, I found myself writing the following account, illustrating the phenomenal creativity of software developers in doing everything within their power to be incompatible with Windows 95. This chapter is a very technical one, originally written for an audience con- sisting of developers deeply steeped in the minutiae of protected-mode pro- gramming. I have attempted to clarify the jargon, but the issue is unavoidably technical. Here are some terms you will encounter: •The Global Descriptor Table (GDT) is a central data structure that is used by the CPU and that controls how programs access memory. Allowing access to the GDT effectively grants total control of the computer. • Real mode was the only mode supported by the CPU prior to the introduction of the 80286. MS-DOS was originally developed to run in real mode. Real mode has no memory protection. Modern operating systems use real mode only transitionally on their way to 1 Chen_Rev_Appendix B.qxp 12/6/06 10:54 AM Page 2 2 the old new thing protected mode, which is a mode of the CPU in which memory protection becomes available. •The DOS Protected-Mode Interface (DPMI) and the Virtual Control Program Interface (VCPI) are two popular interfaces for writing 32-bit DOS-based programs. Windows 3.0 and higher support DPMI. •An MS-DOS extender (often called a DOS extender,or even just an extender) is a library that assists in running 32-bit MS-DOS-based programs. DOS extenders typically detect that a DPMI or VCPI server is already running and use the corresponding interface to provide necessary services to the 32-bit MS-DOS-based program. In the absence of such a server, the DOS extender will provide one on its own. At the time of the Windows 95 project, there were several commercial DOS extenders available to choose from. The interface to MS-DOS and the MS-DOS extender is a register-based one, so all the programs of the era in which these programs were written con- tained some degree of assembly language. Furthermore, it was considered standard practice for applications to do such things as reprogram hardware devices and replace hardware interrupt handlers (operations that in today’s programming environment would be considered beyond the scope of what applications can or even should be allowed to do). Such activities necessitated the use of assembly language, and as a result, many of the topics covered here will be heavy on 80386 assembly language, both 16-bit and 32-bit. I have con- verted the assembly language back to pseudo-C when possible; when this is not possible, I have attempted to explain, in the accompanying text, what the assembly language does. Bear in mind that I wrote this chapter back in 1995 as a way of letting off steam. Its purpose was not to ridicule the vendors in question; that was just a side effect of the ironic tone. But just to make sure nobody takes it person- ally, I’ve made all the product and company names anonymous. Chen_Rev_Appendix B.qxp 12/6/06 10:54 AM Page 3 How to Ensure That Your Program Does Not Run . 3 Prologue There have been myriad articles describing how to write programs to run properly under Windows 95, but a title sorely lacking is one describing how to write a program that will fail spectacularly when run under Windows 95. This document attempts to fill that void by describing steps you can take when developing your application to ensure that it encounters as many com- patibility problems as possible. By carefully following these steps, you can be relatively certain that your program will not run on any Microsoft operating system well into the next century. MS-DOS-Extended programs Congratulations on your decision to write an MS-DOS-extended program. You stand at the frontier of protected-mode programming. Unwilling to take the leap to a protected-mode operating system like Windows, you prefer to keep one foot in the comfortable world of MS-DOS while venturing with the other foot into the gnarly depths of protected mode. Here are some tips for making sure your program will resist the pull of Windows for as long as possible. Just party the GDT yourself Remember that the Global Descriptor Table (GDT) belongs to the operating system. Any operating system that even pretends to protect itself from applica- tions will not allow applications to access the GDT, much less try to change it. The easiest way to ensure that you will not run under any operating system whatsoever is to execute an lgdt instruction, which loads a new global descriptor table. This instruction bypasses the operating system and enters protected mode directly. It helps if you don’t even check if the CPU is in real mode before doing this. Chen_Rev_Appendix B.qxp 12/6/06 10:54 AM Page 4 4 the old new thing Example 1 All known versions of one game try to enter protected mode by loading the global descriptor table register directly. Under a protected-mode operating system, this crashes with a general protection fault. Another game refuses to run unless it is in real mode and can take complete control of the machine. Example 2 One game goes into protected mode with the help of a particular DOS extender (which we will call Extender 2), thereby creating the illusion that it wants to play friendly with the operating system. But then it goes ahead and edits GDT selectors directly. Use VCPI Windows 95 does not support the Virtual Control Program Interface (VCPI) because that interface gives applications total control of the computer at the lowest level, something generally frowned on in today’s computing environ- ment. If you design your program to require VCPI, it will never run on any operating system that wants to remain in charge. It helps if you also display a really confusing error message when you fail to detect a VCPI server. Example 3 Two games by a popular game publisher (which we will call Publisher 3) merely display the message EMS driver is not VCPI compliant. and unceremoniously exit if a VCPI server cannot be found. Example 4 Another program by Publisher 3 displays the wonderfully useful error message Protected mode driver is not responding to EMS function calls. Make sure your EMS driver is not configured with the NOEMS option. If it is, replace the option 'NOEMS' with 'RAM'. This leads the user on a wild goose chase trying to configure expanded memory in myriad ways, when the real problem has nothing to do with EMS. Maxim 1: The more confusing the error message, the better. Chen_Rev_Appendix B.qxp 12/6/06 10:54 AM Page 5 How to Ensure That Your Program Does Not Run . 5 Write your own (DPMI) DOS extender An excellent first step in writing an MS-DOS-extended program that will not run under Windows 95 is to try to write your own extender. Writing a DOS extender is not something that should be left in the hands of qualified professionals. If you use a third-party DOS extender, you run the risk that any problems resulting from the extender might be fixed by the vendor, or that the operating system developers might come up with a workaround for the problem in the DOS extender. By writing your own DOS extender, you can ensure that any problem in the extender is completely your own. This way,the operating system developers will give higher priority to prob- lems with commercial DOS extenders rather than your problem, because any such workaround would fix only your program and no other. Example 5 The DOS extender used by one game is a home-grown one. (You might find it amusing that the author of this extender subsequently came to work for Microsoft for several years.) The application makes an Int 21h function 250Dh call to the DOS extender to set the interrupt vector for IRQ 5, the sound card. The extender saves the application’s vector address into a private table and loads AX:ECX with the address of the extender’s private wrapper. And then, oh wait, it gets distracted for a little bit, and goes down a random code path that scrambles the AX and ECX registers, loading it instead with random values from uninitialized memory. And then it jumps back to the main code, which tries to set this as the interrupt vector to this garbage address, which fails. The application then hangs waiting for a hardware interrupt that never arrives. The application documentation says Do NOT run Program 5 from a shell in Windows. The virtual memory 'feature' [sic] of Windows causes Program Name to crash. This is an important lesson. Maxim 2: If it doesn’t run under Windows, then it’s Windows’ fault. The flag that the program in Example 5 checks to decide whether to scram- ble AX:ECX appears to be a flag that is set if the extender is acting as a DPMI client rather than a server. Maxim 3: Detect Windows, and crash. Chen_Rev_Appendix B.qxp 12/6/06 10:54 AM Page 6 6 the old new thing Ignore the manuals If you choose to go with a commercial DOS extender, make sure never to read the manual.