Skip to content

Commit dbd7ffb

Browse files
committed
installer: make sure we can delete files after killing processes
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
1 parent 49bb125 commit dbd7ffb

1 file changed

Lines changed: 39 additions & 9 deletions

File tree

installer/customactions.c

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,22 @@ __declspec(dllexport) UINT __stdcall EvaluateWireGuardComponents(MSIHANDLE insta
366366
return ret == ERROR_SUCCESS ? ret : ERROR_INSTALL_FAILURE;
367367
}
368368

369+
static bool can_open_for_deletion(const TCHAR *path)
370+
{
371+
bool ret;
372+
FILE_DISPOSITION_INFO di = { .DeleteFile = TRUE };
373+
HANDLE file = CreateFile(path, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
374+
if (file == INVALID_HANDLE_VALUE)
375+
return GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME;
376+
ret = SetFileInformationByHandle(file, FileDispositionInfo, &di, sizeof(di));
377+
if (ret) {
378+
di.DeleteFile = FALSE;
379+
SetFileInformationByHandle(file, FileDispositionInfo, &di, sizeof(di));
380+
}
381+
CloseHandle(file);
382+
return ret;
383+
}
384+
369385
struct file_id { DWORD volume, index_high, index_low; };
370386

371387
static bool calculate_file_id(const TCHAR *path, struct file_id *id)
@@ -391,9 +407,9 @@ __declspec(dllexport) UINT __stdcall KillWireGuardProcesses(MSIHANDLE installer)
391407
{
392408
HANDLE snapshot, process;
393409
PROCESSENTRY32 entry = { .dwSize = sizeof(PROCESSENTRY32) };
394-
TCHAR process_path[MAX_PATH], executable[MAX_PATH];
395-
DWORD process_path_len = _countof(process_path);
396-
struct file_id file_ids[3], file_id;
410+
TCHAR process_path[MAX_PATH], executables[2][MAX_PATH];
411+
DWORD process_path_len = _countof(process_path), tries = 0;
412+
struct file_id file_ids[2], file_id;
397413
size_t file_ids_len = 0;
398414
bool is_com_initialized = SUCCEEDED(CoInitialize(NULL)), have_killed;
399415
LSTATUS mret;
@@ -408,10 +424,13 @@ __declspec(dllexport) UINT __stdcall KillWireGuardProcesses(MSIHANDLE installer)
408424

409425
log_messagef(installer, LOG_LEVEL_INFO, TEXT("Detecting running processes"));
410426

411-
if (PathCombine(executable, process_path, TEXT("wg.exe")) && calculate_file_id(executable, &file_ids[file_ids_len]))
412-
++file_ids_len;
413-
if (PathCombine(executable, process_path, TEXT("wireguard.exe")) && calculate_file_id(executable, &file_ids[file_ids_len]))
414-
++file_ids_len;
427+
if (!PathCombine(executables[0], process_path, TEXT("wg.exe")) ||
428+
!PathCombine(executables[1], process_path, TEXT("wireguard.exe")))
429+
goto out;
430+
for (size_t i = 0; i < _countof(executables); ++i) {
431+
if (calculate_file_id(executables[i], &file_ids[file_ids_len]))
432+
++file_ids_len;
433+
}
415434
if (!file_ids_len)
416435
goto out;
417436

@@ -445,14 +464,25 @@ __declspec(dllexport) UINT __stdcall KillWireGuardProcesses(MSIHANDLE installer)
445464
WaitForSingleObject(process, INFINITE);
446465
log_messagef(installer, LOG_LEVEL_INFO, TEXT("Killed \"%1\" (pid %2!d!)"), process_path, entry.th32ProcessID);
447466
have_killed = true;
448-
}
467+
} else
468+
log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("Unable to kill \"%1\" (pid %2!d!)"), process_path, entry.th32ProcessID);
449469
next:
450470
CloseHandle(process);
451471
}
452472
CloseHandle(snapshot);
453473
if (have_killed)
454474
goto retry;
455-
475+
for (size_t i = 0; i < _countof(executables); ++i) {
476+
if (!can_open_for_deletion(executables[i])) {
477+
if (++tries > 50) {
478+
log_messagef(installer, LOG_LEVEL_WARN, TEXT("File \"%1\" is still open"), executables[i]);
479+
continue;
480+
}
481+
log_messagef(installer, LOG_LEVEL_INFO, TEXT("File \"%1\" is still open, sleeping and retrying"), executables[i]);
482+
Sleep(100);
483+
goto retry;
484+
}
485+
}
456486
out:
457487
if (is_com_initialized)
458488
CoUninitialize();

0 commit comments

Comments
 (0)