@@ -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+
369385struct file_id { DWORD volume , index_high , index_low ; };
370386
371387static 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+ }
456486out :
457487 if (is_com_initialized )
458488 CoUninitialize ();
0 commit comments