Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
21bd1ad
Create napi safe wrap
dajimenezriv-internxt Aug 15, 2025
819a1f1
Extract create folder placeholder
dajimenezriv-internxt Aug 16, 2025
cc1b678
Extract create file placeholder
dajimenezriv-internxt Aug 16, 2025
444a2d5
Extract get file identity
dajimenezriv-internxt Aug 19, 2025
b5eff5e
Update package.json
dajimenezriv-internxt Aug 19, 2025
fe31746
Extract connect sync root
dajimenezriv-internxt Aug 27, 2025
32c5ea9
Extract hydrate file
dajimenezriv-internxt Sep 8, 2025
75681d6
Hydrate file thread safe
dajimenezriv-internxt Sep 8, 2025
205f2be
Improve safe wrap
dajimenezriv-internxt Sep 8, 2025
9648c94
Remove delete file from c++
dajimenezriv-internxt Sep 8, 2025
46ee84c
Extract convert to placeholder
dajimenezriv-internxt Sep 10, 2025
313dfbf
Refactor register sync root
dajimenezriv-internxt Sep 15, 2025
ff28084
Extract code
dajimenezriv-internxt Sep 15, 2025
d1a7164
Improve
dajimenezriv-internxt Sep 15, 2025
70d004e
Simplify providerId
dajimenezriv-internxt Sep 15, 2025
69ce991
Commit
dajimenezriv-internxt Sep 15, 2025
1020526
Commit
dajimenezriv-internxt Sep 15, 2025
e94646e
Commit
dajimenezriv-internxt Sep 15, 2025
0601df9
Update get_registered_sync_roots.cpp
dajimenezriv-internxt Sep 15, 2025
73a1c9e
Update addon.node
dajimenezriv-internxt Sep 15, 2025
ae38d77
Commt
dajimenezriv-internxt Sep 15, 2025
f7b6a44
Commit
dajimenezriv-internxt Sep 16, 2025
41028a0
Simplify unregister
dajimenezriv-internxt Sep 16, 2025
38a0e29
Fix wrapper
dajimenezriv-internxt Sep 16, 2025
4832626
Remove context
dajimenezriv-internxt Sep 16, 2025
d947054
Improve napi
dajimenezriv-internxt Sep 16, 2025
9d096c0
Template napi_extract_args
dajimenezriv-internxt Sep 16, 2025
249d71c
Extract dehydrate file wrapper
dajimenezriv-internxt Sep 17, 2025
2d39fb1
Refactor dehydrate file
dajimenezriv-internxt Sep 17, 2025
0a6216f
Throw exceptions
dajimenezriv-internxt Sep 17, 2025
4577789
Commit
dajimenezriv-internxt Sep 17, 2025
2a9867b
Merge branch 'master' into refactor-dehydrate-file
dajimenezriv-internxt Sep 18, 2025
4388e5c
Update hydrate_file.cpp
dajimenezriv-internxt Sep 18, 2025
da16704
Update hydrate_file.cpp
dajimenezriv-internxt Sep 18, 2025
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 binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"native-src/virtual_drive/convert_to_placeholder.cpp",
"native-src/virtual_drive/create_file_placeholder.cpp",
"native-src/virtual_drive/create_folder_placeholder.cpp",
"native-src/virtual_drive/dehydrate_file.cpp",
"native-src/virtual_drive/get_file_identity.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",
Expand Down
Binary file modified dist/addon.node
Binary file not shown.
1 change: 0 additions & 1 deletion include/sync_root_interface/SyncRoot.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class SyncRoot
static HRESULT DisconnectSyncRoot(const wchar_t *syncRootPath);
static std::string GetFileIdentity(const wchar_t *path);
static void HydrateFile(const wchar_t *filePath);
static void DehydrateFile(const wchar_t *filePath);

private:
CF_CONNECTION_KEY connectionKey;
Expand Down
5 changes: 5 additions & 0 deletions include/virtual_drive/dehydrate_file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include <node_api.h>

