singrdk/base/Windows/Inc/VidDefs.h

870 lines
24 KiB
C

/*++
Copyright (c) 2005 Microsoft Corporation All Rights Reserved
Module Name:
VidDefs.h
Abstract:
This module contains the common definitions for Vid.sys shared by
the driver, user mode Vid clients and kernel mode Vid clients.
Author:
John Gregg (jgregg) 06-Jun-2005
--*/
#pragma once
#include <hvgdk.h>
//
// Define an interface Guid for the VID device class.
//
// This Guid is used to register an instance so the the VID node is
// by VID (both user mode and kernel mode) clients.
//
// {7896e901-fe60-446e-828d-d65920654a23}
//
DEFINE_GUID(GUID_DEVICEINTERFACE_VID,
0x7896e901, 0xfe60, 0x446e, 0x82, 0x8d,
0xd6, 0x59, 0x20, 0x65, 0x4a, 0x23);
//
// The maximum size, in characters, of a Vid object name (Partition or Message
// Queue).
//
#define VID_MAX_OBJECT_NAME_CHAR_COUNT 256
//
// The maximum number of virtual processors supported on a Partition.
//
#define VID_MAX_PROCESSORS_PER_PARTITION ((VID_PROCESSOR_INDEX)(HV_MAX_VP_INDEX + 1))
//
//
// A partition handle and a queue handle are handles to a file object
// returned from the Win32 function CreateFile).
//
typedef HANDLE PT_HANDLE;
typedef HANDLE QUEUE_HANDLE;
typedef UINT32 VID_PHYSICAL_NODE_INDEX, *PVID_PHYSICAL_NODE_INDEX;
typedef UINT32 VID_LOGICAL_PROCESSOR_INDEX, *PVID_LOGICAL_PROCESSOR_INDEX;
//
// This structure contain both static and dynamic information about a single
// NUMA node. When a user mode client queries the VID about a single NUMA
// node, the node's information is returned within this structure.
//
typedef struct _VID_NUMA_NODE_INFORMATION
{
//
// The NUMA node index that identifies the node.
//
VID_PHYSICAL_NODE_INDEX NodeIndex;
//
// The total number of parent GPA pages that are local to this node.
//
UINT64 TotalPageCount;
//
// The number of parent GPA pages that are local to this node and that can
// be used for backing the minimum working set of a newly created Memory
// Block. Note that the user mode client should treat this number only as
// an estmiation, because we don't actually allocate the free pages when
// the client queries for the available node memory.
//
UINT64 FreePageCount;
//
// The number of logical processors contained within the node.
//
UINT32 LogicalProcessorCount;
//
// A bit mask that represents the logical processors on the node. The
// number of set bits in this mask equal LogicalProcessorCount.
//
UINT64 LogicalProcessorMask;
} VID_NUMA_NODE_INFORMATION, *PVID_NUMA_NODE_INFORMATION;
//
// ISSUE-jgregg-2006/8/2: Temporary code to enabled statistics access.
//
typedef enum _VID_NUMA_NODE_STAT_PROPERTY
{
PageCount,
PagesInUse,
SharedParentGpaPageCount
} VID_NUMA_NODE_STAT_PROPERTY,
*PVID_NUMA_NODE_STAT_PROPERTY;
#define VID_PAGE_SIZE 4096
//
// The following are internal VID handles that don't correspond to Win32 file
// handles.
//
typedef UINT64 HANDLER_REF;
typedef PVOID TIMER_REF;
typedef PVOID MB_HANDLE;
typedef PVOID RG_HANDLE;
#define INVALID_HANDLER_REF (HANDLER_REF)(-1)
#define INVALID_TIMER_REF (TIMER_REF)(-1)
#define INVALID_MB_HANDLE (MB_HANDLE)(-1)
#define INVALID_RG_HANDLE (RG_HANDLE)(-1)
//
// VID public types and enumerations.
//
typedef UINT16 VID_IO_PORT_ADDRESS;
typedef UINT32 VID_MSR_ADDRESS;
typedef UINT32 VID_PROCESSOR_INDEX;
#define VID_ALL_PROCESSORS 0xFFFF
typedef enum _VID_PROCESSOR_STATUS
{
VidProcessorStatusStopped = 0x0,
VidProcessorStatusRunning,
VidProcessorStatusSuspended,
VidProcessorStatusUndefined = 0xFFFF
} VID_PROCESSOR_STATUS;
//
// Types used to get and set Vp state. These types
// currently map 1-to-1 with hypervisor registers, but allow
// the possibility of future VID state.
//
typedef HV_REGISTER_NAME VID_VP_STATE_CODE;
typedef HV_REGISTER_VALUE VID_VP_STATE_VALUE;
//
// Flags used by VidSetupPartition
//
// ..._ENABLE_DEBUGGING - Enable Viridian Unified Debugging (VUD) (see
// hypervisor TLFS).
//
// ..._EXPOSE_HYPERTHREADING - Expose hyperthreading (see hypervisor
// TLFS).
//
#define VID_PARTITION_PROPERTY_FLAG_ENABLE_DEBUGGING (1 << 0)
#define VID_PARTITION_PROPERTY_FLAG_EXPOSE_HYPERTHREADING (1 << 1)
//
// Flags used by VidCreateMessageQueue
//
#define VID_QUEUE_ORDER_NOT_ENFORCED (1 << 0)
//
// Flags used by VidHandleAndGetNextMessage()
//
#define VID_GET_NEXT_MESSAGE (1 << 0)
#define VID_HANDLE_MESSAGE (1 << 1)
//
// The maximum number of threads which can be concurrently handling
// messages on one queue.
//
// The max concurrency is limited by the 32-bit bitmasks used in the dispatch
// interface to manage the exchange buffer.
//
#define VID_QUEUE_MAX_CONCURRENCY \
(32)
//
// Flags used by VidRegisterXxxHandler()
//
#define VID_HANDLER_READ (1 << 0)
#define VID_HANDLER_WRITE (1 << 1)
#define VID_HANDLER_IO_PORT_8BIT (1 << 2)
#define VID_HANDLER_IO_PORT_16BIT (1 << 3)
#define VID_HANDLER_IO_PORT_32BIT (1 << 4)
#define VID_HANDLER_CATCH_ALL (1 << 5)
//
// VSMM related public definitions.
//
typedef UINT64 MB_PAGE_INDEX;
typedef UINT64 GUEST_PHYSICAL_PAGE_INDEX;
typedef UINT64 GUEST_PHYSICAL_ADDRESS;
typedef enum _VID_ACCESS_TYPE
{
VidAccessInvalid = 0x00,
VidAccessReadOnly,
VidAccessReadWrite
} VID_ACCESS_TYPE;
//
// This structure describes a sequence of pages for bulk
// locking and unlocking.
//
typedef struct _VID_BULK_LOCK_RANGE
{
UINT32 ByteCount;
UINT32 ByteOffset;
UINT64 PfnArray[1];
} VID_BULK_LOCK_RANGE, *PVID_BULK_LOCK_RANGE;
//
// Flags values used in VidCreateMemoryBlockGpaRange().
//
#define VID_ROM_GPA_PAGE_RANGE 0x0000000000000001
#define VID_MEMORY_BLOCK_PRIMARY_GPA_PAGE_RANGE 0x0000000000000002
//
// Value used to limit the number of PPMs which can be destroyed in a
// single VID call.
//
#define VID_MAX_PPM_DESTROY_COUNT 256
//
// Flags values used in VidSetMemoryBlockClientNotifications().
//
#define VID_MB_READ_NOTIFY 0x00000001
#define VID_MB_WRITE_NOTIFY 0x00000002
#define VID_APPLY_READ_SETTINGS 0x00010000
#define VID_APPLY_WRITE_SETTINGS 0x00020000
//
// Flags values used in VidCreateMemoryBlock. These flags can be set
// explicitly by the client when VidCreateMemoryBlock is invoked or implicitly
// by the VSMM.
//
#define VID_FLAG_DO_NOT_SHARE_MBPS (UINT64)0x1
#define VID_FLAG_ALLOW_NOTIFICATIONS_ON_LOCKED_MBPS (UINT64)0x2
#define VID_FLAG_DO_NOT_BACK_OVER_COMMIT_MBPS_WITH_SHARED_PAGES (UINT64)0x4
#define VID_FLAG_DO_NOT_BACK_OVER_COMMIT_MBPS_WITH_MM_PAGES (UINT64)0x8
//
// Structures and definitions used by the Vid clients for handling / receiving
// messages from the driver.
//
typedef UINT64 VID_MESSAGE_ID;
typedef LONG VID_MSG_STATUS_CODE;
#define EXCEPTION_INSTRUCTION_SIZE 16
//
// The largest batch read/write INS or OUTS that will
// be sent with a single message. Larger guest operations
// will be sent using multiple messages.
//
#define VID_MAX_IO_STRING (4096)
//
// VID_MESSAGE_TYPE_MASK
//
#define VID_MESSAGE_TYPE_MASK 0x00FFFFFFUL
#define VID_MESSAGE_TYPE_FLAG_NO_RETURN 0x01000000UL
#define VID_MESSAGE_TYPE_FLAG_INTERCEPT 0x02000000UL
//
// VID_MESSAGE_TYPE identifies a message embedded within the VID_MSG_DATA
// structure.
//
// Note: This must be kep in sync with the VID message type information array.
//
typedef enum _VID_MESSAGE_TYPE
{
VidMessageInvalid = 0x0000,
//
// Message types corresponding to hypervisor intercepts.
//
VidMessageCpuid = 0x0001 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
VidMessageMmio = 0x0002 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
VidMessageMbpAccess = 0x0003,
VidMessageMsr = 0x0004 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
VidMessageIoPort = 0x0005 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
VidMessageException = 0x0006 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
VidMessageTripleFault = 0x0007 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
VidMessageApicEoi = 0x0008 | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
VidMessageTimerExpired = 0x0009,
VidMessageLegacyFpError = 0x000A | VID_MESSAGE_TYPE_FLAG_INTERCEPT,
//
// Message types corresponding to other monitored events. These do not
// require a return message.
//
VidMessageHandlerUnregistered = 0x000B | VID_MESSAGE_TYPE_FLAG_NO_RETURN,
VidMessageStopRequestComplete = 0x000C | VID_MESSAGE_TYPE_FLAG_NO_RETURN,
VidMessageSingleStepComplete = 0x000D | VID_MESSAGE_TYPE_FLAG_NO_RETURN,
VidMessageBreakpointHit = 0x000E | VID_MESSAGE_TYPE_FLAG_NO_RETURN,
VidMessageMmioRangeDestroyed = 0x000F | VID_MESSAGE_TYPE_FLAG_NO_RETURN,
VidMessageHvMemoryPolicy = 0x0010 | VID_MESSAGE_TYPE_FLAG_NO_RETURN,
// Must be last
VidMessageTypeCount = 0x0011
} VID_MESSAGE_TYPE;
//
// Message structures for CPUID.
//
typedef struct _VID_MSG_DATA_CPUID
{
UINT32 CpuidFunction;
//
// The values in the registers when CPUID was executed.
//
UINT64 Rax;
UINT64 Rbx;
UINT64 Rdx;
UINT64 Rcx;
//
// The values suggested by the hypervisor as the default
// ones to be placed in the registers by CPUID.
//
UINT64 RaxDefaultReturn;
UINT64 RbxDefaultReturn;
UINT64 RdxDefaultReturn;
UINT64 RcxDefaultReturn;
} VID_MSG_DATA_CPUID, *PVID_MSG_DATA_CPUID;
typedef struct _VID_MSG_RETURN_DATA_CPUID
{
//
// The values to be placed in the registers in order to
// complete the CPUID instruction.
//
UINT64 Rax;
UINT64 Rbx;
UINT64 Rdx;
UINT64 Rcx;
} VID_MSG_RETURN_DATA_CPUID, *PVID_MSG_RETURN_DATA_CPUID;
//
// The maximum size, in bytes, of an MMIO read/write. This value dictates the
// size of the VID message used for passing MMIO data.
//
#define VID_MAX_MMIO_ACCESS_SIZE 16
typedef struct _VID_MSG_DATA_MMIO
{
GUEST_PHYSICAL_ADDRESS Gpa;
UINT32 DataSize;
BOOLEAN AccessIsWrite;
BYTE WriteData[VID_MAX_MMIO_ACCESS_SIZE];
//
// If this field is set, the VID will allow the client to complete
// the entire instruction and return InstructionCompleted = TRUE in
// the return message.
//
BOOLEAN InstructionCompletionAllowed;
} VID_MSG_DATA_MMIO, *PVID_MSG_DATA_MMIO;
typedef struct _VID_MSG_DATA_MMIO_RANGE_DESTROYED
{
UINT8 Reserved;
} VID_MSG_DATA_MMIO_RANGE_DESTROYED, *PVID_MSG_DATA_MMIO_RANGE_DESTROYED;
typedef struct _VID_MSG_RETURN_DATA_MMIO
{
UINT32 ReadDataSize;
BYTE ReadData[VID_MAX_MMIO_ACCESS_SIZE];
//
// If this field is set in the return data, the VID will not take
// further action on this intercept but will simply complete it and
// cause VP execution to resume. This indicates the client has
// completely handled the instruction and the VP state is already correct
// for re-execution.
//
BOOLEAN InstructionCompleted;
} VID_MSG_RETURN_DATA_MMIO, *PVID_MSG_RETURN_DATA_MMIO;
//
// Define the various reasons that can trigger an MBP client notification to
// be sent to user mode.
//
typedef enum _VID_MBP_NOTIFICATION_REASON
{
//
// Notifications triggered when a kernel mode client locks an MBP for
// either read or read/write.
//
VidNotificationReasonLockForRead,
VidNotificationReasonLockForReadWrite,
//
// Notifications triggered when a user mode client maps an MBP for
// either read or read/write.
//
VidNotificationReasonMapForRead,
VidNotificationReasonMapForReadWrite,
//
// Notifications triggered when a Virtual Processor in a child Partition
// accesses a GPA page that maps to the MBP in question.
//
VidNotificationReasonVpRead,
VidNotificationReasonVpWrite
} VID_MBP_NOTIFICATION_REASON;
//
// Represents a user mode client notification for a Memory Block Page.
//
typedef struct _VID_MSG_DATA_MBP_ACCESS
{
VID_MBP_NOTIFICATION_REASON NotificationReason;
MB_HANDLE MemoryBlock;
MB_PAGE_INDEX MbpIndex;
//
// The following fields are only used in case the NotificationReason
// field is either VidNotificationReasonVpRead or
// VidNotificationReasonVpWrite.
//
GUEST_PHYSICAL_PAGE_INDEX GpaPageIndex;
} VID_MSG_DATA_MBP_ACCESS, *PVID_MSG_DATA_MBP_ACCESS;
typedef struct _VID_MSG_DATA_MSR
{
UINT32 MsrAddress;
BOOLEAN AccessIsWrite;
union
{
struct
{
UINT32 LowPart;
UINT32 HighPart;
} u;
UINT64 QuadPart;
} WriteData;
} VID_MSG_DATA_MSR, *PVID_MSG_DATA_MSR;
typedef union _VID_MSG_RETURN_DATA_MSR
{
struct
{
UINT32 LowPart;
UINT32 HighPart;
} u;
UINT64 QuadPart;
} VID_MSG_RETURN_DATA_MSR, *PVID_MSG_RETURN_DATA_MSR;
typedef struct _VID_MSG_DATA_IOPORT
{
UINT16 PortAddress;
UINT16 AccessSize;
BOOLEAN AccessIsWrite;
BOOLEAN AccessIsString;
UINT16 AccessCount;
//
// If this field is set, the VID will allow the client to complete
// the entire instruction and return InstructionCompleted = TRUE in
// the return message.
//
BOOLEAN InstructionCompletionAllowed;
//
// Since the data payload is variable length, it should be at the end of
// the message.
//
union
{
UINT32 SingleWrite;
UINT8 StringWrite[VID_MAX_IO_STRING];
} WriteData;
} VID_MSG_DATA_IOPORT, *PVID_MSG_DATA_IOPORT;
typedef struct _VID_MSG_RETURN_DATA_IOPORT
{
//
// Sampling data.
//
UINT64 MessageReceiptTsc;
UINT64 MessageReturnTsc;
UINT16 DataSize;
UINT16 DataCount;
//
// If this field is set in the return data, the VID will not take
// further action on this intercept but will simply complete it and
// cause VP execution to resume. This indicates the client has
// completely handled the instruction and the VP state is already correct
// for re-execution.
//
BOOLEAN InstructionCompleted;
//
// Since the data payload is variable length, it should be at the end of
// the message.
//
union
{
UINT32 Read;
UINT8 StringRead[VID_MAX_IO_STRING];
} Data;
} VID_MSG_RETURN_DATA_IOPORT, *PVID_MSG_RETURN_DATA_IOPORT;
typedef struct _VID_MSG_DATA_EXCEPTION
{
UINT8 ExceptionVector;
UINT32 ErrorCode;
BOOLEAN ErrorCodeValid;
UINT64 ExceptionParameter;
} VID_MSG_DATA_EXCEPTION, *PVID_MSG_DATA_EXCEPTION;
typedef struct _VID_MSG_RETURN_DATA_EXCEPTION
{
BOOLEAN AdvanceIp;
} VID_MSG_RETURN_DATA_EXCEPTION, *PVID_MSG_RETURN_DATA_EXCEPTION;
typedef struct _VID_MSG_DATA_TRIPLEFAULT
{
UINT8 Reserved;
} VID_MSG_DATA_TRIPLEFAULT, *PVID_MSG_DATA_TRIPLEFAULT;
typedef struct _VID_MSG_RETURN_DATA_TRIPLEFAULT
{
BOOLEAN StopVp;
} VID_MSG_RETURN_DATA_TRIPLEFAULT, *PVID_MSG_RETURN_DATA_TRIPLEFAULT;
typedef struct _VID_MSG_DATA_BREAKPOINT
{
UINT64 Gva;
} VID_MSG_DATA_BREAKPOINT, *PVID_MSG_DATA_BREAKPOINT;
typedef struct _VID_MSG_DATA_TIMER
{
UINT64 ExpirationTime;
UINT64 CurrentReferenceTime;
} VID_MSG_DATA_TIMER, *PVID_MSG_DATA_TIMER;
typedef struct _VID_MSG_RETURN_DATA_TIMER
{
BOOLEAN ResetTimer;
UINT64 NewExpirationTime;
} VID_MSG_RETURN_DATA_TIMER, *PVID_MSG_RETURN_DATA_TIMER;
typedef struct _VID_MSG_DATA_HANDLER_UNREGISTER
{
HANDLER_REF HandlerRef;
} VID_MSG_DATA_HANDLER_UNREGISTER, *PVID_MSG_DATA_HANDLER_UNREGISTER;
typedef struct _VID_MSG_DATA_STOP
{
UINT8 Reserved;
} VID_MSG_DATA_STOP;
typedef struct _VID_MSG_DATA_SINGLESTEP
{
UINT64 Rip;
} VID_MSG_DATA_SINGLESTEP;
typedef struct _VID_MSG_DATA_APIC_EOI
{
HV_INTERRUPT_VECTOR InterruptVector;
} VID_MSG_DATA_APIC_EOI, *PVID_MSG_DATA_APIC_EOI;
typedef struct _VID_MSG_DATA_LEGACY_FP_ERROR
{
HV_INTERRUPT_VECTOR InterruptVector;
} VID_MSG_DATA_LEGACY_FP_ERROR, *PVID_MSG_DATA_LEGACY_FP_ERROR;
typedef struct _VID_MSG_HV_MEMORY_POLICY
{
UINT64 CurrentDepositTotalKb;
} VID_MSG_HV_MEMORY_POLICY, *PVID_MSG_HV_MEMORY_POLICY;
//
// Message information returned by the driver to a registered VID client.
//
typedef struct _VID_MSG_DATA
{
VID_MESSAGE_ID MessageID;
VID_MESSAGE_TYPE MessageType;
UINT32 PayloadSizeInBytes;
//
// Sampling data.
//
UINT64 MessageReceiptTsc;
PVOID UserContext; // Used for all message types.
UINT32 ProcessorIndex; // Used for most message types.
union
{
VID_MSG_DATA_CPUID Cpuid;
VID_MSG_DATA_MMIO Mmio;
VID_MSG_DATA_MBP_ACCESS MbpAccess;
VID_MSG_DATA_MSR Msr;
VID_MSG_DATA_IOPORT IoPort;
VID_MSG_DATA_EXCEPTION Exception;
VID_MSG_DATA_TRIPLEFAULT TripleFault;
VID_MSG_DATA_APIC_EOI ApicEoi;
VID_MSG_DATA_LEGACY_FP_ERROR LegacyFpError;
VID_MSG_DATA_BREAKPOINT Breakpoint;
VID_MSG_DATA_HANDLER_UNREGISTER HandlerUnregister;
VID_MSG_DATA_STOP Stop;
VID_MSG_DATA_SINGLESTEP SingleStep;
VID_MSG_DATA_TIMER Timer;
VID_MSG_DATA_MMIO_RANGE_DESTROYED MmioRangeDestroyed;
VID_MSG_HV_MEMORY_POLICY HvMemoryPolicy;
} Data;
} VID_MSG_DATA, *PVID_MSG_DATA;
typedef const PVID_MSG_DATA PCVID_MSG_DATA;
//
// Information sent to the driver by a VID client when handling a message.
//
typedef struct _VID_MSG_RETURN_DATA
{
VID_MESSAGE_ID MessageID;
VID_MSG_STATUS_CODE StatusCode;
UINT32 PayloadSizeInBytes;
//
// Sampling data.
//
UINT64 MessageReturnTsc;
union
{
VID_MSG_RETURN_DATA_CPUID Cpuid;
VID_MSG_RETURN_DATA_MMIO Mmio;
VID_MSG_RETURN_DATA_MSR Msr;
VID_MSG_RETURN_DATA_IOPORT IoPort;
VID_MSG_RETURN_DATA_EXCEPTION Exception;
VID_MSG_RETURN_DATA_TRIPLEFAULT TripleFault;
VID_MSG_RETURN_DATA_TIMER Timer;
} Data;
} VID_MSG_RETURN_DATA, *PVID_MSG_RETURN_DATA;
//
// A simple wrapper object which contains a data message and the return
// message, which is used to define shared communication memory for a message
// queue object.
//
// FUTURE-kbroas-2007/03/07: To save memory (and increase the number of
// exchange buffer slots available), It may be possible to make a union of the
// data message and associated return data? Can clients handle
// overwritting the message data? Are there cases where both are used
// simultaneously?
//
typedef struct _VID_MESSAGE_EXCHANGE_BUFFER
{
//
// The outgoing message.
//
VID_MSG_DATA DataMessage;
//
// The return message.
//
VID_MSG_RETURN_DATA ReturnDataMessage;
//
// Sanity check via user context cookie
UINT64 Cookie;
} VID_MESSAGE_EXCHANGE_BUFFER, *PVID_MESSAGE_EXCHANGE_BUFFER;
//
// Flags for Save & Restore
//
#define VID_SAVE_STATE_HEADER_ONLY (1 << 1)
#define VID_SAVE_STATE_PREFLIGHT_ONLY (1 << 2)
//
// This structure defines the descriptor for VID partition saved states,
// which will occur at the beginning of all (otherwise opaque) saved
// state blobs.
//
typedef struct _VID_SAVED_STATE_DESCRIPTOR
{
//
// Size of this descriptor structure.
//
UINT64 DescriptorSize;
//
// Size of the pre-data sections, which includes
// the descriptor and header areas.
//
UINT64 HeaderSize;
//
// Total size of the blob, which includes descriptor,
// header, and data areas.
//
UINT64 TotalSize;
} VID_SAVED_STATE_DESCRIPTOR, *PVID_SAVED_STATE_DESCRIPTOR;
typedef struct _VID_MESSAGE_INFO
{
UINT32 DataSendPayloadSizeInBytes;
UINT32 DataRecvPayloadSizeInBytes;
} VID_MESSAGE_INFO, *PVID_MESSAGE_INFO;
#define VID_MESSAGE_TYPE_INDEX(_MessageType) \
((((_MessageType) & VID_MESSAGE_TYPE_MASK) < VidMessageTypeCount) ? \
((_MessageType) & VID_MESSAGE_TYPE_MASK) : VidMessageInvalid)
#define VID_MESSAGE_INFO_GET(_MessageType) \
(&VidMessageInfoArray[VID_MESSAGE_TYPE_INDEX(_MessageType)])
#define VID_MESSAGE_INFO_GET_PROPERTY(_MessageType, _Property) \
(VID_MESSAGE_INFO_GET(_MessageType)->_Property)
#define VID_MESSAGE_INFO_GET_DATA_SEND_PAYLOAD_SIZE(_MessageType) \
(VID_MESSAGE_INFO_GET_PROPERTY(_MessageType, DataSendPayloadSizeInBytes))
#define VID_MESSAGE_INFO_GET_DATA_RECV_PAYLOAD_SIZE(_MessageType) \
(VID_MESSAGE_INFO_GET_PROPERTY(_MessageType, DataRecvPayloadSizeInBytes))
#define VID_MESSAGE_DATA_SEND_PAYLOAD_SIZE_MAX \
(sizeof(VID_MSG_DATA) - offsetof(VID_MSG_DATA, Data))
#define VID_MESSAGE_DATA_RECV_PAYLOAD_SIZE_MAX \
(sizeof(VID_MSG_RETURN_DATA) - offsetof(VID_MSG_RETURN_DATA, Data))
//
// Copy full message for send data
//
#define VID_MESSAGE_COPY_DATA_SEND_FULL(_DataSendDst, _DataSendSrc) \
do \
{ \
ASSERT(_DataSendDst != NULL); \
ASSERT(_DataSendSrc != NULL); \
ASSERT((_DataSendSrc)->PayloadSizeInBytes <= \
VID_MESSAGE_DATA_SEND_PAYLOAD_SIZE_MAX); \
if ((_DataSendSrc)->PayloadSizeInBytes > \
VID_MESSAGE_DATA_SEND_PAYLOAD_SIZE_MAX) \
{ \
(_DataSendSrc)->PayloadSizeInBytes = \
VID_MESSAGE_DATA_SEND_PAYLOAD_SIZE_MAX; \
} \
RtlCopyMemory( \
(_DataSendDst), \
(_DataSendSrc), \
offsetof(VID_MSG_DATA, Data) + (_DataSendSrc)->PayloadSizeInBytes); \
} while (0)
//
// Copy full message for receive / return data
//
#define VID_MESSAGE_COPY_DATA_RECV_FULL(_DataRecvDst, _DataRecvSrc) \
do \
{ \
ASSERT(_DataRecvDst != NULL); \
ASSERT(_DataRecvSrc != NULL); \
ASSERT((_DataRecvSrc)->PayloadSizeInBytes <= \
VID_MESSAGE_DATA_RECV_PAYLOAD_SIZE_MAX); \
if ((_DataRecvSrc)->PayloadSizeInBytes > \
VID_MESSAGE_DATA_RECV_PAYLOAD_SIZE_MAX) \
{ \
(_DataRecvSrc)->PayloadSizeInBytes = \
VID_MESSAGE_DATA_RECV_PAYLOAD_SIZE_MAX; \
} \
RtlCopyMemory( \
(_DataRecvDst), \
(_DataRecvSrc), \
offsetof(VID_MSG_RETURN_DATA, Data) + (_DataRecvSrc)->PayloadSizeInBytes); \
} while (0)
//
// Copy payload only for message send data
//
#define VID_MESSAGE_COPY_DATA_SEND_PAYLOAD_ONLY(_DataSendDst, _DataSendSrc) \
do \
{ \
ASSERT(_DataSendDst != NULL); \
ASSERT(_DataSendSrc != NULL); \
ASSERT((_DataSendSrc)->PayloadSizeInBytes <= \
VID_MESSAGE_DATA_SEND_PAYLOAD_SIZE_MAX); \
if ((_DataSendSrc)->PayloadSizeInBytes > \
VID_MESSAGE_DATA_SEND_PAYLOAD_SIZE_MAX) \
{ \
(_DataSendSrc)->PayloadSizeInBytes = \
VID_MESSAGE_DATA_SEND_PAYLOAD_SIZE_MAX; \
} \
if ((_DataSendSrc)->PayloadSizeInBytes) \
{ \
RtlCopyMemory( \
&(_DataSendDst)->Data, \
&(_DataSendSrc)->Data, \
(_DataSendSrc)->PayloadSizeInBytes); \
} \
(_DataSendDst)->PayloadSizeInBytes = (_DataSendSrc)->PayloadSizeInBytes; \
} while (0)
//
// Copy payload only for message receive / return data
//
#define VID_MESSAGE_COPY_DATA_RECV_PAYLOAD_ONLY(_DataRecvDst, _DataRecvSrc) \
do \
{ \
ASSERT(_DataRecvDst != NULL); \
ASSERT(_DataRecvSrc != NULL); \
ASSERT((_DataRecvSrc)->PayloadSizeInBytes <= \
VID_MESSAGE_DATA_RECV_PAYLOAD_SIZE_MAX); \
if ((_DataRecvSrc)->PayloadSizeInBytes > \
VID_MESSAGE_DATA_RECV_PAYLOAD_SIZE_MAX) \
{ \
(_DataRecvSrc)->PayloadSizeInBytes = \
VID_MESSAGE_DATA_RECV_PAYLOAD_SIZE_MAX; \
} \
if ((_DataRecvSrc)->PayloadSizeInBytes) \
{ \
RtlCopyMemory( \
&(_DataRecvDst)->Data, \
&(_DataRecvSrc)->Data, \
(_DataRecvSrc)->PayloadSizeInBytes); \
} \
(_DataRecvDst)->PayloadSizeInBytes = (_DataRecvSrc)->PayloadSizeInBytes; \
} while (0)