Windows ME includes the ability to create a bootable DOS floppy. This floppy contains versions of COMMAND.COM and IO.SYS that are "crippled" to remove real mode. This is done with only one changed byte in each - it is easy enough to change this back to re-enable real mode in the image:

* COMMAND.COM and IO.SYS from diskcopy.dll are from the WinME crippled version  
* that removed real mode DOS => they must be patched:  
* IO.SYS            000003AA          75 -> EB 
* COMMAND.COM       00006510          75 -> EB 

(Direct source, Closer to original source)

How do these patches work? Why is it so easy to re-enable real mode? (The patch is too similar in both for this to be accidental.) Why was real mode disabled instead of just being unused?

  • 10
    The real question is....why would anyone use Windows ME in the first place? ;-) – cbmeeks Aug 2 '17 at 15:32
  • 3
    My conjecture: They wanted to officially demote any real mode DOS functionality as unsupported. Meaning they won't have to support it. – rackandboneman Nov 8 '18 at 22:19
  • @cbmeeks - I tried it just for fun before XP came out. I found it more stable than win98. – cup Nov 13 '20 at 5:36

There's actually two versions IO.SYS and COMMAND.COM used with Windows ME. The normal "crippled" versions used to boot from hard disks, and the "Emergency Boot Disk" versions use to boot from floppies. It's those later EBD versions that are embedded in diskcopy.dll under Windows XP, Windows Vista, Windows 7 and Windows 8.

The EBD versions are crippled in only one respect, they can't be used to boot off a hard disk. This is what the patches you quoted actually are meant to fix. The unpatched EBD versions of IO.SYS and COMMAND.COM fully support booting into real mode MS-DOS, as that is their sole purpose. The files CONFIG.SYS and AUTOEXEC.BAT are fully supported in the EBD version.

The crippled version that Windows ME normally uses to boot from a hard disk doesn't support CONFIG.SYS and won't boot to a real mode command prompt and instead will always start Windows. It will process the AUTOEXEC.BAT file but Windows ME will remove anything from AUTOEXEC.BAT that does anything other than setting an environment variable.

Another related issue with Windows ME is that the version EMM386.EXE included with it is broken, preventing it from being used on Windows ME EBD floppies.

Technical Description of the Patches

Here's a disassembly of the code in the EBD version of IO.SYS that is changed by the patch:

seg000:03A4                 mov     dl, [bp+?dos_internal.?vbr.?vbr_24]
seg000:03A7                 cmp     dl, 80h
seg000:03AA                 jnz     short loc_3B5
seg000:03AC                 lea     si, [bp+?dos_internal.?error_invalid_system_disk_2]
seg000:03B0                 push    cs
seg000:03B1                 pop     ds
seg000:03B2                 jmp     ?print_error_and_reboot
seg000:03B5 loc_3B5:
seg000:03B5                 mov     dh, [bp+?dos_internal.?vbr.?bpb.?media_id_byte]
seg000:03B8                 pop     di
seg000:03B9                 mov     ax, cs:word_7FA
seg000:03BD                 mov     bx, cs:word_7FC
seg000:03C2                 jmp     far ptr 70h:0

This what the relevant code looks like before being patched. The names starting with question marks (?) in the disassembly were made up by me.

The code above compares the BIOS disk number stored in the volume boot sector (?vbr_24) to 80h, which is the BIOS disk number for the first hard disk. If these numbers are equal then IO.SYS was booted from a hard disk and it results in the jnz short loc_385 instruction not jumping to loc_385 and instead falling through to the following instructions. These instructions result in the code jumping to a routine that prints the message "Invalid system disk" and then rebooting the computer when the user press a key.

When IO.SYS is booted from a floppy ?vbr_24 will contain the value 0 (zero) which is the BIOS disk number for the first floppy drive. This results in the comparison not being equal and the jnz short loc_3B5 statement jumping to the code at at the loc_3B5 label. This causes IO.SYS to proceed to boot normally, the jmp far ptr 70h:0 instruction jumps to the main IO.SYS entry point.

