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
1 change: 1 addition & 0 deletions include/sync_root_interface/Utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Utilities
static std::wstring ProcessErrorNameToWString(_In_ ProcessErrorName error);
static std::wstring FileOperationErrorToWString(_In_ FileOperationError error);
static bool IsTemporaryFile(const std::wstring &fullPath);
static std::wstring GetErrorMessageCloudFiles(HRESULT hr);

static winrt::com_array<wchar_t>
ConvertSidToStringSid(_In_ PSID sid)
Expand Down
171 changes: 92 additions & 79 deletions native-src/placeholders_interface/Planceholders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void Placeholders::CreateOne(
{
Placeholders::ConvertToPlaceholder(fullPath, fileIdentity);
Placeholders::MaintainIdentity(fullPath, fileIdentity, false);
return; // No hacer nada si ya existe
return;
}

std::wstring relativeName(fileIdentity);
Expand Down Expand Up @@ -189,22 +189,20 @@ bool Placeholders::ConvertToPlaceholder(const std::wstring &fullPath, const std:
{
if (!std::filesystem::exists(fullPath))
{
// El archivo no existe
wprintf(L"[ConvertToPlaceholder] File does not exist\n");
return false;
}

// Obtener un handle al archivo
wprintf(L"[ConvertToPlaceholder] Full path: %ls\n", fullPath.c_str());
bool isDirectory = fs::is_directory(fullPath);

// Obtener un handle al archivo o carpeta
HANDLE fileHandle = CreateFileW(
fullPath.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, // Agregar FILE_FLAG_BACKUP_SEMANTICS si es una carpeta
isDirectory ? FILE_FLAG_BACKUP_SEMANTICS : 0,
nullptr);

if (fileHandle == INVALID_HANDLE_VALUE)
Expand All @@ -217,7 +215,6 @@ bool Placeholders::ConvertToPlaceholder(const std::wstring &fullPath, const std:
USN convertUsn;
OVERLAPPED overlapped = {};

// Convierte la cadena de la identidad del servidor a LPCVOID
LPCVOID idStrLPCVOID = static_cast<LPCVOID>(serverIdentity.c_str());
DWORD idStrByteLength = static_cast<DWORD>(serverIdentity.size() * sizeof(wchar_t));

Expand Down Expand Up @@ -246,13 +243,19 @@ bool Placeholders::ConvertToPlaceholder(const std::wstring &fullPath, const std:
LocalFree(errorMsg);

CloseHandle(fileHandle);

return false;
}

if (!isDirectory)
{
CfSetPinState(fileHandle, CF_PIN_STATE_PINNED, CF_SET_PIN_FLAG_NONE, nullptr);
HRESULT hrPinState = CfSetPinState(fileHandle, CF_PIN_STATE_PINNED, CF_SET_PIN_FLAG_NONE, nullptr);
if (FAILED(hrPinState))
{
std::wstring errorMessage = Utilities::GetErrorMessageCloudFiles(hrPinState);
wprintf(L"[ConvertToPlaceholder] Error setting pin state, HRESULT: 0x%X\nDetails: %s\n", hrPinState, errorMessage.c_str());
CloseHandle(fileHandle);
return false;
}
}

CloseHandle(fileHandle);
Expand All @@ -267,43 +270,102 @@ bool Placeholders::ConvertToPlaceholder(const std::wstring &fullPath, const std:
}
}

std::wstring GetErrorMessageFromHRESULT(HRESULT hr)
{
LPWSTR errorMessage = nullptr;
DWORD result = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPWSTR>(&errorMessage),
0,
nullptr);

std::wstring message;
if (result > 0 && errorMessage)
{
message = errorMessage;
LocalFree(errorMessage);
}
else
{
message = L"Error desconocido";
}

return message;
}

/**
* @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 &filePath,
bool inputSyncState,
bool isDirectory /* = false */)
{
wprintf(L"[UpdateSyncStatus] Path: %ls\n", filePath.c_str());
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);

if (fileHandle == INVALID_HANDLE_VALUE)
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] Error al abrir el archivo: %d\n", GetLastError());
wprintf(L"[UpdateSyncStatus] CreateFileW falló: %lu\n", GetLastError());
CloseHandle(fileHandle);
return;
}

