diff --git a/binding.gyp b/binding.gyp index 569bf740..858e963a 100644 --- a/binding.gyp +++ b/binding.gyp @@ -32,7 +32,6 @@ "native-src/virtual_drive/create_folder_placeholder.cpp", "native-src/virtual_drive/dehydrate_file.cpp", "native-src/virtual_drive/disconnect_sync_root.cpp", - "native-src/virtual_drive/get_file_identity.cpp", "native-src/virtual_drive/get_placeholder_state/get_placeholder_state_wrapper.cpp", "native-src/virtual_drive/get_registered_sync_roots/get_registered_sync_roots.cpp", "native-src/virtual_drive/get_registered_sync_roots/get_registered_sync_roots_wrapper.cpp", diff --git a/dist/addon.node b/dist/addon.node index 9ce5ed95..747ed9a7 100644 Binary files a/dist/addon.node and b/dist/addon.node differ diff --git a/include/placeholders_interface/PlaceHolderInfo.h b/include/placeholders_interface/PlaceHolderInfo.h index 483785d0..fa0514fc 100644 --- a/include/placeholders_interface/PlaceHolderInfo.h +++ b/include/placeholders_interface/PlaceHolderInfo.h @@ -3,42 +3,10 @@ #include "stdafx.h" #include -enum class PinState +struct FileState { - /* The pin state is derived from the state of the parent folder. For example new remote files start out in this state, following the state of their parent folder. This state is used purely for resetting pin states to their derived value. The effective state for an item will never be "Inherited". */ - Inherited = 0, - /* The file shall be available and up to date locally. Also known as "pinned". Pinned dehydrated files shall be hydrated as soon as possible. */ - AlwaysLocal = 1, - /* File shall be a dehydrated placeholder, filled on demand. Also known as "unpinned". Unpinned hydrated files shall be dehydrated as soon as possible. If a unpinned file becomes hydrated (such as due to an implicit hydration where the user requested access to the file's data) its pin state changes to Unspecified. */ - OnlineOnly = 2, - /* The user hasn't made a decision. The client or platform may hydrate or dehydrate as they see fit. New remote files in unspecified directories start unspecified, and dehydrated (which is an arbitrary decision).*/ - Unspecified = 3, - /* The file will never be synced to the cloud. Useful for ignored files to indicate to the OS the file will never besynced */ - Excluded = 4, -}; - -struct FileState { - PinState pinstate; -}; - -class PlaceHolderInfo -{ -public: - using Deleter = void (*)(CF_PLACEHOLDER_BASIC_INFO *); - - PlaceHolderInfo(); - PlaceHolderInfo(CF_PLACEHOLDER_BASIC_INFO *data, Deleter deleter); - - inline CF_PLACEHOLDER_BASIC_INFO *get() const noexcept { return _data.get(); } - inline CF_PLACEHOLDER_BASIC_INFO *operator->() const noexcept { return _data.get(); } - inline explicit operator bool() const noexcept { return static_cast(_data); } - - std::optional pinState() const; - std::optional FileId() const; - std::optional FileIdentity() const; - -private: - std::unique_ptr _data; + std::string placeholderId; + CF_PIN_STATE pinState; }; class FileHandle @@ -51,12 +19,9 @@ class FileHandle inline void *get() const { return _data.get(); } inline explicit operator bool() const noexcept { return static_cast(_data); } - static void deletePlaceholderInfo(CF_PLACEHOLDER_BASIC_INFO *data); private: std::unique_ptr _data; }; FileHandle handleForPath(const std::wstring &path); - -CF_PIN_STATE pinStateToCfPinState(PinState state); \ No newline at end of file diff --git a/include/placeholders_interface/Placeholders.h b/include/placeholders_interface/Placeholders.h index b9ce5ac8..0c0eff49 100644 --- a/include/placeholders_interface/Placeholders.h +++ b/include/placeholders_interface/Placeholders.h @@ -6,9 +6,8 @@ class Placeholders { public: - static void MaintainIdentity(std::wstring &fullPath, PCWSTR fileIdentity, bool isDirectory); + static void MaintainIdentity(const std::wstring &fullPath, PCWSTR fileIdentity, bool isDirectory); static void UpdateSyncStatus(const std::wstring &filePath, bool isDirectory); - static std::string GetFileIdentity(const std::wstring &filePath); static void UpdateFileIdentity(const std::wstring &filePath, const std::wstring &fileIdentity, bool isDirectory); static FileState GetPlaceholderInfo(const std::wstring &directoryPath); }; \ No newline at end of file diff --git a/include/sync_root_interface/SyncRoot.h b/include/sync_root_interface/SyncRoot.h index 0294cb0f..d4d25d37 100644 --- a/include/sync_root_interface/SyncRoot.h +++ b/include/sync_root_interface/SyncRoot.h @@ -18,7 +18,6 @@ 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 std::string GetFileIdentity(const wchar_t *path); static void HydrateFile(const wchar_t *filePath); private: diff --git a/include/virtual_drive/Wrappers.h b/include/virtual_drive/Wrappers.h index 07f269e7..2fcac9d9 100644 --- a/include/virtual_drive/Wrappers.h +++ b/include/virtual_drive/Wrappers.h @@ -9,7 +9,6 @@ napi_value RegisterSyncRootWrapper(napi_env env, napi_callback_info args); napi_value GetRegisteredSyncRootsWrapper(napi_env env, napi_callback_info args); napi_value ConnectSyncRootWrapper(napi_env env, napi_callback_info args); napi_value DisconnectSyncRootWrapper(napi_env env, napi_callback_info args); -napi_value GetFileIdentityWrapper(napi_env env, napi_callback_info args); napi_value addLoggerPathWrapper(napi_env env, napi_callback_info args); napi_value UpdateSyncStatusWrapper(napi_env env, napi_callback_info args); napi_value GetPlaceholderStateWrapper(napi_env env, napi_callback_info args); diff --git a/include/virtual_drive/get_file_identity.h b/include/virtual_drive/get_file_identity.h deleted file mode 100644 index 5ffc6608..00000000 --- a/include/virtual_drive/get_file_identity.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -napi_value get_file_identity_impl(napi_env env, napi_callback_info args); diff --git a/native-src/main.cpp b/native-src/main.cpp index f7ed265a..ddb1a1e8 100644 --- a/native-src/main.cpp +++ b/native-src/main.cpp @@ -11,7 +11,6 @@ napi_value init(napi_env env, napi_value exports) {"connectSyncRoot", nullptr, ConnectSyncRootWrapper, nullptr, nullptr, nullptr, napi_default, nullptr}, {"createFolderPlaceholder", nullptr, CreateFolderPlaceholderWrapper, nullptr, nullptr, nullptr, napi_default, nullptr}, {"disconnectSyncRoot", nullptr, DisconnectSyncRootWrapper, nullptr, nullptr, nullptr, napi_default, nullptr}, - {"getFileIdentity", nullptr, GetFileIdentityWrapper, nullptr, nullptr, nullptr, napi_default, nullptr}, {"addLoggerPath", nullptr, addLoggerPathWrapper, nullptr, nullptr, nullptr, napi_default, nullptr}, {"updateSyncStatus", nullptr, UpdateSyncStatusWrapper, nullptr, nullptr, nullptr, napi_default, nullptr}, {"getPlaceholderState", nullptr, GetPlaceholderStateWrapper, nullptr, nullptr, nullptr, napi_default, nullptr}, @@ -19,7 +18,9 @@ napi_value init(napi_env env, napi_value exports) {"hydrateFile", nullptr, HydrateFileWrapper, nullptr, nullptr, nullptr, napi_default, nullptr}, {"dehydrateFile", nullptr, DehydrateFileWrapper, nullptr, nullptr, nullptr, napi_default, nullptr}}; - if (napi_define_properties(env, exports, 14, properties) != napi_ok) + size_t property_count = sizeof(properties) / sizeof(properties[0]); + + if (napi_define_properties(env, exports, property_count, properties) != napi_ok) { napi_throw_error(env, nullptr, "Failed to define properties"); return nullptr; diff --git a/native-src/placeholders_interface/PlaceHolderInfo.cpp b/native-src/placeholders_interface/PlaceHolderInfo.cpp index c4a06826..efb60713 100644 --- a/native-src/placeholders_interface/PlaceHolderInfo.cpp +++ b/native-src/placeholders_interface/PlaceHolderInfo.cpp @@ -6,90 +6,6 @@ #include #include "Logger.h" -PinState cfPinStateToPinState(CF_PIN_STATE state) -{ - switch (state) - { - case CF_PIN_STATE_UNSPECIFIED: - return PinState::Unspecified; - case CF_PIN_STATE_PINNED: - return PinState::AlwaysLocal; - case CF_PIN_STATE_UNPINNED: - return PinState::OnlineOnly; - case CF_PIN_STATE_INHERIT: - return PinState::Inherited; - case CF_PIN_STATE_EXCLUDED: - return PinState::Excluded; - default: - return PinState::Inherited; - } -} - -CF_PIN_STATE pinStateToCfPinState(PinState state) -{ - switch (state) - { - case PinState::Unspecified: - return CF_PIN_STATE_UNSPECIFIED; - case PinState::AlwaysLocal: - return CF_PIN_STATE_PINNED; - case PinState::OnlineOnly: - return CF_PIN_STATE_UNPINNED; - case PinState::Inherited: - return CF_PIN_STATE_INHERIT; - case PinState::Excluded: - return CF_PIN_STATE_EXCLUDED; - default: - return CF_PIN_STATE_INHERIT; - } -} - -PlaceHolderInfo::PlaceHolderInfo() - : _data(nullptr, [](CF_PLACEHOLDER_BASIC_INFO *) {}) -{ -} - -PlaceHolderInfo::PlaceHolderInfo(CF_PLACEHOLDER_BASIC_INFO *data, Deleter deleter) - : _data(data, deleter) -{ -} - -std::optional PlaceHolderInfo::pinState() const -{ - if (!_data) - { - return {}; - } - - return cfPinStateToPinState(_data->PinState); -} - -std::optional PlaceHolderInfo::FileId() const -{ - if (!_data) - { - return {}; - } - return _data->FileId; -} - -std::optional PlaceHolderInfo::FileIdentity() const -{ - if (!_data) - { - return {}; - } - - printf("FILE OPTIONAL: %d\n", _data->FileIdentity[0]); - return _data->FileIdentity[0]; // Devuelve el primer byte del array -} - -void FileHandle::deletePlaceholderInfo(CF_PLACEHOLDER_BASIC_INFO *info) -{ - auto byte = reinterpret_cast(info); - delete[] byte; -} - FileHandle::FileHandle() : _data( nullptr, [](void *) {}) diff --git a/native-src/placeholders_interface/Planceholders.cpp b/native-src/placeholders_interface/Planceholders.cpp index 9148b297..eaf97236 100644 --- a/native-src/placeholders_interface/Planceholders.cpp +++ b/native-src/placeholders_interface/Planceholders.cpp @@ -36,9 +36,9 @@ std::string cleanString(const std::string &str) return cleanedStr; } -void Placeholders::MaintainIdentity(std::wstring &fullPath, PCWSTR itemIdentity, bool isDirectory) +void Placeholders::MaintainIdentity(const std::wstring &fullPath, PCWSTR itemIdentity, bool isDirectory) { - std::string identity = Placeholders::GetFileIdentity(fullPath); + std::string identity = Placeholders::GetPlaceholderInfo(fullPath).placeholderId; if (!identity.empty()) { int len = WideCharToMultiByte(CP_UTF8, 0, itemIdentity, -1, NULL, 0, NULL, NULL); @@ -145,63 +145,28 @@ void Placeholders::UpdateFileIdentity(const std::wstring &filePath, const std::w CloseHandle(fileHandle); } -std::string Placeholders::GetFileIdentity(const std::wstring &filePath) +FileState Placeholders::GetPlaceholderInfo(const std::wstring &path) { - constexpr auto fileIdMaxLength = 128; - const auto infoSize = sizeof(CF_PLACEHOLDER_BASIC_INFO) + fileIdMaxLength; - auto info = PlaceHolderInfo(reinterpret_cast(new char[infoSize]), FileHandle::deletePlaceholderInfo); + constexpr DWORD fileIdMaxLength = 400; + constexpr DWORD infoSize = sizeof(CF_PLACEHOLDER_BASIC_INFO) + fileIdMaxLength; - HRESULT result = CfGetPlaceholderInfo(handleForPath(filePath).get(), CF_PLACEHOLDER_INFO_BASIC, info.get(), Utilities::sizeToDWORD(infoSize), nullptr); - - if (result == S_OK) - { - BYTE *FileIdentity = info->FileIdentity; - size_t length = info->FileIdentityLength; - - std::string fileIdentityString(reinterpret_cast(FileIdentity), length); - return fileIdentityString; - } - else - { - return ""; - } -} - -FileState Placeholders::GetPlaceholderInfo(const std::wstring &directoryPath) -{ - - constexpr auto fileIdMaxLength = 400; - const auto infoSize = sizeof(CF_PLACEHOLDER_BASIC_INFO) + fileIdMaxLength; - auto info = PlaceHolderInfo(reinterpret_cast(new char[infoSize]), FileHandle::deletePlaceholderInfo); - - FileState fileState; - auto fileHandle = handleForPath(directoryPath); + std::vector buffer(infoSize); + auto *info = reinterpret_cast(buffer.data()); + auto fileHandle = handleForPath(path); if (!fileHandle) { - printf("Error: Invalid file handle.\n"); - fileState.pinstate = PinState::Unspecified; - return fileState; + throw std::runtime_error("Failed to get file handle: " + std::to_string(GetLastError())); } - HRESULT result = CfGetPlaceholderInfo(fileHandle.get(), CF_PLACEHOLDER_INFO_BASIC, info.get(), Utilities::sizeToDWORD(infoSize), nullptr); - - if (result != S_OK) - { - printf("CfGetPlaceholderInfo failed with HRESULT %lx\n", result); - fileState.pinstate = PinState::Unspecified; - return fileState; - } - - auto pinStateOpt = info.pinState(); - - if (pinStateOpt.has_value()) - { - - PinState pinState = pinStateOpt.value(); - } - - fileState.pinstate = pinStateOpt.value_or(PinState::Unspecified); + winrt::check_hresult(CfGetPlaceholderInfo( + fileHandle.get(), + CF_PLACEHOLDER_INFO_BASIC, + info, + infoSize, + nullptr)); - return fileState; + return FileState{ + std::string(reinterpret_cast(info->FileIdentity), info->FileIdentityLength), + info->PinState}; } diff --git a/native-src/virtual_drive/Wrappers.cpp b/native-src/virtual_drive/Wrappers.cpp index ecf1513a..2e087185 100644 --- a/native-src/virtual_drive/Wrappers.cpp +++ b/native-src/virtual_drive/Wrappers.cpp @@ -11,7 +11,6 @@ #include "register_sync_root_wrapper.h" #include "create_folder_placeholder.h" #include "create_file_placeholder.h" -#include "get_file_identity.h" #include "connect_sync_root.h" #include "hydrate_file.h" #include "convert_to_placeholder.h" @@ -23,38 +22,41 @@ #include "update_sync_status_wrapper.h" #include "NAPI_SAFE_WRAP.h" -napi_value CreateFilePlaceholderWrapper(napi_env env, napi_callback_info args) { +napi_value CreateFilePlaceholderWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, create_file_placeholder_impl); } -napi_value UnregisterSyncRootWrapper(napi_env env, napi_callback_info args) { +napi_value UnregisterSyncRootWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, unregister_sync_root_wrapper); } -napi_value RegisterSyncRootWrapper(napi_env env, napi_callback_info info) { +napi_value RegisterSyncRootWrapper(napi_env env, napi_callback_info info) +{ return NAPI_SAFE_WRAP(env, info, register_sync_root_wrapper); } -napi_value GetRegisteredSyncRootsWrapper(napi_env env, napi_callback_info args) { +napi_value GetRegisteredSyncRootsWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, get_registered_sync_roots_wrapper); } -napi_value ConnectSyncRootWrapper(napi_env env, napi_callback_info args) { +napi_value ConnectSyncRootWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, connect_sync_root_impl); } -napi_value CreateFolderPlaceholderWrapper(napi_env env, napi_callback_info args) { +napi_value CreateFolderPlaceholderWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, create_folder_placeholder_impl); } -napi_value DisconnectSyncRootWrapper(napi_env env, napi_callback_info args) { +napi_value DisconnectSyncRootWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, disconnect_sync_root); } -napi_value GetFileIdentityWrapper(napi_env env, napi_callback_info args) { - return NAPI_SAFE_WRAP(env, args, get_file_identity_impl); -} - napi_value addLoggerPathWrapper(napi_env env, napi_callback_info args) { size_t argc = 1; @@ -95,22 +97,27 @@ napi_value addLoggerPathWrapper(napi_env env, napi_callback_info args) return result; } -napi_value UpdateSyncStatusWrapper(napi_env env, napi_callback_info args) { +napi_value UpdateSyncStatusWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, update_sync_status_wrapper); } -napi_value GetPlaceholderStateWrapper(napi_env env, napi_callback_info args) { +napi_value GetPlaceholderStateWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, get_placeholder_state_wrapper); } -napi_value ConvertToPlaceholderWrapper(napi_env env, napi_callback_info args) { +napi_value ConvertToPlaceholderWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, convert_to_placeholder_wrapper); } -napi_value HydrateFileWrapper(napi_env env, napi_callback_info args) { +napi_value HydrateFileWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, hydrate_file_impl); } -napi_value DehydrateFileWrapper(napi_env env, napi_callback_info args) { +napi_value DehydrateFileWrapper(napi_env env, napi_callback_info args) +{ return NAPI_SAFE_WRAP(env, args, dehydrate_file); } diff --git a/native-src/virtual_drive/convert_to_placeholder.cpp b/native-src/virtual_drive/convert_to_placeholder.cpp index 7d617b5a..1f30c4f4 100644 --- a/native-src/virtual_drive/convert_to_placeholder.cpp +++ b/native-src/virtual_drive/convert_to_placeholder.cpp @@ -2,6 +2,7 @@ #include #include "stdafx.h" #include "napi_extract_args.h" +#include "Placeholders.h" void convert_to_placeholder(const std::wstring &path, const std::wstring &placeholderId) { @@ -30,8 +31,11 @@ void convert_to_placeholder(const std::wstring &path, const std::wstring &placeh HRESULT hr = CfConvertToPlaceholder(fileHandle.get(), idStrLPCVOID, idStrByteLength, convertFlags, &convertUsn, &overlapped); - // Only throw if it's not "already a placeholder" error - if (hr != 0x8007017C) + if (hr == 0x8007017C) // Already a placeholder + { + Placeholders::MaintainIdentity(path, placeholderId.c_str(), isDirectory); + } + else { winrt::check_hresult(hr); } diff --git a/native-src/virtual_drive/create_file_placeholder.cpp b/native-src/virtual_drive/create_file_placeholder.cpp index f2e913c2..5850ab3c 100644 --- a/native-src/virtual_drive/create_file_placeholder.cpp +++ b/native-src/virtual_drive/create_file_placeholder.cpp @@ -18,7 +18,6 @@ napi_value create_file_placeholder_impl(napi_env env, napi_callback_info info) if (std::filesystem::exists(path)) { convert_to_placeholder(path, placeholderId); - Placeholders::MaintainIdentity(path, placeholderId.c_str(), false); return nullptr; } diff --git a/native-src/virtual_drive/create_folder_placeholder.cpp b/native-src/virtual_drive/create_folder_placeholder.cpp index f4842627..e4597346 100644 --- a/native-src/virtual_drive/create_folder_placeholder.cpp +++ b/native-src/virtual_drive/create_folder_placeholder.cpp @@ -18,7 +18,6 @@ napi_value create_folder_placeholder_impl(napi_env env, napi_callback_info info) if (std::filesystem::exists(path)) { convert_to_placeholder(path, placeholderId); - Placeholders::MaintainIdentity(path, placeholderId.c_str(), true); return nullptr; } diff --git a/native-src/virtual_drive/get_file_identity.cpp b/native-src/virtual_drive/get_file_identity.cpp deleted file mode 100644 index d1f98d86..00000000 --- a/native-src/virtual_drive/get_file_identity.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include "napi_extract_args.h" -#include "Placeholders.h" - -napi_value get_file_identity_impl(napi_env env, napi_callback_info info) { - auto [path] = napi_extract_args(env, info); - - std::string fileIdentity = Placeholders::GetFileIdentity(path); - fileIdentity.erase(std::remove(fileIdentity.begin(), fileIdentity.end(), '\0'), fileIdentity.end()); - fileIdentity.erase(std::remove(fileIdentity.begin(), fileIdentity.end(), ' '), fileIdentity.end()); - - napi_value jsFileIdentity; - napi_create_string_utf8(env, fileIdentity.c_str(), fileIdentity.length(), &jsFileIdentity); - - return jsFileIdentity; -} 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 aec01da6..05868a7f 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 @@ -2,16 +2,24 @@ #include "napi_extract_args.h" #include "Placeholders.h" -napi_value get_placeholder_state_wrapper(napi_env env, napi_callback_info info) { +napi_value get_placeholder_state_wrapper(napi_env env, napi_callback_info info) +{ auto [path] = napi_extract_args(env, 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); + napi_value jsPlaceholderId; + napi_create_string_utf8(env, state.placeholderId.c_str(), state.placeholderId.length(), &jsPlaceholderId); + napi_set_named_property(env, result, "placeholderId", jsPlaceholderId); + napi_value jsPinState; - napi_create_int32(env, static_cast(state.pinstate), &jsPinState); + napi_create_int32(env, static_cast(state.pinState), &jsPinState); napi_set_named_property(env, result, "pinState", jsPinState); return result;