BeginProc

include vmm.inc

BeginProc ProcName, Attributes
 

Marks the start of a procedure having the specified attributes.

ProcName
Name of the procedure to create.
Attributes
One or more procedure attributes. Can be any number of these attributes, with multiple attributes separated by commas:
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.

See Also

EndProc