cfapi CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS calls back repeatedly

Chris Wheeler 1 Reputation point
2020-08-14T09:50:38.29+00:00

Bringing this here from Stack...

I'm working with the cfapi and are attempting to extend the sample project available here https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/CloudMirror

Specifically we are looking to implement the CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS to provide directory content on-demand. Our callbacks are registered like so:-

CF_CALLBACK_REGISTRATION FakeCloudProvider::s_MirrorCallbackTable[] =
{
    { CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS, FakeCloudProvider::OnFetchPlaceholders },
    { CF_CALLBACK_TYPE_FETCH_DATA, FakeCloudProvider::OnFetchData },
    { CF_CALLBACK_TYPE_CANCEL_FETCH_DATA, FakeCloudProvider::OnCancelFetchData },
    CF_CALLBACK_REGISTRATION_END
};

The OnFetchPlaceholders method calls CfExecute() to respond to the callback with an array of placeholders for the associated files in the server directory.

CF_OPERATION_INFO opInfo = { 0 };
CF_OPERATION_PARAMETERS opParams = { 0 };

opInfo.StructSize = sizeof(opInfo);
opInfo.Type = CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS;
opInfo.ConnectionKey = callbackInfo->ConnectionKey;
opInfo.TransferKey = callbackInfo->TransferKey;

opParams.ParamSize = sizeof(opParams);
opParams.TransferPlaceholders.CompletionStatus = status;
opParams.TransferPlaceholders.Flags = CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_NONE;
opParams.TransferPlaceholders.PlaceholderArray = placeholders;
opParams.TransferPlaceholders.PlaceholderCount = placeholdersCount;
opParams.TransferPlaceholders.PlaceholderTotalCount.QuadPart = placeholdersCount;

winrt::check_hresult(CfExecute(&opInfo, &opParams));

The issue that I am seeing is that the callback is invoked over and over again despite the fact that we have provided all of the placeholders that are currently available. The invocation does eventually stop but the number of times that it's called seems random.

I've tried setting the flag CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_DISABLE_ON_DEMAND_POPULATION in the callback and when I do this we are only called once but once set we are never asked again for the placeholders even if we have new ones to provide.

I've tried doing the following when we have no new placeholders to provide:-

opParams.TransferPlaceholders.PlaceholderCount = 0;
opParams.TransferPlaceholders.PlaceholderTotalCount.QuadPart = 0;
opParams.TransferPlaceholders.PlaceholderArray = NULL;

...and this works to a point but we're still called back again and again. I suspect that there must be some other piece of the puzzle here but unfortunately the documentation isn't very detailed on this and the sample project doesn't implement this callback.

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,498 questions
{count} votes

1 answer

Sort by: Most helpful
  1. WebDAV 21 Reputation points
    2020-08-21T04:35:54.873+00:00

    I experience the same behavior. My opinion is that the behavior, when the callback is called only 1 time with flags = CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_DISABLE_ON_DEMAND_POPULATION is correct.

    My guess is that you are expected to populate the folder only during first access. After that, you will add, delete, and update placeholders via other Cloud Files API functions, not inside a callback. My dev team was able to build a working prototype using this approach in .NET+Win32 API.