Marshalling for Windows Embedded CE 6.0 Driver Migration
Other versions of this page are also available for the following:
In Windows CE 5.0 and earlier, the MapCallerPtrfunction also performed marshalling for pointers. A driver called MapCallerPtr on parameters as well as embedded pointers both for validation and marshalling.
In Windows Embedded CE 6.0, marshalling is dependent on if 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 into the driver. This eliminates any requirements for marshalling. The pointer of the calling process can be used unchanged by the driver, which can then access the memory of the caller directly. This method of marshalling is referred to as direct access.
However, if a pointer is used asynchronously, it is critical that the caller buffer is accessible when the caller's address space is unavailable. This means that direct access is not possible for any kind of asynchronous work after the call has returned. Windows Embedded CE 6.0 includes the CeAllocAsynchronousBuffer and CeFreeAsynchronousBuffer functions for drivers to marshal pointer parameters and embedded pointers when asynchronous access is required. For example, when a thread such as the IST requires access to the buffer of the caller, the marshalling helper functions can choose between the duplication and aliasing marshalling mechanisms. This is dependant on the size of the buffer involved. If the buffer is small enough, the kernel duplicates the buffer. However, this can affect performance, and if the buffer is too large to duplicate, the kernel will alias the buffer instead.
The following code example shows some of the code changes associate with marshalling when pointers are required to be accessed asynchronously.
// Pre-Windows Embedded CE 6.0 = MapCallerPtr //Now in Windows Embedded CE 6.0 // In XXX_IOControl after CeOpenCallerPtr generates // g_pMappedEmbedded hr = CeAllocAsynchronousBuffer((PVOID*) &g_pMarshalled, g_pMappedEmbedded, pInput->dwSize, ARG_I_PTR); // Fail if FAILED(hr) == true // // When done with pointer hr = CeFreeAsynchronousBuffer((PVOID)g_pMarshalled, g_pMappedEmbedded, pInput->dwSize, ARG_I_PTR); // Now call CeCloseCallerBuffer as usual