Share via


MarshalledBuffer_t (Compact 2013)

3/28/2014

This class is a wrapper for the CeOpenCallerBuffer, the CeCloseCallerBuffer, the CeAllocAsynchronousBuffer, and the CeFreeAsynchronousBuffer functions. Only use it with embedded pointers that have not already been access-checked or marshaled by the kernel.

To duplicate a buffer that has already been marshaled, use the DuplicatedBuffer_t function. To obtain asynchronous access to a buffer that has already been marshaled, use the AsynchronousBuffer_t function.

Syntax

class MarshalledBuffer_t {
public:
   MarshalledBuffer_t()
        MarshalledBuffer_t()

      MarshalledBuffer_t(
            PVOID pSrcUnmarshalled,
            DWORD cbSrc,
            DWORD ArgumentDescriptor,
            BOOL  ForceDuplicate = TRUE,
            BOOL  Asynchronous = FALSE
      );

      MarshalledBuffer_t(
            PCVOID pSrcUnmarshalled,
          DWORD cbSrc,
            DWORD ArgumentDescriptor,
            BOOL  ForceDuplicate = TRUE,
            BOOL  Asynchronous = FALSE
      );

      HRESULT Marshal(
            PVOID pSrcUnmarshalled,
            DWORD cbSrc,
            DWORD ArgumentDescriptor,
            BOOL  ForceDuplicate = TRUE,
            BOOL  Asynchronous = FALSE
      );

      HRESULT Marshal(
            PCVOID pSrcUnmarshalled,
            DWORD cbSrc,
            DWORD ArgumentDescriptor,
            BOOL  ForceDuplicate = TRUE,
            BOOL  Asynchronous = FALSE
      );

      HRESULT Flush();
      HRESULT Unmarshal();
          LPVOID ptr() const;
          DWORD size() const;
};

Methods

Methods

Description

MarshalledBuffer_t();
~MarshalledBuffer_t();

Access-checks and marshals a buffer pointer from the source process, so that it can be accessed by the current process. Exposes the marshaled pointer with the ptr accessor. Any allocated resources related to the marshaling are freed only by a subsequent call to Unmarshal, or by the destructor.

Typically, you would either use the default constructor and Marshal to marshal the buffer or the marshaling constructor. Use the former method if you require an HRESULT. Similarly, you can allow the destructor to release marshaling resources, or use Unmarshal. If an HRESULT is required, use the Unmarshal function.

MarshalledBuffer_t(
    PVOID pSrcUnmarshalled,
    DWORD cbSrc,
    DWORD ArgumentDescriptor,
    BOOL  ForceDuplicate = TRUE,
    BOOL  Asynchronous = FALSE
);

If marshaling fails, ptr returns NULL, and size retursn zero.

Otherwise, the marshaled buffer is accessible with ptr and size.

For more information, see CeOpenCallerBuffer and CeAllocAsynchronousBuffer.

MarshalledBuffer_t(
    PCVOID pSrcUnmarshalled,
    DWORD cbSrc,
    DWORD ArgumentDescriptor,
    BOOL  ForceDuplicate = TRUE,
    BOOL  Asynchronous = FALSE
);

Takes a constructor pSrcUnmarshalled. This method can be used only with ARG_I_* types.

AsynchronousBuffer_t {
    PVOID  pSrcMarshalled,
    DWORD cbSrc,
    DWORD ArgumentDescriptor
};

Takes a constructor pSrcMarshalled.

AsynchronousBuffer_t {
    PCVOID  pSrcMarshalled,
    DWORD cbSrc,
    DWORD ArgumentDescriptor
};

Takes a constructor pSrcMarshalled. This method can only be used with ARG_I_* types.

DuplicatedBuffer_t {
    PVOID  pSrcMarshalled,
    DWORD cbSrc,
    DWORD ArgumentDescriptor
};

Takes a constructor pSrcMarshalled.

DuplicatedBuffer_t(
    PCVOID pSrcMarshalled,
    DWORD cbSrc,
    DWORD ArgumentDescriptor
);

Takes a const pSrcMarshalled. This method can be used only with ARG_I_* types.

