Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Binary file modified dist/addon.node
Binary file not shown.
4 changes: 1 addition & 3 deletions include/placeholders_interface/Placeholders.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ class Placeholders
{
public:
static void MaintainIdentity(std::wstring &fullPath, PCWSTR fileIdentity, bool isDirectory);
static void ForceShellRefresh(const std::wstring &path);
static void UpdateSyncStatus(const std::wstring &filePath, bool syncState, bool isDirectory);
static HRESULT UpdatePinState(const std::wstring &path, const PinState state);
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);
Expand Down
251 changes: 18 additions & 233 deletions native-src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,244 +3,29 @@

napi_value init(napi_env env, napi_value exports)
{
napi_property_descriptor desc = {
"createFilePlaceholder",
nullptr,
CreateFilePlaceholderWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};
napi_property_descriptor properties[] = {
{"createFilePlaceholder", nullptr, CreateFilePlaceholderWrapper, nullptr, nullptr, nullptr, napi_default, nullptr},
{"unregisterSyncRoot", nullptr, UnregisterSyncRootWrapper, nullptr, nullptr, nullptr, napi_default, nullptr},
{"registerSyncRoot", nullptr, RegisterSyncRootWrapper, nullptr, nullptr, nullptr, napi_default, nullptr},
{"getRegisteredSyncRoots", nullptr, GetRegisteredSyncRootsWrapper, nullptr, nullptr, nullptr, napi_default, nullptr},
{"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},
{"convertToPlaceholder", nullptr, ConvertToPlaceholderWrapper, nullptr, nullptr, nullptr, napi_default, nullptr},
{"hydrateFile", nullptr, HydrateFileWrapper, nullptr, nullptr, nullptr, napi_default, nullptr},
{"dehydrateFile", nullptr, DehydrateFileWrapper, nullptr, nullptr, nullptr, napi_default, nullptr}};

napi_status defineStatus = napi_define_properties(env, exports, 1, &desc);
if (defineStatus != napi_ok)
if (napi_define_properties(env, exports, 14, properties) != napi_ok)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of defining all functions one by one we define all of them at the same time. See that we replaced 1 by 14 which is the number of elements in the array.

{
napi_throw_error(env, nullptr, "Failed to define function");
return nullptr;
}

napi_property_descriptor unregisterDesc = {
"unregisterSyncRoot",
nullptr,
UnregisterSyncRootWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineUnregisterStatus = napi_define_properties(env, exports, 1, &unregisterDesc);
if (defineUnregisterStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define UnregisterSyncRoot function");
return nullptr;
}

napi_property_descriptor registerSyncRootDesc = {
"registerSyncRoot",
nullptr,
RegisterSyncRootWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineRegisterSyncRootStatus = napi_define_properties(env, exports, 1, &registerSyncRootDesc);
if (defineRegisterSyncRootStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define RegisterSyncRoot function");
return nullptr;
}

napi_property_descriptor getRegisteredSyncRootsRootDesc = {
"getRegisteredSyncRoots",
nullptr,
GetRegisteredSyncRootsWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineGetRegisteredSyncRootsRootDescStatus = napi_define_properties(env, exports, 1, &getRegisteredSyncRootsRootDesc);
if (defineGetRegisteredSyncRootsRootDescStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define getRegisteredSyncRoots function");
return nullptr;
}

napi_property_descriptor connectSyncRootDesc = {
"connectSyncRoot",
nullptr,
ConnectSyncRootWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineConnectSyncRootStatus = napi_define_properties(env, exports, 1, &connectSyncRootDesc);
if (defineConnectSyncRootStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define ConnectSyncRoot function");
return nullptr;
}

napi_property_descriptor createFolderPlaceholderDesc = {
"createFolderPlaceholder",
nullptr,
CreateFolderPlaceholderWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineCreateFolderPlaceholderStatus = napi_define_properties(env, exports, 1, &createFolderPlaceholderDesc);
if (defineCreateFolderPlaceholderStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define createFolderPlaceholder function");
return nullptr;
}

napi_property_descriptor disconnectDesc = {
"disconnectSyncRoot",
nullptr,
DisconnectSyncRootWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineDisconnectStatus = napi_define_properties(env, exports, 1, &disconnectDesc);
if (defineDisconnectStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define DisconnectSyncRoot function");
return nullptr;
}

napi_property_descriptor getFileIdentityDesc = {
"getFileIdentity",
nullptr,
GetFileIdentityWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineGetFileIdentityStatus = napi_define_properties(env, exports, 1, &getFileIdentityDesc);
if (defineGetFileIdentityStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define getFileIdentity function");
return nullptr;
}

napi_property_descriptor addLoggerPathDesc = {
"addLoggerPath",
nullptr,
addLoggerPathWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineAddLoggerPathStatus = napi_define_properties(env, exports, 1, &addLoggerPathDesc);
if (defineAddLoggerPathStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define addLoggerPath function");
return nullptr;
}

napi_property_descriptor updateSyncStatusDesc = {
"updateSyncStatus",
nullptr,
UpdateSyncStatusWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status updateSyncStatusStatus = napi_define_properties(env, exports, 1, &updateSyncStatusDesc);
if (updateSyncStatusStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define updateSyncStatus function");
return nullptr;
}

napi_property_descriptor getPlaceholderStateDesc = {
"getPlaceholderState",
nullptr,
GetPlaceholderStateWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineGetPlaceholderStateStatus = napi_define_properties(env, exports, 1, &getPlaceholderStateDesc);
if (defineGetPlaceholderStateStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define getPlaceholderState function");
return nullptr;
}

napi_property_descriptor convertToPlaceholderDesc = {
"convertToPlaceholder",
nullptr,
ConvertToPlaceholderWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status convertToPlaceholderStatus = napi_define_properties(env, exports, 1, &convertToPlaceholderDesc);
if (convertToPlaceholderStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define convertToPlaceholder function");
return nullptr;
}

napi_property_descriptor hydrateFileDesc = {
"hydrateFile",
nullptr,
HydrateFileWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineHydrateFileStatus = napi_define_properties(env, exports, 1, &hydrateFileDesc);
if (defineHydrateFileStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define hydrateFile function");
return nullptr;
}

napi_property_descriptor dehydrateFileDesc = {
"dehydrateFile",
nullptr,
DehydrateFileWrapper,
nullptr,
nullptr,
nullptr,
napi_default,
nullptr};

napi_status defineDehydrateFileStatus = napi_define_properties(env, exports, 1, &dehydrateFileDesc);
if (defineDehydrateFileStatus != napi_ok)
{
napi_throw_error(env, nullptr, "Failed to define dehydrateFile function");
napi_throw_error(env, nullptr, "Failed to define properties");
return nullptr;
}

return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, init)
99 changes: 17 additions & 82 deletions native-src/placeholders_interface/Planceholders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,76 +62,33 @@ void Placeholders::MaintainIdentity(std::wstring &fullPath, PCWSTR itemIdentity,
}
}

/**
* @brief Mark a file or directory as synchronized
* @param filePath path to the file or directory
* @param isDirectory true if the path is a directory, false if it is a file
* @return void
*/
void Placeholders::UpdateSyncStatus(const std::wstring &filePath,
bool inputSyncState,
bool isDirectory /* = false */)
void Placeholders::UpdateSyncStatus(const std::wstring &path, bool isDirectory)
{
wprintf(L"[UpdateSyncStatus] Path: %ls\n", filePath.c_str());

DWORD flags = FILE_FLAG_OPEN_REPARSE_POINT;
if (isDirectory)
flags |= FILE_FLAG_BACKUP_SEMANTICS;

HANDLE h = CreateFileW(filePath.c_str(),
FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr,
OPEN_EXISTING,
flags,
nullptr);

if (h == INVALID_HANDLE_VALUE)
{
wprintf(L"[UpdateSyncStatus] CreateFileW falló: %lu\n", GetLastError());
CloseHandle(h);
return;
}

CF_IN_SYNC_STATE sync = inputSyncState ? CF_IN_SYNC_STATE_IN_SYNC
: CF_IN_SYNC_STATE_NOT_IN_SYNC;

HRESULT hr = CfSetInSyncState(h, sync, CF_SET_IN_SYNC_FLAG_NONE, nullptr);

if (FAILED(hr))
Copy link
Contributor Author

@dajimenezriv-internxt dajimenezriv-internxt Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't care about the different types of errors, we just throw the error. If this is not inside a cloud provider (second case) we are going to have an error before reaching this function and if the file is not a placeholder (third case) we are going to have an error before reaching this function too.

{
switch (HRESULT_CODE(hr))
{
case ERROR_RETRY:
Sleep(50);
hr = CfSetInSyncState(h, sync, CF_SET_IN_SYNC_FLAG_NONE, nullptr);
wprintf(L"[UpdateSyncStatus] Retry CfSetInSyncState\n");
break;

case ERROR_CLOUD_FILE_PROVIDER_NOT_RUNNING: // 0x1A94
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, filePath.c_str(), nullptr);
wprintf(L"[UpdateSyncStatus] Retry CfSetInSyncState\n");
break;

case ERROR_CLOUD_FILE_NOT_IN_SYNC:
convert_to_placeholder(filePath, L"temp_identity");
hr = CfSetInSyncState(h, sync, CF_SET_IN_SYNC_FLAG_NONE, nullptr);
wprintf(L"[UpdateSyncStatus] Retry CfSetInSyncState\n");
break;
winrt::file_handle fileHandle{CreateFileW(
path.c_str(),
FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr,
OPEN_EXISTING,
flags,
nullptr)};

default:
wprintf(L"[UpdateSyncStatus] CfSetInSyncState 0x%08X\n", hr);
break;
}
}
else
if (!fileHandle)
{
wprintf(L"[UpdateSyncStatus] Estado actualizado\n");
throw std::runtime_error("Failed to open item: " + std::to_string(GetLastError()));
}

CloseHandle(h);
winrt::check_hresult(CfSetInSyncState(
fileHandle.get(),
CF_IN_SYNC_STATE_IN_SYNC,
CF_SET_IN_SYNC_FLAG_NONE,
nullptr));

SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, filePath.c_str(), nullptr);
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, path.c_str(), nullptr);
}

void Placeholders::UpdateFileIdentity(const std::wstring &filePath, const std::wstring &fileIdentity, bool isDirectory)
Expand Down Expand Up @@ -248,25 +205,3 @@ FileState Placeholders::GetPlaceholderInfo(const std::wstring &directoryPath)

return fileState;
}

void Placeholders::ForceShellRefresh(const std::wstring &path)
{
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH, path.c_str(), nullptr);
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, path.c_str(), nullptr);
}

HRESULT Placeholders::UpdatePinState(const std::wstring &path, const PinState state)
{

const auto cfState = pinStateToCfPinState(state);
HRESULT result = CfSetPinState(handleForPath(path).get(), cfState, CF_SET_PIN_FLAG_NONE, nullptr);

// ForceShellRefresh(path);

if (result != S_OK)
{
Logger::getInstance().log("[UpdatePinState] Error updating pin state.", LogLevel::WARN);
}

return result;
}
Loading