提交 9201390a 编写于 作者: R Richard Stanway

UI/updater: Move in-use files away before writing

On a modern Windows OS, you can rename an in-use file despite not being
able to write to it. With the introduction of the virtual camera, it is
now quite common that users will have in-use files when updating. This
commit renames in-use files, allowing the new version to be installed.
Upon a reboot, the previously in-use file will be deleted.
上级 c0d7602b
......@@ -786,6 +786,41 @@ static void UpdateWithPatchIfAvailable(const char *name, const char *hash,
}
}
static bool MoveInUseFileAway(update_t &file)
{
_TCHAR deleteMeName[MAX_PATH];
_TCHAR randomStr[MAX_PATH];
BYTE junk[40];
BYTE hash[BLAKE2_HASH_LENGTH];
CryptGenRandom(hProvider, sizeof(junk), junk);
blake2b(hash, sizeof(hash), junk, sizeof(junk), NULL, 0);
HashToString(hash, randomStr);
randomStr[8] = 0;
StringCbCopy(deleteMeName, sizeof(deleteMeName),
file.outputPath.c_str());
StringCbCat(deleteMeName, sizeof(deleteMeName), L".");
StringCbCat(deleteMeName, sizeof(deleteMeName), randomStr);
StringCbCat(deleteMeName, sizeof(deleteMeName), L".deleteme");
if (MoveFile(file.outputPath.c_str(), deleteMeName)) {
if (MyCopyFile(deleteMeName, file.outputPath.c_str())) {
MoveFileEx(deleteMeName, NULL,
MOVEFILE_DELAY_UNTIL_REBOOT);
return true;
} else {
MoveFile(deleteMeName, file.outputPath.c_str());
}
}
return false;
}
static bool UpdateFile(update_t &file)
{
wchar_t oldFileRenamedPath[MAX_PATH];
......@@ -838,6 +873,9 @@ static bool UpdateFile(update_t &file)
int error_code;
bool installed_ok;
bool already_tried_to_move = false;
retryAfterMovingFile:
if (file.patchable) {
error_code = ApplyPatch(file.tempPath.c_str(),
......@@ -877,15 +915,23 @@ static bool UpdateFile(update_t &file)
int is_sharing_violation =
(error_code == ERROR_SHARING_VIOLATION);
if (is_sharing_violation)
if (is_sharing_violation) {
if (!already_tried_to_move) {
already_tried_to_move = true;
if (MoveInUseFileAway(file))
goto retryAfterMovingFile;
}
Status(L"Update failed: %s is still in use. "
L"Close all "
L"programs and try again.",
curFileName);
else
} else {
Status(L"Update failed: Couldn't update %s "
L"(error %d)",
curFileName, GetLastError());
}
file.state = STATE_INSTALL_FAILED;
return false;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册