YSTest: MinGW32.cpp 源文件

YSTest PreAlpha_b700_20160611 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

MinGW32.cpp
浏览该文件的文档.
1 /*
2 © 2013-2016 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
29 #include "YCLib/YModules.h"
30 #include YFM_YCLib_Platform
31 #if YCL_Win32
32 # include YFM_Win32_YCLib_Registry // for platform::FileOperationFailure,
33 // RegistryKey, ystdex::pun_storage_t, ystdex::throw_error,
34 // std::errc::not_supported, std::invalid_argument;
35 # include <cerrno> // for EINVAL, ENOENT, EMFILE, EACCESS, EBADF, ENOMEM,
36 // ENOEXEC, EXDEV, EEXIST, EAGAIN, EPIPE, ENOSPC, ECHILD, ENOTEMPTY;
37 # include YFM_YSLib_Core_YCoreUtilities // for YSLib::IsInClosedInterval,
38 // YSLib::CheckPositiveScalar, YSLib::make_unique_default_init,
39 // platform::EndsWithNonSeperator, YSLib::FilterExceptions;
40 # include <ystdex/container.hpp> // for ystdex::retry_for_vector;
41 # include <functional> // for std::bind, std::placeholders::_1;
42
43 using namespace YSLib;
44 #endif
45
47 using platform::NodeCategory;
48
49 namespace platform_ex
50 {
51
52 #if YCL_Win32
53
54 inline namespace Windows
55 {
56
57 int
58 ConvertToErrno(ErrorCode err) ynothrow
59 {
60 // NOTE: This mapping is from Windows Kits 10.0.10150.0,
61 // ucrt/misc/errno.cpp, except for fix of the bug error 124: it shall be
62 // %ERROR_INVALID_LEVEL but not %ERROR_INVALID_HANDLE. See https://connect.microsoft.com/VisualStudio/feedback/details/1641428.
63 switch(err)
64 {
65 case ERROR_INVALID_FUNCTION:
66 return EINVAL;
67 case ERROR_FILE_NOT_FOUND:
68 case ERROR_PATH_NOT_FOUND:
69 return ENOENT;
70 case ERROR_TOO_MANY_OPEN_FILES:
71 return EMFILE;
72 case ERROR_ACCESS_DENIED:
73 return EACCES;
74 case ERROR_INVALID_HANDLE:
75 return EBADF;
76 case ERROR_ARENA_TRASHED:
77 case ERROR_NOT_ENOUGH_MEMORY:
78 case ERROR_INVALID_BLOCK:
79 return ENOMEM;
80 case ERROR_BAD_ENVIRONMENT:
81 return E2BIG;
82 case ERROR_BAD_FORMAT:
83 return ENOEXEC;
84 case ERROR_INVALID_ACCESS:
85 case ERROR_INVALID_DATA:
86 return EINVAL;
87 case ERROR_INVALID_DRIVE:
88 return ENOENT;
89 case ERROR_CURRENT_DIRECTORY:
90 return EACCES;
91 case ERROR_NOT_SAME_DEVICE:
92 return EXDEV;
93 case ERROR_NO_MORE_FILES:
94 return ENOENT;
95 case ERROR_LOCK_VIOLATION:
96 return EACCES;
97 case ERROR_BAD_NETPATH:
98 return ENOENT;
99 case ERROR_NETWORK_ACCESS_DENIED:
100 return EACCES;
101 case ERROR_BAD_NET_NAME:
102 return ENOENT;
103 case ERROR_FILE_EXISTS:
104 return EEXIST;
105 case ERROR_CANNOT_MAKE:
106 case ERROR_FAIL_I24:
107 return EACCES;
108 case ERROR_INVALID_PARAMETER:
109 return EINVAL;
110 case ERROR_NO_PROC_SLOTS:
111 return EAGAIN;
112 case ERROR_DRIVE_LOCKED:
113 return EACCES;
114 case ERROR_BROKEN_PIPE:
115 return EPIPE;
116 case ERROR_DISK_FULL:
117 return ENOSPC;
118 case ERROR_INVALID_TARGET_HANDLE:
119 return EBADF;
120 case ERROR_INVALID_LEVEL:
121 return EINVAL;
122 case ERROR_WAIT_NO_CHILDREN:
123 case ERROR_CHILD_NOT_COMPLETE:
124 return ECHILD;
125 case ERROR_DIRECT_ACCESS_HANDLE:
126 return EBADF;
127 case ERROR_NEGATIVE_SEEK:
128 return EINVAL;
129 case ERROR_SEEK_ON_DEVICE:
130 return EACCES;
131 case ERROR_DIR_NOT_EMPTY:
132 return ENOTEMPTY;
133 case ERROR_NOT_LOCKED:
134 return EACCES;
135 case ERROR_BAD_PATHNAME:
136 return ENOENT;
137 case ERROR_MAX_THRDS_REACHED:
138 return EAGAIN;
139 case ERROR_LOCK_FAILED:
140 return EACCES;
141 case ERROR_ALREADY_EXISTS:
142 return EEXIST;
143 case ERROR_FILENAME_EXCED_RANGE:
144 return ENOENT;
145 case ERROR_NESTING_NOT_ALLOWED:
146 return EAGAIN;
147 case ERROR_NOT_ENOUGH_QUOTA:
148 return ENOMEM;
149 default:
150 break;
151 }
152 if(IsInClosedInterval<ErrorCode>(err, ERROR_WRITE_PROTECT,
153 ERROR_SHARING_BUFFER_EXCEEDED))
154 return EACCES;
155 if(IsInClosedInterval<ErrorCode>(err, ERROR_INVALID_STARTING_CODESEG,
156 ERROR_INFLOOP_IN_RELOC_CHAIN))
157 return ENOEXEC;
158 return EINVAL;
159 }
160
161
163 namespace
164 {
165
167 int WINAPI
168 ConsoleHandler(unsigned long ctrl)
169 {
170 switch (ctrl)
171 {
172 case CTRL_C_EVENT:
173 case CTRL_BREAK_EVENT:
174 case CTRL_CLOSE_EVENT:
175 case CTRL_LOGOFF_EVENT:
176 case CTRL_SHUTDOWN_EVENT:
177 std::_Exit(int(STATUS_CONTROL_C_EXIT));
178 }
179 return 0;
180 }
181
182 class Win32ErrorCategory : public std::error_category
183 {
184 public:
185 PDefH(const char*, name, ) const ynothrow override
186 ImplRet("Win32Error")
188 PDefH(std::string, message, int ev) const override
189 // NOTE: For Win32 a %::DWORD can be mapped one-to-one for 32-bit %int.
190 ImplRet(Win32Exception::FormatMessage(ErrorCode(ev)))
191 };
192
193
195
196 YB_NONNULL(2) string
197 MBCSToMBCS(int l, const char* str, unsigned cp_src, unsigned cp_dst)
198 {
199 if(cp_src != cp_dst)
200 {
201 const int
202 w_len(::MultiByteToWideChar(cp_src, 0, Nonnull(str), l, {}, 0));
203
204 if(w_len != 0)
205 {
206 wstring wstr(CheckPositiveScalar<size_t>(w_len), wchar_t());
207 const auto w_str(&wstr[0]);
208
209 ::MultiByteToWideChar(cp_src, 0, str, l, w_str, w_len);
210 if(l == -1 && !wstr.empty())
211 wstr.pop_back();
212 return WCSToMBCS({w_str, wstr.length()}, cp_dst);
213 }
214 return {};
215 }
216 return str;
217 }
218
219 YB_NONNULL(2) wstring
220 MBCSToWCS(int l, const char* str, unsigned cp)
221 {
222 const int
223 w_len(::MultiByteToWideChar(cp, 0, Nonnull(str), l, {}, 0));
224
225 if(w_len != 0)
226 {
227 wstring res(CheckPositiveScalar<size_t>(w_len), wchar_t());
228
229 ::MultiByteToWideChar(cp, 0, str, l, &res[0], w_len);
230 if(l == -1 && !res.empty())
231 res.pop_back();
232 return res;
233 }
234 return {};
235 }
236
237 YB_NONNULL(2) string
238 WCSToMBCS(int l, const wchar_t* str, unsigned cp)
239 {
240 const int r_l(::WideCharToMultiByte(cp, 0, Nonnull(str), l, {}, 0, {}, {}));
241
242 if(r_l != 0)
243 {
244 string res(CheckPositiveScalar<size_t>(r_l), char());
245
246 ::WideCharToMultiByte(cp, 0, str, l, &res[0], r_l, {}, {});
247 if(l == -1 && !res.empty())
248 res.pop_back();
249 return res;
250 }
251 return {};
252 }
254
255
257
258 template<typename _func>
259 auto
260 FetchFileInfo(_func f, UniqueHandle::pointer h)
261 -> decltype(f(std::declval<::BY_HANDLE_FILE_INFORMATION&>()))
262 {
263 ::BY_HANDLE_FILE_INFORMATION info;
264
265 YCL_CallWin32F(GetFileInformationByHandle, h, &info);
266 return f(info);
267 }
268
269 template<typename _func, typename... _tParams>
270 auto
271 MakeFileToDo(_func f, _tParams&&... args)
272 -> decltype(f(UniqueHandle::pointer()))
273 {
274 if(const auto h = MakeFile(yforward(args)...))
275 return f(h.get());
276 YCL_Raise_Win32Exception("CreateFileW");
277 }
278
280 PDefH(FileAttributesAndFlags, FollowToAttr, bool follow_reparse_point) ynothrow
281 ImplRet(follow_reparse_point ? FileAttributesAndFlags::NormalWithDirectory
282 : FileAttributesAndFlags::NormalAll)
284
285
286 struct REPARSE_DATA_BUFFER
288 {
289 struct tagSymbolicLinkReparseBuffer
290 {
291 unsigned short SubstituteNameOffset;
292 unsigned short SubstituteNameLength;
293 unsigned short PrintNameOffset;
294 unsigned short PrintNameLength;
295 unsigned long Flags;
296 wchar_t PathBuffer[1];
297
298 DefGetter(const ynothrow, wstring_view, PrintName,
299 {PathBuffer + size_t(PrintNameOffset) / sizeof(wchar_t),
300 size_t(PrintNameLength / sizeof(wchar_t))})
301 };
302 struct tagMountPointReparseBuffer
303 {
304 unsigned short SubstituteNameOffset;
305 unsigned short SubstituteNameLength;
306 unsigned short PrintNameOffset;
307 unsigned short PrintNameLength;
308 wchar_t PathBuffer[1];
309
310 DefGetter(const ynothrow, wstring_view, PrintName,
311 {PathBuffer + size_t(PrintNameOffset) / sizeof(wchar_t),
312 size_t(PrintNameLength / sizeof(wchar_t))})
313 };
314 struct tagGenericReparseBuffer
315 {
316 unsigned char DataBuffer[1];
317 };
318
319 unsigned long ReparseTag;
320 unsigned short ReparseDataLength;
321 unsigned short Reserved;
322 union
323 {
324 tagSymbolicLinkReparseBuffer SymbolicLinkReparseBuffer;
325 tagMountPointReparseBuffer MountPointReparseBuffer;
326 tagGenericReparseBuffer GenericReparseBuffer;
327 };
328 };
329
331 yconstexpr const auto FSCTL_GET_REPARSE_POINT(0x000900A8UL);
332
333
335
336 enum class SystemPaths
337 {
338 System,
339 Windows
340 };
341
342 wstring
343 FetchFixedSystemPath(SystemPaths e, size_t s)
344 {
345 // XXX: Depends right behavior on external API.
346 const auto p_buf(make_unique_default_init<wchar_t[]>(s));
347 const auto str(p_buf.get());
348
349 switch(e)
350 {
351 case SystemPaths::System:
352 YCL_CallWin32F(GetSystemDirectoryW, str, unsigned(s));
353 break;
354 case SystemPaths::Windows:
355 YCL_CallWin32F(GetSystemWindowsDirectoryW, str, unsigned(s));
356 break;
357 }
358 return ystdex::rtrim(wstring(str), L'\\') + L'\\';
359 }
361
362 } // unnamed namespace;
363
364
365 Win32Exception::Win32Exception(ErrorCode ec, string_view msg, RecordLevel lv)
366 : Exception(int(ec), GetErrorCategory(), msg, lv)
367 {
368 YAssert(ec != 0, "No error should be thrown.");
369 }
370 Win32Exception::Win32Exception(ErrorCode ec, string_view msg, const char* fn,
371 RecordLevel lv)
372 : Win32Exception(ec, msg.to_string() + " @ " + Nonnull(fn), lv)
373 {}
374 ImplDeDtor(Win32Exception)
375
376 const std::error_category&
377 Win32Exception::GetErrorCategory()
378 {
379 static const Win32ErrorCategory ecat{};
380
381 return ecat;
382 }
383
384 std::string
385 Win32Exception::FormatMessage(ErrorCode ec) ynothrow
386 {
387 return TryInvoke([=]{
388 try
389 {
390 wchar_t* buf{};
391
392 YCL_CallWin32F(FormatMessageW, FORMAT_MESSAGE_ALLOCATE_BUFFER
393 | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
394 {}, ec, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
395 reinterpret_cast<wchar_t*>(&buf), 1, {});
396
397 const auto p(unique_raw(buf, LocalDelete()));
398
399 return WCSToMBCS(buf, unsigned(CP_UTF8));
400 }
401 CatchExpr(..., YTraceDe(Warning, "FormatMessage failed."), throw)
402 });
403 }
404
405
406 ModuleProc*
407 LoadProc(::HMODULE h_module, const char* proc)
408 {
409 return YCL_CallWin32F(GetProcAddress, h_module, proc);
410 }
411
412
413 wstring
414 FetchModuleFileName(::HMODULE h_module)
415 {
416 return ystdex::retry_for_vector<wstring>(MAX_PATH,
417 [=](wstring& res, size_t s) -> bool{
418 const auto r(size_t(::GetModuleFileNameW(h_module, &res[0], s)));
419 const auto e(::GetLastError());
420
421 if(e != ERROR_SUCCESS && e != ERROR_INSUFFICIENT_BUFFER)
422 throw Win32Exception(e, "GetModuleFileNameW");
423 if(r < s)
424 {
425 res.resize(r);
426 return {};
427 }
428 return true;
429 });
430 }
431
432
433 void
434 GlobalDelete::operator()(pointer h) const ynothrow
435 {
436 // NOTE: %::GlobalFree does not ignore null handle value.
437 if(h && YB_UNLIKELY(::GlobalFree(h)))
438 YTraceDe(Warning, "Error %lu: failed calling GlobalFree @ %s.",
439 ::GetLastError(), yfsig);
440 }
441
442
443 GlobalLocked::GlobalLocked(::HGLOBAL h)
444 : p_locked(YCL_CallWin32F(GlobalLock, h))
445 {}
446 GlobalLocked::~GlobalLocked()
447 {
448 YCL_CallWin32F_Trace(GlobalUnlock, p_locked);
449 }
450
451
452 void
453 LocalDelete::operator()(pointer h) const ynothrow
454 {
455 // FIXME: For some platforms, no %::LocalFree available. See https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms679351(v=vs.85).aspx.
456 // NOTE: %::LocalFree ignores null handle value.
457 if(YB_UNLIKELY(::LocalFree(h)))
458 YTraceDe(Warning, "Error %lu: failed calling LocalFree @ %s.",
459 ::GetLastError(), yfsig);
460 }
461
462
463 NodeCategory
464 CategorizeNode(const ::WIN32_FIND_DATAW& d) ynothrow
465 {
466 auto res(NodeCategory::Empty);
467
468 if(IsDirectory(d))
469 res |= NodeCategory::Directory;
470 if(d.dwFileAttributes & ReparsePoint)
471 {
472 switch(d.dwReserved0)
473 {
474 case IO_REPARSE_TAG_SYMLINK:
475 res |= NodeCategory::SymbolicLink;
476 break;
477 case IO_REPARSE_TAG_MOUNT_POINT:
478 res |= NodeCategory::MountPoint;
479 default:
480 ;
481 }
482 }
483 return res;
484 }
485 NodeCategory
486 CategorizeNode(UniqueHandle::pointer h) ynothrowv
487 {
488 YAssertNonnull(h);
489
490 auto res(NodeCategory::Empty);
491
492 switch(::GetFileType(h)
493 & ~static_cast<unsigned long>(FILE_TYPE_REMOTE))
494 {
495 case FILE_TYPE_CHAR:
496 res |= NodeCategory::Character;
497 break;
498 case FILE_TYPE_PIPE:
499 res |= NodeCategory::FIFO;
500 break;
501 case FILE_TYPE_UNKNOWN:
502 res |= NodeCategory::Unknown;
503 default:
504 ;
505 }
506 return res;
507 }
508
509
510 UniqueHandle
511 MakeFile(const wchar_t* path, FileAccessRights desired_access,
512 FileShareMode shared_mode, CreationDisposition creation_disposition,
513 FileAttributesAndFlags attributes_and_flags) ynothrowv
514 {
515 using ystdex::underlying;
516 const auto h(::CreateFileW(Nonnull(path), underlying(
517 desired_access), underlying(shared_mode), {}, underlying(
518 creation_disposition), underlying(attributes_and_flags), {}));
519
520 return UniqueHandle(h != INVALID_HANDLE_VALUE ? h
521 : UniqueHandle::pointer());
522 }
523
524
525 void
526 FixConsoleHandler(int(WINAPI* handler)(unsigned long), bool add)
527 {
528 YCL_CallWin32F(SetConsoleCtrlHandler, handler ? handler : ConsoleHandler,
529 add);
530 }
531
532 bool
533 CheckWine()
534 {
535 try
536 {
537 RegistryKey k1(HKEY_CURRENT_USER, L"Software\\Wine");
538 RegistryKey k2(HKEY_LOCAL_MACHINE, L"Software\\Wine");
539
540 yunused(k1),
541 yunused(k2);
542 return true;
543 }
544 CatchIgnore(Win32Exception&)
545 return {};
546 }
547
548
549 string
550 MBCSToMBCS(const char* str, unsigned cp_src, unsigned cp_dst)
551 {
552 return MBCSToMBCS(-1, str, cp_src, cp_dst);
553 }
554 string
555 MBCSToMBCS(string_view sv, unsigned cp_src, unsigned cp_dst)
556 {
557 return sv.length() != 0 ? MBCSToMBCS(CheckNonnegativeScalar<int>(
558 sv.length()), sv.data(), cp_src, cp_dst) : string();
559 }
560
561 wstring
562 MBCSToWCS(const char* str, unsigned cp)
563 {
564 return MBCSToWCS(-1, str, cp);
565 }
566 wstring
567 MBCSToWCS(string_view sv, unsigned cp)
568 {
569 return sv.length() != 0 ? MBCSToWCS(CheckNonnegativeScalar<int>(
570 sv.length()), sv.data(), cp) : wstring();
571 }
572
573 string
574 WCSToMBCS(const wchar_t* str, unsigned cp)
575 {
576 return WCSToMBCS(-1, str, cp);
577 }
578 string
579 WCSToMBCS(wstring_view sv, unsigned cp)
580 {
581 return sv.length() != 0 ? WCSToMBCS(CheckNonnegativeScalar<int>(
582 sv.length()), sv.data(), cp) : string();
583 }
584
585
586 DirectoryFindData::DirectoryFindData(wstring_view name)
587 : dir_name(name), find_data()
588 {
589 if(ystdex::rtrim(dir_name, L"/\\").empty())
590 dir_name = L'.';
591 YAssert(platform::EndsWithNonSeperator(dir_name),
592 "Invalid argument found.");
593
594 using platform::FileOperationFailure;
595 const auto attr(FileAttributes(::GetFileAttributesW(dir_name.c_str())));
596 yconstexpr const auto& msg("Opening directory failed.");
597
598 if(attr != Invalid)
599 {
600 if(attr & Directory)
601 dir_name += L"\\*";
602 else
603 ystdex::throw_error<FileOperationFailure>(ENOTDIR, msg);
604 }
605 else
606 ystdex::throw_error<FileOperationFailure>(GetErrnoFromWin32(), msg);
607 }
608
609 DirectoryFindData::~DirectoryFindData()
610 {
611 if(h_node)
612 Close();
613 }
614
615 NodeCategory
616 DirectoryFindData::GetNodeCategory() const ynothrow
617 {
618 if(h_node && !d_name.empty())
619 {
620 auto res(CategorizeNode(find_data));
621
622 FilterExceptions([&]{
623 wstring_view name(GetDirName());
624
625 name.remove_suffix(1);
626 // NOTE: Only existed and accessable files are considered.
627 // FIXME: Blocked. TOCTTOU access.
628 if(const auto h = MakeFile((wstring(name) + d_name).c_str(),
629 FileSpecificAccessRights::ReadAttributes,
630 FileAttributesAndFlags::NormalWithDirectory))
631 res |= CategorizeNode(h.get());
632 }, yfsig);
633 return res;
634 }
635 return NodeCategory::Empty;
636 }
637
638 void
639 DirectoryFindData::Close() ynothrow
640 {
641 FilterExceptions(std::bind(YCL_WrapCallWin32(FindClose, h_node), yfsig),
642 yfsig);
643 }
644
645 observer_ptr<wstring>
646 DirectoryFindData::Read()
647 {
648 if(!h_node)
649 {
650 if((h_node = ::FindFirstFileW(GetDirName().c_str(), &find_data))
651 == INVALID_HANDLE_VALUE)
652 h_node = {};
653 }
654 else if(!::FindNextFileW(h_node, &find_data))
655 {
656 Close();
657 h_node = {};
658 }
659 if(h_node && h_node != INVALID_HANDLE_VALUE)
660 d_name = find_data.cFileName;
661 return h_node && d_name[0] != wchar_t() ? make_observer(&d_name) : nullptr;
662 }
663
664 void
665 DirectoryFindData::Rewind() ynothrow
666 {
667 if(h_node)
668 {
669 Close();
670 h_node = {};
671 }
672 }
673
674
675 wstring
676 ResolveReparsePoint(const wchar_t* path)
677 {
678 return wstring(MakeFileToDo([=](UniqueHandle::pointer h){
679 return FetchFileInfo([&](::BY_HANDLE_FILE_INFORMATION& info)
680 -> wstring_view{
681 if(info.dwFileAttributes & ReparsePoint)
682 {
683 ystdex::pun_storage_t<byte[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]>
684 target_buffer;
685 const auto rdb(reinterpret_cast<REPARSE_DATA_BUFFER*>(
686 &target_buffer));
687
688 YCL_CallWin32F(DeviceIoControl, h, FSCTL_GET_REPARSE_POINT, {},
689 0, &target_buffer, sizeof(target_buffer), {}, {});
690 switch(rdb->ReparseTag)
691 {
692 case IO_REPARSE_TAG_SYMLINK:
693 return rdb->SymbolicLinkReparseBuffer.GetPrintName();
694 case IO_REPARSE_TAG_MOUNT_POINT:
695 return rdb->MountPointReparseBuffer.GetPrintName();
696 default:
697 YTraceDe(Warning, "Unsupported reparse tag '%lu' found",
698 rdb->ReparseTag);
699 ystdex::throw_error(std::errc::not_supported);
700 }
701 }
702 throw std::invalid_argument(
703 "Specified file is not a reparse point.");
704 }, h);
705 }, path, FileAttributesAndFlags::NormalAll));
706 }
707
708
709 size_t
710 QueryFileLinks(UniqueHandle::pointer h)
711 {
712 return FetchFileInfo([](::BY_HANDLE_FILE_INFORMATION& info){
713 return size_t(info.nNumberOfLinks);
714 }, h);
715 }
716 size_t
717 QueryFileLinks(const wchar_t* path, bool follow_reparse_point)
718 {
719 return MakeFileToDo<size_t(UniqueHandle::pointer)>(QueryFileLinks, path,
720 FollowToAttr(follow_reparse_point));
721 }
722
723 pair<VolumeID, FileID>
724 QueryFileNodeID(UniqueHandle::pointer h)
725 {
726 return FetchFileInfo([](::BY_HANDLE_FILE_INFORMATION& info) ynothrow
727 -> pair<VolumeID, FileID>{
728 return {VolumeID(info.dwVolumeSerialNumber),
729 FileID(info.nFileIndexHigh) << 32 | info.nFileIndexLow};
730 }, h);
731 }
732 pair<VolumeID, FileID>
733 QueryFileNodeID(const wchar_t* path, bool follow_reparse_point)
734 {
735 return MakeFileToDo<pair<VolumeID, FileID>(UniqueHandle::pointer)>(
736 QueryFileNodeID, path, FollowToAttr(follow_reparse_point));
737 }
738
739 void
740 QueryFileTime(UniqueHandle::pointer h, ::FILETIME* p_ctime, ::FILETIME* p_atime,
741 ::FILETIME* p_mtime)
742 {
743 YCL_CallWin32F(GetFileTime, h, p_ctime, p_atime, p_mtime);
744 }
745 void
746 QueryFileTime(const wchar_t* path, ::FILETIME* p_ctime, ::FILETIME* p_atime,
747 ::FILETIME* p_mtime, bool follow_reparse_point)
748 {
749 MakeFileToDo(std::bind<void(UniqueHandle::pointer, ::FILETIME*, ::FILETIME*,
750 ::FILETIME*)>(QueryFileTime, std::placeholders::_1, p_ctime, p_atime,
751 p_mtime), path, AccessRights::GenericRead,
752 FollowToAttr(follow_reparse_point));
753 }
754
755 void
756 SetFileTime(UniqueHandle::pointer h, ::FILETIME* p_ctime, ::FILETIME* p_atime,
757 ::FILETIME* p_mtime)
758 {
759 using ::SetFileTime;
760
761 YCL_CallWin32F(SetFileTime, h, p_ctime, p_atime, p_mtime);
762 }
763 void
764 SetFileTime(const wchar_t* path, ::FILETIME* p_ctime, ::FILETIME* p_atime,
765 ::FILETIME* p_mtime, bool follow_reparse_point)
766 {
767 MakeFileToDo(std::bind<void(UniqueHandle::pointer, ::FILETIME*, ::FILETIME*,
768 ::FILETIME*)>(SetFileTime, std::placeholders::_1, p_ctime, p_atime,
769 p_mtime), path, AccessRights::GenericWrite,
770 FollowToAttr(follow_reparse_point));
771 }
772
773 std::chrono::nanoseconds
774 ConvertTime(const ::FILETIME& file_time)
775 {
776 if(file_time.dwLowDateTime != 0 || file_time.dwHighDateTime != 0)
777 {
778 // FIXME: Local time conversion for FAT volumes.
779 // NOTE: See $2014-10 @ %Documentation::Workflow::Annual2014.
780 ::LARGE_INTEGER date;
781
782 // NOTE: The epoch is Jan. 1, 1601: 134774 days to Jan. 1, 1970, i.e.
783 // 11644473600 seconds, or 116444736000000000 * 100 nanoseconds.
784 // TODO: Strip away the magic number;
785 yunseq(date.HighPart = long(file_time.dwHighDateTime),
786 date.LowPart = file_time.dwLowDateTime);
787 return std::chrono::nanoseconds((date.QuadPart - 116444736000000000LL)
788 * 100U);
789 }
790 else
791 ystdex::throw_error(std::errc::not_supported);
792 }
793 ::FILETIME
794 ConvertTime(std::chrono::nanoseconds file_time)
795 {
796 ::FILETIME res;
797 ::LARGE_INTEGER date;
798
799 date.QuadPart = file_time.count() / 100LL + 116444736000000000LL;
800 yunseq(res.dwHighDateTime = static_cast<unsigned long>(date.HighPart),
801 res.dwLowDateTime = date.LowPart);
802 if(res.dwLowDateTime != 0 || res.dwHighDateTime != 0)
803 return res;
804 ystdex::throw_error(std::errc::not_supported);
805 }
806
807 wstring
808 ExpandEnvironmentStrings(const wchar_t* p_src)
809 {
810 const auto w_len(YCL_CallWin32F(ExpandEnvironmentStringsW, Nonnull(p_src),
811 {}, 0));
812 wstring wstr(w_len, wchar_t());
813
814 YCL_CallWin32F(ExpandEnvironmentStringsW, p_src, &wstr[0], w_len);
815 return wstr;
816 }
817
818 wstring
819 FetchSystemPath(size_t s)
820 {
821 return FetchFixedSystemPath(SystemPaths::System, s);
822 }
823
824 wstring
825 FetchWindowsPath(size_t s)
826 {
827 return FetchFixedSystemPath(SystemPaths::Windows, s);
828 }
829
830 } // inline namespace Windows;
831
832 #endif
833
834 } // namespace YSLib;
835
platform::p
while p p
Definition: YCLib/FileSystem.h:225
YSLib::lv
RecordLevel lv
Definition: YException.cpp:58
platform_ex::Windows::SetFileTime
YF_API void SetFileTime(UniqueHandle::pointer,::FILETIME *={},::FILETIME *={},::FILETIME *={})
设置文件的创建、访问和/或修改时间。
ystdex::to_string
std::string to_string(const std::thread::id &)
转换 thread::id 为字符串表示。
ystdex::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:415
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:653
platform::KeyCategory::System
表示系统键（如 SysRq/PrintScr 、 Break/Pause 和电源管理）。
Definition: Keys.h:125
platform::containers::string
basic_string< char > string
Definition: Container.h:101
platform::Nonnull
_type && Nonnull(_type &&p) ynothrow
断言并返回非空指针。
Definition: Debug.h:411
platform::Descriptions::Warning
Definition: YCommon.h:157
YSLib::Text::buf
const char * buf
Definition: TextFile.h:77
platform_ex::Windows::shared_mode
const wchar_t FileAccessRights FileShareMode shared_mode
Definition: MinGW32.h:548
platform::KeyCodes::DS::L
Definition: Keys.h:227
NPL::A1::name
ctx const string & name
Definition: NPLA1.h:248
platform::KeyCategory::Character
表示产生字符的键。
Definition: Keys.h:111
ystdex::nullptr
const class ystdex::nullptr_t nullptr
platform_ex::Windows::ReparsePoint
Definition: MinGW32.h:448
platform_ex::Windows::QueryFileTime
YF_API void QueryFileTime(UniqueHandle::pointer,::FILETIME *={},::FILETIME *={},::FILETIME *={})
查询文件的创建、访问和/或修改时间。
ystdex::underlying
underlying_type_t< _type > underlying(_type val)
取枚举值的底层整数。
Definition: utility.hpp:120
YSLib::UI::Close
void Close(IWidget &wgt)
Definition: YWidget.cpp:92
YSLib
YSLib 命名空间。
Definition: AndroidHost.h:45
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:109
YSLib::UI::empty
!sv empty()&&sv.front()!
YSLib::PDefH
PDefH(Environment &, FetchEnvironment,) ImplRet(FetchGlobalInstance().GetEnvironmentRef()) inline PDefH(GUIHost &
取单一环境对象引用。
platform::NodeCategory
NodeCategory
文件节点类别。
Definition: FileIO.h:117
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:760
YSLib::FilterExceptions
bool FilterExceptions(_func f, const char *desc={}, RecordLevel lv=Alert, ExceptionTracer trace=ExtractAndTrace) ynothrow
调用函数并过滤宿主异常。
Definition: YException.h:202
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
platform_ex::Windows::FileID
std::uint64_t FileID
文件标识。
Definition: MinGW32.h:775
CHRLib::d
_tDst * d
Definition: CharacterProcessing.h:139
platform_ex::Windows::FetchWindowsPath
YF_API wstring FetchWindowsPath(size_t=MAX_PATH)
取系统目录路径。
yunused
#define yunused(...)
标记未使用的表达式。
Definition: ydef.h:942
platform_ex::Windows::CheckWine
YF_API bool CheckWine()
判断是否在 Wine 环境下运行。
platform_ex::Windows::Directory
Definition: MinGW32.h:442
platform_ex::Windows::CreationDisposition
YF_API CreationDisposition
Definition: MinGW32.h:545
ystdex::wstring_view
basic_string_view< wchar_t > wstring_view
Definition: string_view.hpp:418
yfsig
#define yfsig
展开为表示函数签名的预定义变量的宏。
Definition: ydef.h:702
DefGetter
#define DefGetter(_q, _t, _n,...)
Definition: YBaseMacro.h:240
YSLib::RecordLevel
YF_API RecordLevel
Definition: YException.h:141
YCL_CallWin32F
#define YCL_CallWin32F(_fn,...)
Definition: MinGW32.h:179
YSLib::UI::ImplDeDtor
ImplDeDtor(Thumb) void DecorateAsCloseButton(Thumb &tmb)
Definition: Button.cpp:125
YSLib::size_t
name const ValueNode::Container const string &name ynothrow observer_ptr< ValueNode::Container > const string &name ynothrow observer_ptr< const ValueNode::Container > const string &name ynothrow size_t
Definition: ValueNode.h:639
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:305
CatchIgnore
#define CatchIgnore(_ex)
指定异常处理器忽略指定异常。
Definition: YBaseMacro.h:133
YSLib::ynothrow
YB_PURE const _type size_t n ynothrow
Definition: YCoreUtilities.h:168
YSLib::TryInvoke
ystdex::result_of_t< _fCallable &&(_tParams &&...)> TryInvoke(_fCallable &&f, _tParams &&...args) ynothrow
调用函数并试图返回。
Definition: YException.h:185
platform_ex::Windows::QueryFileNodeID
YF_API pair< VolumeID, FileID > QueryFileNodeID(UniqueHandle::pointer)
查询文件标识。
FileAttributesAndFlags
FileAttributesAndFlags
Definition: MinGW32.h:494
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:438
container.hpp
通用容器操作。
ystdex::rtrim
_tString && rtrim(_tString &&str, typename string_traits< _tString >::value_type c)
删除字符串中指定的连续后缀字符。
Definition: string.hpp:618
ystdex::throw_error
void throw_error(std::error_code ec, _tParams &&...args)
抛出错误： std::system_error 或允许相同构造函数参数的异常。
Definition: ystdex/exception.h:162
FileAttributes
FileAttributes
文件共享模式。
Definition: MinGW32.h:437
platform_ex::Windows::ConvertTime
YF_API std::chrono::nanoseconds ConvertTime(const ::FILETIME &)
转换文件时间为以 POSIX 历元起始度量的时间间隔。
std
Definition: memory.hpp:1100
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:114
platform_ex::Windows::FileAccessRights
YF_API FileAccessRights
Definition: MinGW32.h:543
platform_ex::Windows::NormalAll
Definition: MinGW32.h:497
platform::KeyCodes::Win32::Empty
Definition: Keys.h:279
platform_ex::Windows::ConvertToErrno
YF_API YB_STATELESS int ConvertToErrno(ErrorCode) ynothrow
转换 Win32 错误为 errno 。
YSLib::YAssert
YAssert(!(v< Deref(a)),"Value less than lower bound found.")
platform_ex::Windows::CategorizeNode
const ::WIN32_FIND_DATAW &d ynothrow ImplRet(d.dwFileAttributes &Directory) YF_API platform YF_API platform::NodeCategory CategorizeNode(UniqueHandle::pointer) ynothrowv
按 ::WIN32_FIND_DATAW 归类节点类别。
Definition: MinGW32.h:532
platform_ex::Windows::MBCSToMBCS
YF_API string MBCSToMBCS(string_view, unsigned=CP_UTF8, unsigned=CP_ACP)
platform::containers::wstring
basic_string< wchar_t > wstring
Definition: Container.h:108
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:996
platform_ex
平台扩展命名空间。
Definition: Android.h:45
YSLib::path
YF_API const char * path
Definition: Initialization.h:74
ystdex::make_unique_default_init
enable_if_t<!is_array< _type >::value, std::unique_ptr< _type > > make_unique_default_init()
Definition: memory.hpp:756
platform_ex::Windows::FetchModuleFileName
YF_API wstring FetchModuleFileName(::HMODULE={})
取模块映像路径。
YSLib::Text::str
const char const char * str
Definition: TextFile.h:77
platform::FileOperationFailure
表示文件操作失败的异常。
Definition: FileIO.h:1142
platform_ex::Windows::WCSToMBCS
YF_API string WCSToMBCS(wstring_view, unsigned=CP_ACP)
YSLib::Drawing::r
The boundary is out of the const Graphics const Rect const Point const Point Color c const Rect const Rect & r
Definition: YDraw.h:174
platform_ex::Windows::VolumeID
std::uint32_t VolumeID
卷序列号。
Definition: MinGW32.h:777
YModules.h
YSLib::IO::int
YF_API int
Definition: File.h:49
platform_ex::Windows::MBCSToWCS
YF_API wstring MBCSToWCS(string_view, unsigned=CP_ACP)
YSLib::YB_NONNULL
YF_API YB_NONNULL(1, 2) ValueNode LoadNPLA1File(const char *disp
载入 NPLA1 配置文件。
YSLib::UI::e
void e
Definition: YWidget.h:352
platform_ex::Windows::FetchSystemPath
YF_API wstring FetchSystemPath(size_t=MAX_PATH)
取系统目录路径。
platform_ex::Windows::creation_disposition
const wchar_t FileAccessRights FileShareMode FileAttributesAndFlags attributes_and_flags ynothrowv const wchar_t FileAccessRights CreationDisposition creation_disposition
Definition: MinGW32.h:553
platform_ex::Windows::proc
const char * proc
Definition: MinGW32.h:230
platform_ex::Windows::MakeFile
MakeFile
Definition: MinGW32.h:548
platform_ex::Windows::NormalWithDirectory
Definition: MinGW32.h:496
platform_ex::Windows::attributes_and_flags
const wchar_t FileAccessRights FileShareMode FileAttributesAndFlags attributes_and_flags ynothrowv const wchar_t FileAccessRights CreationDisposition FileAttributesAndFlags attributes_and_flags
Definition: MinGW32.h:556
NPL::c_str
YF_API const char src c_str())) YF_API void InstallDirectory(const string &
安装目录：复制目录树。
platform_ex::Windows::QueryFileLinks
YF_API size_t QueryFileLinks(UniqueHandle::pointer)
查询文件链接数。
yforward
#define yforward(_expr)
根据参数类型使用 std::forward 传递对应参数。
Definition: ydef.h:969
ystdex::make_observer
observer_ptr< _type > make_observer(_type *p)
Definition: memory.hpp:1042
platform_ex::Windows::desired_access
const wchar_t FileAccessRights desired_access
Definition: MinGW32.h:548
YCL_Raise_Win32Exception
#define YCL_Raise_Win32Exception(...)
取转换为 errno 的 Win32 错误。
Definition: MinGW32.h:132
platform_ex::Windows::ModuleProc
ystdex::remove_reference_t< decltype(*::GetProcAddress(::HMODULE(),{}))> ModuleProc
加载过程地址得到的过程类型。
Definition: MinGW32.h:212
YSLib::IO::f
const string &path const String &path _func f
Definition: YSLib/Service/FileSystem.h:430
CHRLib::args
_tParams && args
Definition: CharacterProcessing.h:538
YSLib::UI::name
yconstfn const string & name
Definition: Loader.h:130
YCL_WrapCallWin32
#define YCL_WrapCallWin32(_fn,...)
调用 Win32 API 或其它可用 ::GetLastError 取得调用状态的例程。
Definition: MinGW32.h:167
platform_ex::Windows::IsDirectory
IsDirectory
Definition: MinGW32.h:512
YSLib::ImplRet
ImplRet(FetchGlobalInstance().GetGUIHostRef()) YF_API void Execute(GUIApplication &
执行程序主消息循环。
platform_ex::Windows::ErrorCode
unsigned long ErrorCode
Definition: MinGW32.h:54
ystdex::unique_raw
std::unique_ptr< _type > unique_raw(_pSrc *p)
Definition: memory.hpp:617
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
YCL_CallWin32F_Trace
#define YCL_CallWin32F_Trace(_fn,...)
Definition: MinGW32.h:202
platform_ex::Windows::FileShareMode
YF_API FileShareMode
Definition: MinGW32.h:544