include vmm.inc
BeginProc ProcName, Attributes
Marks the start of a procedure having the specified attributes.
Attribute | Description |
---|---|
HIGH_FREQ | Specifies a frequently called procedure. The macro aligns the start of the procedure on a doubleword boundary to optimize calls to the procedure. |
PUBLIC | Creates a global procedure that other procedures in the virtual device can call. |
PCALL | Use the Pascal calling convention. |
CCALL | Use the C calling convention. |
SCALL | Use the StdCall calling convention. |
ESP | Use ESP instead of EBP to access arguments. See caveats below. |
HOOK_PROC, hook_var | This procedure is being used to hook a service or fault. See remarks below. |
segment_type | Place the procedure in the segment_type code segment. Valid segment types are LOCKED, INIT, PAGEABLE, STATIC, DEBUG_ONLY, SYSEXIT, INT21, RARE, W16, W32, VMCREATE, VMDESTROY, THCREATE, THDESTROY, VMSUSPEND, VMRESUME, PNP, DOSVM, and LOCKABLE. |
If the DEBUG symbol is defined, then the following keywords are also recognized. (If the DEBUG symbol is not defined, then the following keywords have no effect.)
Attribute | Description |
---|---|
NO_LOG | Prevents entry to this procedure from being logged via Log_Call_Proc. |
SERVICE | Indicates that this procedure is an exported service. Additional code is generated to ensure that the service is not called asynchronously, as well some code for system performance profiling, and checking that basic ring 0 assumptions are not violated. |
ASYNC_SERVICE | The same as SERVICE, except that the check that the service is not called asynchronously is not performed. |
NO_PROFILE | If the procedure is a service, disables the generation of code which does performance profiling. |
NO_TEST_CLD | Disables the normal check that the processor direction flag is clear (up). |
TEST_BLOCK | Generate code to check on entry to the procedure that there are no outstanding ENTER_NOBLOCK calls. This is the default if the procedure resides in pageable code. See _Debug_Flags_Service for more information. |
TEST_REENTER | Generate code to check on entry to the procedure that VMM has not been re-entered. See _Debug_Flags_Service for more information. |
NEVER_REENTER | Generate code to check on entry to the procedure that VMM has not been re-entered, not even when Begin_Reentrant_Execution has been called. See _Debug_Flags_Service for more information. |
NOT_SWAPPING | Generate code to check on entry to the procedure that the current thread is not swapping. See _Debug_Flags_Service for more information. |
If a procedure is marked ASYNC_SERVICE, then it must be re-entrant, must not call synchronous services, and must restrict itself to locked code and data. Asynchronous services may be called by interrupt handling routines when processing interrupts. Therefore, virtual devices which export asynchronous services must be prepared for the service to be called any time interrupts are disabled.
Marking a procedure as PCALL, SCALL, or CCALL indicates to the ArgVar, LocalVar, EnterProc, LeaveProc and Return macros how code should be generated to access procedure parameters and local variables, and how code should be generated to return to the calling procedure.
If a procedure is marked ESP, then extra care must be taken to maintain the assumptions made by the ArgVar and LocalVar macros. All stack pushes must be performed with the SaveReg macro, and all stack pops must be performed with the RestoreReg macro. You may not adjust the stack manually, and you may not jump over code that adjusts the stack. These are relatively severe restrictions, but that's the way it is. If you can't live within them, then don't use the ESP attribute. Nobody's forcing you.
If a procedure will be passed to Hook_Device_Service, Hook_V86_Fault, Hook_PM_Fault, or Hook_VMM_Fault, then it must be marked with the HOOK_PROC attribute so that the service can be unhooked. This is important, even if you do not plan to unhook the service or fault yourself. Failure to comply may prevent other virtual devices from unhooking the service. The hook_var parameter is the name of the variable into which the address of the previous hook will be stored. See the discussion of hook procedure in the Overview for additional information about hook procedures.
If a segment type is provided, then the procedure will be placed in the segment named VxD_segment_type_CODE_SEG. This is provided for convenience in procedure-level page tuning.
EndProc