diff options
| author | 2026-04-18 22:58:31 +0200 | |
|---|---|---|
| committer | 2026-04-19 15:47:50 +0200 | |
| commit | e50b710dae42a442607d9409d113f4f1367082da (patch) | |
| tree | c26aa6d89e68818c53516cb8a6a87d5e04dd281e /installer | |
| parent | installer: don't follow reparse points when computing file IDs (diff) | |
| download | wireguard-windows-master.tar.xz wireguard-windows-master.zip | |
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'installer')
| -rw-r--r-- | installer/customactions.c | 79 |
1 files changed, 62 insertions, 17 deletions
diff --git a/installer/customactions.c b/installer/customactions.c index 634597dd..8006815a 100644 --- a/installer/customactions.c +++ b/installer/customactions.c @@ -366,11 +366,33 @@ out: return ret == ERROR_SUCCESS ? ret : ERROR_INSTALL_FAILURE; } +static bool can_be_deleted(const TCHAR *path) +{ + FILE_DISPOSITION_INFO di = { .DeleteFile = TRUE }; + DWORD last_error; + HANDLE file; + bool ret; + + file = CreateFile(path, DELETE, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + if (file == INVALID_HANDLE_VALUE) + return GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME; + ret = SetFileInformationByHandle(file, FileDispositionInfo, &di, sizeof(di)); + last_error = GetLastError(); + if (ret) { + di.DeleteFile = FALSE; + SetFileInformationByHandle(file, FileDispositionInfo, &di, sizeof(di)); + } + CloseHandle(file); + SetLastError(last_error); + return ret; +} + struct file_id { DWORD volume, index_high, index_low; }; static bool calculate_file_id(const TCHAR *path, struct file_id *id) { BY_HANDLE_FILE_INFORMATION file_info = { 0 }; + DWORD last_error; HANDLE file; bool ret; @@ -378,22 +400,22 @@ static bool calculate_file_id(const TCHAR *path, struct file_id *id) if (file == INVALID_HANDLE_VALUE) return false; ret = GetFileInformationByHandle(file, &file_info); + last_error = GetLastError(); CloseHandle(file); - if (!ret) - return false; id->volume = file_info.dwVolumeSerialNumber; id->index_high = file_info.nFileIndexHigh; id->index_low = file_info.nFileIndexLow; - return true; + SetLastError(last_error); + return ret; } __declspec(dllexport) UINT __stdcall KillWireGuardProcesses(MSIHANDLE installer) { HANDLE snapshot, process; PROCESSENTRY32 entry = { .dwSize = sizeof(PROCESSENTRY32) }; - TCHAR process_path[MAX_PATH], executable[MAX_PATH]; - DWORD process_path_len = _countof(process_path); - struct file_id file_ids[3], file_id; + TCHAR process_path[MAX_PATH], executables[2][MAX_PATH]; + DWORD process_path_len = _countof(process_path), tries = 0; + struct file_id file_ids[2], file_id; size_t file_ids_len = 0; bool is_com_initialized = SUCCEEDED(CoInitialize(NULL)); LSTATUS mret; @@ -406,30 +428,43 @@ __declspec(dllexport) UINT __stdcall KillWireGuardProcesses(MSIHANDLE installer) if (!process_path[0]) goto out; - log_messagef(installer, LOG_LEVEL_INFO, TEXT("Detecting running processes")); + if (!PathCombine(executables[0], process_path, TEXT("wg.exe")) || + !PathCombine(executables[1], process_path, TEXT("wireguard.exe"))) + goto out; + if (can_be_deleted(executables[0]) && can_be_deleted(executables[1])) + goto out; - if (PathCombine(executable, process_path, TEXT("wg.exe")) && calculate_file_id(executable, &file_ids[file_ids_len])) - ++file_ids_len; - if (PathCombine(executable, process_path, TEXT("wireguard.exe")) && calculate_file_id(executable, &file_ids[file_ids_len])) - ++file_ids_len; + log_messagef(installer, LOG_LEVEL_INFO, TEXT("Detecting running processes")); + for (size_t i = 0; i < _countof(executables); ++i) { + if (calculate_file_id(executables[i], &file_ids[file_ids_len])) + ++file_ids_len; + else + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("Unable to calculate file ID \"%1\""), executables[i]); + } if (!file_ids_len) goto out; +retry: snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (snapshot == INVALID_HANDLE_VALUE) goto out; - for (bool ret = Process32First(snapshot, &entry); ret; ret = Process32Next(snapshot, &entry)) { if (_tcsicmp(entry.szExeFile, TEXT("wireguard.exe")) && _tcsicmp(entry.szExeFile, TEXT("wg.exe"))) continue; process = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION, false, entry.th32ProcessID); - if (!process) + if (!process) { + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("Unable to open process \"%1\" (pid %2!d!)"), entry.szExeFile, entry.th32ProcessID); continue; + } process_path_len = _countof(process_path); - if (!QueryFullProcessImageName(process, 0, process_path, &process_path_len)) + if (!QueryFullProcessImageName(process, 0, process_path, &process_path_len)) { + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("Unable to query process \"%1\" (pid %2!d!)"), entry.szExeFile, entry.th32ProcessID); goto next; - if (!calculate_file_id(process_path, &file_id)) + } + if (!calculate_file_id(process_path, &file_id)) { + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("Unable to calculate file ID \"%1\" (pid %2!d!)"), process_path, entry.th32ProcessID); goto next; + } ret = false; for (size_t i = 0; i < file_ids_len; ++i) { if (!memcmp(&file_id, &file_ids[i], sizeof(file_id))) { @@ -442,12 +477,22 @@ __declspec(dllexport) UINT __stdcall KillWireGuardProcesses(MSIHANDLE installer) if (TerminateProcess(process, STATUS_DLL_INIT_FAILED_LOGOFF)) { WaitForSingleObject(process, INFINITE); log_messagef(installer, LOG_LEVEL_INFO, TEXT("Killed \"%1\" (pid %2!d!)"), process_path, entry.th32ProcessID); - } + } else + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("Unable to kill \"%1\" (pid %2!d!)"), process_path, entry.th32ProcessID); next: CloseHandle(process); } CloseHandle(snapshot); - + for (size_t i = 0; i < _countof(executables); ++i) { + if (!can_be_deleted(executables[i])) { + if (++tries > 100) { + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("File \"%1\" cannot be deleted"), executables[i]); + continue; + } + Sleep(100); + goto retry; + } + } out: if (is_com_initialized) CoUninitialize(); |
