Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Mendapatkan informasi rentang tentang file atau folder tempat penampung. Informasi rentang ini identik dengan apa yang dikembalikan CfGetPlaceholderRangeInfo . Namun, tidak mengambil fileHandle sebagai parameter. Sebagai gantinya, ia menggunakan ConnectionKey, TransferKey, dan FileId untuk mengidentifikasi file dan aliran yang informasi rentangnya diminta.
Platform ini menyediakan ConnectionKey, TransferKey, dan FileId ke semua fungsi panggilan balik yang terdaftar melalui CfConnectSyncRoot dan penyedia dapat menggunakan parameter ini untuk mendapatkan informasi rentang tentang tempat penampung dari panggilan balik CF_CALLBACK_TYPE_FETCH_DATA tanpa mengharuskannya membuka handel ke file.
Jika file bukan tempat penampung file cloud, API akan gagal. Jika berhasil, informasi rentang dikembalikan sesuai dengan InfoClass tertentu yang diminta.
Catatan
API ini hanya tersedia jika PlatformVersion.IntegrationNumber
diperoleh dari CfGetPlatformInfo0x600
atau lebih tinggi.
Sintaks
HRESULT CfGetPlaceholderRangeInfoForHydration(
[in] CF_CONNECTION_KEY ConnectionKey,
[in] CF_TRANSFER_KEY TransferKey,
[in] LARGE_INTEGER FileId,
[in] CF_PLACEHOLDER_RANGE_INFO_CLASS InfoClass,
[in] LARGE_INTEGER StartingOffset,
[in] LARGE_INTEGER RangeLength,
[out] PVOID InfoBuffer,
[in] DWORD InfoBufferSize,
[out, optional] PDWORD InfoBufferWritten
);
Parameter
[in] ConnectionKey
Handel buram yang dibuat oleh CfConnectSyncRoot untuk akar sinkronisasi yang dikelola oleh penyedia sinkronisasi. Ini dikembalikan juga dalam CF_CALLBACK_INFO dalam panggilan balik CF_CALLBACK_TYPE_FETCH_DATA dan panggilan balik lainnya.
[in] TransferKey
Handel buram ke file tempat penampung yang panggilan balik CF_CALLBACK_TYPE_FETCH_DATA telah dipanggil. Ini juga dikembalikan dalam CF_CALLBACK_INFO dalam panggilan balik CF_CALLBACK_TYPE_FETCH_DATA . Ini dapat diperoleh secara alternatif oleh CfGetTransferKey jika API tidak dipanggil dari CF_CALLBACK_TYPE_FETCH_DATA Callback.
[in] FileId
ID unik seluruh volume yang dikelola sistem file 64bit dari file/direktori tempat penampung yang akan dilayankan. Seperti TransferKey, ini dikembalikan dalam CF_CALLBACK_INFO di CF_CALLBACK_TYPE_FETCH_DATA dan panggilan balik lainnya sehingga penyedia tidak perlu mengambilnya lagi.
[in] InfoClass
Jenis rentang data tempat penampung. Nilainya bisa menjadi salah satu dari berikut ini:
Nilai | Deskripsi |
---|---|
CF_PLACEHOLDER_RANGE_INFO_ONDISK | Data pada disk adalah data yang ada secara fisik dalam file. Ini adalah set super dari jenis rentang lainnya. |
CF_PLACEHOLDER_RANGE_INFO_VALIDATED | Data yang divalidasi adalah subset data pada disk yang saat ini sinkron dengan cloud. |
CF_PLACEHOLDER_RANGEINFO_MODIFIED | Data yang dimodifikasi adalah subset data pada disk yang saat ini tidak sinkron dengan cloud (yaitu, dimodifikasi atau ditambahkan.) |
[in] StartingOffset
Offset titik awal rentang data. StartingOffset dan RangeLength menentukan rentang dalam file tempat penampung yang informasinya seperti yang dijelaskan oleh parameter InfoClass diminta
[in] RangeLength
Panjang rentang data. Penyedia dapat menentukan CF_EOF
untuk RangeLength untuk menunjukkan bahwa rentang yang informasinya diminta adalah dari StartingOffset ke akhir file.
[out] InfoBuffer
Penunjuk ke buffer yang akan menerima data. Buffer adalah array struktur CF_FILE_RANGE , yang merupakan pasangan offset/panjang, yang menjelaskan rentang yang diminta.
[in] InfoBufferSize
Panjang InfoBuffer dalam byte.
[out, optional] InfoBufferWritten
Menerima jumlah byte yang dikembalikan di InfoBuffer.
Menampilkan nilai
Jika fungsi ini berhasil, fungsi akan mengembalikan S_OK
. Jika tidak, kode kesalahan HRESULT akan dikembalikan. Beberapa kode kesalahan umum tercantum dalam tabel berikut:
Kode kesalahan | Makna |
---|---|
HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ) | Ini berarti bahwa StartingOffset>= posisi akhir file. |
HRESULT_FROM_WIN32( ERROR_MORE_DATA ) | Ini menyiratkan bahwa entri CF_FILE_RANGE berikutnya tidak cocok dalam buffer yang disediakan. Pemanggil harus memverifikasi apakah ada entri yang diterima atau tidak menggunakan nilai InfoBufferWritten yang dikembalikan. |
Keterangan
Meskipun API untuk mengkueri rentang file terhidrasi dari tempat penampung sudah ada, API baru diperlukan untuk meningkatkan keandalan platform.
API yang ada, CfGetPlaceholderRangeInfo, memerlukan handel yang dibuka ke file lalu memicu FSCTL_HSM_CONTROL menggunakan handel tersebut. Penyedia/Mesin Sinkronisasi biasanya menggunakan API ini untuk menilai bagian file mana yang tidak terhidrasi dari konteks panggilan balik CF_CALLBACK_TYPE_FETCH_DATA yang dipanggil oleh filter untuk menghidrasi file untuk memenuhi IO.
Filter mini di tumpukan IO dapat mengeluarkan pemindaian data pada file ketika penyedia/Mesin sinkronisasi mencoba membuka handel ke file untuk diteruskan sebagai parameter ke CfGetPlaceholderRangeInfo. Atau, filter mini dapat memblokir FSCTL_HSM_CONTROL yang dipicu CfGetPlaceholderRangeInfo secara internal.
Filter cldflt dirancang untuk memanggil hanya satu panggilan balik CF_CALLBACK_TYPE_FETCH_DATA per rentang file yang diperlukan untuk menghidrasi file. Sebagai akibat dari salah satu kasus di atas, pemindaian data terjebak di belakang CF_CALLBACK_TYPE_FETCH_DATA asli atau CF_CALLBACK_TYPE_FETCH_DATA terjebak di belakang FSCTL yang diblokir. Hal ini menyebabkan kebuntuan di jalur hidrasi.
Oleh karena itu, API ini diperlukan. Ini melakukan fungsionalitas yang sama dengan CfGetPlaceholderRangeInfo, tetapi berkomunikasi ke filter secara langsung menggunakan port pesan filter yang melewati tumpukan IO menengah. Oleh karena itu, tidak ada filter mini perantara yang dapat menghalangi CreateFile atau FSCTL_HSM_CONTROL.
Perhatikan bahwa pemanggil selalu memiliki ConnectionKey yang diperoleh melalui CfConnectSyncRoot. Ini dapat memperoleh TransferKey melalui CfGetTransferKey dan mendapatkan FileId menggunakan GetFileInformationByHandle. Tetapi pendekatan ini membutuhkan handel untuk dibuka ke file dan karenanya tidak berbeda dengan menggunakan CfGetPlaceholderRangeInfo.
Untuk meringkas, ketika info rentang diperlukan dari konteks panggilan balik CF_CALLBACK_TYPE_FETCH_DATA , API ini harus digunakan. Dalam semua kasus lain, termasuk ketika penyedia ingin menghidrasi file tanpa diminta oleh filter, CfGetPlaceholderRangeInfo harus digunakan. Platform tidak dapat mengenali API mana yang dipanggil dalam konteks tertentu dan karenanya onus ada di penyedia/Mesin Sinkronisasi untuk melakukan hal yang benar.
Contoh
Ini adalah contoh sederhana di mana fungsi melewati InfoBuffer cukup untuk mengambil hanya satu entri CF_FILE_RANGE pada satu waktu. Dalam praktiknya, pemanggil dapat meneruskan InfoBuffer yang dapat sesuai dengan beberapa entri CF_FILE_RANGE per pemanggilan API. Kode kesalahan HRESULT_FROM_WIN32( ERROR_MORE_DATA ) dapat digunakan untuk melewati buffer yang lebih besar jika perlu.
#include <cfapi.h>
// ******************************************************************************************************
// From within the CF_CALLBACK_TYPE_FETCH_DATA Callback, the provider can use
// g_PlatformInfo.IntegrationNumber to see if the new API is supported. If it is, the provider can pass
// ConnectionKey, TransferKey and FileId along with other parameters to obtain information about file
// ranges which have already been hydrated.
// *******************************************************************************************************
// The provider could obtain file ranges that are hydrated like this:
std::vector<CF_FILE_RANGE> hydratedRanges = GetFileRangesFromCallback( CallbackInfo->ConnectionKey,
CallbackInfo->TransferKey,
CallbackInfo->FileId,
CF_PLACEHOLDER_RANGE_INFO_ONDISK
0,
CF_EOF);
// Based on these hydratedRanges, the provider can chose to hydrate only ranges which aren’t on the disk.
// ******************************************************************************************************
// Implementation of a function that eventually calls this API.
// ******************************************************************************************************
typedef HRESULT( __stdcall* t_CfGetPlaceholderRangeInfoForHydration )(
CF_CONNECTION_KEY ConnectionKey,
CF_TRANSFER_KEY TransferKey,
LARGE_INTEGER FileId,
CF_PLACEHOLDER_RANGE_INFO_CLASS InfoClass,
LARGE_INTEGER StartingOffset,
LARGE_INTEGER RangeLength,
PVOID InfoBuffer,
DWORD InfoBufferSize,
PDWORD InfoBufferWritten );
t_CfGetPlaceholderRangeInfoForHydration _CfGetPlaceholderRangeInfoForHydration = nullptr;
std::vector<CF_FILE_RANGE>
GetFileRangesFromCallback( CF_CONNECTION_KEY ConnectionKey,
CF_TRANSFER_KEY TransferKey,
LARGE_INTEGER FileId,
CF_PLACEHOLDER_RANGE_INFO_CLASS RangeInfoClass,
long long StartOffset,
long long Length,
PBOOLEAN UseOldAPI )
{
long long StartOffset = 0;
CF_FILE_RANGE fileRange;
long long Length = 0;
LARGE_INTEGER queryOffset = ll2li( StartOffset );
LARGE_INTEGER queryLength = ll2li( Length );
DWORD inforBufferWritten = 0;
// This will contain all the hydrated ranges in the file if the function succeeds.
std::vector<CF_FILE_RANGE> ranges;
bool stop = false;
CF_PLATFORM_INFO platformInfo;
hr = (CfGetPlatformInfo( &platformInfo ));
if(FAILED(hr)) {
*UseOldAPI = TRUE;
return ranges; //empty.
}
if (platformInfo.IntegrationNumber < 600) {
*UseOldAPI = TRUE;
return ranges; //empty.
}
wil::unique_hmodule CloudFilesApi( LoadLibrary( L"cldapi.dll" ) );
THROW_LAST_ERROR_IF_NULL( CloudFilesApi );
_CfGetPlaceholderRangeInfoForHydration = reinterpret_cast<t_CfGetPlaceholderRangeInfoForHydration>(
GetProcAddress( CloudFilesApi.get(), "CfGetPlaceholderRangeInfoForHydration" ) );
THROW_LAST_ERROR_IF_NULL( _CfGetPlaceholderRangeInfoForHydration );
while ( !stop ) {
hr = _CfGetPlaceholderRangeInfoForHydration ( ConnectionKey,
TransferKey,
FileId,
RangeInfoClass,
queryOffset,
queryLength,
&fileRange,
sizeof( fileRange ),
&infoBufferWritten );
if ( hr == HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ) ||
hr == HRESULT_FROM_WIN32( ERROR_MORE_DATA ) ) {
// We need to break the loop only if there is no more data.
if ( hr == HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ) ) {
stop = true;
}
hr = S_OK;
}
if ( FAILED( hr ) || infoBufferWritten == 0 ) {
return ranges;
}
ranges.push_back( fileRange );
queryOffset.QuadPart = fileRange.StartingOffset.QuadPart + fileRange.Length.QuadPart;
if ( Length != CF_EOF && queryOffset.QuadPart >= ( StartOffset + Length ) ) {
stop = true;
} else if ( Length != CF_EOF) {
// Update the new query length
queryLength.QuadPart = StartOffset + Length - queryOffset.QuadPart
if ( queryLength.QuadPart <= 0 ) {
stop = true;
}
}
}
return ranges;
}
Persyaratan
Persyaratan | Nilai |
---|---|
Header | cfapi.h |