The patch changes the jnz short loc_3B5 instruction to a jmp short loc_3B5 instruction. This causes the code to always jump to loc_3B5 regardless of the result of the comparison, so IO.SYS always boots normally regardless of whether it was booted from a floppy or a hard disk.

The patched code in the EBD version of COMMAND.COM is more obscure. It apparently checks to see if its being started during a hard disk boot before Windows has loaded. If so then it prints (I believe) the message "Please press CTRL+ALT+DELETE to restart your computer" and halts the computer. This check is apparently done to prevent restoring normal AUTOEXEC.BAT processing by replacing the crippled hard disk version of COMMAND.COM with the otherwise uncrippled COMMAND.COM from a EBD floppy.

While the patch to COMMAND.COM also changes a JNZ instruction to a JMP instruction, the code being changed is actually quite different. It's only a coincidence that code can be effectively disabled by the same single byte change used for IO.SYS. Also note that the code Microsoft added to IO.SYS and COMMAND.COM (relative to the completely uncrippled versions used in Windows 95 and Windows 98) was more than a single byte change. In the disassembly above the entire sequence of instructions from address to 03A4 to 03B2 inclusive wouldn't have been present in previous versions of IO.SYS.

  • I assumed that there was a helper utility that would switch to protected mode then start IO.SYS, MSDOS.SYS etc. and that both versions were the same. Thanks for clearing that up. – wizzwizz4 Jul 11 '17 at 6:22
  • It's unclear to me why this patch would need to be applied by a tool whose purpose is to create bootable USB media. Isn't that media booting in floppy-disk emulation mode? – Cody Gray Jul 11 '17 at 11:19
  • 2
    @CodyGray Based on the comment from the Rufus source code quoted in the question it appears that the authors don't know what the patch actually does. I'm guessing they also can't depend on BIOSes booting a USB drive in floppy emulation mode anyways. – user722 Jul 11 '17 at 21:06
  • 2
    My understanding is that USB boot on PC bioses emulates a hard drive, not a floppy. – Peter Green Sep 19 '18 at 18:41
  • @PeterGreen BIOSes can either emulate USB drives as either floppies or hard drives. If the BIOS hasn't been configured to use one or either then it'll will choose which to emulate automatically. The criteria can vary, but the 530MB limit on floppy drive emulator is often used as the deciding factor. – user722 Sep 19 '18 at 18:58

EB is short jump relative. 75 is short jump if not equal. So Microsoft replaced a conditional jump with an unconditional one to prevent entry to a certain section of code — presumably there was a path that goes one way if installed on a hard disk, another if installed on a floppy disk, and Micorsoft hard-wired it always to act like it was on a floppy disk.

  • 1
    Actually, I've got this the wrong way around, and am about to lose service so cannot immediately fix it. Will delete and fix later if time allows. – Tommy Jul 10 '17 at 22:23
  • 6
    Updated and reinstated; since it mentions the meaning of EB versus 75 I think it still adds something as an answer. – Tommy Jul 11 '17 at 12:31

It crippled DOS quite half-heartedly.

As for why, Microsoft has apparently been intending to deprecate DOS (and Win16) in favour of Windows NT for quite some time0, for both technical and business reasons: I estimate it was since at least the inception of Windows 95, and possibly even earlier. They couldn’t afford to drop support for DOS software right away, though; after all, most of the value proposition of DOS (and any operating system ever) came from the programs written for it. If they ceased supporting them, Digital Research for example (or actually Novell at this point, if I remember correctly) would be more than eager to fill the void. So Microsoft painstakingly maintained backwards compatibility with DOS programs, while simultaneously incentivising application vendors to write new software against new, NT-compatible APIs that, of course, only Microsoft provided. They ported the Win32 API, created for Windows NT 3.1, first to DOS-based Windows 3.x (as Win32s) and then to Windows 95. They unified NT and 9x driver architecture with the Windows Driver Model; it’s telling that on the 9x side, the driver providing WDM support was named NTKERN.VXD. The clearly wanted to move away from DOS to NT, but needed to do so gradually.

