Marshal Data Between Memory Buffers (Compact 2013)
3/26/2014
In Windows Embedded Compact 2013, each process has its own virtual memory space and memory context. When an application moves data to or from your device driver, you must marshal the data between the address space of the application and the address space of your device driver. You marshal data in one of two ways:
- Copy the data between the application memory buffer and a memory buffer that your device driver manages.
- Map the virtual memory address of the application memory buffer to a physical memory location so that your device driver can directly access the application memory buffer without making an extra copy.
You can use the kernel buffer marshaling functions in the following table to marshal data between an application and your device driver.
Function |
Description |
---|---|
Checks access and marshals a buffer pointer from the source process so that the current process can access it. |
|
Frees any resources that CeOpenCallerBuffer allocated. |
|
Remarshals a buffer that CeOpenCallerBuffer already marshaled so that the server can use it asynchronously after returning from the API call. |
|
Abstracts the work that is required to make secure copies of the API parameters. |
|
Frees any resources that CeAllocAsynchronousBuffer allocated. |
|
Frees a duplicate buffer that CeAllocDuplicateBuffer allocated. |
|
Flushes any changed data between the source and the destination buffer that CeAllocAsynchronousBuffer allocated. |
Note that your device driver must explicitly map all the pointers that the data structures contain. For example, DeviceIoControl buffers are often structures that contain data, and some of this data could be pointers to other data structures. For more information about buffer marshaling functions, see Kernel Buffer Marshaling Reference.
Synchronous and Asynchronous Access
In Windows Embedded Compact 2013, marshaling depends on whether a pointer is used synchronously or asynchronously. If a pointer parameter or embedded pointer is used synchronously, the address space of the calling process is accessible for the duration of a call to the driver. This availability eliminates the need for a copy. The driver can use, unchanged, the calling process pointer, which can then directly access the memory of the caller. This is the direct access method of marshaling.
If your driver uses a pointer asynchronously, it is critical that the caller memory buffer be accessible when the address space of the caller is unavailable. Windows Embedded Compact 2013 includes the CeAllocAsynchronousBuffer and CeFreeAsynchronousBuffer functions for drivers to marshal pointer parameters and embedded pointers when your driver needs asynchronous access to a caller memory buffer. When a thread like an IST requires access to the caller buffer, these marshaling helper functions choose between copying the data or using a buffer aliasing mechanism to avoid copying data. This choice is dependent on the size of the buffer involved. If the buffer is small enough, the kernel duplicates the buffer by copying the data. However, this duplication can affect performance, and if the buffer is too large to duplicate, the kernel creates an alias for the buffer instead of copying the data.
The following code is an example of marshaling pointers for asynchronous access in a device driver IOControl function.
// In XXX_IOControl
// CeOpenCallerBuffer generates g_pMappedEmbedded
// . . .
hr = CeAllocAsynchronousBuffer((PVOID *) &g_pMarshaled,
g_pMappedEmbedded, pInput->dwSize, ARG_I_PTR);
// Check for FAILED(hr) == true, handle the error.
// . . .
// Use the pointer
// . . .
// When done with the pointer:
Hr = CeFreeAsynchronousBuffer((PVOID)g_pMarshaled,
g_pMappedEmbedded, pInput->dwSize, ARG_I_PTR);
// Call CeCloseCallerBuffer . . .
For more information about asynchronous access, see CeAllocAsynchronousBuffer.