Late-Breaking News (last update 08/01/1999)

Download OSR2CFIX.ZIP now

What Is OSR2CFIX?
Program Usage
Program Operation
Unpatchable Files
Removing the Patch
A Technical Explanation of What's Going On
Revision History


This program may be copied freely but not modified. If you discover a problem with the program or the patch it applies, please email me the details at dgl@visi.com so I can make any appropriate updates available to everyone.

What is OSR2CFIX?

OSR2CFIX is a program designed to make a small alteration to the COMMAND.COM file which comes with Windows 98 or Windows 95 OSR2 (sometimes also called version B of Windows 95) which makes it possible to run certain DOS programs which refuse to run otherwise.

As reported by Sean Erwin on his OSR2 Frequently Asked Questions page, some programs compiled with a 16-bit Borland C compiler cause a general protection fault (GPF) when run under Windows 95 OSR2, though they run properly under OSR1 (the original public release of Windows 95). The same problem also shows up under Windows 98. The programs affected are those which run COMMAND.COM themselves, perhaps in order to run a batch file or DOS command. The problem is caused by a minor change made to COMMAND.COM when Windows 95 OSR2 was released. OSR2CFIX makes another minor change to the COMMAND.COM file which makes it load successfully when called by a 16-bit Borland C program. Details concerning the problem and the solution can be found in the Technical Explanation section near the end of this document.

This program should be run only on systems running Windows 95 OSR2 or Windows 98. To identify if your system is running Windows 95 OSR2, type VER at a DOS prompt. If it says

Windows 95. [Version 4.00.1111]
you are running OSR2; if the version number is different (e.g., something other than "1111" appears after the second decimal point), you should not run this utility.

This utility takes considerable precautions to identify correctly each COMMAND.COM it examines and will refuse to modify any version it does not recognize as an OSR2 or Windows 98 version. However, I can not guarantee that it will recognize all versions correctly--most particularly versions not yet released by Microsoft, such as the one that will ship with Windows Millennium. If you patch a COMMAND.COM file with OSR2CFIX and then discover that this has created another problem, you can always run OSR2CFIX again and remove the patch. Of course, I would like to be notified of such problems in case other users might be affected.

Program Usage

Just type OSR2CFIX for a summary of possible usage. The following display will appear:
Usage: OSR2CFIX [-a] [-s] [-v] [fileName]
-a: Autoscan; scans MSDOS.SYS for files to check. -s: Report the states of files only; do not change anything. -v: Verbose output. fileName: Name of a COMMAND.COM file to check.
The -a and fileName options are mutually exclusive.
Except in very unusual circumstances, the most preferred way to use this program is to type
OSR2CFIX -a
and press <Enter>. This will cause OSR2CFIX to check all COMMAND.COM files referenced by MSDOS.SYS on the Windows 95 or 98 boot drive. You will be asked to indicate which drive is used to boot Windows.

As an alternative to using -a, you can specify the full path to a COMMAND.COM file when invoking OSR2CFIX, in which case only that file will be checked:

OSR2CFIX C:\WINDOWS\COMMAND.COM
will only work with the COMMAND.COM in C:\WINDOWS. Note: This usage is not recommended, because it can result in differences among active copies of COMMAND.COM.

There are two other command-line options understood by OSR2CFIX: -s (status) specifies that nothing is to be changed; the program will report the statuses of COMMAND.COM files but will not offer to alter them. -v (verbose) causes extra output to be generated while COMMAND.COM files are being scanned. For each copy of COMMAND.COM examined, the location and first two bytes of each pattern match are shown. For OSR2 COMMAND.COM files, this output should look like this:

04260h: 7Ah,17h 04360h: 06h,17h
These numbers will be different for other versions of COMMAND.COM, including those patched by this program. The -v option is primarily intended as a debugging aid but may also be interesting to the curious.

Program Operation

