`GetConsoleMode` can fail with `ERROR_INVALID_HANDLE` when redirecting output to `nul`, which is considered a character file but cannot be used as a console.
The function `fs_makedir_rec_for` for recursively creating folders did not handle paths containing backslashes correctly and only created folders after every occurrence of a regular slash. This could cause the recursive folder creation to fail when a parent folder is not created before the child folder. For example when recursively creating folders for the path `D:\Games/DDNet\downloadedskins`, the `DDNet` folder was not being created because this path segment does not end in a forward slash. Now, backslashes are handled the same as regular slashes, which is consistent with the other filesystem functions.
Additionally, the function tried to create folders for drive letters on Windows (e.g. `C:` and `D:`). Trying to create a system drive as a folder will fail due to access being denied, whereas it seems to work for already existing non-system drives. For example when recursively creating folders for the path `C:/Games/DDNet/downloadedskins`, the `C:` "folder" could not be created which caused the entire operation to fail. Now, the function will not try to create folders for drive letters anymore, i.e. if the name of the to be created folder ends with `:`.
Closes#8148.
Instead of defining the macro `WIN32_LEAN_AND_MEAN` and sometimes also the macro `_WIN32_WINNT` in each file that directly or indirectly includes `<windows.h>`, only define these macros once consistently in `CMakeLists.txt`.
Also define `NTDDI_VERSION`, which is the new macro to specify the minimum Windows version starting with Windows Vista. This macro needs to be defined in addition to old `_WIN32_WINNT` macro, according to the documentation.
See https://learn.microsoft.com/en-us/windows/win32/winprog/using-the-windows-headers
Assert on failures in all `thread_*` and `sphore_*` functions on all operating systems instead of only printing log messages on Unix, as these functions are only expected to fail when used with incorrect arguments or in some cases when a dead-lock is detected.
On macOS, `sphore_wait` was not correctly calling `sem_wait` in a loop to repeat the wait operation if it is interrupted by a signal.
On Windows, the AIO tests were failing with the additional assertions. The maximum count that semaphores on Windows could be incremented to was previously, arbitrarily limited to 10000, which was causing the `ReleaseSemaphore` call to fail as the AIO semaphore is signaled 65536 times (for each write operation) in multiple of the AIO tests.
Add/update doxygen comments for all `shell_*`, `os_*`, `secure_*`, `cmdline_*`, `windows_*` and related functions.
Move `open_link` and `open_file` declarations to shell group, to the same relative position as their function definitions.
Add parameter to `shell_execute` to either start the process in the foreground or background on Windows. Previously, all processes were started in the background, because this is desired when starting the server from the client. However, this causes the graphics initialization to fail when restarting the client after updating or with the `restart` command when using Vulkan with windowed and windowed fullscreen mode.
Closes#6578.
Use [virtual terminal processing](https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences) for Windows console output when possible, using the existing async logger. Fallback to the old Windows logger when virtual terminal processing is not available. Do not set any logger when there is no console/file/pipe to output to.
This adds support for 24 bit RGB colors using ANSI escape codes (when Terminal emulator supports it) instead of only supporting 16 fixed colors.
Use the existing async logger also on Windows by converting the console standard output handle to an IOHANDLE. Avoid converting console output to UTF-16 by changing the console output codepage to UTF-8 and outputting that directly. Overall, this reduces the time until the loading screen first appears when launching the client from the console on Windows by around 70%, from 80-100ms down to 25ms.
Add support for `NO_COLOR` environment variable also on Windows.
Use the async logger also for writing output to files and pipes instead of using a Windows specific implementation for this, to reduce lags when redirecting the standard output.
Closes#3925. The client/server will not freeze anymore when entering selection mode in the console because we are using the async logger on Windows now.
Closes#1108. We were already using AIO on Windows to write the logfile, which was not causing any known issues. We are now also using AIO with the async loggers for console/files/pipes on Windows.
On Windows, the result of the `localtime` function is thread-local, hence our uses of this function are already thread-safe.
On non-Windows, the `localtime` function is potentially not thread-safe, so the reentrant `localtime_r` function is used instead with a thread-local buffer for the result.
Closes#7788.
Files were not being truncated on Windows anymore when using `io_open` with `IOFLAG_WRITE` due to a regression from #7254. Instead, the existing file contents were kept and the file pointer was set to the beginning of the file.
This caused broken demo files to be created (#7349) when recording a shorter demo with the same filename as an existing longer demo. It also caused the map tools to produce maps with additional junk data at the end, if an existing map is overridden by a smaller map.
This is fixed by using the creation disposition `CREATE_ALWAYS` instead of `OPEN_EXISTING` with [`CreateFileW`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew), which ensures that a file is always created and truncated.
A regression test case is added, which fails without this change.
We support little and big endian but not PDP endian (Middle-endian).
Define endianness as string `CONF_ARCH_ENDIAN_STRING` to avoid conditional compilation when printing endianness.
On Windows the function `setsockopt` does not set `errno` on errors but instead `WSAGetLastError` must be used. This is encapsulated in the `net_errno` function.
Additionally, ensure snapshots are cleared and dummy is disconnected when disconnecting programatically with `DisconnectWithReason`.
Add `NETADDR_ZEROED` and `UUID_ZEROED` for more convenient initialization without using `mem_zero`.
Add stricter error handling when converting between UTF-16 (wide characters) and UTF-8 (multi-byte) on Windows.
The `windows_wide_to_utf8` function now returns an `std::optional`, which will be empty if the argument contains invalid UTF-16. Files/folders with names containing invalid UTF-16 are now ignored on Windows. It was previously not possible to use these files either, as converting their names to UTF-8 changed the invalid codepoints to unicode replacement characters.
The `windows_utf8_to_wide` function now fails with an assertion error if the argument contains invalid UTF-8, as this should never happen.
Closes#7486.
Initialize nontrivial types with a constructor instead. Make the
compiler aware that some of our constructors are indeed trivial.
This allows `mem_zero` calls to actually always zero the memory.
Partially replaces #5690.
POD types are just memset. Other types are either destructed if not
trivial and/or constructed if not trivial. Types need to have a default
constructor.
Virtual classes can be mem_zeroed only if they already have been
constructed, otherwise it is UB.
On Unix, the encoding of filenames is unspecified, although UTF-8 is likely used in most cases. Detecting and converting from several possible encodings to UTF-8 would be too much effort, considering that most systems already use UTF-8 per default. Therefore, any filenames which are not valid UTF-8 will be ignored when listing directories with `fs_listdir(_fileinfo)`, `fs_storage_path` will fail if the storage location is not valid UTF-8 and `fs_getcwd` will fail if the current working directory is not valid UTF-8. Paths specified in `storage.cfg` must also be valid UTF-8.
On Windows, we already ensure that all filenames are converted to UTF-8.
Use `CLock` and `CLockScope` instead of `std::mutex` and add clang thread-safety analysis annotations everywhere except for usages in engine graphics and video, as those usages also involve `std::condition_variable`.
Fix lock not being unlocked on all code paths in `CFutureLogger::Log`, which is caught by the static analysis.
Replace usages of platform specific `lock_*` functions with `std::mutex` through the wrapper class `CLock`. Move lock classes to `base/lock.h`.
The `CLock` wrapper class is only necessary because the clang thread-safety attributes are not available for `std::mutex` except when explicitly using libc++.
Round to nearest integer instead of truncating in `f2fx` to ensure correct round-trip with `fx2f`.
Add test to ensure correct round-trip with maximum `0.0005f` absolute error.
After the error message popup is shown for graphics assertions, the client window was destroyed but the process was not terminated properly. Now the graphics assertion error is handled like a normal assertion error, as those are also shown in an error message popup and correctly cause the client to break into the debugger or terminate.
However, calling `dbg_assert` while already owning the lock that `WaitForIdle` waits on will cause a deadlock, so error handling must be delayed until after the lock is released.
The buffer size for assertion messages is increased, as it was not sufficient for some graphics assertions.
The `ICommandProcessor::GetError` and `ICommandProcessor::GetWarning` functions are marked as `const`.
Add easter, halloween and xmas to `enum ETimeSeason` and `time_season` function. This unifies the logic for detecting these events and seasons in one function. This allows adding support for special easter, halloween and xmas theme maps in the future. The `localtime` function is not used outside `system.c` anymore. The code for detecting easter is taken from upstream.
The function returns 0 on success and -1 on error, as it delegates to `io_seek`, instead of returning the number of bytes skipped, which the documentation previously suggested. The return type is changed from `unsigned` to `int`, as this is also the type of `io_seek` and this better handles -1 as a return value.
The TODO in the `Dilate` function is removed, as the code already appears to be safe without additional checks. The variable `k` is at most `(w * h - 1) * BPP`, as `ix` and `iy` are clamped to maximum `w - 1` and `h - 1` respectively. Because `p < BPP - 1` the index `k + p` is therefore always valid for the buffers. (The caller must ensure that the source and destination buffers are of size `w * h * BPP`.)