CeAllocAsynchronousBuffer (Compact 7)

3/12/2014

This function re-marshals a buffer that was already marshaled by CeOpenCallerBuffer so that the server can use it asynchronously after the API call has returned. Call this function synchronously before your API call returns. You cannot call this function asynchronously. This function allocates resources that must be freed by a subsequent call to CeFreeAsynchronousBuffer.

For more information about parameter descriptors see MarshalledBuffer_t.

Syntax

HRESULT CeAllocAsynchronousBuffer(
  PVOID * ppDestAsyncMarshalled,
  PVOID pSrcSyncMarshalled,
  DWORD cbSrc,
  DWORD ArgumentDescriptor
);

Parameters

  • ppDestAsyncMarshalled
    [out] Receives a pointer that the current process can use to access the buffer asynchronously.
  • pSrcSyncMarshalled
    [in] Pointer to the buffer that has already been marshaled for synchronous access by the current process.
  • cbSrc
    [in] Size of the marshalled buffer, in bytes. If the ArgumentDescriptor is a WSTR or ASTR, a size of zero can be used. If the size of a string is non-zero, it must include a terminating NULL.
  • ArgumentDescriptor
    [in] Descriptor explaining what kind of parameter the buffer is. For example, ARG_I_WSTR or ARG_O_PTR. ARG_DW is NOT a valid descriptor for marshaling.

    If you are running inside the kernel process and you are using an ARM microprocessor with a virtually tagged cache, you can pass MARSHAL_FORCE_ALIAS as the ArgumentDescriptor. On all other CPUs, inside the kernel process, CeAllocAsynchronousBuffer always creates an alias to the memory with VirtualCopy. On ARM CPUs that use a virtually tagged cache inside the kernel process, CeAllocAsynchronousBuffer will creates a duplicate copy of the memory on the heap by default. On large buffers, creating the duplicate heap can have an effect on 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 cause both the source and destination memory to be accessed as uncached, until the alias is destroyed by CeFreeAsynchronousBuffer. This means that memory accesses become slower at both the source and destination.

    Do not use the MARSHAL_FORCE_ALIAS flag unless you are using buffers greater than 16 KB.

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

Return Value

  • E_ACCESSDENIED
    The source buffer was an invalid address.
  • E_INVALIDARG
    The pSrcUnmarshalled parameter was NULL, or the length was zero.
  • E_OUTOFMEMORY
    The memory allocation failed.
  • S_OK
    The allocation and duplication, if necessary, succeeded.

Remarks

In kernel mode, you can call CeAllocAsynchronousBuffer on an API parameter that has already been marshaled by the kernel. The AsynchronousBuffer_t class has also been provided for this purpose. However if there is any chance that your code will run in user mode, do not use CeAllocAsynchronousBuffer or AsynchronousBuffer_t in this manner. Instead, use the user-mode instructions below. If you attempt to call CeAllocAsynchronousBuffer on an API parameter in user mode, the buffer becomes inaccessible after the synchronous call returns, or the buffer may be reused for other purposes.

In user mode, you can define the API function signature so that the parameter that is to be accessed asynchronously is declared as an ARG_DW value to prevent the kernel from automatically marshaling the parameter for you. Then call CeOpenCallerBuffer to marshal the parameter, and CeAllocAsynchronousBuffer subsequently. If you cannot change the function signature, for example, you cannot change the signature of the ReadFile and WriteFile functions exported by stream drivers, you cannot access the buffer asynchronously in user mode.

CeAllocAsynchronousBuffer is not required for buffers that have been duplicated by CeAllocDuplicateBuffer. You do not need to do anything in order to use those buffers asynchronously. Those buffers can be used until they are closed and freed. However, if you call CeAllocAsynchronousBuffer on a duplicated buffer, it works. In that case, you must not call CeFreeDuplicateBuffer until after you have called CeFreeAsynchronousBuffer.

This function does not allocate any resources if the call fails or if the source buffer was NULL. If duplication is required but no memory is allocated, the pointer returned by CeFreeAsynchronousBuffer is NULL.

This function is protected by __try/__except so that it does not throw an exception while accessing the input pointer pSrcSyncMarshalled.

Use the SUCCEEDED and FAILED macros to test the return value of this function.

Link Library: Coredll.lib.

Requirements

Header

kernsdk.h

Library

coredll.lib

See Also

Reference

Kernel Buffer Marshaling Functions
MarshalledBuffer_t
AsynchronousBuffer_t
CeOpenCallerBuffer
CeFreeAsynchronousBuffer
CeFlushAsynchronousBuffer

Other Resources

ReadFile
WriteFile