Maintaining compatibility with DOS meant that Microsoft had to keep the basic architecture that began with Windows 386 Enhanced Mode unchanged: a hypervisor (the Virtual Machine Manager), initially launched in a DOS environment, that takes over the responsibility of managing hardware from DOS drivers, loads its own virtual device drivers (VxDs) and then oversees a number of virtual machines that mimic the DOS ABI and physical hardware just well enough to allow most DOS programs to run unmodified. Any change to this basic design would risk introducing incompatibilities, which Microsoft wanted to avoid. When DOS and the VMM were integrated into a single product, Windows 95 (the VMM being launched automatically at boot time), a number of backwards compatibility features were introduced to keep supporting software that couldn’t run under the supervision of the VMM: single-application mode, an option to boot to a command prompt without launching Windows, and even an option to boot to a previously-installed version of MS-DOS.

Millenium in particular was a pretty rushed release; I remember reading somewhere that Microsoft wanted to switch the ‘consumer’ line of Windows to the NT codebase already back then, but apparently they felt they weren’t quite ready yet, so they came up with yet another DOS-based release to fill the gap until the switch was realised with Windows XP. They still could not afford to change the architecture too much; any radical change would risk breaking compatibility with existing software, which this time meant VxDs. So to continue with their deprecation plan, Microsoft simply removed single-application mode and the ability of the DOS component to do anything else but launch the VMM.

To restore DOS mode support, it suffices to replace the DOS component of Windows with a more functional version, and remove some other behaviour interfering with it. This requires patching three files: IO.SYS, COMMAND.COM and REGENV32.EXE.


IO.SYS is the file containing the DOS kernel; it is the first file loaded and executed, straight from the boot sector. Unlike Windows 95 and 98 which use the same IO.SYS file in all situations, in Windows Me this file comes in multiple versions, of which I am going to highlight three:

  • The usual ‘crippled’ version, used to boot from hard disks.

    This version ignores CONFIG.SYS and AUTOEXEC.BAT completely, won’t boot to a real mode command prompt and will always launch the VMM (i.e. execute %winbootdir%\SYSTEM\VMM32.VXD instead of %winbootdir%\COMMAND.COM). Otherwise though, it contains a fully-functional DOS kernel capable of running any DOS program. If one were to replace VMM32.VXD with some other executable, IO.SYS will happily load that instead. (Although it can’t just be the original COMMAND.COM: see below for that.)

  • The ‘Emergency Boot Disk’ version, used to boot from floppies.

    This version can only boot to a command line and cannot be used to boot off a hard disk. It fully supports booting into real mode MS-DOS (including processing CONFIG.SYS and AUTOEXEC.BAT files), as that is its sole purpose: the boot menu (accessible via the F8 or Ctrl key) includes only a single item, ‘Normal’, which behaves just like ‘Command prompt only’ did in earlier versions. To actually start Windows from this version, one has to invoke WIN.COM, either manually or from inside AUTOEXEC.BAT. It is likewise a mostly fully-functional DOS, albeit it lacks serial and parallel port drivers that are present in the hard-disk version; the AUX, PRN, COMn and LPTn file names are still reserved, but the drivers are vestigial and always return failure.

    In 32-bit Windows XP and later versions, diskcopy.dll contains a copy of this version, altered only to remove the Windows Millenium branding in error messages. The un-branding was pretty half-hearted, though: the boot splash logo, for example, is still there, and the VER command of COMMAND.COM still reports the version as ‘Windows Millenium’.

  • The version used to boot from the Windows Me installation CD.

    This version is similar to the previous one: it also prevents booting off a hard disk, but is otherwise the most similar to IO.SYS of earlier Windows versions. It includes the full boot menu and can actually boot Windows by itself (without having COMMAND.COM do it). The serial and parallel port drivers are still non-functional, though.

The patch, applied to either of the latter two versions, simply disables the boot device check and allows hard disk boot to go through. Since Ross Ridge’s answer contains a detailed disassembly already, I’m not going to repeat it here; this answer is long enough as it is.

There are even reports of the Windows Me installation CD containing, stashed away in CAB files, a number of alternative versions of this file (and of COMMAND.COM) that don’t require any patching. (They have fully-functional port drivers, too.)