napi_value dehydrate_file(napi_env env, napi_callback_info info);
48 changes: 0 additions & 48 deletions native-src/sync_root_interface/SyncRoot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,54 +56,6 @@ void SyncRoot::HydrateFile(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))
{
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_UNPINNED)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We neo longer need to check this manually, the error given by CfDehydratePlaceholder is better as explained below.

{
// 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);

if (FAILED(hr))
{
DWORD err = HRESULT_CODE(hr);
if (err == ERROR_SHARING_VIOLATION || err == ERROR_CLOUD_FILE_IN_USE)
{
wprintf(L"Cannot dehydrate because the file is currently in use: %ls\n", filePath);

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);
}
else
{
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 SyncRoot::ConnectSyncRoot(const wchar_t *syncRootPath, InputSyncCallbacks syncCallbacks, napi_env env, CF_CONNECTION_KEY *connectionKey)
{
Utilities::AddFolderToSearchIndexer(syncRootPath);
Expand Down
33 changes: 4 additions & 29 deletions native-src/virtual_drive/Wrappers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "convert_to_placeholder.h"
#include "get_registered_sync_roots_wrapper.h"
#include "unregister_sync_root_wrapper.h"
#include "dehydrate_file.h"
#include "NAPI_SAFE_WRAP.h"

napi_value CreatePlaceholderFile(napi_env env, napi_callback_info args) {
Expand Down Expand Up @@ -228,38 +229,12 @@ napi_value UpdateFileIdentityWrapper(napi_env env, napi_callback_info args)
return result;
}

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)
{
size_t argc = 1;
napi_value argv[1];
napi_value thisArg;
napi_get_cb_info(env, args, &argc, argv, &thisArg, nullptr);

if (argc < 1)
{
napi_throw_type_error(env, nullptr, "The file path is required for DehydrateFile");
return nullptr;
}

// Obtener el argumento de JavaScript y convertirlo a una cadena de C++
LPCWSTR fullPath;
size_t pathLength;
napi_get_value_string_utf16(env, argv[0], nullptr, 0, &pathLength);
fullPath = new WCHAR[pathLength + 1];
napi_get_value_string_utf16(env, argv[0], reinterpret_cast<char16_t *>(const_cast<wchar_t *>(fullPath)), pathLength + 1, nullptr);

// Llamar a la función DehydrateFile
SyncRoot::DehydrateFile(fullPath);

napi_value result;
napi_get_boolean(env, true, &result);

return result;
napi_value DehydrateFileWrapper(napi_env env, napi_callback_info args) {
return NAPI_SAFE_WRAP(env, args, dehydrate_file);
}

napi_value GetPlaceholderAttributeWrapper(napi_env env, napi_callback_info args)
Expand Down
39 changes: 39 additions & 0 deletions native-src/virtual_drive/dehydrate_file.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <windows.h>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Code is nearly the same.

  1. We check if it's a directory, in that case we throw an exception. Previously we were just ignoring it.
  2. We remove the check of a file has the attribute FILE_ATTRIBUTE_UNPINNED since the error given by CfDehydratePlaceholder is better: [DehydrateFileWrapper] WinRT error: The operation cannot be performed on pinned cloud files. (HRESULT: 0x80070188).
  3. We keep the mssage box in case the file is used in that moment and we cannot dehydrate.
  4. We throw the exception to let the javascript code know that something failed.

I've tested these three possible errors and all work perfectly.

#include "napi_extract_args.h"
#include "stdafx.h"

napi_value dehydrate_file(napi_env env, napi_callback_info info) {
auto [rawPath] = napi_extract_args<1>(env, info);
const wchar_t* path = rawPath.c_str();

DWORD attrib = GetFileAttributesW(path);

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));

LARGE_INTEGER offset;
offset.QuadPart = 0;
LARGE_INTEGER length;
GetFileSizeEx(placeholder.get(), &length);

HRESULT hr = CfDehydratePlaceholder(placeholder.get(), offset, length, CF_DEHYDRATE_FLAG_NONE, NULL);

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);
}