Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/sync_root_interface/Utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Utilities
static std::wstring FileOperationErrorToWString(_In_ FileOperationError error);
static bool IsTemporaryFile(const std::wstring &fullPath);
static std::wstring GetErrorMessageCloudFiles(HRESULT hr);
static void ClearTransferProperties(_In_ LPCWSTR fullPath);

static winrt::com_array<wchar_t>
ConvertSidToStringSid(_In_ PSID sid)
Expand Down
82 changes: 48 additions & 34 deletions native-src/sync_root_interface/SyncRoot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ void SyncRoot::HydrateFile(const wchar_t *filePath)

if (attrib & FILE_ATTRIBUTE_PINNED)
{
// if (!(attrib & FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS))
// {
Logger::getInstance().log("Hydration file init", LogLevel::INFO);

auto start = std::chrono::steady_clock::now();
Expand All @@ -68,50 +66,66 @@ void SyncRoot::HydrateFile(const wchar_t *filePath)
wprintf(L"Hydration finished %ls\n", filePath);
}
}
// }
// else
// {
// wprintf(L"File is already hydrated: %ls\n", filePath);
// Logger::getInstance().log("File is already hydrated " + Logger::fromWStringToString(filePath), LogLevel::INFO);
// }
}
}
}

void SyncRoot::DehydrateFile(const wchar_t *filePath)
void SyncRoot::DehydrateFile(const wchar_t* filePath)
{
// Logger::getInstance().log("Dehydration file init", LogLevel::INFO);
wprintf(L"Dehydration file init %ls\n", filePath);
DWORD attrib = GetFileAttributesW(filePath);
if (!(attrib & FILE_ATTRIBUTE_DIRECTORY))
DWORD attr = GetFileAttributesW(filePath);
if (attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY))
return;

DWORD flags = FILE_FLAG_OPEN_REPARSE_POINT;
winrt::handle h(CreateFileW(filePath,
FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE |
FILE_SHARE_DELETE,
nullptr,
OPEN_EXISTING,
flags,
nullptr));
if (!h)
{
winrt::handle placeholder(CreateFileW(filePath, 0, FILE_READ_DATA, nullptr, OPEN_EXISTING, 0, nullptr));
wprintf(L"[DehydrateFile] CreateFileW falló: %lu\n", GetLastError());
return;
}

LARGE_INTEGER offset;
offset.QuadPart = 0;
LARGE_INTEGER length;
GetFileSizeEx(placeholder.get(), &length);
if (!(attr & FILE_ATTRIBUTE_UNPINNED))
{
CfSetPinState(h.get(), CF_PIN_STATE_UNPINNED,
CF_SET_PIN_FLAG_NONE, nullptr);
}

if (attrib & FILE_ATTRIBUTE_UNPINNED)
{
// Logger::getInstance().log("Dehydrating file " + Logger::fromWStringToString(filePath), LogLevel::INFO);
wprintf(L"Dehydrating file starteeed %ls\n", filePath);
HRESULT hr = CfDehydratePlaceholder(placeholder.get(), offset, length, CF_DEHYDRATE_FLAG_NONE, NULL);
LARGE_INTEGER len; GetFileSizeEx(h.get(), &len);

if (FAILED(hr))
{
wprintf(L"Error dehydrating file %ls\n", filePath);
// Logger::getInstance().log("Error dehydrating file " + Logger::fromWStringToString(filePath), LogLevel::ERROR);
}
else
{
wprintf(L"Dehydration finished %ls\n", filePath);
// Logger::getInstance().log("Dehydration finished " + Logger::fromWStringToString(filePath), LogLevel::INFO);
}
}
HRESULT hr = CfDehydratePlaceholder(h.get(), {}, len, CF_DEHYDRATE_FLAG_NONE, nullptr);

if (hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION))
{
wprintf(L"[DehydrateFile] sharing-violation; reintentaré luego\n");
return;
}

if (FAILED(hr))
{
wprintf(L"[DehydrateFile] CfDehydratePlaceholder 0x%08X\n", hr);
return;
}

CfSetInSyncState(h.get(), CF_IN_SYNC_STATE_NOT_IN_SYNC,
CF_SET_IN_SYNC_FLAG_NONE, nullptr);


Utilities::ClearTransferProperties(filePath);


SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, filePath, nullptr);

wprintf(L"[DehydrateFile] OK %ls\n", filePath);
}


HRESULT SyncRoot::RegisterSyncRoot(const wchar_t *syncRootPath, const wchar_t *providerName, const wchar_t *providerVersion, const GUID &providerId, const wchar_t *logoPath)
{
try
Expand Down
80 changes: 56 additions & 24 deletions native-src/sync_root_interface/Utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,26 @@ void Utilities::AddFolderToSearchIndexer(_In_ PCWSTR folder)
}
}

