diff options
Diffstat (limited to 'src/openvpnmsica/openvpnmsica.c')
-rw-r--r-- | src/openvpnmsica/openvpnmsica.c | 92 |
1 files changed, 89 insertions, 3 deletions
diff --git a/src/openvpnmsica/openvpnmsica.c b/src/openvpnmsica/openvpnmsica.c index de1cf65..98111fb 100644 --- a/src/openvpnmsica/openvpnmsica.c +++ b/src/openvpnmsica/openvpnmsica.c @@ -2,7 +2,7 @@ * openvpnmsica -- Custom Action DLL to provide OpenVPN-specific support to MSI packages * https://community.openvpn.net/openvpn/wiki/OpenVPNMSICA * - * Copyright (C) 2018-2020 Simon Rozman <simon@rozman.si> + * Copyright (C) 2018-2021 Simon Rozman <simon@rozman.si> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -59,6 +59,7 @@ #define MSICA_ADAPTER_TICK_SIZE (16*1024) /** Amount of tick space to reserve for one TAP/TUN adapter creation/deletition. */ +#define FILE_NEED_REBOOT L".ovpn_need_reboot" /** * Joins an argument sequence and sets it to the MSI property. @@ -956,6 +957,19 @@ cleanup_hRecord: } } + /* save path to user's temp dir to be used later by deferred actions */ + TCHAR tmpDir[MAX_PATH]; + GetTempPath(MAX_PATH, tmpDir); + + TCHAR str[MAX_PATH + 7]; + _stprintf_s(str, _countof(str), TEXT("tmpdir=%") TEXT(PRIsLPTSTR), tmpDir); + msica_arg_seq_add_tail(&seqInstall, str); + msica_arg_seq_add_tail(&seqInstallCommit, str); + msica_arg_seq_add_tail(&seqInstallRollback, str); + msica_arg_seq_add_tail(&seqUninstall, str); + msica_arg_seq_add_tail(&seqUninstallCommit, str); + msica_arg_seq_add_tail(&seqUninstallRollback, str); + /* Store deferred custom action parameters. */ if ((uiResult = setup_sequence(hInstall, TEXT("InstallTUNTAPAdapters" ), &seqInstall )) != ERROR_SUCCESS || (uiResult = setup_sequence(hInstall, TEXT("InstallTUNTAPAdaptersCommit" ), &seqInstallCommit )) != ERROR_SUCCESS @@ -1015,6 +1029,33 @@ parse_guid( } +/** + * Create empty file in user's temp directory. The existence of this file + * is checked in the end of installation by ScheduleReboot immediate custom action + * which schedules reboot. + * + * @param szTmpDir path to user's temp dirctory + * + */ +static void +CreateRebootFile(_In_z_ LPCWSTR szTmpDir) +{ + TCHAR path[MAX_PATH]; + swprintf_s(path, _countof(path), L"%s%s", szTmpDir, FILE_NEED_REBOOT); + + msg(M_WARN, "%s: Reboot required, create reboot indication file \"%" PRIsLPTSTR "\"", __FUNCTION__, path); + + HANDLE file = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (file == INVALID_HANDLE_VALUE) + { + msg(M_NONFATAL | M_ERRNO, "%s: CreateFile(\"%" PRIsLPTSTR "\") failed", __FUNCTION__, path); + } + else + { + CloseHandle(file); + } +} + UINT __stdcall ProcessDeferredAction(_In_ MSIHANDLE hInstall) { @@ -1026,6 +1067,7 @@ ProcessDeferredAction(_In_ MSIHANDLE hInstall) UINT uiResult; BOOL bIsCoInitialized = SUCCEEDED(CoInitialize(NULL)); + WCHAR tmpDir[MAX_PATH] = {0}; OPENVPNMSICA_SAVE_MSI_SESSION(hInstall); @@ -1168,6 +1210,10 @@ ProcessDeferredAction(_In_ MSIHANDLE hInstall) } dwResult = tap_enable_adapter(NULL, &guid, FALSE, &bRebootRequired); } + else if (wcsncmp(szArg[i], L"tmpdir=", 7) == 0) + { + wcscpy_s(tmpDir, _countof(tmpDir), szArg[i] + 7); + } else { goto invalid_argument; @@ -1194,9 +1240,9 @@ invalid_argument: } cleanup: - if (bRebootRequired) + if (bRebootRequired && wcslen(tmpDir) > 0) { - MsiSetMode(hInstall, MSIRUNMODE_REBOOTATEND, TRUE); + CreateRebootFile(tmpDir); } MsiCloseHandle(hRecordProg); LocalFree(szArg); @@ -1209,3 +1255,43 @@ cleanup_CoInitialize: } return uiResult; } + +UINT __stdcall +CheckAndScheduleReboot(_In_ MSIHANDLE hInstall) +{ +#ifdef _MSC_VER +#pragma comment(linker, DLLEXP_EXPORT) +#endif + + debug_popup(TEXT(__FUNCTION__)); + + UINT ret = ERROR_SUCCESS; + BOOL bIsCoInitialized = SUCCEEDED(CoInitialize(NULL)); + + OPENVPNMSICA_SAVE_MSI_SESSION(hInstall); + + /* get user-specific temp path, to where we create reboot indication file */ + TCHAR tempPath[MAX_PATH]; + GetTempPath(MAX_PATH, tempPath); + + /* check if reboot file exists */ + TCHAR path[MAX_PATH]; + _stprintf_s(path, _countof(path), L"%s%s", tempPath, FILE_NEED_REBOOT); + WIN32_FIND_DATA data = { 0 }; + HANDLE searchHandle = FindFirstFile(path, &data); + if (searchHandle != INVALID_HANDLE_VALUE) + { + msg(M_WARN, "%s: Reboot file exists, schedule reboot", __FUNCTION__); + + FindClose(searchHandle); + DeleteFile(path); + + MsiSetMode(hInstall, MSIRUNMODE_REBOOTATEND, TRUE); + } + + if (bIsCoInitialized) + { + CoUninitialize(); + } + return ret; +} |