As for COMMAND.COM, the file is identical on the hard disk and the EBD. The problem with this file is that if it detects that DOS has booted from a hard disk, it will refuse to run, unless in it also detects it’s running inside a DOS box. The patch modifies COMMAND.COM so that the result of this check is ignored.

The patched code is as follows:

seg000:2223                 mov     bx, 1
seg000:2226                 mov     ax, 1683h
seg000:2229                 int     2Fh
seg000:222B                 cmp     bx, 1
seg000:222E                 jnz     short ?ok
seg000:2230                 mov     ax, 160Eh
seg000:2233                 mov     dl, 0
seg000:2235                 mov     bl, 6
seg000:2237                 int     2Fh
seg000:2239                 or      ax, ax
seg000:223B                 jnz     short ?ok
seg000:223D                 cmp     dl, 3
seg000:2240                 jnz     short ?ok                 ; ← the patched byte
seg000:2242                 mov     ax, 160Eh
seg000:2245                 mov     bl, 3
seg000:2247                 int     2Fh
seg000:2249                 mov     dx, ds:?msg_please_reboot
seg000:224D                 call    ?print_msg
seg000:2250 ?hang:
seg000:2250                 jmp     short ?hang
seg000:2252 ?ok:

First, COMMAND.COM checks if it is running inside a Windows DOS box; it does this by calling interrupt 0x2f service 0x1683 that returns the virtual machine ID in the BX register. If Windows is not running, the register is unmodified and keeps the value 1 set up before the call; inside a DOS box, the returned value is greater than 1. (The call may also return 1 if COMMAND.COM is running in the system VM; this may happen if %winbootdir%\SYSTEM\KRNL386.EXE is replaced with a copy of COMMAND.COM, like described in Andrew Schulman’s Unauthorized Windows 95.) If the value in the register is different from 1, the rest of the code is skipped and COMMAND.COM starts normally. Next, COMMAND.COM uses an undocumented interrupt 0x2f service 0x160e subfunction 6 to determine what drive the system was booted from. If the call is unsupported or returns something other than 3 (drive C), the rest of this code is again skipped. Otherwise, COMMAND.COM uses subfunction 3 to disable the boot splash screen, then it displays a message "Please press CTRL+ALT+DEL to restart your computer" and hangs the system.

(Amusingly enough though, COMMAND.COM still contains code that will invoke WIN.COM after processing AUTOEXEC.BAT if instructed so by IO.SYS.)

The patch makes it so that the result of the last of these checks is ignored, and the code that hangs the system is skipped always.

Another way to avoid problems with this file is to use an entirely different command interpreter (for example, FreeCOM) by putting a SHELL= statement in CONFIG.SYS. The ‘hidden CAB file’ version of COMMAND.COM on the installation CD also doesn’t contain this code, so it may be used instead.


Modifying IO.SYS and COMMAND.COM is enough to obtain a functional DOS mode for Windows Me. To make it actually suitable for daily use, however, another file needs to be modified.

While the hard-disk version of IO.SYS will ignore AUTOEXEC.BAT and CONFIG.SYS, the VMM does not quite ignore them. On bootup, both files are scanned for commands that set environment variables and replaced with dummy versions (CONFIG.SYS is emptied, while AUTOEXEC.BAT is modified to contain only SET commands). This means that all device drivers and TSRs are going to be removed from CONFIG.SYS and AUTOEXEC.BAT if Windows boots even once. To have an MS-DOS mode suitable for daily use, this mechanism has to be disabled.

This task is performed by a program named REGENV32.EXE. The simplest way to disable it is to replace the file names it looks for, so that the actual AUTOEXEC.BAT and CONFIG.SYS files are left untouched. This method is rather crude, but perfectly viable.

0 Look for example how Raymond Chen refers to DOS support in Windows 95 as a mere backwards-compatibility feature. This was written in 2007, so obviously there may be some hindsight bias there: perhaps there is a better source for this.

  • 1
    This was initially an edit to Ross Ridge’s answer, so don’t be surprised by plagiarised^W similar wording. I’ll welcome this being edited for length. – user3840170 Nov 12 '20 at 11:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.