1717#include < shlobj.h>
1818#include " convert_to_placeholder.h"
1919
20- using namespace std ;
21-
22- namespace fs = std::filesystem;
23-
2420#pragma comment(lib, "shlwapi.lib")
2521
26- std::string cleanString (const std::string &str )
22+ winrt::file_handle Placeholders::OpenFileHandle (const std::wstring &path, DWORD dwDesiredAccess, bool openAsPlaceholder )
2723{
28- std::string cleanedStr;
29- for (char ch : str)
30- {
31- if (std::isprint (static_cast <unsigned char >(ch)))
32- {
33- cleanedStr.push_back (ch);
34- }
35- }
36- return cleanedStr;
37- }
38-
39- void Placeholders::MaintainIdentity (const std::wstring &fullPath, PCWSTR itemIdentity, bool isDirectory)
40- {
41- std::string identity = Placeholders::GetPlaceholderInfo (fullPath).placeholderId ;
42- if (!identity.empty ())
43- {
44- int len = WideCharToMultiByte (CP_UTF8, 0 , itemIdentity, -1 , NULL , 0 , NULL , NULL );
45- if (len > 0 )
46- {
47- std::string itemIdentityStr (len, 0 );
48- WideCharToMultiByte (CP_UTF8, 0 , itemIdentity, -1 , &itemIdentityStr[0 ], len, NULL , NULL );
49- std::string cleanIdentity = cleanString (identity);
50- std::string cleanItemIdentity = cleanString (itemIdentityStr);
51- if (cleanIdentity != cleanItemIdentity)
52- {
53- wprintf (L" [MaintainIdentity] Identity is incorrect, updating...\n " );
54- std::wstring itemIdentityStrW (itemIdentity);
55- Placeholders::UpdateFileIdentity (fullPath, itemIdentityStrW, isDirectory);
56- }
57- }
58- else
59- {
60- // Handle error as needed
61- }
62- }
63- }
24+ bool isDirectory = std::filesystem::is_directory (path);
6425
65- void Placeholders::UpdateSyncStatus ( const std::wstring &path, bool isDirectory)
66- {
67- DWORD flags = FILE_FLAG_OPEN_REPARSE_POINT;
26+ DWORD dwFlagsAndAttributes = 0 ;
27+ if (openAsPlaceholder)
28+ dwFlagsAndAttributes | = FILE_FLAG_OPEN_REPARSE_POINT;
6829 if (isDirectory)
69- flags |= FILE_FLAG_BACKUP_SEMANTICS;
30+ dwFlagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
31+
32+ DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
7033
7134 winrt::file_handle fileHandle{CreateFileW (
7235 path.c_str (),
73- FILE_WRITE_ATTRIBUTES ,
74- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
36+ dwDesiredAccess ,
37+ dwShareMode ,
7538 nullptr ,
7639 OPEN_EXISTING,
77- flags ,
40+ dwFlagsAndAttributes ,
7841 nullptr )};
7942
8043 if (!fileHandle)
8144 {
82- throw std::runtime_error (" Failed to open item : " + std::to_string (GetLastError ()));
45+ throw std::runtime_error (" Failed to open file handle : " + std::to_string (GetLastError ()));
8346 }
8447
48+ return fileHandle;
49+ }
50+
51+ void Placeholders::UpdateSyncStatus (const std::wstring &path)
52+ {
53+ auto fileHandle = Placeholders::OpenFileHandle (path, FILE_WRITE_ATTRIBUTES, true );
54+
8555 winrt::check_hresult (CfSetInSyncState (
8656 fileHandle.get (),
8757 CF_IN_SYNC_STATE_IN_SYNC,
@@ -91,82 +61,42 @@ void Placeholders::UpdateSyncStatus(const std::wstring &path, bool isDirectory)
9161 SHChangeNotify (SHCNE_UPDATEITEM, SHCNF_PATH, path.c_str (), nullptr );
9262}
9363
94- void Placeholders::UpdateFileIdentity (const std::wstring &filePath , const std::wstring &fileIdentity, bool isDirectory )
64+ void Placeholders::UpdateFileIdentity (const std::wstring &path , const std::wstring &placeholderId )
9565{
96- HANDLE fileHandle = CreateFileW (
97- filePath.c_str (),
98- FILE_WRITE_ATTRIBUTES, // permisson needed to change the state
99- FILE_SHARE_READ | FILE_SHARE_WRITE,
100- nullptr ,
101- OPEN_EXISTING,
102- isDirectory ? FILE_FLAG_BACKUP_SEMANTICS : FILE_ATTRIBUTE_NORMAL,
103- nullptr );
66+ auto fileHandle = OpenFileHandle (path, FILE_WRITE_ATTRIBUTES, true );
10467
105- if (fileHandle == INVALID_HANDLE_VALUE)
106- {
107- DWORD errorCode = GetLastError ();
108- wprintf (L" [UpdateFileIdentity] Error opening file: %d\n " , errorCode);
109- LPWSTR errorMessage = nullptr ;
110- FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
111- nullptr ,
112- errorCode,
113- MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
114- reinterpret_cast <LPWSTR>(&errorMessage),
115- 0 ,
116- nullptr );
117- if (errorMessage)
118- {
119- wprintf (L" [UpdateFileIdentity] Error: %ls\n " , errorMessage);
120- LocalFree (errorMessage);
121- }
122- return ;
123- }
124-
125- HRESULT hr = CfUpdatePlaceholder (
126- fileHandle, // Handle del archivo.
127- nullptr , // CF_FS_METADATA opcional.
128- fileIdentity.c_str (), // Identidad del archivo.
129- static_cast <DWORD>(fileIdentity.size () * sizeof (wchar_t )), // Longitud de la identidad del archivo.
130- nullptr , // Rango a deshidratar, opcional.
131- 0 , // Conteo de rangos a deshidratar, debe ser 0 si no se usa.
132- CF_UPDATE_FLAG_NONE, // Flags de actualización.
133- nullptr , // USN opcional.
134- nullptr // OVERLAPPED opcional.
135- );
136-
137- if (FAILED (hr))
138- {
139- std::wstring errorMessage = Utilities::GetErrorMessageCloudFiles (hr);
140- wprintf (L" [UpdateFileIdentity] Error updating fileIdentity: %ls\n " , errorMessage.c_str ());
141- CloseHandle (fileHandle);
142- return ;
143- }
144-
145- CloseHandle (fileHandle);
68+ winrt::check_hresult (CfUpdatePlaceholder (
69+ fileHandle.get (),
70+ nullptr ,
71+ placeholderId.c_str (),
72+ static_cast <DWORD>(placeholderId.size () * sizeof (wchar_t )),
73+ nullptr ,
74+ 0 ,
75+ CF_UPDATE_FLAG_NONE,
76+ nullptr ,
77+ nullptr ));
14678}
14779
14880FileState Placeholders::GetPlaceholderInfo (const std::wstring &path)
14981{
82+ auto fileHandle = OpenFileHandle (path, FILE_READ_ATTRIBUTES, true );
83+
15084 constexpr DWORD fileIdMaxLength = 400 ;
15185 constexpr DWORD infoSize = sizeof (CF_PLACEHOLDER_BASIC_INFO) + fileIdMaxLength;
15286
15387 std::vector<char > buffer (infoSize);
15488 auto *info = reinterpret_cast <CF_PLACEHOLDER_BASIC_INFO *>(buffer.data ());
15589
156- auto fileHandle = handleForPath (path);
157- if (!fileHandle)
158- {
159- throw std::runtime_error (" Failed to get file handle: " + std::to_string (GetLastError ()));
160- }
161-
16290 winrt::check_hresult (CfGetPlaceholderInfo (
16391 fileHandle.get (),
16492 CF_PLACEHOLDER_INFO_BASIC,
16593 info,
16694 infoSize,
16795 nullptr ));
16896
169- return FileState{
170- std::string (reinterpret_cast <const char *>(info->FileIdentity ), info->FileIdentityLength ),
171- info->PinState };
97+ std::string placeholderId (reinterpret_cast <const char *>(info->FileIdentity ), info->FileIdentityLength );
98+
99+ placeholderId.erase (std::remove (placeholderId.begin (), placeholderId.end (), ' \0 ' ), placeholderId.end ());
100+
101+ return FileState{placeholderId, info->PinState };
172102}
0 commit comments