Skip to main content
Write-to-storage handler that PlayFab calls when it needs to write data to storage. Implement it as an XAsyncProvider.

Syntax

Parameters

context   _In_opt_ void* The context member of the PFLocalStorageHooks structure that you passed to PFPlatformLocalStorageSetHandlers. Can be nullptr. PlayFab doesn’t own this pointer. key   _In_z_ const char* Identifies the data. Typically a file path. Write the data under this key. dataSize   _In_ size_t The size, in bytes, of data. data   _In_reads_bytes_(dataSize) void const* The data to write. async   _Inout_ XAsyncBlock* The XAsyncBlock for the write operation.

Return value

Type: HRESULT Return S_OK if you started the asynchronous operation on async, for example with XAsyncBegin. If the handler returns a failure HRESULT, PlayFab fails the storage operation with that HRESULT and doesn’t wait for async to complete, so return a failure only when you haven’t started an operation on async. Report the result of the storage operation itself by completing async with XAsyncComplete.

Remarks

To install this handler, set it in the write member of a PFLocalStorageHooks structure, together with the other two storage handlers, and pass the structure to PFPlatformLocalStorageSetHandlers before you call PFInitialize. PFPlatformLocalStorageSetHandlers returns E_INVALIDARG if any of the three handlers is nullptr. If you don’t set custom handlers, PlayFab uses a default implementation based on cstdio and std::fstream objects. Complete async with XAsyncComplete, passing the result of the write and a result size of 0. The default implementation appends data to the existing data for key; it doesn’t replace it. PlayFab depends on this behavior: when trace output to a file is enabled with PFTraceEnableTraceToFile, PlayFab clears the trace file once and then writes each trace message as a separate write to the same key. Append in your handler too, or the trace file keeps only the last message. data stays valid until the operation completes. Copy it if you need it after that. PlayFab can call this handler inline on the thread that starts the storage operation, so don’t depend on which thread it runs on. The queue of async is a queue that PlayFab derives from the queueHandle member of PFLocalStorageHooks. If queueHandle is nullptr, PlayFab derives it from the background queue that you passed to PFInitialize, or from the process task queue if that queue was also nullptr. The work and completion callbacks of the derived queue both run on the work port of the queue that it’s derived from. PlayFab runs one storage operation at a time and starts the next one only after the current one completes. PlayFab can cancel a pending operation by calling XAsyncCancel on async. Handle XAsyncOp::Cancel in your provider if your storage operation can be canceled. The key and async arguments are owned by PlayFab and stay valid until the operation completes. The context argument isn’t covered by this guarantee.

Requirements

Header: PFPlatform.h Library: PlayFabCore.lib Supported platforms: Windows, XBOX One family consoles, and XBOX Series consoles

See also

PFPlatform members PFLocalStorageHooks PFPlatformLocalStorageSetHandlers XAsyncProvider PFPlatformLocalStorageReadAsyncHandler PFPlatformLocalStorageClearAsyncHandler
Last modified on November 3, 2026