Okay, I have had some time to look into this issue a little more. Some observations:
1) I just noticed that the bug report states that both mirc.ini and servers.ini were empty after a BSOD. However, mIRC can update only one file at a time. If mIRC had been terminated half way through a DeleteFile/MoveFile, it should have affected only one file.
2) I came across the following reports where using ReplaceFile() and MoveFileEx() still resulted in corrupt files after a BSOD or power failure:http://stackoverflow.com/questions/31710431/how-to-reliably-overwrite-a-file-in-windowshttp://stackoverflow.com/questions/6525943/cause-of-corrupted-file-contents
As the point of switching to ReplaceFile() is to resolve this issue, I decided to do a little more testing.
I created a version of mIRC that supports the following modes for replacing files, set by a command line switch when mIRC is run:
mode0 Original DeleteFile()/MoveFile().
mode1 ReplaceFile() (with backup file and REPLACEFILE_IGNORE_MERGE_ERRORS | REPLACEFILE_WRITE_THROUGH).
mode2 MoveFileEx() (with MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH).
mode3 Alternative to mode0 that renames the original mirc.ini to a temporary file, renames the replacement to mirc.ini, and then deletes the original.
I then created a perl script that repeatedly runs mIRC in each mode. When mIRC starts, it repeatedly updates mirc.ini using the mode specified on the command line. The perl script waits for one second and then forcefully terminates mIRC. It then checks to see if mirc.ini still exists and if its size matches a reference file. If mirc.ini is lost or corrupted, it is reset to the reference file.
lost: number of times mirc.ini was lost.
min: shortest number of runs before mirc.ini was lost.
max: longest number of runs before mirc.ini was lost.
mean: average number of runs before mirc.ini was lost.
When mIRC is set to update mirc.ini 150 times a second, the results after 3500 runs (per mode) were:
mode0 lost:328 min:1 max:52 mean:11 loss rate:9.37%
mode1 lost:133 min:1 max:93 mean:26 loss rate:3.80%
mode2 lost:0 min:0 max:0 mean:0 loss rate:0.00%
mode3 lost:182 min:1 max:128 mean:19 loss rate:5.20%
When mIRC is set to update mirc.ini 50 times a second, the results after 3500 runs (per mode) were:
mode0 lost:120 min:1 max:203 mean:29 loss rate:3.43%
mode1 lost:67 min:1 max:196 mean:52 loss rate:1.91%
mode2 lost:1 min:1098 max:1098 mean:1098 loss rate:0.03%
mode3 lost:66 min:1 max:244 mean:53 loss rate:1.89%
When mIRC is set to update mirc.ini 10 times a second, the results after 3500 runs (per mode) were:
mode0 lost:30 min:11 max:432 mean:114 loss rate:0.86%
mode1 lost:16 min:4 max:701 mean:179 loss rate:0.46%
mode2 lost:0 min:0 max:0 mean:0 loss rate:0.00%
mode3 lost:15 min:18 max:1061 mean:230 loss rate:0.43%
mIRC normally only updates mirc.ini once or twice a second.
1) The test was performed on Windows 7 with an SSD, so the results are likely to be different on other versions of Windows and on slower, non-SSD drives.
2) The results are unlikely to be applicable to a BSOD or power failure situation, where OS-level caching and drive-level caching are involved, eg. some drives tell the OS that the data has been committed to disk when it is actually still in the drive cache.
3) Mode2 showed almost no file loss. The perl script and implementation in mIRC were checked and looked correct. This appears to be a valid result. The results were the same without MOVEFILE_WRITE_THROUGH for MoveFileEx() and without REPLACEFILE_WRITE_THROUGH for ReplaceFile(), which the documentation says is not supported. The effects of the write-through options might only be apparent on slower, non-SSD drives.
4) When anti-virus software is enabled, ReplaceFile() becomes inceasingly slower than the other modes as the replacement file size increases. With a replacement exe file of 5MB in size, it was ten times slower. Anti-virus software also occasionally locked files and prevented a file replace from completing. The above tests were performed with anti-virus disabled.
5) In both mode0 and mode3, there is a moment when mirc.ini does not exist. However, mode0 performs a delete first, which is more involved due to the DeleteFile() pending issue
, and then a rename, while mode3 performs two successive renames, which are much faster, and then a delete. This is probably why mode3 performs at about the same level as ReplaceFile() at lower update rates.
Overall, it looks like using MoveFileEx() is the best option. However, as other software developers who use it still see file loss in a BSOD or power failure situation, it is not clear how much it will help in those contexts. I will be releasing a beta with this change for testing soon.