void Utilities::ClearTransferProperties(PCWSTR fullPath)
{
winrt::com_ptr<IShellItem2> item;
winrt::com_ptr<IPropertyStore>store;

if (FAILED(SHCreateItemFromParsingName(fullPath, nullptr,
__uuidof(item), item.put_void())))
return;

if (FAILED(item->GetPropertyStore(GPS_READWRITE | GPS_VOLATILEPROPERTIESONLY,
__uuidof(store), store.put_void())))
return;

PROPVARIANT empty; PropVariantInit(&empty);
store->SetValue(PKEY_StorageProviderTransferProgress, empty);
store->SetValue(PKEY_SyncTransferStatus, empty);
store->Commit();
}


void Utilities::ApplyTransferStateToFile(_In_ PCWSTR fullPath, _In_ CF_CALLBACK_INFO &callbackInfo, UINT64 total, UINT64 completed)
{
Logger::getInstance().log("ApplyTransferStateToFile", LogLevel::INFO);
Expand Down Expand Up @@ -116,10 +136,10 @@ void Utilities::ApplyTransferStateToFile(_In_ PCWSTR fullPath, _In_ CF_CALLBACK_
{
// First, get the Volatile property store for the file. That's where the properties are maintained.
winrt::com_ptr<IShellItem2> shellItem;
winrt::com_ptr<IPropertyStore>propStoreVolatile;

winrt::check_hresult(SHCreateItemFromParsingName(fullPath, nullptr, __uuidof(shellItem), shellItem.put_void()));
// wprintf(L"transfer-> fullPath \"%s\"\n", fullPath);
// wprintf(L"transfer-> shellItem \"%s\"\n", shellItem);
winrt::com_ptr<IPropertyStore> propStoreVolatile;

// wprintf(L"transfer-> propStoreVolatile \"%s\"\n", propStoreVolatile);
winrt::check_hresult(
shellItem->GetPropertyStore(
Expand All @@ -130,27 +150,39 @@ void Utilities::ApplyTransferStateToFile(_In_ PCWSTR fullPath, _In_ CF_CALLBACK_
// The PKEY_StorageProviderTransferProgress property works with a UINT64 array that is two elements, with
// element 0 being the amount of data transferred, and element 1 being the total amount
// that will be transferred.
PROPVARIANT transferProgress;
UINT64 values[]{completed, total};
winrt::check_hresult(InitPropVariantFromUInt64Vector(values, ARRAYSIZE(values), &transferProgress)); // TODO: should work, but doesn't the library doesn't have this function implemented
winrt::check_hresult(propStoreVolatile->SetValue(PKEY_StorageProviderTransferProgress, transferProgress));
// wprintf(L"transfer-> transferProgress \"%s\"\n", transferProgress);
// Set the sync transfer status accordingly

PROPVARIANT transferStatus;
winrt::check_hresult(
InitPropVariantFromUInt32(
(completed < total) ? SYNC_TRANSFER_STATUS::STS_TRANSFERRING : SYNC_TRANSFER_STATUS::STS_NONE,
&transferStatus));
winrt::check_hresult(propStoreVolatile->SetValue(PKEY_SyncTransferStatus, transferStatus));
// wprintf(L"transfer-> transferStatus \"%s\"\n", transferStatus);
// Without this, all your hard work is wasted.
winrt::check_hresult(propStoreVolatile->Commit());
// wprintf(L"transfer-> propStoreVolatile \"%s\"\n", propStoreVolatile);
// Broadcast a notification that something about the file has changed, so that apps
// who subscribe (such as File Explorer) can update their UI to reflect the new progress
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, static_cast<LPCVOID>(fullPath), nullptr);
wprintf(L"Succesfully Set Transfer Progress on \"%s\" to %llu/%llu\n", fullPath, completed, total);
if (completed < total)
{
PROPVARIANT pvProgress, pvStatus;
UINT64 values[] { completed, total };
InitPropVariantFromUInt64Vector(values, ARRAYSIZE(values), &pvProgress);
InitPropVariantFromUInt32(SYNC_TRANSFER_STATUS::STS_TRANSFERRING, &pvStatus);

propStoreVolatile->SetValue(PKEY_StorageProviderTransferProgress, pvProgress);
propStoreVolatile->SetValue(PKEY_SyncTransferStatus, pvStatus);
propStoreVolatile->Commit();

PropVariantClear(&pvProgress);
}
else
{
PROPVARIANT empty; PropVariantInit(&empty);
propStoreVolatile->SetValue(PKEY_StorageProviderTransferProgress, empty);
propStoreVolatile->SetValue(PKEY_SyncTransferStatus, empty);
propStoreVolatile->Commit();

HANDLE h = CreateFileW(fullPath,
FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr,
OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT,
nullptr);
if (h != INVALID_HANDLE_VALUE) {
CfSetInSyncState(h, CF_IN_SYNC_STATE_IN_SYNC,
CF_SET_IN_SYNC_FLAG_NONE, nullptr);
CloseHandle(h);
}
}
}
catch (...)
{
Expand Down
Loading