> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# PFPlatformLocalStorageReadAsyncHandler

> Storage handler that PlayFab calls to read the data stored under a key; it starts an XAsync operation that completes with the number of bytes read.

Read-from-storage handler that PlayFab calls when it needs to read data from storage. Implement it as an [XAsyncProvider](https://docs.xbox.com/reference/system/xasyncprovider/functions/xasyncprovider.md).

## Syntax

```cpp theme={null}
HRESULT STDAPIVCALLTYPE PFPlatformLocalStorageReadAsyncHandler(
    void* context,
    const char* key,
    XAsyncBlock* async
);
```

### Parameters

**`context`**   `_In_opt_` void\*

The `context` member of the [PFLocalStorageHooks](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/structs/pflocalstoragehooks.md) structure that you passed to [PFPlatformLocalStorageSetHandlers](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/functions/pfplatformlocalstoragesethandlers.md). Can be `nullptr`. PlayFab doesn't own this pointer.

**`key`**   `_In_z_` const char\*

Identifies the data. Typically a file path. Read the data stored under this key.

**`async`**   `_Inout_` [XAsyncBlock](https://docs.xbox.com/reference/system/xasync/structs/xasyncblock.md)\*

The `XAsyncBlock` for the read operation.

### Return value

Type: HRESULT

Return `S_OK` if you started the asynchronous operation on `async`, for example with [XAsyncBegin](https://docs.xbox.com/reference/system/xasyncprovider/functions/xasyncbegin.md). 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](https://docs.xbox.com/reference/system/xasyncprovider/functions/xasynccomplete.md).

## Remarks

To install this handler, set it in the `read` member of a [PFLocalStorageHooks](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/structs/pflocalstoragehooks.md) structure, together with the other two storage handlers, and pass the structure to [PFPlatformLocalStorageSetHandlers](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/functions/pfplatformlocalstoragesethandlers.md) before you call [PFInitialize](https://docs.xbox.com/services/playfab/api-references/c/pfcore/functions/pfinitialize.md). 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](https://docs.xbox.com/reference/system/xasyncprovider/functions/xasynccomplete.md), passing the result of the read and the size, in bytes, of the data that you read. PlayFab then calls `XAsyncGetResultSize` and `XAsyncGetResult` to copy the data, so your provider must copy the data into the `buffer` member of [XAsyncProviderData](https://docs.xbox.com/reference/system/xasyncprovider/structs/xasyncproviderdata.md) when it receives `XAsyncOp::GetResult`.

If no data is stored under `key`, the default implementation completes the operation with `S_OK` and a result size of 0. Do the same in your handler.

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](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/pfplatform_members.md)

[PFLocalStorageHooks](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/structs/pflocalstoragehooks.md)

[PFPlatformLocalStorageSetHandlers](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/functions/pfplatformlocalstoragesethandlers.md)

[XAsyncProvider](https://docs.xbox.com/reference/system/xasyncprovider/functions/xasyncprovider.md)

[PFPlatformLocalStorageWriteAsyncHandler](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/functions/pfplatformlocalstoragewriteasynchandler.md)

[PFPlatformLocalStorageClearAsyncHandler](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/functions/pfplatformlocalstorageclearasynchandler.md)


## Related topics

- [PFPlatformLocalStorageWriteAsyncHandler](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/functions/pfplatformlocalstoragewriteasynchandler.md)
- [PFPlatformLocalStorageClearAsyncHandler](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/functions/pfplatformlocalstorageclearasynchandler.md)
- [PFLocalStorageHooks](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/structs/pflocalstoragehooks.md)
- [Services C API overview - PFPlatform.h](https://docs.xbox.com/services/playfab/api-references/c/pfplatform/pfplatform_members.md)
- [XblLocalStorageReadHandler](https://docs.xbox.com/reference/live/xsapi-c/platform_c/functions/xbllocalstoragereadhandler.md)
