/* * Implementation of open_for_write_would_lose_data for Windows. */ #include "putty.h" /* * This is slightly fiddly because we want to be backwards-compatible * with systems too old to have GetFileAttributesEx. The next best * thing is FindFirstFile, which will return a different data * structure, but one that also contains the fields we want. (But it * will behave more unhelpfully - for this application - in the * presence of wildcards, so we'd prefer to use GFAE if we can.) */ static inline bool open_for_write_would_lose_data_impl( DWORD dwFileAttributes, DWORD nFileSizeHigh, DWORD nFileSizeLow) { if (dwFileAttributes & (FILE_ATTRIBUTE_DEVICE|FILE_ATTRIBUTE_DIRECTORY)) { /* * File is something other than an ordinary disk file, so * opening it for writing will not cause truncation. (It may * not _succeed_ either, but that's not our problem here!) */ return false; } if (nFileSizeHigh == 0 && nFileSizeLow == 0) { /* * File is zero-length (or may be a named pipe, which * dwFileAttributes can't tell apart from a regular file), so * opening it for writing won't truncate any data away because * there's nothing to truncate anyway. */ return false; } return true; } bool open_for_write_would_lose_data(const Filename *fn) { static HMODULE kernel32_module; DECL_WINDOWS_FUNCTION(static, BOOL, GetFileAttributesExA, (LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID)); if (!kernel32_module) { kernel32_module = load_system32_dll("kernel32.dll"); GET_WINDOWS_FUNCTION(kernel32_module, GetFileAttributesExA); } if (p_GetFileAttributesExA) { WIN32_FILE_ATTRIBUTE_DATA attrs; if (!p_GetFileAttributesExA(fn->path, GetFileExInfoStandard, &attrs)) { /* * Generally, if we don't identify a specific reason why we * should return true from this function, we return false, and * let the subsequent attempt to open the file for real give a * more useful error message. */ return false; } return open_for_write_would_lose_data_impl( attrs.dwFileAttributes, attrs.nFileSizeHigh, attrs.nFileSizeLow); } else { WIN32_FIND_DATA fd; HANDLE h = FindFirstFile(fn->path, &fd); if (h == INVALID_HANDLE_VALUE) { /* * As above, if we can't find the file at all, return false. */ return false; } CloseHandle(h); return open_for_write_would_lose_data_impl( fd.dwFileAttributes, fd.nFileSizeHigh, fd.nFileSizeLow); } }