Note

The preceding description implies that the only meaningful place to use Call_When_VM_Returns is when a Simulate_Far_Call or Build_Int_Stack_Frame is going to happen soon. (As noted, this is typically done inside the callback installed by Hook_V86_Int_Chain.) In particular, in order to hook the back end of a simulated interrupt, you must call Call_When_VM_Returns before the interrupt itself is simulated. If the interrupt or far call has already been simulated, Call_When_VM_Returns will not do what you want. (The name of the service is rather unfortunate. It really means "Call when the VM returns to where it is now", and not "Call when the VM executes a return instruction".)

The system calls this callback procedure as follows:

mov     ebx, VM             ; current VM handle
mov     edi, hCurThread     ; current thread handle
mov     edx, RefData        ; reference data
mov     ebp, OFFSET32 crs   ; points to a Client_Reg_Struc
call    [Callback]
 

The VM parameter is a handle identifying the current virtual machine. The RefData parameter is the value supplied when the callback procedure was installed, and the crs parameter points to a Client_Reg_Struc structure containing the register values for the virtual machine.

If the system calls the callback procedure as a result of a time out, it sets the carry flag before calling the procedure. If the system calls the callback a second time (once for a time out and once for the iret instruction), the system sets the zero flag before calling the procedure a second time. The value of the zero flag is indeterminate unless the TimeOut parameter specifies a negative value.

In other words,

  1. If you passed TimeOut = 0, then the callback is called when the VM returns and at no other time.
  2. If you passed TimeOut > 0, then the callback should begin like this:
    jc      timed_out;  Timeout notification
                     ;  Otherwise, the VM returned
                     ;  before the timeout expired
    
  3. If you passed TimeOut < 0, then the callback should begin like this:
    jc      timed_out    ;  Timeout notification
                         ;  Otherwise, the VM returned
    jnz         normal_return;  VM returned with no timeout
                         ; Else, VM returned with timeout
     

See Also

Hook_V86_Int_Chain