1919#include < combaseapi.h> // Needed for CoTaskMemFree() used in output of some helpers.
2020#include < winbase.h> // LocalAlloc
2121#include < PathCch.h>
22+ #include " wistd_type_traits.h"
2223#include " result.h"
2324#include " win32_helpers.h"
2425#include " resource.h"
@@ -197,6 +198,7 @@ namespace wil
197198 };
198199 DEFINE_ENUM_FLAG_OPERATORS (RemoveDirectoryOptions);
199200
201+ // / @cond
200202 namespace details
201203 {
202204 // Reparse points should not be traversed in most recursive walks of the file system,
@@ -208,6 +210,7 @@ namespace wil
208210 (IsReparseTagDirectory (info.ReparseTag ) || (info.ReparseTag == IO_REPARSE_TAG_WCI))));
209211 }
210212 }
213+ // / @endcond
211214
212215 // Retrieve a handle to a directory only if it is safe to recurse into.
213216 inline wil::unique_hfile TryCreateFileCanRecurseIntoDirectory (PCWSTR path, PWIN32_FIND_DATAW fileFindData, DWORD access = GENERIC_READ | /* DELETE*/ 0x00010000L , DWORD share = FILE_SHARE_READ)
@@ -716,10 +719,10 @@ namespace wil
716719 {
717720 for (auto const & info : create_next_entry_offset_iterator (reinterpret_cast <FILE_NOTIFY_INFORMATION *>(readerState->m_readBuffer )))
718721 {
719- wchar_t realtiveFileName [MAX_PATH];
720- StringCchCopyNW (realtiveFileName , ARRAYSIZE (realtiveFileName ), info.FileName , info.FileNameLength / sizeof (info.FileName [0 ]));
722+ wchar_t relativeFileName [MAX_PATH];
723+ StringCchCopyNW (relativeFileName , ARRAYSIZE (relativeFileName ), info.FileName , info.FileNameLength / sizeof (info.FileName [0 ]));
721724
722- readerState->m_callback (static_cast <FolderChangeEvent>(info.Action ), realtiveFileName );
725+ readerState->m_callback (static_cast <FolderChangeEvent>(info.Action ), relativeFileName );
723726 }
724727 }
725728 else if (result == ERROR_NOTIFY_ENUM_DIR)
@@ -1047,8 +1050,217 @@ namespace wil
10471050 THROW_IF_FAILED (GetFileInfoNoThrow<infoClass>(fileHandle, result));
10481051 return result;
10491052 }
1053+
1054+ // Helpers to make the CreateFileW API easier to use.
1055+ // https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-createfilew
1056+
1057+ struct file_and_error_result
1058+ {
1059+ file_and_error_result (HANDLE file_handle, DWORD error) : file(file_handle), last_error(error)
1060+ {
1061+ }
1062+
1063+ wil::unique_hfile file;
1064+ DWORD last_error{};
1065+ };
1066+
1067+ /* * Non-throwing open existing using OPEN_EXISTING.
1068+ ~~~
1069+ auto handle = wil::try_open_file(filePath.c_str());
1070+ ~~~
1071+ */
1072+ inline file_and_error_result try_open_file (PCWSTR path, DWORD dwDesiredAccess = FILE_READ_ACCESS,
1073+ DWORD dwShareMode = FILE_SHARE_READ, DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
1074+ bool inheritHandle = false ) noexcept
1075+ {
1076+ SECURITY_ATTRIBUTES secAttributes{ sizeof (secAttributes) };
1077+ secAttributes.bInheritHandle = inheritHandle;
1078+ auto handle = CreateFileW (path, dwDesiredAccess, dwShareMode, &secAttributes, OPEN_EXISTING, dwFlagsAndAttributes, nullptr );
1079+ return { handle, ::GetLastError () };
1080+ }
1081+
1082+ /* * open existing using OPEN_EXISTING, throws on error.
1083+ ~~~
1084+ auto handle = wil::open_file(filePath.c_str());
1085+ ~~~
1086+ */
1087+ inline wil::unique_hfile open_file (PCWSTR path, DWORD dwDesiredAccess = FILE_READ_ACCESS,
1088+ DWORD dwShareMode = FILE_SHARE_READ, DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
1089+ bool inheritHandle = false ) noexcept
1090+ {
1091+ auto result = try_open_file (path, dwDesiredAccess, dwShareMode, inheritHandle, dwFlagsAndAttributes);
1092+ THROW_WIN32_IF (result.last_error , !result.file .is_valid ());
1093+ return std::move (result.file );
1094+ }
1095+
1096+ // / @cond
1097+ namespace details
1098+ {
1099+ template <DWORD dwCreateDisposition>
1100+ file_and_error_result create_file (PCWSTR path, DWORD dwDesiredAccess,
1101+ DWORD dwShareMode,
1102+ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1103+ DWORD dwFlagsAndAttributes,
1104+ HANDLE hTemplateFile) noexcept
1105+ {
1106+ auto handle = CreateFileW (
1107+ path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreateDisposition, dwFlagsAndAttributes, hTemplateFile);
1108+ return { handle, ::GetLastError () };
1109+ }
1110+ }
1111+ // / @endcond
1112+
1113+
1114+ /* * create using CREATE_NEW, returns handle and error code.
1115+ ~~~
1116+ auto [handle, error = wil::try_create_new_file(filePath.c_str());
1117+ ~~~
1118+ */
1119+ inline file_and_error_result try_create_new_file (PCWSTR path,
1120+ DWORD dwDesiredAccess = FILE_READ_ACCESS | FILE_WRITE_ACCESS,
1121+ DWORD dwShareMode = FILE_SHARE_READ,
1122+ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr ,
1123+ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
1124+ HANDLE hTemplateFile = nullptr ) noexcept
1125+ {
1126+ return details::create_file<CREATE_NEW>(
1127+ path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes, hTemplateFile);
1128+ }
1129+
1130+ /* * create using OPEN_ALWAYS, returns handle and error code.
1131+ ~~~
1132+ auto [handle, error = wil::try_open_or_create_file(filePath.c_str());
1133+ ~~~
1134+ */
1135+ inline file_and_error_result try_open_or_create_file (PCWSTR path,
1136+ DWORD dwDesiredAccess = FILE_READ_ACCESS | FILE_WRITE_ACCESS,
1137+ DWORD dwShareMode = FILE_SHARE_READ,
1138+ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr ,
1139+ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
1140+ HANDLE hTemplateFile = nullptr ) noexcept
1141+ {
1142+ return details::create_file<OPEN_ALWAYS>(
1143+ path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes, hTemplateFile);
1144+ }
1145+
1146+ /* * create using CREATE_ALWAYS, returns handle and error code.
1147+ ~~~
1148+ auto [handle, error = wil::try_open_or_truncate_existing_file(filePath.c_str());
1149+ ~~~
1150+ */
1151+ inline file_and_error_result try_open_or_truncate_existing_file (PCWSTR path,
1152+ DWORD dwDesiredAccess = FILE_READ_ACCESS | FILE_WRITE_ACCESS,
1153+ DWORD dwShareMode = FILE_SHARE_READ,
1154+ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr ,
1155+ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
1156+ HANDLE hTemplateFile = nullptr ) noexcept
1157+ {
1158+ return details::create_file<CREATE_ALWAYS>(
1159+ path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes, hTemplateFile);
1160+ }
1161+
1162+ /* * create using TRUNCATE_EXISTING, returns handle and error code.
1163+ ~~~
1164+ auto [handle, error = wil::try_truncate_existing_file(filePath.c_str());
1165+ ~~~
1166+ */
1167+ inline file_and_error_result try_truncate_existing_file (PCWSTR path,
1168+ DWORD dwDesiredAccess = FILE_READ_ACCESS | FILE_WRITE_ACCESS | GENERIC_WRITE,
1169+ DWORD dwShareMode = FILE_SHARE_READ,
1170+ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr ,
1171+ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
1172+ HANDLE hTemplateFile = nullptr ) noexcept
1173+ {
1174+ return details::create_file<TRUNCATE_EXISTING>(
1175+ path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes, hTemplateFile);
1176+ }
1177+
1178+ /* * create using CREATE_NEW, returns the file handle, throws on error.
1179+ ~~~
1180+ auto handle = wil::create_new_file(filePath.c_str());
1181+ ~~~
1182+ */
1183+ inline wil::unique_hfile create_new_file (PCWSTR path,
1184+ DWORD dwDesiredAccess = FILE_READ_ACCESS | FILE_WRITE_ACCESS,
1185+ DWORD dwShareMode = FILE_SHARE_READ,
1186+ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr ,
1187+ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
1188+ HANDLE hTemplateFile = nullptr ) noexcept
1189+ {
1190+ auto result = try_create_new_file (
1191+ path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes, hTemplateFile);
1192+ THROW_WIN32_IF (result.last_error , !result.file .is_valid ());
1193+ return std::move (result.file );
1194+ }
1195+
1196+ /* * create using OPEN_ALWAYS, returns the file handle, throws on error.
1197+ ~~~
1198+ auto handle = wil::open_or_create_file(filePath.c_str());
1199+ ~~~
1200+ */
1201+ inline wil::unique_hfile open_or_create_file (PCWSTR path,
1202+ DWORD dwDesiredAccess = FILE_READ_ACCESS | FILE_WRITE_ACCESS,
1203+ DWORD dwShareMode = FILE_SHARE_READ,
1204+ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr ,
1205+ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
1206+ HANDLE hTemplateFile = nullptr ) noexcept
1207+ {
1208+ auto result = try_open_or_create_file (
1209+ path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes, hTemplateFile);
1210+ THROW_WIN32_IF (result.last_error , !result.file .is_valid ());
1211+ return std::move (result.file );
1212+ }
1213+
1214+ /* * create using CREATE_ALWAYS, returns the file handle, throws on error.
1215+ ~~~
1216+ auto handle = wil::open_or_truncate_existing_file(filePath.c_str());
1217+ ~~~
1218+ */
1219+ inline wil::unique_hfile open_or_truncate_existing_file (PCWSTR path,
1220+ DWORD dwDesiredAccess = FILE_READ_ACCESS | FILE_WRITE_ACCESS,
1221+ DWORD dwShareMode = FILE_SHARE_READ,
1222+ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr ,
1223+ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
1224+ HANDLE hTemplateFile = nullptr ) noexcept
1225+ {
1226+ auto result = try_open_or_truncate_existing_file (
1227+ path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes, hTemplateFile);
1228+ THROW_WIN32_IF (result.last_error , !result.file .is_valid ());
1229+ return std::move (result.file );
1230+ }
1231+
1232+ /* * create using TRUNCATE_EXISTING, returns the file handle, throws on error.
1233+ ~~~
1234+ auto handle = wil::truncate_existing_file(filePath.c_str());
1235+ ~~~
1236+ */
1237+ inline wil::unique_hfile truncate_existing_file (PCWSTR path,
1238+ DWORD dwDesiredAccess = FILE_READ_ACCESS | FILE_WRITE_ACCESS,
1239+ DWORD dwShareMode = FILE_SHARE_READ,
1240+ LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr ,
1241+ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,
1242+ HANDLE hTemplateFile = nullptr ) noexcept
1243+ {
1244+ auto result = try_truncate_existing_file (
1245+ path, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwFlagsAndAttributes, hTemplateFile);
1246+ THROW_WIN32_IF (result.last_error , !result.file .is_valid ());
1247+ return std::move (result.file );
1248+ }
1249+
10501250#endif // _CPPUNWIND
10511251#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && (_WIN32_WINNT >= _WIN32_WINNT_WIN7)
10521252}
10531253
1254+ #ifndef WIL_NO_FILE_TYPE_OPERATORS
1255+ inline bool operator ==(const FILE_ID_128& left, const FILE_ID_128& right)
1256+ {
1257+ return memcmp (&left, &right, sizeof (left)) == 0 ;
1258+ }
1259+
1260+ inline bool operator !=(const FILE_ID_128& left, const FILE_ID_128& right)
1261+ {
1262+ return !operator ==(left, right);
1263+ }
1264+ #endif
1265+
10541266#endif // __WIL_FILESYSTEM_INCLUDED
0 commit comments