24#include <wx/filename.h>
43#if !defined( __MINGW32__ )
67#define FileFullDirectoryInformation ( (FILE_INFORMATION_CLASS) 2 )
74#if defined( _MSC_VER ) || !defined( USE_MSYS2_FALLBACK )
77 HANDLE hFile = INVALID_HANDLE_VALUE;
78 hFile = CreateFileW( aPath.wc_str(),
83 FILE_FLAG_SEQUENTIAL_SCAN,
86 if (hFile == INVALID_HANDLE_VALUE)
91 int fd = _open_osfhandle(
reinterpret_cast<intptr_t
>( hFile ), 0 );
100 FILE* fp = _fdopen( fd, aMode.c_str() );
111 return wxFopen( aPath, aMode );
121 const SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
129 GetFileSecurityW( aSrc.wc_str(), secInfo,
nullptr, 0, &dwSize );
131 if( dwSize == 0 || GetLastError() != ERROR_INSUFFICIENT_BUFFER )
134 std::vector<BYTE> sdBuffer( dwSize );
135 PSECURITY_DESCRIPTOR pSD =
static_cast<PSECURITY_DESCRIPTOR
>( sdBuffer.data() );
137 return GetFileSecurityW( aSrc.wc_str(), secInfo, pSD, dwSize, &dwSize )
138 && SetFileSecurityW( aDest.wc_str(), secInfo, pSD );
143 DWORD attrs = GetFileAttributesW( aFilePath.wc_str() );
145 if( attrs == INVALID_FILE_ATTRIBUTES )
151 DWORD attrsToRemove = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN;
153 if( attrs & attrsToRemove )
155 attrs &= ~attrsToRemove;
156 return SetFileAttributesW( aFilePath.wc_str(), attrs ) != 0;
164 TARGET_ATTRS snapshot;
165 DWORD attrs = GetFileAttributesW( aPath.wc_str() );
167 if( attrs == INVALID_FILE_ATTRIBUTES )
173 snapshot.value =
static_cast<std::uint32_t
>( attrs )
174 & ( FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN );
175 snapshot.captured =
true;
182 if( !aAttrs.captured )
185 DWORD current = GetFileAttributesW( aPath.wc_str() );
187 if( current == INVALID_FILE_ATTRIBUTES )
190 DWORD merged = current |
static_cast<DWORD
>( aAttrs.value );
192 if( merged == current )
195 return SetFileAttributesW( aPath.wc_str(), merged ) != 0;
200 const wxString& aMode, wxString* aTempPathOut,
205 for(
unsigned attempt = 0; attempt < 32; ++attempt )
208 HANDLE h = CreateFileW( candidate.wc_str(), GENERIC_WRITE, 0,
nullptr, CREATE_NEW,
209 FILE_ATTRIBUTE_NORMAL,
nullptr );
211 if( h != INVALID_HANDLE_VALUE )
213 int fd = _open_osfhandle(
reinterpret_cast<intptr_t
>( h ), _O_WRONLY | _O_BINARY );
218 DeleteFileW( candidate.wc_str() );
222 *aError = wxString::Format( wxT(
"_open_osfhandle failed for '%s'" ),
229 FILE* fp = _wfdopen( fd, aMode.wc_str() );
234 DeleteFileW( candidate.wc_str() );
237 *aError = wxString::Format( wxT(
"_wfdopen failed for '%s'" ), candidate );
243 *aTempPathOut = candidate;
248 DWORD err = GetLastError();
250 if( err != ERROR_FILE_EXISTS && err != ERROR_ALREADY_EXISTS )
253 *aError = wxString::Format( wxT(
"CreateFile failed for '%s' (Win32 %lu)" ),
261 *aError = wxT(
"Exhausted temp-file retry budget" );
281 if( ( GetFileAttributesW( aFileName.fn_str() ) & FILE_ATTRIBUTE_HIDDEN ) )
294 if( aFilename.GetVolume().Length() == 1 )
296 aFilename.SetVolume(
"\\\\?\\" + aFilename.GetVolume() +
":" );
297 else if( aFilename.GetVolume().Length() > 1
298 && aFilename.GetVolume().StartsWith( wxT(
"\\\\" ) )
299 && !aFilename.GetVolume().StartsWith( wxT(
"\\\\?" ) ) )
304 aFilename.SetVolume(
"\\\\?\\UNC" + aFilename.GetVolume().Mid( 1 ) );
305 else if( aFilename.GetVolume().StartsWith( wxT(
"\\\\?" ) )
306 && aFilename.GetDirs().size() >= 2
307 && aFilename.GetDirs()[0] ==
"UNC" )
313 aFilename.SetVolume(
"\\\\?\\UNC\\" + aFilename.GetDirs()[1] );
314 aFilename.RemoveDir( 0 );
315 aFilename.RemoveDir( 0 );
322 long long timestamp = 0;
327 static PFN_NtQueryDirectoryFile pNtQueryDirectoryFile =
nullptr;
329 if( !pNtQueryDirectoryFile )
331 HMODULE ntdll = GetModuleHandleW(
L"ntdll.dll" );
335 pNtQueryDirectoryFile =
336 (PFN_NtQueryDirectoryFile) GetProcAddress( ntdll,
"NtQueryDirectoryFile" );
340 if( !pNtQueryDirectoryFile )
343 std::wstring dirPath( aDirPath.t_str() );
345 if( !dirPath.empty() && dirPath.back() !=
L'\\' )
351 if( dirPath.size() >= 2 && dirPath[0] ==
L'\\' && dirPath[1] ==
L'\\' )
353 if( dirPath.size() >= 4 && dirPath[2] ==
L'?' && dirPath[3] ==
L'\\' )
361 ntPath =
L"\\\\?\\UNC\\" + dirPath.substr( 2 );
367 ntPath =
L"\\\\?\\" + dirPath;
370 HANDLE hDir = CreateFileW( ntPath.c_str(), FILE_LIST_DIRECTORY,
371 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr,
372 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
nullptr );
374 if( hDir == INVALID_HANDLE_VALUE )
377 std::wstring pattern( aFilespec.t_str() );
380 alignas(
sizeof( LONGLONG ) )
char buffer[64 * 1024];
382 IO_STATUS_BLOCK iosb;
384 bool firstQuery =
true;
388 status = pNtQueryDirectoryFile( hDir,
nullptr,
nullptr,
nullptr, &iosb, buffer,
390 nullptr, firstQuery ? TRUE : FALSE );
405 && PathMatchSpecW( fileName.c_str(), pattern.c_str() ) )
430 if( std::fflush( aFp ) != 0 )
433 int fd = _fileno( aFp );
438 HANDLE h =
reinterpret_cast<HANDLE>( _get_osfhandle( fd ) );
440 if( h == INVALID_HANDLE_VALUE )
443 return FlushFileBuffers( h ) != 0;
465 for(
int attempt = 0; attempt < 10; ++attempt )
467 if( MoveFileExW( aSrc.wc_str(), aDst.wc_str(),
468 MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH ) )
471 lastError = GetLastError();
473 if( lastError != ERROR_SHARING_VIOLATION && lastError != ERROR_ACCESS_DENIED
474 && lastError != ERROR_LOCK_VIOLATION )
482 if( ReplaceFileW( aDst.wc_str(), aSrc.wc_str(),
nullptr, REPLACEFILE_WRITE_THROUGH,
nullptr,
486 DWORD fallbackError = GetLastError();
490 wchar_t* msg =
nullptr;
491 FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
492 | FORMAT_MESSAGE_IGNORE_INSERTS,
493 nullptr, fallbackError ? fallbackError : lastError,
494 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
reinterpret_cast<LPWSTR
>( &msg ),
499 *aError = wxString( msg );
504 *aError = wxString::Format( wxT(
"Win32 error %lu" ), fallbackError ? fallbackError
515 m_fileHandle = CreateFileW( aFileName.wc_str(), GENERIC_READ, FILE_SHARE_READ,
516 nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
nullptr );
518 if( m_fileHandle == INVALID_HANDLE_VALUE )
520 m_fileHandle =
nullptr;
521 throw std::runtime_error( std::string(
"Cannot open file: " )
522 + aFileName.ToStdString() );
525 LARGE_INTEGER fileSize;
527 if( !GetFileSizeEx( m_fileHandle, &fileSize ) )
529 CloseHandle( m_fileHandle );
530 m_fileHandle =
nullptr;
531 throw std::runtime_error( std::string(
"Cannot determine file size: " )
532 + aFileName.ToStdString() );
535 m_size =
static_cast<size_t>( fileSize.QuadPart );
539 CloseHandle( m_fileHandle );
540 m_fileHandle =
nullptr;
544 m_mapHandle = CreateFileMappingW( m_fileHandle,
nullptr, PAGE_READONLY, 0, 0,
nullptr );
548 CloseHandle( m_fileHandle );
549 m_fileHandle =
nullptr;
554 void* ptr = MapViewOfFile( m_mapHandle, FILE_MAP_READ, 0, 0, 0 );
558 CloseHandle( m_mapHandle );
559 m_mapHandle =
nullptr;
560 CloseHandle( m_fileHandle );
561 m_fileHandle =
nullptr;
566 m_data =
static_cast<const uint8_t*
>( ptr );
572 if( m_data && m_mapHandle )
573 UnmapViewOfFile( m_data );
576 CloseHandle( m_mapHandle );
579 CloseHandle( m_fileHandle );
wxString result
Test unit parsing edge cases and error handling.
typedef FILE_INFORMATION_CLASS
struct _FILE_FULL_DIR_INFORMATION FILE_FULL_DIR_INFORMATION
typedef NTSTATUS(NTAPI *PFN_NtQueryDirectoryFile)(HANDLE
struct _FILE_FULL_DIR_INFORMATION * PFILE_FULL_DIR_INFORMATION
#define FileFullDirectoryInformation