After OSR2CFIX determines which files should be checked, either by being told directly on the command line or by examining MSDOS.SYS, it will scan each file to determine what version it is. The full pathname and status of each file will then be shown, and you will be asked to choose among two or three choices of what to do next. Though the exact wording of the choices presented to you will depend on what OSR2CFIX found when scanning COMMAND.COM files, there are three basic options: Apply the patch to all files listed, remove the patch from all files listed (restore the files to their original versions), or do nothing. If you elect to do nothing, the program will immediately exit; otherwise, it will carry out whatever function you requested.

Unpatchable Files

This program recognizes Windows 98 and Windows 95 OSR2 COMMAND.COM files, both patched and unpatched, as well as COMMAND.COM files from Windows 95 OSR1. Any Windows 95 OSR1 file or any file not recognized at all is considered unpatchable. This program will refuse to do anything with such files. If any such files are found, a warning to that effect will be displayed, and the program will ask permission to remove these files from the list of files to consider. If you answer no, the program will abort without having changed any files; if you answer yes, it will remove all unpatchable files from the displayed list and then display the new list of files to consider.

WARNING: If OSR2CFIX finds COMMAND.COM files which it believes are not patchable, you should take extreme care before proceeding further. If MSDOS.SYS was used to find files (the -a option was used), and one or more of these is shown not to be patchable, you are probably dealing with either a Windows 95 OSR1 installation or a damaged OSR2 installation. This program should not be run against OSR1 installations. If yours is definitely an OSR2 or Windows 98 installation, and OSR2CFIX reports unpatchable COMMAND.COM files, I strongly recommend that you immediately run SCANDISK and possibly a virus scanner to determine the cause of the problem.

Removing the Patch

This program can restore COMMAND.COM files to their original states if this becomes necessary. The program does not create backups of each COMMAND.COM file it modifies; rather, it contains enough know-how to recreate the original files if asked to do so. If you run OSR2CFIX after having already patched your COMMAND.COM files, you will notice that the first choice will be to "restore" rather than to "patch." If you elect to restore files to their original versions, your COMMAND.COM files will be rewritten as they were before you ran OSR2CFIX the first time.

A note to users of my first patch instructions (as posted in Sean Erwin's OSR2 FAQ and on Usenet): If you patched COMMAND.COM as instructed by my June, 1997 Usenet article and OSR2 FAQ quote, you should "repatch" it with this program. The old patch fails to work on some systems (see the Technical Explanation section below), whereas the patch applied by OSR2CFIX appears to work under all conditions. This program will recognize and inform you of such already-patched versions of COMMAND.COM by saying that they are "patched the old way." This program can apply the new patch to these files, and it can restore them to their original (totally unpatched) states; it can not, however, reapply the old patch once having removed it. In other words, if you use OSR2CFIX to update a COMMAND.COM patched the old way, you can be sure that the old, less reliable patch is gone.

A Technical Explanation of What's Going On

The following explanation is drawn loosely from what I sent Sean Erwin on 08/11/97 for inclusion in his OSR2 FAQ web page. Since then, I have significantly revised this discussion to include further information made available to me at a later time. To those who understand 80x86 assembly language, this will explain what the problem is and how the patch manages to fix it, as well as the problem encountered with the older patch. For those who don't know what I mean by 80x86 assembly language, this section may serve as effective, if unusual, bedtime reading material. :-)

From the user's perspective, the problem is that some programs, when run under Windows 95 OSR2 or Windows 98, crash with no apparent reason, even though they run fine under the OSR1 version of Windows 95. It turns out that all of the programs which do this (at least all those reported to date) share two characteristics: (1) they were compiled with a 16-bit Borland C/C++ compiler, and (2) they attempt, in the course of execution, to run COMMAND.COM via an exec..() function call (or a spawn..() call with a mode of P_OVERLAY). I suspect that this problem may affect programs compiled with some other compilers, but this has yet to be demonstrated.

Due to a change in the format of COMMAND.COM at the release of Windows 95 and to the unusual way Borland 16-bit C compilers run COMMAND.COM (load-then-call), programs compiled with Borland 16-bit C compilers wind up starting Windows 95+ COMMAND.COM at a different point than they used for earlier versions of COMMAND.COM. At the release of Windows 95, the format of COMMAND.COM quietly changed from .COM to .EXE, though the name of the file did not reflect this change in format. For most programs, this doesn't matter, because most programs which call COMMAND.COM do so by making a call to the operating system to run COMMAND.COM; the operating system then handles the difference in file format. However, Borland 16-bit C compilers use INT 21h, function 4Bh, subfunction 03h (load as overlay) to load COMMAND.COM into memory, then jump to offset 100h (using the CS value indicated on the above call's return) to begin executing COMMAND.COM. While this strategy worked with the older .COM format of COMMAND.COM, it fails to work as planned for the .EXE format: Even though IP is set to 100h, CS is set by the INT 21 call such that offset 100h points to a different part of the file. COMMAND.COM is thus started at a different entry point.

