Microsofts C compilers for programming on Intel 80x86 machines support an __asm keyword for introducing in-line assembly language. Under the heading Using C or C++ in __asm Blocks, documentation that accompanies the compiler states that among the C language elements that can be used in an __asm block are constants, including symbolic constants and enum members.
This ability to use enum members in __asm blocks is necessary to the scheme that Microsoft provides for writing virtual device drivers (VxDs) in C. The code for calling a VxD service is an int 20h instruction followed immediately by a 32-bit service identifier. This sequence is not naturally coded in C, but the Windows 95 DDK handles the C-language coding by providing a macro, VxDCall, that expands to the expected assembly language. For a given symbol that names a VxD service, the corresponding service ID is available because other macros, called Begin_Service_Table, Declare_Service and End_Service_Table build the service IDs as C-language enum members.
Because of a simple coding error, Microsoft Visual C++ 4.1 does not correctly compile in-line assembly-language instructions that dereference enum members. Among the possible outcomes are:
The problem lies in one C statement in the C1.EXE program. It can be corrected by patching two bytes in that file.
The following details apply to a version dated 21st February 1996 07:15 and whose size is 408,064 bytes. The files resources show 10.10 as the file version and 4.10 as the product version. The following table shows the bytes expected at three file offsets, together with the corresponding instruction mnemonics as they might be shown in a debugger:
File offset Expected bytes Instruction Mnemonic 00038A35 BE 38 E4 45 00 MOV ESI,0045E438 00038A3F A3 38 E4 45 00 MOV [0045E438],EAX 00038A45 89 15 3C E4 45 00 MOV [0045E43C],EDX
The important property about the last four bytes in each sequence is that if you interpret them each as a dword, then the first two must equal and the third must be four greater. The instruction at file offset 00038A35h loads the esi register with the value 0045E438h. This value is actually an address of a structure. The two instructions at file offsets 00038A3Fh and 00038A45h write a 64-bit value (of an enum member) to the start of that structure.
The coding error that needs to be corrected is that those last two instructions write to the wrong address. The correct addressin the sense of being a necessary condition for other code in C1.EXE to retrieve the value of the enum member correctlyis eight bytes higher. Instead of 0045E438h, the 64-bit value of the enum member should be written to 0045E440h.
Thus, the patches required for a file with the expected bytes are:
If you are even slightly uncertain how to patch a file, do not try it.
This page was created on 1st April 1998. The last significant modification was on 22nd August 1998.
Copyright © 1998. Geoff Chappell. All rights reserved.
[Home][Programming Samples][Application Notes][Security Notes][Editorial][Consultation][Contacts]