HRESULT Marshal(
    PVOID pSrcUnmarshalled,
    DWORD cbSrc,
    DWORD ArgumentDescriptor,
    BOOL  ForceDuplicate = TRUE,
    BOOL  Asynchronous = FALSE
);

Once a MarshalledBuffer is marshaled using the marshaling constructor or the Marshal method, it cannot be re-used by calling Marshal until after Unmarshal is called. An attempt to do so returns ERROR_ALREADY_EXISTS.

If Marshal fails, ptr returns NULL, and size returns zero.

Otherwise, the marshaled buffer is accessible with ptr and size.

For more information, see CeOpenCallerBuffer and CeAllocAsynchronousBuffer.

HRESULT Marshal(
    PCVOID pSrcUnmarshalled,
    DWORD cbSrc,
    DWORD ArgumentDescriptor,
    BOOL  ForceDuplicate = TRUE,
    BOOL  Asynchronous = FALSE
);

Takes a constructor pSrcUnmarshalled. This method can be used only with ARG_I_* types.

HRESULT Flush();

If the buffer has already been unmarshaled or if it is not an asynchronous buffer, this method fails with ERROR_INVALID_PARAMETER.

For more information, see CeFlushAsynchronousBuffer.

HRESULT Unmarshal();

If the buffer has already been unmarshaled, this method fails with ERROR_ALREADY_EXISTS.

For more information, see CeCloseCallerBuffer.

LPVOID ptr() const;

Returns a pointer to the marshaled buffer, or NULL if the buffer has not been marshaled or has already been unmarshaled.

DWORD size() const;

Returns the size of the marshaled buffer, or zero if the buffer has not been marshaled or has already been unmarshaled.

Remarks

You may choose to optimize large asynchronous buffer accesses by using the MARSHAL_FORCE_ALIAS flag. If your code is running inside the kernel process, and you are using an ARM microprocessor with a virtually tagged cache, you can pass MARSHAL_FORCE_ALIAS as part of the ArgumentDescriptor. On all other CPUs, MARSHAL_FORCE_ALIAS has no effect.

Use the MARSHAL_FORCE_ALIAS flag only if you are using buffers greater than 16 KB.

On ARM CPUs that use a virtually tagged cache, inside the kernel process, CeAllocAsynchronousBuffer creates a duplicate copy of the memory on the heap by default. On large buffers, creating the duplicate heap can affect performance. To prevent duplication, pass the MARSHAL_FORCE_ALIAS flag to cause CeAllocAsynchronousBuffer to create an alias, instead. However, the creation of aliased memory on ARM CPUs that use a virtually tagged cache causes both the source and destination memory to be accessed as uncached, until the alias is destroyed by CeFreeAsynchronousBuffer. This means that the memory accesses become slower at both the source and destination.

On all CPUs, inside user-mode processes, CeAllocAsynchronousBuffer always creates a duplicate of the memory with VirtualCopy, regardless of whether the MARSHAL_FORCE_ALIAS flag is passed. There is no way to force the creation of an alias from user mode.

If you pass MARSHAL_FORCE_ALIAS to CeAllocAsynchronousBuffer, you should also pass it when you call CeFlushAsynchronousBuffer and CeFreeAsynchronousBuffer. Not passing it can cause the system to become unresponsive or resource leaks.

The following table describes the descriptors.

Descriptors

Purpose

ARG_I_PTR

Input-only pointer.

ARG_I_WSTR

Input-only Unicode string.

ARG_I_ASTR

Input-only ASCII string.

ARG_I_PDW

Input-only pointer to a DWORD.

ARG_O_PTR

Output-only pointer.

ARG_O_PDW

Output-only pointer to a DWORD.

ARG_O_PI64

Output-only pointer to a 64-bit value.

ARG_IO_PTR

Input and output pointer.

ARG_IO_PDW

I/O pointer to a DWORD.

ARG_IO_PI64

I/O pointer to a 64-bit value.

Requirements

Header

marshal.hpp

Library

coredll.lib

See Also

Reference

Kernel Buffer Marshaling Classes
CeOpenCallerBuffer
CeCloseCallerBuffer
CeAllocAsynchronousBuffer
CeFlushAsynchronousBuffer
CeFreeAsynchronousBuffer
DuplicatedBuffer_t
AsynchronousBuffer_t