diff --git a/dist/addon.node b/dist/addon.node index 747ed9a7..35fe60b1 100644 Binary files a/dist/addon.node and b/dist/addon.node differ diff --git a/include/placeholders_interface/Placeholders.h b/include/placeholders_interface/Placeholders.h index 0c0eff49..ac1befec 100644 --- a/include/placeholders_interface/Placeholders.h +++ b/include/placeholders_interface/Placeholders.h @@ -6,8 +6,8 @@ class Placeholders { public: - static void MaintainIdentity(const std::wstring &fullPath, PCWSTR fileIdentity, bool isDirectory); - static void UpdateSyncStatus(const std::wstring &filePath, bool isDirectory); - static void UpdateFileIdentity(const std::wstring &filePath, const std::wstring &fileIdentity, bool isDirectory); - static FileState GetPlaceholderInfo(const std::wstring &directoryPath); + static winrt::file_handle OpenFileHandle(const std::wstring &path, DWORD accessRights, bool openAsPlaceholder); + static void UpdateSyncStatus(const std::wstring &path); + static void UpdateFileIdentity(const std::wstring &path, const std::wstring &placeholderId); + static FileState GetPlaceholderInfo(const std::wstring &path); }; \ No newline at end of file diff --git a/include/sync_root_interface/SyncRoot.h b/include/sync_root_interface/SyncRoot.h index d4d25d37..4864fa34 100644 --- a/include/sync_root_interface/SyncRoot.h +++ b/include/sync_root_interface/SyncRoot.h @@ -6,19 +6,11 @@ #include #include -struct ItemInfo -{ - std::wstring path; - std::wstring fileIdentity; - bool isPlaceholder; -}; - class SyncRoot { public: static HRESULT ConnectSyncRoot(const wchar_t *syncRootPath, InputSyncCallbacks syncCallbacks, napi_env env, CF_CONNECTION_KEY *connectionKey); static HRESULT DisconnectSyncRoot(const wchar_t *syncRootPath); - static void HydrateFile(const wchar_t *filePath); private: CF_CONNECTION_KEY connectionKey; diff --git a/include/sync_root_interface/Utilities.h b/include/sync_root_interface/Utilities.h index b6f781ea..34b67cd3 100644 --- a/include/sync_root_interface/Utilities.h +++ b/include/sync_root_interface/Utilities.h @@ -4,7 +4,6 @@ class Utilities { public: static void ApplyTransferStateToFile(_In_ LPCWSTR fullPath, _In_ CF_CALLBACK_INFO &callbackInfo, UINT64 total, UINT64 completed); - static std::wstring GetErrorMessageCloudFiles(HRESULT hr); static winrt::com_array ConvertSidToStringSid(_In_ PSID sid) @@ -20,16 +19,17 @@ class Utilities } }; - inline static LARGE_INTEGER JsTimestampToLargeInteger(int64_t jsTimestamp) { + inline static LARGE_INTEGER JsTimestampToLargeInteger(int64_t jsTimestamp) + { const int64_t EPOCH_DIFFERENCE = 11644473600000LL; const int64_t MS_TO_100NS = 10000LL; - + int64_t windowsTime = (jsTimestamp + EPOCH_DIFFERENCE) * MS_TO_100NS; - + LARGE_INTEGER largeInteger; largeInteger.LowPart = static_cast(windowsTime & 0xFFFFFFFF); largeInteger.HighPart = static_cast((windowsTime >> 32) & 0xFFFFFFFF); - + return largeInteger; } @@ -39,18 +39,4 @@ class Utilities largeInteger.QuadPart = longlong; return largeInteger; } - - static DWORD convertSizeToDWORD(size_t &convertVar) - { - if (convertVar > UINT_MAX) - { - convertVar = UINT_MAX; - } - return static_cast(convertVar); - } - - static DWORD sizeToDWORD(size_t size) - { - return convertSizeToDWORD(size); - } }; diff --git a/native-src/placeholders_interface/Planceholders.cpp b/native-src/placeholders_interface/Planceholders.cpp index eaf97236..56664ad4 100644 --- a/native-src/placeholders_interface/Planceholders.cpp +++ b/native-src/placeholders_interface/Planceholders.cpp @@ -17,71 +17,41 @@ #include #include "convert_to_placeholder.h" -using namespace std; - -namespace fs = std::filesystem; - #pragma comment(lib, "shlwapi.lib") -std::string cleanString(const std::string &str) +winrt::file_handle Placeholders::OpenFileHandle(const std::wstring &path, DWORD dwDesiredAccess, bool openAsPlaceholder) { - std::string cleanedStr; - for (char ch : str) - { - if (std::isprint(static_cast(ch))) - { - cleanedStr.push_back(ch); - } - } - return cleanedStr; -} - -void Placeholders::MaintainIdentity(const std::wstring &fullPath, PCWSTR itemIdentity, bool isDirectory) -{ - std::string identity = Placeholders::GetPlaceholderInfo(fullPath).placeholderId; - if (!identity.empty()) - { - int len = WideCharToMultiByte(CP_UTF8, 0, itemIdentity, -1, NULL, 0, NULL, NULL); - if (len > 0) - { - std::string itemIdentityStr(len, 0); - WideCharToMultiByte(CP_UTF8, 0, itemIdentity, -1, &itemIdentityStr[0], len, NULL, NULL); - std::string cleanIdentity = cleanString(identity); - std::string cleanItemIdentity = cleanString(itemIdentityStr); - if (cleanIdentity != cleanItemIdentity) - { - wprintf(L"[MaintainIdentity] Identity is incorrect, updating...\n"); - std::wstring itemIdentityStrW(itemIdentity); - Placeholders::UpdateFileIdentity(fullPath, itemIdentityStrW, isDirectory); - } - } - else - { - // Handle error as needed - } - } -} + bool isDirectory = std::filesystem::is_directory(path); -void Placeholders::UpdateSyncStatus(const std::wstring &path, bool isDirectory) -{ - DWORD flags = FILE_FLAG_OPEN_REPARSE_POINT; + DWORD dwFlagsAndAttributes = 0; + if (openAsPlaceholder) + dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT; if (isDirectory) - flags |= FILE_FLAG_BACKUP_SEMANTICS; + dwFlagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS; + + DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; winrt::file_handle fileHandle{CreateFileW( path.c_str(), - FILE_WRITE_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + dwDesiredAccess, + dwShareMode, nullptr, OPEN_EXISTING, - flags, + dwFlagsAndAttributes, nullptr)}; if (!fileHandle) { - throw std::runtime_error("Failed to open item: " + std::to_string(GetLastError())); + throw std::runtime_error("Failed to open file handle: " + std::to_string(GetLastError())); } + return fileHandle; +} + +void Placeholders::UpdateSyncStatus(const std::wstring &path) +{ + auto fileHandle = Placeholders::OpenFileHandle(path, FILE_WRITE_ATTRIBUTES, true); + winrt::check_hresult(CfSetInSyncState( fileHandle.get(), CF_IN_SYNC_STATE_IN_SYNC, @@ -91,74 +61,32 @@ void Placeholders::UpdateSyncStatus(const std::wstring &path, bool isDirectory) SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, path.c_str(), nullptr); } -void Placeholders::UpdateFileIdentity(const std::wstring &filePath, const std::wstring &fileIdentity, bool isDirectory) +void Placeholders::UpdateFileIdentity(const std::wstring &path, const std::wstring &placeholderId) { - HANDLE fileHandle = CreateFileW( - filePath.c_str(), - FILE_WRITE_ATTRIBUTES, // permisson needed to change the state - FILE_SHARE_READ | FILE_SHARE_WRITE, - nullptr, - OPEN_EXISTING, - isDirectory ? FILE_FLAG_BACKUP_SEMANTICS : FILE_ATTRIBUTE_NORMAL, - nullptr); + auto fileHandle = OpenFileHandle(path, FILE_WRITE_ATTRIBUTES, true); - if (fileHandle == INVALID_HANDLE_VALUE) - { - DWORD errorCode = GetLastError(); - wprintf(L"[UpdateFileIdentity] Error opening file: %d\n", errorCode); - LPWSTR errorMessage = nullptr; - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, - errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast(&errorMessage), - 0, - nullptr); - if (errorMessage) - { - wprintf(L"[UpdateFileIdentity] Error: %ls\n", errorMessage); - LocalFree(errorMessage); - } - return; - } - - HRESULT hr = CfUpdatePlaceholder( - fileHandle, // Handle del archivo. - nullptr, // CF_FS_METADATA opcional. - fileIdentity.c_str(), // Identidad del archivo. - static_cast(fileIdentity.size() * sizeof(wchar_t)), // Longitud de la identidad del archivo. - nullptr, // Rango a deshidratar, opcional. - 0, // Conteo de rangos a deshidratar, debe ser 0 si no se usa. - CF_UPDATE_FLAG_NONE, // Flags de actualización. - nullptr, // USN opcional. - nullptr // OVERLAPPED opcional. - ); - - if (FAILED(hr)) - { - std::wstring errorMessage = Utilities::GetErrorMessageCloudFiles(hr); - wprintf(L"[UpdateFileIdentity] Error updating fileIdentity: %ls\n", errorMessage.c_str()); - CloseHandle(fileHandle); - return; - } - - CloseHandle(fileHandle); + winrt::check_hresult(CfUpdatePlaceholder( + fileHandle.get(), + nullptr, + placeholderId.c_str(), + static_cast(placeholderId.size() * sizeof(wchar_t)), + nullptr, + 0, + CF_UPDATE_FLAG_NONE, + nullptr, + nullptr)); } FileState Placeholders::GetPlaceholderInfo(const std::wstring &path) { + auto fileHandle = OpenFileHandle(path, FILE_READ_ATTRIBUTES, true); + constexpr DWORD fileIdMaxLength = 400; constexpr DWORD infoSize = sizeof(CF_PLACEHOLDER_BASIC_INFO) + fileIdMaxLength; std::vector buffer(infoSize); auto *info = reinterpret_cast(buffer.data()); - auto fileHandle = handleForPath(path); - if (!fileHandle) - { - throw std::runtime_error("Failed to get file handle: " + std::to_string(GetLastError())); - } - winrt::check_hresult(CfGetPlaceholderInfo( fileHandle.get(), CF_PLACEHOLDER_INFO_BASIC, @@ -166,7 +94,9 @@ FileState Placeholders::GetPlaceholderInfo(const std::wstring &path) infoSize, nullptr)); - return FileState{ - std::string(reinterpret_cast(info->FileIdentity), info->FileIdentityLength), - info->PinState}; + std::string placeholderId(reinterpret_cast(info->FileIdentity), info->FileIdentityLength); + + placeholderId.erase(std::remove(placeholderId.begin(), placeholderId.end(), '\0'), placeholderId.end()); + + return FileState{placeholderId, info->PinState}; } diff --git a/native-src/sync_root_interface/SyncRoot.cpp b/native-src/sync_root_interface/SyncRoot.cpp index 0ce63565..4a135d5f 100644 --- a/native-src/sync_root_interface/SyncRoot.cpp +++ b/native-src/sync_root_interface/SyncRoot.cpp @@ -8,51 +8,6 @@ std::map connectionMap; -void SyncRoot::HydrateFile(const wchar_t *filePath) -{ - wprintf(L"Hydration file started %ls\n", filePath); - DWORD attrib = GetFileAttributesW(filePath); - if (!(attrib & FILE_ATTRIBUTE_DIRECTORY)) - { - winrt::handle placeholder(CreateFileW(filePath, 0, FILE_READ_DATA, nullptr, OPEN_EXISTING, 0, nullptr)); - - LARGE_INTEGER offset; - offset.QuadPart = 0; - LARGE_INTEGER length; - GetFileSizeEx(placeholder.get(), &length); - - 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(); - - HRESULT hr = CfHydratePlaceholder(placeholder.get(), offset, length, CF_HYDRATE_FLAG_NONE, NULL); - - if (FAILED(hr)) - { - Logger::getInstance().log("Error hydrating file " + Logger::fromWStringToString(filePath), LogLevel::ERROR); - } - else - { - auto end = std::chrono::steady_clock::now(); - auto elapsedMilliseconds = std::chrono::duration_cast(end - start).count(); - - if (elapsedMilliseconds < 200) - { - wprintf(L"Already Hydrated: %d ms\n", elapsedMilliseconds); - } - else - { - wprintf(L"Hydration finished %ls\n", filePath); - } - } - } - } -} - HRESULT SyncRoot::ConnectSyncRoot(const wchar_t *syncRootPath, InputSyncCallbacks syncCallbacks, napi_env env, CF_CONNECTION_KEY *connectionKey) { register_threadsafe_fetch_data_callback("FetchDataThreadSafe", env, syncCallbacks); @@ -61,23 +16,22 @@ HRESULT SyncRoot::ConnectSyncRoot(const wchar_t *syncRootPath, InputSyncCallback CF_CALLBACK_REGISTRATION callbackTable[] = { {CF_CALLBACK_TYPE_FETCH_DATA, fetch_data_callback_wrapper}, {CF_CALLBACK_TYPE_CANCEL_FETCH_DATA, cancel_fetch_data_callback_wrapper}, - CF_CALLBACK_REGISTRATION_END - }; + CF_CALLBACK_REGISTRATION_END}; HRESULT hr = CfConnectSyncRoot( syncRootPath, callbackTable, nullptr, CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO | CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH, - connectionKey - ); + connectionKey); wprintf(L"Connection key: %llu\n", connectionKey->Internal); - - if (SUCCEEDED(hr)) { + + if (SUCCEEDED(hr)) + { connectionMap[syncRootPath] = *connectionKey; } - + return hr; } diff --git a/native-src/sync_root_interface/Utilities.cpp b/native-src/sync_root_interface/Utilities.cpp index 69f1be21..98626db4 100644 --- a/native-src/sync_root_interface/Utilities.cpp +++ b/native-src/sync_root_interface/Utilities.cpp @@ -34,7 +34,7 @@ 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 shellItem; - winrt::com_ptrpropStoreVolatile; + winrt::com_ptr propStoreVolatile; winrt::check_hresult(SHCreateItemFromParsingName(fullPath, nullptr, __uuidof(shellItem), shellItem.put_void())); @@ -51,7 +51,7 @@ void Utilities::ApplyTransferStateToFile(_In_ PCWSTR fullPath, _In_ CF_CALLBACK_ if (completed < total) { PROPVARIANT pvProgress, pvStatus; - UINT64 values[] { completed, total }; + UINT64 values[]{completed, total}; InitPropVariantFromUInt64Vector(values, ARRAYSIZE(values), &pvProgress); InitPropVariantFromUInt32(SYNC_TRANSFER_STATUS::STS_TRANSFERRING, &pvStatus); @@ -63,21 +63,23 @@ void Utilities::ApplyTransferStateToFile(_In_ PCWSTR fullPath, _In_ CF_CALLBACK_ } else { - PROPVARIANT empty; PropVariantInit(&empty); + 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) { + 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); + CF_SET_IN_SYNC_FLAG_NONE, nullptr); CloseHandle(h); } } @@ -89,23 +91,3 @@ void Utilities::ApplyTransferStateToFile(_In_ PCWSTR fullPath, _In_ CF_CALLBACK_ wprintf(L"Failed to Set Transfer Progress on \"%s\" with %08x\n", fullPath, static_cast(winrt::to_hresult())); } } - -std::wstring Utilities::GetErrorMessageCloudFiles(HRESULT hr) { - LPWSTR errorMsg = nullptr; - DWORD size = FormatMessageW( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, - hr, - 0, - (LPWSTR)&errorMsg, - 0, - nullptr - ); - - std::wstring message; - if (size > 0 && errorMsg != nullptr) { - message.assign(errorMsg, size); - } - LocalFree(errorMsg); - return message; -} diff --git a/native-src/virtual_drive/convert_to_placeholder.cpp b/native-src/virtual_drive/convert_to_placeholder.cpp index 1f30c4f4..cbf4ab54 100644 --- a/native-src/virtual_drive/convert_to_placeholder.cpp +++ b/native-src/virtual_drive/convert_to_placeholder.cpp @@ -6,21 +6,7 @@ void convert_to_placeholder(const std::wstring &path, const std::wstring &placeholderId) { - bool isDirectory = std::filesystem::is_directory(path); - - winrt::file_handle fileHandle{CreateFileW( - path.c_str(), - FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - nullptr, - OPEN_EXISTING, - isDirectory ? FILE_FLAG_BACKUP_SEMANTICS : 0, - nullptr)}; - - if (!fileHandle) - { - throw std::runtime_error("Failed to open item: " + std::to_string(GetLastError())); - } + auto fileHandle = Placeholders::OpenFileHandle(path, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, false); CF_CONVERT_FLAGS convertFlags = CF_CONVERT_FLAG_MARK_IN_SYNC; USN convertUsn; @@ -31,11 +17,7 @@ void convert_to_placeholder(const std::wstring &path, const std::wstring &placeh HRESULT hr = CfConvertToPlaceholder(fileHandle.get(), idStrLPCVOID, idStrByteLength, convertFlags, &convertUsn, &overlapped); - if (hr == 0x8007017C) // Already a placeholder - { - Placeholders::MaintainIdentity(path, placeholderId.c_str(), isDirectory); - } - else + if (hr != 0x8007017C) // Already a placeholder { winrt::check_hresult(hr); } diff --git a/native-src/virtual_drive/create_folder_placeholder.cpp b/native-src/virtual_drive/create_folder_placeholder.cpp index e4597346..b64b3d0e 100644 --- a/native-src/virtual_drive/create_folder_placeholder.cpp +++ b/native-src/virtual_drive/create_folder_placeholder.cpp @@ -32,7 +32,7 @@ napi_value create_folder_placeholder_impl(napi_env env, napi_callback_info info) cloudEntry.FsMetadata.BasicInfo.LastAccessTime = lastAccessTime; winrt::check_hresult(CfCreatePlaceholders(parentPath.c_str(), &cloudEntry, 1, CF_CREATE_FLAG_NONE, NULL)); - Placeholders::UpdateSyncStatus(path, true); + Placeholders::UpdateSyncStatus(path); return nullptr; } diff --git a/native-src/virtual_drive/dehydrate_file.cpp b/native-src/virtual_drive/dehydrate_file.cpp index 7453492e..857d7803 100644 --- a/native-src/virtual_drive/dehydrate_file.cpp +++ b/native-src/virtual_drive/dehydrate_file.cpp @@ -2,38 +2,30 @@ #include "napi_extract_args.h" #include "stdafx.h" -napi_value dehydrate_file(napi_env env, napi_callback_info info) { - auto [rawPath] = napi_extract_args(env, info); - const wchar_t* path = rawPath.c_str(); +napi_value dehydrate_file(napi_env env, napi_callback_info info) +{ + auto [path] = napi_extract_args(env, info); - DWORD attrib = GetFileAttributesW(path); + DWORD attrib = GetFileAttributesW(path.c_str()); - if (attrib & FILE_ATTRIBUTE_DIRECTORY) { + if (attrib & FILE_ATTRIBUTE_DIRECTORY) + { throw std::runtime_error("Cannot dehydrate folder"); } - winrt::handle placeholder(CreateFileW(path, 0, FILE_READ_DATA, nullptr, OPEN_EXISTING, 0, nullptr)); + winrt::handle fileHandle(CreateFileW(path.c_str(), 0, FILE_READ_DATA, nullptr, OPEN_EXISTING, 0, nullptr)); LARGE_INTEGER offset; offset.QuadPart = 0; LARGE_INTEGER length; - GetFileSizeEx(placeholder.get(), &length); + GetFileSizeEx(fileHandle.get(), &length); - HRESULT hr = CfDehydratePlaceholder(placeholder.get(), offset, length, CF_DEHYDRATE_FLAG_NONE, NULL); + winrt::check_hresult(CfDehydratePlaceholder( + fileHandle.get(), + offset, + length, + CF_DEHYDRATE_FLAG_NONE, + nullptr)); - if (SUCCEEDED(hr)) { - return nullptr; - } - - DWORD err = HRESULT_CODE(hr); - - if (err == ERROR_SHARING_VIOLATION || err == ERROR_CLOUD_FILE_IN_USE) { - // MessageBoxW( - // nullptr, - // L"Unable to free up space because the file is currently in use.\nPlease close the file and try again.", - // L"File in use", - // MB_OK | MB_ICONWARNING | MB_SYSTEMMODAL); - } - - winrt::throw_hresult(hr); + return nullptr; } diff --git a/native-src/virtual_drive/get_placeholder_state/get_placeholder_state_wrapper.cpp b/native-src/virtual_drive/get_placeholder_state/get_placeholder_state_wrapper.cpp index 05868a7f..feb93b8c 100644 --- a/native-src/virtual_drive/get_placeholder_state/get_placeholder_state_wrapper.cpp +++ b/native-src/virtual_drive/get_placeholder_state/get_placeholder_state_wrapper.cpp @@ -8,9 +8,6 @@ napi_value get_placeholder_state_wrapper(napi_env env, napi_callback_info info) FileState state = Placeholders::GetPlaceholderInfo(path); - state.placeholderId.erase(std::remove(state.placeholderId.begin(), state.placeholderId.end(), '\0'), state.placeholderId.end()); - state.placeholderId.erase(std::remove(state.placeholderId.begin(), state.placeholderId.end(), ' '), state.placeholderId.end()); - napi_value result; napi_create_object(env, &result); diff --git a/native-src/virtual_drive/hydrate_file.cpp b/native-src/virtual_drive/hydrate_file.cpp index a5a1e3c0..a5b1b152 100644 --- a/native-src/virtual_drive/hydrate_file.cpp +++ b/native-src/virtual_drive/hydrate_file.cpp @@ -4,7 +4,8 @@ #include "napi_extract_args.h" #include "SyncRoot.h" -struct AsyncWork { +struct AsyncWork +{ napi_async_work work; napi_deferred deferred; std::wstring path; @@ -12,29 +13,63 @@ struct AsyncWork { bool success; }; -void execute_work(napi_env env, void* data) { - AsyncWork* asyncWork = static_cast(data); +void hydrate_file(const std::wstring &path) +{ + DWORD attrib = GetFileAttributesW(path.c_str()); - try { - SyncRoot::HydrateFile(asyncWork->path.c_str()); + if (attrib & FILE_ATTRIBUTE_DIRECTORY) + { + throw std::runtime_error("Cannot hydrate folder"); + } + + winrt::handle fileHandle(CreateFileW(path.c_str(), 0, FILE_READ_DATA, nullptr, OPEN_EXISTING, 0, nullptr)); + + LARGE_INTEGER offset; + offset.QuadPart = 0; + LARGE_INTEGER length; + GetFileSizeEx(fileHandle.get(), &length); + + winrt::check_hresult(CfHydratePlaceholder( + fileHandle.get(), + offset, + length, + CF_HYDRATE_FLAG_NONE, + nullptr)); +} + +void execute_work(napi_env env, void *data) +{ + AsyncWork *asyncWork = static_cast(data); + + try + { + hydrate_file(asyncWork->path); asyncWork->success = true; - } catch (const std::exception& e) { + } + catch (const std::exception &e) + { asyncWork->error = e.what(); asyncWork->success = false; - } catch (...) { + } + catch (...) + { asyncWork->error = "Unknown error"; asyncWork->success = false; } } -void complete_work(napi_env env, napi_status status, void* data) { - AsyncWork* asyncWork = static_cast(data); +void complete_work(napi_env env, napi_status status, void *data) +{ + AsyncWork *asyncWork = static_cast(data); - if (asyncWork->success) { + if (asyncWork->success) + { napi_value result; napi_get_undefined(env, &result); napi_resolve_deferred(env, asyncWork->deferred, result); - } else { + } + else + { napi_value error; napi_create_string_utf8(env, asyncWork->error.c_str(), NAPI_AUTO_LENGTH, &error); napi_reject_deferred(env, asyncWork->deferred, error); @@ -44,16 +79,15 @@ void complete_work(napi_env env, napi_status status, void* data) { delete asyncWork; } -napi_value hydrate_file_impl(napi_env env, napi_callback_info info) { +napi_value hydrate_file_impl(napi_env env, napi_callback_info info) +{ auto [path] = napi_extract_args(env, info); - // Create promise napi_deferred deferred; napi_value promise; napi_create_promise(env, &deferred, &promise); - // Create and queue async work - AsyncWork* asyncWork = new AsyncWork{}; + AsyncWork *asyncWork = new AsyncWork{}; asyncWork->deferred = deferred; asyncWork->path = std::move(path); diff --git a/native-src/virtual_drive/update_sync_status/update_sync_status_wrapper.cpp b/native-src/virtual_drive/update_sync_status/update_sync_status_wrapper.cpp index 93bc35e6..a314a09e 100644 --- a/native-src/virtual_drive/update_sync_status/update_sync_status_wrapper.cpp +++ b/native-src/virtual_drive/update_sync_status/update_sync_status_wrapper.cpp @@ -4,9 +4,9 @@ napi_value update_sync_status_wrapper(napi_env env, napi_callback_info info) { - auto [path, isDirectory] = napi_extract_args(env, info); + auto [path] = napi_extract_args(env, info); - Placeholders::UpdateSyncStatus(path, isDirectory); + Placeholders::UpdateSyncStatus(path); return nullptr; } diff --git a/package.json b/package.json index 0588ecc2..63b952b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@internxt/node-win", - "version": "1.0.26", + "version": "1.0.27", "author": "Internxt ", "description": "Drive desktop node addon", "main": "dist/index.js",