Tips and Traps

This section describes common problems that VxD writers encounter and suggests ways to avoid them.

Tip: To avoid cancelling a timeout after it has been dispatched, ensure that the timeout callback procedure immediately set the variable that holds the timeout handle to zero.

Tip: To avoid cancelling a timeout twice by mistake, use the following method:


    xor     esi, esi
    xchg    [hTimeOut], esi
    VMMCall Cancel_Time_Out

If this code is executed twice by mistake, the second time will not cause any harm. Note, however, that there is still an opportunity for a race condition to occur between the xchg instruction and the call to the Cancel_Time_Out service. To be extra sure that you don't cancel the wrong timeout by mistake, put the routine in locked code. If the timeout being cancelled is an asynchronous timeout, you also need to disable interrupts.

Tip: To enumerate all of the threads in the System VM, you can't just call Get_Initial_Thread_Handle to retrieve the System VM (or Get_Sys_Thread_Handle), and then call Get_Next_Thread_Handle until you retrieve the handle of a VM whose parent is not the System VM (or until you get back where you started). The reason is that the initial thread handle happens to be the last thread in the list, so the next time you call Get_Next_Thread_Handle, you will be bumped into the next VM and think the game is over. Instead, call Get_Sys_Thread_Handle, and then call Get_Next_Thread_Handle repeatedly until you get back to the system thread handle. For each thread along the way, skip it if the parent VM is not the System VM.

Trap: Forgetting to zero-initialize the thread data slot. Remember that thread data slots are not zero-initialized. When one is allocated, you have to go through every thread in the system and initialize each one.