The bytes at the new (incorrect) entry point look like valid code, but are not. I actually suspect that most of the bytes at that location are copied for some reason from the "real" entry point (they look almost identical in all COMMAND.COM files I have examined). However, it turns out that the first byte at this offset is used by Windows 95+ as the binary version number for the COMMAND.COM file: 0x70 representing version 7.0 for the original Windows 95, and 0x7A representing version 7.10 for Windows 95 OSR2 (these are the version numbers you see if you issue the "VER" command in DOS).

Even though executing a version number as code is certainly not guaranteed (or likely) to work, it does under the original release of Windows 95; but it does not work under Windows 95 OSR2 or Windows 98. 0x70 (original Windows 95) is a JO (branch on Overflow set) instruction if interpreted as code, whereas 0x7A (OSR2 and later) is JPE (jump on Parity even). The flags set at the time the load-as-overlay call described above returns are Interrupt-enable, Zero, and Parity Even. Thus, the branch is ignored in the original Windows 95 release but taken in later versions of Windows. Presumably because most of the bytes at this invalid entry point are copied from the valid entry point, ignoring the branch causes things to work properly; but taking the branch causes the execution of an invalid code stream, which finally produces the crash the user sees.

Here is the problem in the words of a Microsoft employee with whom I corresponded regarding this issue in October, 1997: The opcode for JO is "x70". The opcode for JPE is "x7A". You are correct that we changed this in OSR-2, and are correct that IO.SYS verifies this byte. The error, however, is that this is not a valid entry point. This is a single byte "version" for the binary. Windows 95's DOS version was 7.0. OSR-2 had MS-DOS 7.10. "10" in decimal is "A" in hex. So, it appears that if the Borland compiler is jumping to offset "0", then it is jumping to the version number and executing it. It is just dumb luck in Win95 that this worked properly. The reason that IO.SYS checks this byte is to make sure that the versions of io.sys and command.com are in sync.

My first solution to the problem was to change the JPE back to a JO. At the time, I was not aware that the JPE was actually the version number of COMMAND.COM (7.10). It turns out that there is code in IO.SYS which tests this byte of COMMAND.COM to make sure it is the right version; if it is not, IO.SYS prints the message, "The following file is missing or corrupt: COMMAND.COM," and pauses to ask the user to type the name of the command interpreter to use. Oddly, this only happens if there is no "SHELL=..." line in CONFIG.SYS--which is how I managed not to notice, since my systems' CONFIG.SYS files contain such a line.

My current solution involves effectively disabling the JPE without changing it by making the branch offset 0. This solution will actually work for any version of COMMAND.COM in which the binary version number happens to correspond to a branch instruction, at least as long as the (apparently copied) block of bytes at that "entry point" otherwise continue to function like the code at the valid entry point. The strategy has already been proven to work for Windows 98.

Revision History

08/12/97
First public release.

I hope this little utility proves helpful. Again, please notify me of any problems via email to dgl@visi.com

Late-Breaking News (last update 08/01/1999)

Download OSR2CFIX.ZIP now