API Documentation
Loading...
Searching...
No Matches
Win32FileUtils.h
Go to the documentation of this file.
1/**--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: Button
29Included in API: False
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#ifdef _WIN32
34#include <NDEVR/String.h>
35#include <NDEVR/Translator.h>
36#include <NDEVR/Thread.h>
37#include <NDEVR/FileCachedData.h>
38#include <NDEVR/RWLock.h>
39#include <sherrors.h>
40#include <Windows.h>
41#include <Shlwapi.h>
42#include "shobjidl_core.h"
43#if NDEVR_SUPPORTS_MTP
44 #include "libraries/MtpLite-master/MtpLite>
45#endif
46namespace NDEVR
47{
48 inline TranslatedString CreateCopyMoveException(DWORD error)
49 {
50 switch (error)
51 {
52 default: return _td("COPYENGINE_E_UNKNOWN", "Unknown Error Occurred while transferring file with code [error_code]").replace("[error_code]", String(cast<uint04>(error)));
53 case COPYENGINE_E_USER_CANCELLED: return _td("COPYENGINE_E_USER_CANCELLED", "User cancelled job");
54 case COPYENGINE_E_CANCELLED: return _td("COPYENGINE_E_CANCELLED", "Engine wants to cancel job");
55 case COPYENGINE_E_REQUIRES_ELEVATION: return _td("COPYENGINE_E_REQUIRES_ELEVATION", "Need to elevate the process to complete the operation");
56 case COPYENGINE_E_SAME_FILE: return _td("COPYENGINE_E_SAME_FILE", "Source and destination file are the same");
57 case COPYENGINE_E_DIFF_DIR: return _td("COPYENGINE_E_DIFF_DIR", "Trying to rename a file into a different location, use move instead");
58 case COPYENGINE_E_MANY_SRC_1_DEST: return _td("COPYENGINE_E_MANY_SRC_1_DEST", "One source specified, multiple destinations");
59 case COPYENGINE_E_DEST_SUBTREE: return _td("COPYENGINE_E_DEST_SUBTREE", "The destination is a sub-tree of the source");
60 case COPYENGINE_E_DEST_SAME_TREE: return _td("COPYENGINE_E_DEST_SAME_TREE", "The destination is the same folder as the source");
61 case COPYENGINE_E_FLD_IS_FILE_DEST: return _td("COPYENGINE_E_FLD_IS_FILE_DEST", "Existing destination file with same name as folder");
62 case COPYENGINE_E_FILE_IS_FLD_DEST: return _td("COPYENGINE_E_FILE_IS_FLD_DEST", "Existing destination folder with same name as file");
63 case COPYENGINE_E_FILE_TOO_LARGE: return _td("COPYENGINE_E_FILE_TOO_LARGE", "File too large for destination file system");
64 case COPYENGINE_E_REMOVABLE_FULL: return _td("COPYENGINE_E_REMOVABLE_FULL", "Removable Device is full");
65 case COPYENGINE_E_DEST_IS_RO_CD: return _td("COPYENGINE_E_DEST_IS_RO_CD", "Destination is a Read-Only CDRom, possibly unformatted");
66 case COPYENGINE_E_DEST_IS_RW_CD: return _td("COPYENGINE_E_DEST_IS_RW_CD", "Destination is a Read/Write CDRom, possibly unformatted");
67 case COPYENGINE_E_DEST_IS_R_CD: return _td("COPYENGINE_E_DEST_IS_R_CD", "Destination is a Recordable (AudioL) CDRom, possibly unformatted");
68 case COPYENGINE_E_DEST_IS_RO_DVD: return _td("COPYENGINE_E_DEST_IS_RO_DVD", "Destination is a Read-Only DVD, possibly unformatted");
69 case COPYENGINE_E_DEST_IS_RW_DVD: return _td("COPYENGINE_E_DEST_IS_RW_DVD", "Destination is a Read/Wrote DVD, possibly unformatted");
70 case COPYENGINE_E_DEST_IS_R_DVD: return _td("COPYENGINE_E_DEST_IS_R_DVD", "Destination is a Recordable (AudioL) DVD, possibly unformatted");
71 case COPYENGINE_E_SRC_IS_RO_CD: return _td("COPYENGINE_E_SRC_IS_RO_CD", "Source is a Read-Only CDRom, possibly unformatted");
72 case COPYENGINE_E_SRC_IS_RW_CD: return _td("COPYENGINE_E_SRC_IS_RW_CD", "Source is a Read/Write CDRom, possibly unformatted");
73 case COPYENGINE_E_SRC_IS_R_CD: return _td("COPYENGINE_E_SRC_IS_R_CD", "Source is a Recordable (AudioL) CDRom, possibly unformatted");
74 case COPYENGINE_E_SRC_IS_RO_DVD: return _td("COPYENGINE_E_SRC_IS_RO_DVD", "Source is a Read-Only DVD, possibly unformatted");
75 case COPYENGINE_E_SRC_IS_RW_DVD: return _td("COPYENGINE_E_SRC_IS_RW_DVD", "Source is a Read/Wrote DVD, possibly unformatted");
76 case COPYENGINE_E_SRC_IS_R_DVD: return _td("COPYENGINE_E_SRC_IS_R_DVD", "Source is a Recordable (AudioL) DVD, possibly unformatted");
77
78 case COPYENGINE_E_INVALID_FILES_SRC: return _td("COPYENGINE_E_INVALID_FILES_SRC", "Invalid source path");
79 case COPYENGINE_E_INVALID_FILES_DEST: return _td("COPYENGINE_E_INVALID_FILES_DEST", "Invalid destination path");
80 case COPYENGINE_E_PATH_TOO_DEEP_SRC: return _td("COPYENGINE_E_PATH_TOO_DEEP_SRC", "Source Files within folders where the overall path is longer than MAX_PATH");
81 case COPYENGINE_E_PATH_TOO_DEEP_DEST: return _td("COPYENGINE_E_PATH_TOO_DEEP_DEST", "Destination files would be within folders where the overall path is longer than MAX_PATH");
82 case COPYENGINE_E_ROOT_DIR_SRC: return _td("COPYENGINE_E_ROOT_DIR_SRC", "Source is a root directory, cannot be moved or renamed");
83 case COPYENGINE_E_ROOT_DIR_DEST: return _td("COPYENGINE_E_ROOT_DIR_DEST", "Destination is a root directory, cannot be renamed");
84 case COPYENGINE_E_ACCESS_DENIED_SRC: return _td("COPYENGINE_E_ACCESS_DENIED_SRC", "Security problem on source");
85 case COPYENGINE_E_ACCESS_DENIED_DEST: return _td("COPYENGINE_E_ACCESS_DENIED_DEST", "Security problem on destination");
86 case COPYENGINE_E_PATH_NOT_FOUND_SRC: return _td("COPYENGINE_E_PATH_NOT_FOUND_SRC", "Source file does not exist, or is unavailable");
87 case COPYENGINE_E_PATH_NOT_FOUND_DEST: return _td("COPYENGINE_E_PATH_NOT_FOUND_DEST", "Destination file does not exist, or is unavailable");
88 case COPYENGINE_E_NET_DISCONNECT_SRC: return _td("COPYENGINE_E_NET_DISCONNECT_SRC", "Source file is on a disconnected network location");
89 case COPYENGINE_E_NET_DISCONNECT_DEST: return _td("COPYENGINE_E_NET_DISCONNECT_DEST", "Destination file is on a disconnected network location");
90 case COPYENGINE_E_SHARING_VIOLATION_SRC: return _td("COPYENGINE_E_SHARING_VIOLATION_SRC", "Sharing Violation on source");
91 case COPYENGINE_E_SHARING_VIOLATION_DEST: return _td("COPYENGINE_E_SHARING_VIOLATION_DEST", "Sharing Violation on destination");
92
93 case COPYENGINE_E_ALREADY_EXISTS_NORMAL: return _td("COPYENGINE_E_ALREADY_EXISTS_NORMAL", "Destination exists, cannot replace");
94 case COPYENGINE_E_ALREADY_EXISTS_READONLY: return _td("COPYENGINE_E_ALREADY_EXISTS_READONLY", "Destination with read-only attribute exists, cannot replace");
95 case COPYENGINE_E_ALREADY_EXISTS_SYSTEM: return _td("COPYENGINE_E_ALREADY_EXISTS_SYSTEM", "Destination with system attribute exists, cannot replace");
96 case COPYENGINE_E_ALREADY_EXISTS_FOLDER: return _td("COPYENGINE_E_ALREADY_EXISTS_FOLDER", "Destination folder exists, cannot replace");
97 case COPYENGINE_E_STREAM_LOSS: return _td("COPYENGINE_E_STREAM_LOSS", "Secondary Stream information would be lost");
98 case COPYENGINE_E_EA_LOSS: return _td("COPYENGINE_E_EA_LOSS", "Extended Attributes would be lost");
99 case COPYENGINE_E_PROPERTY_LOSS: return _td("COPYENGINE_E_PROPERTY_LOSS", "Property would be lost");
100 case COPYENGINE_E_PROPERTIES_LOSS: return _td("COPYENGINE_E_PROPERTIES_LOSS", "Properties would be lost");
101 case COPYENGINE_E_ENCRYPTION_LOSS: return _td("COPYENGINE_E_ENCRYPTION_LOSS", "Encryption would be lost");
102 case COPYENGINE_E_DISK_FULL: return _td("COPYENGINE_E_DISK_FULL", "Windows is reporting that the destination disk or device is full.");
103 case COPYENGINE_E_DISK_FULL_CLEAN: return _td("COPYENGINE_E_DISK_FULL_CLEAN", "Windows is reporting that the destination disk or device is full");
104 case COPYENGINE_E_EA_NOT_SUPPORTED: return _td("COPYENGINE_E_EA_NOT_SUPPORTED", "Volume does not support Extended Attributes");
105 case COPYENGINE_E_CANT_REACH_SOURCE: return _td("COPYENGINE_E_CANT_REACH_SOURCE", "Can't reach source folder");
106
107
108 case COPYENGINE_E_RECYCLE_FORCE_NUKE: return _td("COPYENGINE_E_RECYCLE_FORCE_NUKE", "Recycling not available (usually turned offL)");
109 case COPYENGINE_E_RECYCLE_SIZE_TOO_BIG: return _td("COPYENGINE_E_RECYCLE_SIZE_TOO_BIG", "Item is too large for the recycle-bin");
110 case COPYENGINE_E_RECYCLE_PATH_TOO_LONG: return _td("COPYENGINE_E_RECYCLE_PATH_TOO_LONG", "Folder is too deep to fit in the recycle-bin");
111 case COPYENGINE_E_RECYCLE_BIN_NOT_FOUND: return _td("COPYENGINE_E_RECYCLE_BIN_NOT_FOUND", "Recycle bin could not be found or is unavailable");
112 case COPYENGINE_E_NEWFILE_NAME_TOO_LONG: return _td("COPYENGINE_E_NEWFILE_NAME_TOO_LONG", "Name of the new file being created is too long");
113 case COPYENGINE_E_NEWFOLDER_NAME_TOO_LONG: return _td("COPYENGINE_E_NEWFOLDER_NAME_TOO_LONG", "Name of the new folder being created is too long");
114 case COPYENGINE_E_DIR_NOT_EMPTY: return _td("COPYENGINE_E_DIR_NOT_EMPTY", "The directory being processed is not empty");
115 case COPYENGINE_E_FAT_MAX_IN_ROOT: return _td("COPYENGINE_E_FAT_MAX_IN_ROOT", "A Fat drive can only store and rename a limited number of items on the root.");
116 case COPYENGINE_E_ACCESSDENIED_READONLY: return _td("COPYENGINE_E_ACCESSDENIED_READONLY", "The item cannot be modified because it is set to readonly.");
117
118 case COPYENGINE_E_REDIRECTED_TO_WEBPAGE: return _td("COPYENGINE_E_REDIRECTED_TO_WEBPAGE", "The server redirected the download request to a web page.");
119 case COPYENGINE_E_SERVER_BAD_FILE_TYPE: return _td("COPYENGINE_E_SERVER_BAD_FILE_TYPE", "The server returned data with an unexpected MIME type or extension.");
120
121 case COPYENGINE_E_INTERNET_ITEM_UNAVAILABLE: return _td("COPYENGINE_E_INTERNET_ITEM_UNAVAILABLE", "The item is unavailable currently due to no internet connectivity");
122
123 case COPYENGINE_E_CANNOT_MOVE_FROM_RECYCLE_BIN: return _td("COPYENGINE_E_CANNOT_MOVE_FROM_RECYCLE_BIN", "The item cannot be moved out of the recycle bin, can perform other operations like restored/delete");
124
125 case COPYENGINE_E_CANNOT_MOVE_SHARED_FOLDER: return _td("COPYENGINE_E_CANNOT_MOVE_SHARED_FOLDER", "The item cannot be moved from a grouped folder to another shared folder");
126
127 case COPYENGINE_E_INTERNET_ITEM_STORAGE_PROVIDER_ERROR: return _td("COPYENGINE_E_INTERNET_ITEM_STORAGE_PROVIDER_ERROR", "The item is unavailable currently due to storage provider being in error state");
128 case COPYENGINE_E_INTERNET_ITEM_STORAGE_PROVIDER_PAUSED: return _td("COPYENGINE_E_INTERNET_ITEM_STORAGE_PROVIDER_PAUSED", "The item is unavailable currently due to storage provider being paused");
129
130 case COPYENGINE_E_REQUIRES_EDP_CONSENT: return _td("COPYENGINE_E_REQUIRES_EDP_CONSENT", "The file can only be copied if the user consents to override the EDP block");
131 case COPYENGINE_E_BLOCKED_BY_EDP_POLICY: return _td("COPYENGINE_E_BLOCKED_BY_EDP_POLICY", "The file cannot be copied per EDP policy");
132 case COPYENGINE_E_REQUIRES_EDP_CONSENT_FOR_REMOVABLE_DRIVE: return _td("COPYENGINE_E_REQUIRES_EDP_CONSENT_FOR_REMOVABLE_DRIVE", "The file can be copied as personal if the user consents to override the EDP block");
133 case COPYENGINE_E_BLOCKED_BY_EDP_FOR_REMOVABLE_DRIVE: return _td("COPYENGINE_E_BLOCKED_BY_EDP_FOR_REMOVABLE_DRIVE", "The file can only be copied as work protected per EDP policy");
134 case COPYENGINE_E_RMS_REQUIRES_EDP_CONSENT_FOR_REMOVABLE_DRIVE: return _td("COPYENGINE_E_RMS_REQUIRES_EDP_CONSENT_FOR_REMOVABLE_DRIVE", "The file can be copied as personal if the user consents to override the EDP block");
135 case COPYENGINE_E_RMS_BLOCKED_BY_EDP_FOR_REMOVABLE_DRIVE: return _td("COPYENGINE_E_RMS_BLOCKED_BY_EDP_FOR_REMOVABLE_DRIVE", "The file can only be copied as work protected per EDP policy");
136 }
137 }
138 FILETIME Win32FileTime(const Time& time)
139 {
140 SYSTEMTIME stUTC;
141 stUTC.wYear = time.year(false);
142 stUTC.wMonth = time.month(false);
143 stUTC.wDay = time.monthDay(false);
144 stUTC.wHour = time.hour(false);
145 stUTC.wMinute = time.minute(false);
146 stUTC.wSecond = time.second(false);
147 stUTC.wMilliseconds = cast<WORD>(time.millisecond());
148 stUTC.wDayOfWeek = 0;
149 FILETIME file_time;
150 SystemTimeToFileTime(&stUTC, &file_time);
151 return file_time;
152 }
153 Time Win32FileTime(FILETIME time)
154 {
155 SYSTEMTIME stUTC;
156 BOOL success = FileTimeToSystemTime(&time, &stUTC);
157
158 Time t = Constant<Time>::NaN;
159 if (success == TRUE)
160 {
161 try
162 {
163 t.setYear(cast<uint02>(stUTC.wYear), false);
164 t.setMonth(cast<uint01>(stUTC.wMonth), false);
165 t.setMonthDay(cast<uint01>(stUTC.wDay), false);
166 t.setHour(cast<uint01>(stUTC.wHour), false);
167 t.setMinute(cast<uint01>(stUTC.wMinute), false);
168 t.setSecond(cast<uint01>(stUTC.wSecond), false);
169 t.setMillisecond(cast<uint02>(stUTC.wMilliseconds));
170
171 }
172 catch (Exception&)
173 {
174 return t;
175 }
176 }
177 return t;
178 }
179 FileCachedData WIN32CreateCached(const WIN32_FILE_ATTRIBUTE_DATA& fad)
180 {
181 FileCachedData cache;
182 cache.file_properties(FileProperty::e_file_cache_is_valid, true);
183 if (fad.dwFileAttributes == INVALID_FILE_ATTRIBUTES)
184 {
185 cache.file_properties(FileProperty::e_file_exists, false);
186 cache.file_properties(FileProperty::e_file_is_hidden, false);
187 cache.file_properties(FileProperty::e_file_is_directory, false);
188 cache.file_size = Constant<uint08>::NaN;
189 }
190 else
191 {
192 LARGE_INTEGER size;
193 size.HighPart = fad.nFileSizeHigh;
194 size.LowPart = fad.nFileSizeLow;
195 cache.file_size = cast<uint08>(size.QuadPart);
196 cache.file_properties(FileProperty::e_file_exists, true);
197 cache.file_properties(FileProperty::e_file_is_directory, fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
198 cache.file_properties(FileProperty::e_file_is_hidden, fad.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN);
199 cache.accessed_time = Win32FileTime(fad.ftLastAccessTime);
200 cache.modified_time = Win32FileTime(fad.ftLastWriteTime);
201 cache.created_time = Win32FileTime(fad.ftCreationTime);
202 //lib_assert(cache.file_size != 0 || cache.file_properties[FileProperty::e_file_is_directory], "Unexpected 0 size");
203 }
204 return cache;
205 }
206 FileCachedData WIN32CreateCached(const WIN32_FIND_DATAW& fad)
207 {
208 FileCachedData cache;
209 cache.file_properties(FileProperty::e_file_cache_is_valid, true);
210 if (fad.dwFileAttributes == INVALID_FILE_ATTRIBUTES)
211 {
212 cache.file_properties(FileProperty::e_file_exists, false);
213 cache.file_properties(FileProperty::e_file_is_hidden, false);
214 cache.file_size = Constant<uint08>::NaN;
215 }
216 else
217 {
218 LARGE_INTEGER size;
219 size.HighPart = fad.nFileSizeHigh;
220 size.LowPart = fad.nFileSizeLow;
221 cache.file_size = cast<uint08>(size.QuadPart);
222 cache.file_properties(FileProperty::e_file_exists, true);
223 cache.file_properties(FileProperty::e_file_is_directory, fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
224 cache.file_properties(FileProperty::e_file_is_hidden, fad.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN);
225 cache.accessed_time = Win32FileTime(fad.ftLastAccessTime);
226 cache.modified_time = Win32FileTime(fad.ftLastWriteTime);
227 cache.created_time = Win32FileTime(fad.ftCreationTime);
228 //lib_assert(cache.file_size != 0 || cache.file_properties[FileProperty::e_file_is_directory], "Unexpected 0 size");
229 }
230 return cache;
231 }
232 FileCachedData WIN32CreateCached(const File& file)
233 {
234 if (!file.isDrive())
235 {
236 WIN32_FILE_ATTRIBUTE_DATA fad;
237 if (!GetFileAttributesExW(file.getAs<std::wstring>().c_str(), GetFileExInfoStandard, &fad))
238 return FileCachedData(); // error condition, could call GetLastError to find out more
239 return WIN32CreateCached(fad);
240 }
241 else
242 {
243 FileCachedData cache;
244 cache.file_properties(FileProperty::e_file_exists, true);
245 cache.file_properties(FileProperty::e_file_is_directory, true);
246 cache.file_properties(FileProperty::e_file_is_hidden, false);
247 return cache;
248 }
249 }
250 class NDEVRWIN32LogView final : public IOperationsProgressDialog, public IFileOperationProgressSink
251 {
252 public:
253 ProgressInfo* m_log;
254 bool show_progress;
255 String m_action;
256 DWORD id;
257 NDEVRWIN32LogView(ProgressInfo* info)
258 : m_log(info)
259 , show_progress(false)
260 , id(0)
261 {}
262
263 HRESULT status() const
264 {
265 return S_OK;
266 }
267
268 virtual HRESULT STDMETHODCALLTYPE StartOperations(void) override
269 {
270 return status();
271 }
272
273 virtual HRESULT STDMETHODCALLTYPE FinishOperations(HRESULT) override
274 {
275 if (m_log) m_log->setProgress(1.0f);
276 return status();
277 }
278
279 virtual HRESULT STDMETHODCALLTYPE PreRenameItem(
280 /* [in] */ DWORD,
281 /* [in] */ __RPC__in_opt IShellItem*,
282 /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR) override
283 {
284 return status();
285 }
286
287 virtual HRESULT STDMETHODCALLTYPE PostRenameItem(
288 /* [in] */ DWORD,
289 /* [in] */ __RPC__in_opt IShellItem*,
290 /* [string][in] */ __RPC__in_string LPCWSTR,
291 /* [in] */ HRESULT,
292 /* [in] */ __RPC__in_opt IShellItem*) override
293 {
294 if (m_log) m_log->setProgress(1.0f);
295 return status();
296 }
297
298 virtual HRESULT STDMETHODCALLTYPE PreMoveItem(
299 /* [in] */ DWORD,
300 /* [in] */ __RPC__in_opt IShellItem*,
301 /* [in] */ __RPC__in_opt IShellItem*,
302 /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR) override
303 {
304 if (m_log) m_log->setProgress(1.0f);
305 return status();
306 }
307
308 virtual HRESULT STDMETHODCALLTYPE PostMoveItem(
309 /* [in] */ DWORD,
310 /* [in] */ __RPC__in_opt IShellItem*,
311 /* [in] */ __RPC__in_opt IShellItem*,
312 /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR,
313 /* [in] */ HRESULT,
314 /* [in] */ __RPC__in_opt IShellItem*)
315 {
316 return status();
317 }
318
319 virtual HRESULT STDMETHODCALLTYPE PreCopyItem(
320 /* [in] */ DWORD,
321 /* [in] */ __RPC__in_opt IShellItem*,
322 /* [in] */ __RPC__in_opt IShellItem*,
323 /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR) override
324 {
325 return status();
326 }
327
328 virtual HRESULT STDMETHODCALLTYPE PostCopyItem(
329 /* [in] */ DWORD,
330 /* [in] */ __RPC__in_opt IShellItem*,
331 /* [in] */ __RPC__in_opt IShellItem*,
332 /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR,
333 /* [in] */ HRESULT,
334 /* [in] */ __RPC__in_opt IShellItem*) override
335 {
336 return status();
337 }
338
339 virtual HRESULT STDMETHODCALLTYPE PreDeleteItem(
340 /* [in] */ DWORD,
341 /* [in] */ __RPC__in_opt IShellItem*) override
342 {
343 return status();
344 }
345
346 virtual HRESULT STDMETHODCALLTYPE PostDeleteItem(
347 /* [in] */ DWORD,
348 /* [in] */ __RPC__in_opt IShellItem*,
349 /* [in] */ HRESULT,
350 /* [in] */ __RPC__in_opt IShellItem*) override
351 {
352 if (m_log) m_log->setProgress(1.0f);
353 return status();
354 }
355
356 virtual HRESULT STDMETHODCALLTYPE PreNewItem(
357 /* [in] */ DWORD,
358 /* [in] */ __RPC__in_opt IShellItem*,
359 /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR) override
360 {
361 return status();
362 }
363
364 virtual HRESULT STDMETHODCALLTYPE PostNewItem(
365 /* [in] */ DWORD,
366 /* [in] */ __RPC__in_opt IShellItem*,
367 /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR,
368 /* [string][unique][in] */ __RPC__in_opt_string LPCWSTR,
369 /* [in] */ DWORD,
370 /* [in] */ HRESULT,
371 /* [in] */ __RPC__in_opt IShellItem*) override
372 {
373 if (m_log) m_log->setProgress(1.0f);
374 return status();
375 }
376
377 virtual HRESULT STDMETHODCALLTYPE UpdateProgress(
378 /* [in] */ UINT iWorkTotal,
379 /* [in] */ UINT iWorkSoFar) override
380 {
381 if (m_log) m_log->setProgress(cast<fltp04>(iWorkSoFar) / cast<fltp04>(iWorkTotal));
382 return status();
383 }
384
385 virtual HRESULT STDMETHODCALLTYPE ResetTimer(void) override
386 {
387 return status();
388 }
389
390 virtual HRESULT STDMETHODCALLTYPE PauseTimer(void) override
391 {
392 return status();
393 }
394
395 virtual HRESULT STDMETHODCALLTYPE ResumeTimer(void) override
396 {
397 return status();
398 }
399 virtual HRESULT STDMETHODCALLTYPE StartProgressDialog(HWND, OPPROGDLGF flags) override
400 {
401 if (m_log) m_log->setProgress(0.0f);
402 show_progress = (flags & PROGDLG_NOPROGRESSBAR) == 0;
403 return status();
404 }
405
406 HRESULT STDMETHODCALLTYPE StopProgressDialog(void) override
407 {
408 if (m_log) m_log->setProgress(1.0f);
409 return status();
410 }
411
412 HRESULT STDMETHODCALLTYPE SetOperation(SPACTION action) override
413 {
414 if (m_log == nullptr)
415 return status();
416 switch (action)
417 {
418 case SPACTION_NONE: break;
419 case SPACTION_MOVING: m_log->addMessage(_t("Moving File Item")); break;
420 case SPACTION_COPYING: m_log->addMessage(_t("Copying File Item")); break;
421 case SPACTION_RECYCLING: m_log->addMessage(_t("Recyling File Item")); break;
422 case SPACTION_APPLYINGATTRIBS: m_log->addMessage(_t("Appling Attributes")); break;
423 case SPACTION_DOWNLOADING: m_log->addMessage(_t("Downloading")); break;
424 case SPACTION_SEARCHING_INTERNET: m_log->addMessage(_t("Searching Web")); break;
425 case SPACTION_CALCULATING: m_log->addMessage(_t("Calculating")); break;
426 case SPACTION_UPLOADING: m_log->addMessage(_t("Uploading")); break;
427 case SPACTION_SEARCHING_FILES: m_log->addMessage(_t("Searching File Items")); break;
428 case SPACTION_DELETING: m_log->addMessage(_t("Deleting")); break;
429 case SPACTION_RENAMING: m_log->addMessage(_t("Renaming File Item")); break;
430 case SPACTION_FORMATTING: m_log->addMessage(_t("Formatting")); break;
431 case SPACTION_COPY_MOVING: m_log->addMessage(_t("Copying File Item")); break;
432 }
433 return status();
434 }
435
436 HRESULT STDMETHODCALLTYPE SetMode(PDMODE mode) override
437 {
438 switch (mode)
439 {
440 case PDM_DEFAULT:
441 case PDM_RUN:
442 case PDM_PREFLIGHT:
443 case PDM_UNDOING:
444 case PDM_ERRORSBLOCKING:
445 case PDM_INDETERMINATE:
446 break;
447 }
448 return status();
449 }
450
451 HRESULT STDMETHODCALLTYPE UpdateProgress(
452 ULONGLONG /*ullPointsCurrent*/, ULONGLONG /*ullPointsTotal*/
453 , ULONGLONG ullSizeCurrent, ULONGLONG ullSizeTotal
454 , ULONGLONG /*ullItemsCurrent*/, ULONGLONG /*ullItemsTotal*/) override
455 {
456 if (m_log) m_log->setProgress(cast<fltp04>(ullSizeCurrent) / cast<fltp04>(ullSizeTotal));
457 return status();
458 }
459
460 HRESULT STDMETHODCALLTYPE UpdateLocations(IShellItem*, IShellItem*, IShellItem*) override
461 {
462 return status();
463 }
464
465 HRESULT STDMETHODCALLTYPE GetMilliseconds(ULONGLONG*, ULONGLONG*) override
466 {
467 return status();
468 }
469
470 HRESULT STDMETHODCALLTYPE GetOperationStatus(PDOPSTATUS* popstatus) override
471 {
472 if (m_log->cancelRequested())
473 *popstatus = PDOPS_CANCELLED;
474 else
475 *popstatus = PDOPS_RUNNING;
476 return status();
477 }
478 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override
479 {
480 if (riid == IID_IUnknown || riid == IID_IFileOperationProgressSink || riid == IID_IOperationsProgressDialog) {
481 *ppvObject = this;
482
483 return S_OK;
484 }
485
486 *ppvObject = NULL;
487
488 return E_NOINTERFACE;
489 };
490
491 ULONG STDMETHODCALLTYPE AddRef(void) override
492 {
493 return status();
494 }
495
496 ULONG STDMETHODCALLTYPE Release(void) override
497 {
498 return status();
499 }
500
501 };
502 HRESULT NDEVRWIN32EnsureInitialized()
503 {
504#if NDEVR_SUPPORTS_THREADING
505 unsigned thread_id = NDEVR::ThreadFunctions::CurrentThreadID();
506 static NDEVR::Dictionary<unsigned, bool> Thread_Dictionary;
507 NDEVR::WLock lock(&Thread_Dictionary);
508 if (Thread_Dictionary.hasKey(thread_id) && Thread_Dictionary.get(thread_id))
509 return 0;
510 Thread_Dictionary.add(thread_id, false);
511#endif
512 HRESULT hr = S_OK;
513 hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY);
514 if (!SUCCEEDED(hr)) return hr;
515#if NDEVR_SUPPORTS_THREADING
516 Thread_Dictionary.set(thread_id, true);
517#endif
518 return hr;
519 }
520
521 HRESULT NDEVRWIN32CreateFileOperation(IFileOperation** pfo, NDEVRWIN32LogView* log)
522 {
523 HRESULT hr = NDEVRWIN32EnsureInitialized();
524 if (!SUCCEEDED(hr)) return hr;
525 hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_PPV_ARGS(pfo));
526 if (!SUCCEEDED(hr)) return hr;
527 if (log)
528 {
529 hr = (*pfo)->Advise(log, &log->id);
530 if (!SUCCEEDED(hr)) { (*pfo)->Release(); return hr; }
531 }
532 hr = (*pfo)->SetOperationFlags(FOF_NO_UI | FOFX_EARLYFAILURE);
533 if (!SUCCEEDED(hr))
534 (*pfo)->Release();
535 return hr;
536 }
537 HRESULT NDEVRWIN32CopyOrMoveItem(PCWSTR pszSrcItem, PCWSTR pszDest, PCWSTR pszNewName, bool is_copy, NDEVRWIN32LogView* log)
538 {
539 IFileOperation* pfo = NULL;
540 HRESULT hr = NDEVRWIN32CreateFileOperation(&pfo, log);
541 if (!SUCCEEDED(hr)) return hr;
542
543 IShellItem* psiFrom = NULL;
544 hr = SHCreateItemFromParsingName(pszSrcItem, NULL, IID_PPV_ARGS(&psiFrom));
545 if (!SUCCEEDED(hr)) { pfo->Release(); return hr; }
546
547 IShellItem* psiTo = NULL;
548 if (NULL != pszDest)
549 hr = SHCreateItemFromParsingName(pszDest, NULL, IID_PPV_ARGS(&psiTo));
550 if (!SUCCEEDED(hr)) { psiFrom->Release(); pfo->Release(); return hr; }
551 if (is_copy)
552 hr = pfo->CopyItem(psiFrom, psiTo, pszNewName, NULL);
553 else
554 hr = pfo->MoveItem(psiFrom, psiTo, pszNewName, NULL);
555 if (NULL != psiTo)
556 psiTo->Release();
557 if (NULL != psiFrom)
558 psiFrom->Release();
559 if (!SUCCEEDED(hr)) { pfo->Release(); return hr; }
560
561 hr = pfo->PerformOperations();
562 if (!SUCCEEDED(hr)) { pfo->Release(); return hr; }
563 BOOL operations_aborted;
564 hr = pfo->GetAnyOperationsAborted(&operations_aborted);
565 pfo->Release();
566 lib_assert(!operations_aborted, "file move/save aborted?");
567 return hr;
568 }
569
570 HRESULT NDEVRWIN32DeleteItem(PCWSTR item_to_delete, NDEVRWIN32LogView* log)
571 {
572 //Create Operation
573 IFileOperation* pfo = NULL;
574 HRESULT hr = NDEVRWIN32CreateFileOperation(&pfo, log);
575 if (!SUCCEEDED(hr)) return hr;
576
577 IShellItem* psiDelete = NULL;
578 hr = SHCreateItemFromParsingName(item_to_delete, NULL, IID_PPV_ARGS(&psiDelete));
579 if (!SUCCEEDED(hr)) { pfo->Release(); return hr; }
580
581 hr = pfo->DeleteItem(psiDelete, NULL);
582 if (NULL != psiDelete)
583 psiDelete->Release();
584 if (!SUCCEEDED(hr)) { pfo->Release(); return hr; }
585
586 hr = pfo->PerformOperations();
587 pfo->Release();
588 return hr;
589 }
590 bool dirExists(const wchar* const dir_name_in)
591 {
592 if (dir_name_in == nullptr)
593 return false;
594 DWORD ftyp = GetFileAttributesW(dir_name_in);
595 if (ftyp == INVALID_FILE_ATTRIBUTES)
596 return false;
597 if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
598 return true;
599 return false;
600 }
601 bool IsPathHidden(const wchar* const dir_name_in)
602 {
603 if (dir_name_in == nullptr)
604 return false;
605 DWORD ftyp = GetFileAttributesW(dir_name_in);
606 if (ftyp == INVALID_FILE_ATTRIBUTES)
607 return false;
608 if (ftyp & FILE_ATTRIBUTE_HIDDEN)
609 return true;
610 return false;
611 }
612#if NDEVR_SUPPORTS_MTP
613 IPortableDevice* getMTPDevice(const File& file)
614 {
615 IPortableDevice* device = nullptr;
616 uint04 start = 0;// getMax(0U, file.pathID().indexOf('>') + 1);
617 uint04 end = getMin(file.pathID().size(), file.pathID().indexOf('|'));
618 String id = file.pathID().substr(start, end);
619 HRESULT result = MTP::ChooseDevice(id.getAs<std::wstring>().c_str(), &device);
620 return device;
621 }
622 bool MTPCreateFile(IPortableDevice* device, const File& file_to_create)
623 {
624 file_to_create.resolveMTPPath();
625 File parent = file_to_create.getParentDirectory();
626 if (parent.resolveMTPPath())
627 {
628 HRESULT result;
629 if (file_to_create.isDirectory())
630 {
631 result = MTP::CreateFolderOnDevice(device
632 , parent.pathNameID().getAs<std::wstring>().c_str()
633 , file_to_create.getPath(File::e_file_name).getAs<std::wstring>().c_str());
634 }
635 else
636 {
637 lib_assert(false, "Not yet finished");
638 /*result = MTP::Cre(device
639 , parent.pathNameID().getAs<std::wstring>().c_str()
640 , file_to_create.getPath(File::e_file_name).getAs<std::wstring>().c_str());*/
641 }
642 return SUCCEEDED(result);
643 }
644 return false;
645 }
646 Buffer<File> getMTPChildren(IPortableDevice* device, const File& dir)
647 {
648 Buffer<File> children;
649 if (device == nullptr)
650 return children;
651 PWSTR values[1024];
652 DWORD count = 1024;
653 Buffer<String> path_ids = dir.pathID().splitString('|', false);
654 std::wstring object_id;
655 if (path_ids.size() == 0)
656 return children;
657 if (path_ids.size() == 1)
658 object_id = WPD_DEVICE_OBJECT_ID;
659 else
660 object_id = path_ids.last().getAs<std::wstring>();
661 HRESULT result = MTP::GetChildren(device, object_id.c_str(), &count, values);
662 if (SUCCEEDED(result))
663 {
664 PWSTR file_name;
665 for (uint04 i = 0; i < cast<uint04>(count); i++)
666 {
667 file_name = nullptr;
668 result = MTP::GetProperty(device, values[i], WPD_OBJECT_NAME, &file_name);
669 GUID guid;
670 result = MTP::GetProperty(device, values[i], WPD_OBJECT_CONTENT_TYPE, &guid);
671 if (guid == WPD_CONTENT_TYPE_FOLDER || guid == WPD_CONTENT_TYPE_FUNCTIONAL_OBJECT)
672 {
673 children.add(File(
674 String(dir) + String(file_name) + File::PathSep
675 , dir.pathID() + String(values[i]) + File::IDSep));
676 }
677 else
678 {
679 children.add(File(
680 String(dir) + String(file_name)
681 , dir.pathID() + String(values[i])));
682 }
683 }
684 }
685 return children;
686 }
687#endif
688}
689#endif
#define lib_assert(expression, message)
Asserts some logic in the code. Disabled in non debug mode by default. Can be re-enabled in release u...
Definition LibAssert.h:70
#define _t(english_string)
Definition Translator.h:87
#define _td(def, english_string)
Definition Translator.h:91
Definition Dictionary.h:48
const t_value & get(const t_key &key) const
Definition Dictionary.h:70
void add(const t_key &key, const t_value &value)
Definition Dictionary.h:57
bool hasKey(const t_key &key) const
Definition Dictionary.h:53
void set(const t_key &key, const t_value &value)
Definition Dictionary.h:126
static constexpr char PathSep
Definition File.h:180
static constexpr char IDSep
Definition File.h:184
@ e_file_name
Definition File.h:73
static uint04 CurrentThreadID()
Definition Thread.cpp:80
Definition RWLock.h:99
Definition ACIColor.h:37
wchar_t wchar
Definition BaseValues.hpp:184
bool dirExists(const char *const dir_name_in)
Definition File.cpp:198
@ e_file_cache_is_valid
Definition FileCache.h:9
@ e_file_exists
Definition FileCache.h:10
@ e_file_is_hidden
Definition FileCache.h:11
@ e_file_is_directory
Definition FileCache.h:12
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:120
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:514
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator.
Definition BaseFunctions.hpp:67
static const t_type NaN
Definition BaseValues.hpp:274