// https://learn.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfsetinsyncstate
// https://learn.microsoft.com/en-us/windows/win32/api/cfapi/ne-cfapi-cf_in_sync_state
CF_IN_SYNC_STATE syncState = inputSyncState ? CF_IN_SYNC_STATE_IN_SYNC : CF_IN_SYNC_STATE_NOT_IN_SYNC;
// wprintf(L"Marking item as %s: %ls\n", inputSyncState ? L"IN_SYNC" : L"NOT_IN_SYNC", filePath.c_str());
HRESULT hr = CfSetInSyncState(fileHandle, syncState, CF_SET_IN_SYNC_FLAG_NONE, nullptr);
// imprimir hresult
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))
{
wprintf(L"[UpdateSyncStatus] Error al establecer el estado de sincronización: %ld\n", hr);
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:
ConvertToPlaceholder(filePath, L"temp_identity");
hr = CfSetInSyncState(h, sync, CF_SET_IN_SYNC_FLAG_NONE, nullptr);
wprintf(L"[UpdateSyncStatus] Retry CfSetInSyncState\n");
break;

default:
wprintf(L"[UpdateSyncStatus] CfSetInSyncState 0x%08X\n", hr);
break;
}
}
else
{
wprintf(L"[UpdateSyncStatus] Estado actualizado\n");
}

CloseHandle(fileHandle);
CloseHandle(h);

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

void Placeholders::UpdateFileIdentity(const std::wstring &filePath, const std::wstring &fileIdentity, bool isDirectory)
Expand Down Expand Up @@ -351,46 +413,13 @@ void Placeholders::UpdateFileIdentity(const std::wstring &filePath, const std::w

if (FAILED(hr))
{
wprintf(L"[UpdateFileIdentity] Error updating fileIdentity: 0x%08X\n", hr);
LPWSTR errorMessage = nullptr;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
HRESULT_CODE(hr),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPWSTR>(&errorMessage),
0,
nullptr);
if (errorMessage)
{
wprintf(L"[UpdateFileIdentity] Error: %ls\n", errorMessage);
LocalFree(errorMessage);
}
}

CloseHandle(fileHandle);
}

CF_PLACEHOLDER_STATE Placeholders::GetPlaceholderState(const std::wstring &filePath)
{
HANDLE fileHandle = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (fileHandle == INVALID_HANDLE_VALUE)
{
// Error al abrir el archivo
return CF_PLACEHOLDER_STATE_INVALID;
}

FILE_BASIC_INFO fileBasicInfo;
if (!GetFileInformationByHandleEx(fileHandle, FileBasicInfo, &fileBasicInfo, sizeof(fileBasicInfo)))
{
// Error al obtener la información básica del archivo
std::wstring errorMessage = Utilities::GetErrorMessageCloudFiles(hr);
wprintf(L"[UpdateFileIdentity] Error updating fileIdentity: %ls\n", errorMessage.c_str());
CloseHandle(fileHandle);
return CF_PLACEHOLDER_STATE_INVALID;
return;
}

CF_PLACEHOLDER_STATE placeholderState = CfGetPlaceholderStateFromFileInfo(&fileBasicInfo, FileBasicInfo);
CloseHandle(fileHandle);

return placeholderState;
}

std::string Placeholders::GetFileIdentity(const std::wstring &filePath)
Expand All @@ -415,22 +444,6 @@ std::string Placeholders::GetFileIdentity(const std::wstring &filePath)
}
}

CF_PLACEHOLDER_STATE GetPlaceholderStateMock(const std::wstring &filePath)
{
static std::random_device rd;
static std::mt19937 gen(rd());
static std::uniform_int_distribution<int> dis(0, 1);

if (dis(gen) == 0)
{
return CF_PLACEHOLDER_STATE_IN_SYNC;
}
else
{
return CF_PLACEHOLDER_STATE_SYNC_ROOT;
}
}

FileState Placeholders::GetPlaceholderInfo(const std::wstring &directoryPath)
{

Expand Down
20 changes: 20 additions & 0 deletions native-src/sync_root_interface/Utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,26 @@ void Utilities::ApplyTransferStateToFile(_In_ PCWSTR fullPath, _In_ CF_CALLBACK_
}
}

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


bool Utilities::IsTemporaryFile(const std::wstring &fullPath)
{
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@internxt/node-win",
"version": "1.0.9",
"version": "1.0.10",
"description": "Drive desktop node addon",
"main": "dist/index.ts",
"types": "dist/index.d.ts",
Expand Down
Loading