|
15 | 15 | #include <cctype> |
16 | 16 | #include <windows.h> |
17 | 17 | #include <shlobj.h> |
| 18 | +#include "convert_to_placeholder.h" |
18 | 19 |
|
19 | 20 | using namespace std; |
20 | 21 |
|
21 | 22 | namespace fs = std::filesystem; |
22 | 23 |
|
23 | 24 | #pragma comment(lib, "shlwapi.lib") |
24 | 25 |
|
25 | | -bool DirectoryExists(const wchar_t *path) |
26 | | -{ |
27 | | - DWORD attributes = GetFileAttributesW(path); |
28 | | - return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY); |
29 | | -} |
30 | | - |
31 | | -PlaceholderResult Placeholders::CreateOne( |
32 | | - const wchar_t *fileName, |
33 | | - const wchar_t *fileIdentity, |
34 | | - int64_t fileSize, |
35 | | - LARGE_INTEGER creationTime, |
36 | | - LARGE_INTEGER lastWriteTime, |
37 | | - LARGE_INTEGER lastAccessTime, |
38 | | - const wchar_t *destPath) |
39 | | -{ |
40 | | - PlaceholderResult result = {false, L""}; |
41 | | - |
42 | | - try |
43 | | - { |
44 | | - CF_PLACEHOLDER_CREATE_INFO cloudEntry = {}; |
45 | | - |
46 | | - std::wstring fullDestPath = std::wstring(destPath) + L'\\'; |
47 | | - |
48 | | - wstring fullPath = std::wstring(destPath) + L'\\' + fileName; |
49 | | - |
50 | | - if (std::filesystem::exists(fullPath)) |
51 | | - { |
52 | | - Placeholders::ConvertToPlaceholder(fullPath, fileIdentity); |
53 | | - Placeholders::MaintainIdentity(fullPath, fileIdentity, false); |
54 | | - result.success = true; |
55 | | - return result; |
56 | | - } |
57 | | - |
58 | | - std::wstring relativeName(fileIdentity); |
59 | | - |
60 | | - cloudEntry.FileIdentity = relativeName.c_str(); |
61 | | - cloudEntry.FileIdentityLength = static_cast<DWORD>((relativeName.size() + 1) * sizeof(WCHAR)); |
62 | | - |
63 | | - cloudEntry.RelativeFileName = fileName; |
64 | | - cloudEntry.Flags = CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC; |
65 | | - |
66 | | - cloudEntry.FsMetadata.FileSize.QuadPart = fileSize; |
67 | | - cloudEntry.FsMetadata.BasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; |
68 | | - cloudEntry.FsMetadata.BasicInfo.CreationTime = creationTime; |
69 | | - cloudEntry.FsMetadata.BasicInfo.LastWriteTime = lastWriteTime; |
70 | | - cloudEntry.FsMetadata.BasicInfo.LastAccessTime = lastAccessTime; |
71 | | - cloudEntry.FsMetadata.BasicInfo.ChangeTime = lastWriteTime; |
72 | | - |
73 | | - try |
74 | | - { |
75 | | - winrt::check_hresult(CfCreatePlaceholders(fullDestPath.c_str(), &cloudEntry, 1, CF_CREATE_FLAG_NONE, NULL)); |
76 | | - Placeholders::UpdatePinState(fullPath, PinState::OnlineOnly); |
77 | | - result.success = true; |
78 | | - } |
79 | | - catch (const winrt::hresult_error &error) |
80 | | - { |
81 | | - result.errorMessage = error.message().c_str(); |
82 | | - wprintf(L"[CreatePlaceholder] error: %s", error.message().c_str()); |
83 | | - } |
84 | | - winrt::StorageProviderItemProperty prop; |
85 | | - prop.Id(1); |
86 | | - prop.Value(L"Value1"); |
87 | | - prop.IconResource(L"shell32.dll,-44"); |
88 | | - |
89 | | - // UpdateSyncStatus(fullDestPath, true, false); |
90 | | - } |
91 | | - catch (...) |
92 | | - { |
93 | | - result.errorMessage = L"Failed to create or customize placeholder"; |
94 | | - wprintf(L"[CreatePlaceholder] Failed to create or customize placeholder with %08x\n", static_cast<HRESULT>(winrt::to_hresult())); |
95 | | - } |
96 | | - |
97 | | - return result; |
98 | | -} |
99 | | - |
100 | 26 | std::string cleanString(const std::string &str) |
101 | 27 | { |
102 | 28 | std::string cleanedStr; |
@@ -136,133 +62,6 @@ void Placeholders::MaintainIdentity(std::wstring &fullPath, PCWSTR itemIdentity, |
136 | 62 | } |
137 | 63 | } |
138 | 64 |
|
139 | | -PlaceholderResult Placeholders::CreateEntry( |
140 | | - const wchar_t *itemName, |
141 | | - const wchar_t *itemIdentity, |
142 | | - LARGE_INTEGER creationTime, |
143 | | - LARGE_INTEGER lastWriteTime, |
144 | | - LARGE_INTEGER lastAccessTime, |
145 | | - const wchar_t *destPath) |
146 | | -{ |
147 | | - PlaceholderResult result = {false, L""}; |
148 | | - |
149 | | - std::wstring fullDestPath = std::wstring(destPath) + L"\\" + std::wstring(itemName); |
150 | | - CF_PLACEHOLDER_CREATE_INFO cloudEntry = {}; |
151 | | - std::wstring relativeName(itemIdentity); |
152 | | - cloudEntry.FileIdentity = relativeName.c_str(); |
153 | | - cloudEntry.FileIdentityLength = static_cast<DWORD>((relativeName.size() + 1) * sizeof(WCHAR)); |
154 | | - cloudEntry.RelativeFileName = itemName; |
155 | | - cloudEntry.Flags = CF_PLACEHOLDER_CREATE_FLAG_DISABLE_ON_DEMAND_POPULATION; // -> desactive download on demand |
156 | | - cloudEntry.FsMetadata.BasicInfo.FileAttributes = FILE_ATTRIBUTE_DIRECTORY; |
157 | | - cloudEntry.FsMetadata.BasicInfo.CreationTime = creationTime; |
158 | | - cloudEntry.FsMetadata.BasicInfo.LastWriteTime = lastWriteTime; |
159 | | - cloudEntry.FsMetadata.BasicInfo.LastAccessTime = lastAccessTime; |
160 | | - |
161 | | - try |
162 | | - { |
163 | | - // TODO: si existe o es placeholder return |
164 | | - if (DirectoryExists(fullDestPath.c_str())) |
165 | | - { |
166 | | - Placeholders::ConvertToPlaceholder(fullDestPath, itemIdentity); |
167 | | - Placeholders::MaintainIdentity(fullDestPath, itemIdentity, true); |
168 | | - result.success = true; |
169 | | - return result; |
170 | | - } |
171 | | - |
172 | | - // wprintf(L"Create directory, full destination path: %ls, fullDestPath.c_str()"); |
173 | | - PathRemoveFileSpecW(&fullDestPath[0]); |
174 | | - HRESULT hr = CfCreatePlaceholders(fullDestPath.c_str(), &cloudEntry, 1, CF_CREATE_FLAG_NONE, NULL); |
175 | | - if (FAILED(hr)) |
176 | | - { |
177 | | - result.errorMessage = L"Failed to create placeholder directory"; |
178 | | - wprintf(L"[CreatePlaceholder] Failed to create placeholder directory with HRESULT 0x%08x\n", hr); |
179 | | - throw winrt::hresult_error(hr); |
180 | | - } |
181 | | - |
182 | | - std::wstring finalPath = std::wstring(destPath) + L"\\" + std::wstring(itemName); |
183 | | - Placeholders::UpdatePinState(finalPath, PinState::OnlineOnly); |
184 | | - UpdateSyncStatus(finalPath, true, true); |
185 | | - result.success = true; |
186 | | - } |
187 | | - catch (const winrt::hresult_error &error) |
188 | | - { |
189 | | - result.errorMessage = error.message().c_str(); |
190 | | - wprintf(L"[CreatePlaceholder] Error while creating %s: %s\n", L"directory", error.message().c_str()); |
191 | | - } |
192 | | - catch (...) |
193 | | - { |
194 | | - result.errorMessage = L"Unknown error occurred"; |
195 | | - wprintf(L"[CreatePlaceholder] Unknown error occurred\n"); |
196 | | - } |
197 | | - |
198 | | - return result; |
199 | | -} |
200 | | - |
201 | | -PlaceholderResult Placeholders::ConvertToPlaceholder(const std::wstring &fullPath, const std::wstring &serverIdentity) |
202 | | -{ |
203 | | - PlaceholderResult result = {false, L""}; |
204 | | - |
205 | | - if (!std::filesystem::exists(fullPath)) |
206 | | - { |
207 | | - result.errorMessage = L"File does not exist"; |
208 | | - return result; |
209 | | - } |
210 | | - |
211 | | - wprintf(L"[ConvertToPlaceholder] Full path: %ls\n", fullPath.c_str()); |
212 | | - bool isDirectory = fs::is_directory(fullPath); |
213 | | - |
214 | | - HANDLE fileHandle = CreateFileW( |
215 | | - fullPath.c_str(), |
216 | | - FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, |
217 | | - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, |
218 | | - nullptr, |
219 | | - OPEN_EXISTING, |
220 | | - isDirectory ? FILE_FLAG_BACKUP_SEMANTICS : 0, |
221 | | - nullptr); |
222 | | - |
223 | | - if (fileHandle == INVALID_HANDLE_VALUE) |
224 | | - { |
225 | | - result.errorMessage = L"Failed to open file: " + std::to_wstring(GetLastError()); |
226 | | - return result; |
227 | | - } |
228 | | - |
229 | | - CF_CONVERT_FLAGS convertFlags = CF_CONVERT_FLAG_MARK_IN_SYNC; |
230 | | - USN convertUsn; |
231 | | - OVERLAPPED overlapped = {}; |
232 | | - |
233 | | - LPCVOID idStrLPCVOID = static_cast<LPCVOID>(serverIdentity.c_str()); |
234 | | - DWORD idStrByteLength = static_cast<DWORD>(serverIdentity.size() * sizeof(wchar_t)); |
235 | | - |
236 | | - HRESULT hr = CfConvertToPlaceholder(fileHandle, idStrLPCVOID, idStrByteLength, convertFlags, &convertUsn, &overlapped); |
237 | | - |
238 | | - if (FAILED(hr)) |
239 | | - { |
240 | | - CloseHandle(fileHandle); |
241 | | - if (hr != 0x8007017C) // Ignorar error específico de "ya es un placeholder" |
242 | | - { |
243 | | - result.errorMessage = L"Failed to convert to placeholder. HRESULT: 0x" + std::to_wstring(static_cast<unsigned int>(hr)); |
244 | | - return result; |
245 | | - } |
246 | | - return result; |
247 | | - } |
248 | | - |
249 | | - if (!isDirectory) |
250 | | - { |
251 | | - HRESULT hrPinState = CfSetPinState(fileHandle, CF_PIN_STATE_PINNED, CF_SET_PIN_FLAG_NONE, nullptr); |
252 | | - if (FAILED(hrPinState)) |
253 | | - { |
254 | | - CloseHandle(fileHandle); |
255 | | - result.errorMessage = L"Failed to set pin state. HRESULT: 0x" + std::to_wstring(static_cast<unsigned int>(hrPinState)); |
256 | | - return result; |
257 | | - } |
258 | | - } |
259 | | - |
260 | | - CloseHandle(fileHandle); |
261 | | - wprintf(L"[ConvertToPlaceholder] Successfully converted to placeholder: %ls\n", fullPath.c_str()); |
262 | | - result.success = true; |
263 | | - return result; |
264 | | -} |
265 | | - |
266 | 65 | /** |
267 | 66 | * @brief Mark a file or directory as synchronized |
268 | 67 | * @param filePath path to the file or directory |
@@ -315,7 +114,7 @@ void Placeholders::UpdateSyncStatus(const std::wstring &filePath, |
315 | 114 | break; |
316 | 115 |
|
317 | 116 | case ERROR_CLOUD_FILE_NOT_IN_SYNC: |
318 | | - ConvertToPlaceholder(filePath, L"temp_identity"); |
| 117 | + convert_to_placeholder(filePath, L"temp_identity"); |
319 | 118 | hr = CfSetInSyncState(h, sync, CF_SET_IN_SYNC_FLAG_NONE, nullptr); |
320 | 119 | wprintf(L"[UpdateSyncStatus] Retry CfSetInSyncState\n"); |
321 | 120 | break; |
|
0 commit comments