From 356048e2a95502a37e4ce413ddbefab5320737db Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 9 Aug 2019 09:13:10 +0200 Subject: installer: clean up logic --- installer/build.bat | 3 +- installer/customactions.c | 363 +++++++++++++++------------------------------- 2 files changed, 119 insertions(+), 247 deletions(-) (limited to 'installer') diff --git a/installer/build.bat b/installer/build.bat index 8d438af9..1f9fa729 100644 --- a/installer/build.bat +++ b/installer/build.bat @@ -61,9 +61,8 @@ if exist .deps\prepared goto :build set LDFLAGS=-shared -s -Wl,--kill-at -Wl,--major-os-version=6 -Wl,--minor-os-version=1 -Wl,--major-subsystem-version=6 -Wl,--minor-subsystem-version=1 set LDLIBS=-lmsi -lole32 -lshlwapi if not exist "%~1" mkdir "%~1" - echo [+] Compiling custom actions %1 - %CC% %CFLAGS% %LDFLAGS% -o "%~1\customactions.dll" customactions.c %LDLIBS% || exit /b 1 echo [+] Compiling %1 + %CC% %CFLAGS% %LDFLAGS% -o "%~1\customactions.dll" customactions.c %LDLIBS% || exit /b 1 "%WIX%bin\candle" %WIX_CANDLE_FLAGS% -dWIREGUARD_PLATFORM="%~1" -out "%~1\wireguard.wixobj" -arch %3 wireguard.wxs || exit /b %errorlevel% echo [+] Linking %1 "%WIX%bin\light" %WIX_LIGHT_FLAGS% -out "dist\wireguard-%~1-%WIREGUARD_VERSION%.msi" "%~1\wireguard.wixobj" || exit /b %errorlevel% diff --git a/installer/customactions.c b/installer/customactions.c index 7217fca8..ae9e7d7f 100644 --- a/installer/customactions.c +++ b/installer/customactions.c @@ -13,282 +13,168 @@ #define MANAGER_SERVICE_NAME TEXT("WireGuardManager") #define TUNNEL_SERVICE_PREFIX TEXT("WireGuardTunnel$") -#define ENUM_SERVICE_STATUS_PROCESS_SIZE 0x10000 -typedef enum -{ - LOG_LEVEL_INFO = 0, - LOG_LEVEL_WARN, - LOG_LEVEL_ERR -} log_level_t; - -static TCHAR *format_message(const TCHAR *template, const DWORD_PTR argv[]) -{ - TCHAR *formatted_message = NULL; - if (!FormatMessage( - FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_MAX_WIDTH_MASK, - template, - 0, - 0, - (VOID *)&formatted_message, - 0, - (va_list *)argv)) - return NULL; - return formatted_message; -} +enum log_level { LOG_LEVEL_INFO, LOG_LEVEL_WARN, LOG_LEVEL_ERR }; -static void log_message(MSIHANDLE installer, log_level_t level, const TCHAR *log_line) +static void log_messagef(MSIHANDLE installer, enum log_level level, const TCHAR *format, ...) { MSIHANDLE record = MsiCreateRecord(2); + TCHAR *template, *line = NULL; + INSTALLMESSAGE type; + va_list args; + if (!record) return; - TCHAR *template; - INSTALLMESSAGE type; + + va_start(args, format); + FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK, + format, 0, 0, (void *)&line, 0, &args); + va_end(args); + if (!line) + goto out; + switch (level) { case LOG_LEVEL_INFO: - template = TEXT("Custom action: [1]"); + template = TEXT("WireGuard: [1]"); type = INSTALLMESSAGE_INFO; break; case LOG_LEVEL_WARN: - template = TEXT("Custom action warning: [1]"); + template = TEXT("WireGuard warning: [1]"); type = INSTALLMESSAGE_INFO; break; case LOG_LEVEL_ERR: - template = TEXT("Custom action error: [1]"); + template = TEXT("WireGuard error: [1]"); type = INSTALLMESSAGE_ERROR; break; default: - goto cleanup; + goto out; } MsiRecordSetString(record, 0, template); - MsiRecordSetString(record, 1, log_line); + MsiRecordSetString(record, 1, line); MsiProcessMessage(installer, type, record); -cleanup: +out: + LocalFree(line); MsiCloseHandle(record); } -static void log_messagef(MSIHANDLE installer, log_level_t level, const TCHAR *template, const DWORD_PTR argv[]) +static void log_errorf(MSIHANDLE installer, enum log_level level, DWORD error_code, const TCHAR *prefix_format, ...) { - TCHAR *formatted_message = format_message(template, argv); - if (formatted_message) { - log_message(installer, level, formatted_message); - LocalFree(formatted_message); - } -} - -static void log_error(MSIHANDLE installer, DWORD error_code, const TCHAR *prefix) -{ - TCHAR *system_message = NULL; - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK, - NULL, - HRESULT_FROM_SETUPAPI(error_code), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (VOID *)&system_message, - 0, - NULL); - log_messagef( - installer, - LOG_LEVEL_ERR, - system_message ? TEXT("%1: %3(Code 0x%2!08X!)") : TEXT("%1: Code 0x%2!08X!"), - (DWORD_PTR[]){ (DWORD_PTR)prefix, error_code, (DWORD_PTR)system_message }); + TCHAR *system_message = NULL, *prefix = NULL; + va_list args; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (void *)&system_message, 0, NULL); + va_start(args, prefix_format); + FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK, + prefix_format, 0, 0, (void *)&prefix, 0, &args); + va_end(args); + log_messagef(installer, level, system_message ? TEXT("%1: %3(Code 0x%2!08X!)") : TEXT("%1: Code 0x%2!08X!"), + prefix ?: TEXT("Error"), error_code, system_message); + LocalFree(prefix); LocalFree(system_message); } -static void log_errorf(MSIHANDLE installer, DWORD error_code, const TCHAR *template, const DWORD_PTR argv[]) -{ - TCHAR *formatted_message = format_message(template, argv); - if (formatted_message) { - log_error(installer, error_code, formatted_message); - LocalFree(formatted_message); - } -} - -static bool is_valid_tunnel_name(const TCHAR *tunnel_name) -{ - for (size_t i = 0; ; i++) { - TCHAR c = tunnel_name[i]; - if (!c) - return i > 0; - if (i >= 32) - return false; - if ((c < TEXT('a') || c > TEXT('z')) && - (c < TEXT('A') || c > TEXT('Z')) && - (c < TEXT('0') || c > TEXT('9')) && - c != TEXT('_') && - c != TEXT('=') && - c != TEXT('+') && - c != TEXT('.') && - c != TEXT('-')) - return false; - } -} - -static void replace_msi_operators(TCHAR *dest, const TCHAR *src, size_t count) -{ - for (size_t i = 0; i < count; i++) { - TCHAR c = src[i]; - switch (c) { - case 0: - dest[i] = 0; - return; - case TEXT('='): - case TEXT('+'): - case TEXT('-'): - dest[i] = TEXT('_'); - break; - default: - dest[i] = c; - } - } -} - -static bool is_service_started(MSIHANDLE installer, SC_HANDLE scm, const TCHAR *service_name) -{ - bool ret = false; - SC_HANDLE service = NULL; - SERVICE_STATUS_PROCESS service_status; - DWORD service_status_size = 0; - const DWORD_PTR log_argv[] = { (DWORD_PTR)__FUNCTION__, (DWORD_PTR)service_name }; - - service = OpenService(scm, MANAGER_SERVICE_NAME, SERVICE_QUERY_STATUS); - if (!service) { - log_errorf(installer, GetLastError(), TEXT("%1!hs!: OpenService failed for service %2"), log_argv); - goto cleanup; - } - if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (LPBYTE)&service_status, sizeof(service_status), &service_status_size)) { - log_errorf(installer, GetLastError(), TEXT("%1!hs!: QueryServiceStatusEx failed for service %2"), log_argv); - goto cleanup; - } - if (service_status.dwCurrentState != SERVICE_STOPPED && service_status.dwCurrentState != SERVICE_STOP_PENDING) - ret = true; - -cleanup: - if (service) - CloseServiceHandle(service); - return ret; -} - static UINT insert_service_control(MSIHANDLE installer, MSIHANDLE view, const TCHAR *service_name, bool start) { - UINT ret = ERROR_INSTALL_FAILURE; - MSIHANDLE record = 0; - const DWORD_PTR log_argv[] = { (DWORD_PTR)__FUNCTION__, (DWORD_PTR)service_name }; - size_t service_name_len; - TCHAR *sanitized_service_name = NULL, *service_control_stop = NULL, *service_control_start = NULL; static unsigned int index = 0; + UINT ret; + MSIHANDLE record; + TCHAR row_identifier[_countof(TEXT("wireguard_service_control_4294967296"))]; + if (_sntprintf(row_identifier, _countof(row_identifier), TEXT("wireguard_service_control_%u"), ++index) >= _countof(row_identifier)) + return ERROR_INSTALL_FAILURE; record = MsiCreateRecord(5); if (!record) - goto cleanup; - - service_name_len = _tcslen(service_name) + 1; - sanitized_service_name = LocalAlloc(LMEM_FIXED, sizeof(TCHAR) * service_name_len); - if (!sanitized_service_name) { - ret = GetLastError(); - log_errorf(installer, ret, TEXT("%1!hs!: LocalAlloc failed for service %2"), log_argv); - goto cleanup; - } - replace_msi_operators(sanitized_service_name, service_name, service_name_len); + return ERROR_INSTALL_FAILURE; - log_messagef(installer, LOG_LEVEL_INFO, TEXT("%1!hs!: Scheduling stop on upgrade or removal on uninstall of service %2"), log_argv); - service_control_stop = format_message(TEXT("stop_%1%2!u!"), (DWORD_PTR[]){ (DWORD_PTR)sanitized_service_name, index++ }); - if (!service_control_stop) { - ret = GetLastError(); - log_errorf(installer, ret, TEXT("%1!hs!: FormatMessage failed for service %2"), log_argv); - goto cleanup; - } - MsiRecordSetString (record, 1/*ServiceControl*/, service_control_stop); + MsiRecordSetString (record, 1/*ServiceControl*/, row_identifier); MsiRecordSetString (record, 2/*Name */, service_name); MsiRecordSetInteger(record, 3/*Event */, msidbServiceControlEventStop | msidbServiceControlEventUninstallStop | msidbServiceControlEventUninstallDelete); MsiRecordSetString (record, 4/*Component_ */, TEXT("WireGuardExecutable")); MsiRecordSetInteger(record, 5/*Wait */, 1); /* Waits 30 seconds. */ + log_messagef(installer, LOG_LEVEL_INFO, TEXT("Scheduling stop on upgrade or removal on uninstall of service %1"), service_name); ret = MsiViewExecute(view, record); if (ret != ERROR_SUCCESS) { - log_errorf(installer, ret, TEXT("%1!hs!: MsiViewExecute failed for service %2"), log_argv); - goto cleanup; + log_errorf(installer, LOG_LEVEL_ERR, ret, TEXT("MsiViewExecute failed for service %1"), service_name); + goto out; } + if (!start) - goto cleanup; + goto out; - log_messagef(installer, LOG_LEVEL_INFO, TEXT("%1!hs!: Scheduling start on upgrade of service %2"), log_argv); - service_control_start = format_message(TEXT("start_%1%2!u!"), (DWORD_PTR[]){ (DWORD_PTR)sanitized_service_name, index++ }); - if (!service_control_start) { - ret = GetLastError(); - log_errorf(installer, ret, TEXT("%1!hs!: FormatMessage failed for service %2"), log_argv); - goto cleanup; - } - MsiRecordSetString (record, 1/*ServiceControl*/, service_control_start); + ret = ERROR_INSTALL_FAILURE; + if (_sntprintf(row_identifier, _countof(row_identifier), TEXT("wireguard_service_control_%u"), ++index) >= _countof(row_identifier)) + goto out; + MsiRecordSetString (record, 1/*ServiceControl*/, row_identifier); MsiRecordSetString (record, 2/*Name */, service_name); MsiRecordSetInteger(record, 3/*Event */, msidbServiceControlEventStart); MsiRecordSetString (record, 4/*Component_ */, TEXT("WireGuardExecutable")); MsiRecordSetInteger(record, 5/*Wait */, 0); /* No wait, so that failure to restart again isn't fatal. */ + log_messagef(installer, LOG_LEVEL_INFO, TEXT("Scheduling start on upgrade of service %1"), service_name); ret = MsiViewExecute(view, record); if (ret != ERROR_SUCCESS) { - log_errorf(installer, ret, TEXT("%1!hs!: MsiViewExecute failed for service %2"), log_argv); - goto cleanup; + log_errorf(installer, LOG_LEVEL_ERR, ret, TEXT("MsiViewExecute failed for service %1"), service_name); + goto out; } -cleanup: - if (service_control_start) - LocalFree(service_control_start); - if (service_control_stop) - LocalFree(service_control_stop); - if (sanitized_service_name) - LocalFree(sanitized_service_name); - if (record) - MsiCloseHandle(record); +out: + MsiCloseHandle(record); return ret; } -static bool remove_folder(MSIHANDLE installer, TCHAR path[MAX_PATH]) +static bool remove_directory_recursive(MSIHANDLE installer, TCHAR path[MAX_PATH], unsigned int max_depth) { HANDLE find_handle; WIN32_FIND_DATA find_data; TCHAR *path_end; - const DWORD_PTR log_argv[] = { (DWORD_PTR)__FUNCTION__, (DWORD_PTR)path }; + + if (!max_depth) { + log_messagef(installer, LOG_LEVEL_WARN, TEXT("Too many levels of nesting at \"%1\""), path); + return false; + } path_end = path + _tcsnlen(path, MAX_PATH); if (!PathAppend(path, TEXT("*.*"))) { - log_messagef(installer, LOG_LEVEL_ERR, TEXT("%1!hs!: PathAppend(%2) failed"), log_argv); + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("PathAppend(\"%1\", \"*.*\") failed"), path); return false; } find_handle = FindFirstFileEx(path, FindExInfoBasic, &find_data, FindExSearchNameMatch, NULL, 0); if (find_handle == INVALID_HANDLE_VALUE) { - log_errorf(installer, GetLastError(), TEXT("%1!hs!: FindFirstFileEx(%2) failed"), log_argv); + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("FindFirstFileEx(\"%1\") failed"), path); return false; } do { - if (find_data.cFileName[0] == TEXT('.') && (!find_data.cFileName[1] || (find_data.cFileName[1] == TEXT('.') && !find_data.cFileName[2]))) + if (find_data.cFileName[0] == TEXT('.') && (find_data.cFileName[1] == TEXT('\0') || (find_data.cFileName[1] == TEXT('.') && find_data.cFileName[2] == TEXT('\0')))) continue; - path_end[0] = 0; + path_end[0] = TEXT('\0'); if (!PathAppend(path, find_data.cFileName)) { - log_messagef(installer, LOG_LEVEL_ERR, TEXT("%1!hs!: PathAppend(%2) failed"), log_argv); + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("PathAppend(\"%1\", \"%2\") failed"), path, find_data.cFileName); continue; } if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - remove_folder(installer, path); + remove_directory_recursive(installer, path, max_depth - 1); continue; } if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && !SetFileAttributes(path, find_data.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)) - log_errorf(installer, GetLastError(), TEXT("%1!hs!: SetFileAttributes(%2) failed"), log_argv); + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("SetFileAttributes(\"%1\") failed"), path); if (DeleteFile(path)) - log_messagef(installer, LOG_LEVEL_INFO, TEXT("%1!hs!: %2 removed"), log_argv); + log_messagef(installer, LOG_LEVEL_INFO, TEXT("Deleted \"%1\""), path); else - log_errorf(installer, GetLastError(), TEXT("%1!hs!: DeleteFile(%2) failed"), log_argv); + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("DeleteFile(\"%1\") failed"), path); } while (FindNextFile(find_handle, &find_data)); FindClose(find_handle); - path_end[0] = 0; + path_end[0] = TEXT('\0'); if (RemoveDirectory(path)) { - log_messagef(installer, LOG_LEVEL_INFO, TEXT("%1!hs!: %2 removed"), log_argv); + log_messagef(installer, LOG_LEVEL_INFO, TEXT("Removed \"%1\""), path); return true; } else { - log_errorf(installer, GetLastError(), TEXT("%1!hs!: RemoveDirectory(%2) failed"), log_argv); + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("RemoveDirectory(\"%1\") failed"), path); return false; } } @@ -296,81 +182,65 @@ static bool remove_folder(MSIHANDLE installer, TCHAR path[MAX_PATH]) __declspec(dllexport) UINT __stdcall EvaluateWireGuardServices(MSIHANDLE installer) { UINT ret = ERROR_INSTALL_FAILURE; - BOOL is_com_initialized = SUCCEEDED(CoInitialize(NULL)); - MSIHANDLE db = 0, view = 0; + bool is_com_initialized = SUCCEEDED(CoInitialize(NULL)); + MSIHANDLE db, view = 0; SC_HANDLE scm = NULL; ENUM_SERVICE_STATUS_PROCESS *service_status = NULL; DWORD service_status_resume = 0; - const DWORD_PTR log_argv[] = { (DWORD_PTR)__FUNCTION__ }; + enum { SERVICE_STATUS_PROCESS_SIZE = 0x10000 }; db = MsiGetActiveDatabase(installer); if (!db) { - log_messagef(installer, LOG_LEVEL_ERR, TEXT("%1!hs!: MsiGetActiveDatabase failed"), log_argv); - goto cleanup; + log_messagef(installer, LOG_LEVEL_ERR, TEXT("MsiGetActiveDatabase failed")); + goto out; } - ret = MsiDatabaseOpenView( - db, - TEXT("INSERT INTO `ServiceControl` (`ServiceControl`, `Name`, `Event`, `Component_`, `Wait`) VALUES(?, ?, ?, ?, ?) TEMPORARY"), - &view); + ret = MsiDatabaseOpenView(db, + TEXT("INSERT INTO `ServiceControl` (`ServiceControl`, `Name`, `Event`, `Component_`, `Wait`) VALUES(?, ?, ?, ?, ?) TEMPORARY"), + &view); if (ret != ERROR_SUCCESS) { - log_errorf(installer, ret, TEXT("%1!hs!: MsiDatabaseOpenView failed"), log_argv); - goto cleanup; + log_errorf(installer, LOG_LEVEL_ERR, ret, TEXT("MsiDatabaseOpenView failed")); + goto out; } scm = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE); if (!scm) { ret = GetLastError(); - log_errorf(installer, ret, TEXT("%1!hs!: OpenSCManager failed"), log_argv); - goto cleanup; + log_errorf(installer, LOG_LEVEL_ERR, ret, TEXT("OpenSCManager failed")); + goto out; } - insert_service_control(installer, view, MANAGER_SERVICE_NAME, is_service_started(installer, scm, MANAGER_SERVICE_NAME)); - - service_status = LocalAlloc(LMEM_FIXED, ENUM_SERVICE_STATUS_PROCESS_SIZE); + service_status = LocalAlloc(LMEM_FIXED, SERVICE_STATUS_PROCESS_SIZE); if (!service_status) { ret = GetLastError(); - log_errorf(installer, ret, TEXT("%1!hs!: LocalAlloc failed"), log_argv); - goto cleanup; + log_errorf(installer, LOG_LEVEL_ERR, ret, TEXT("LocalAlloc failed")); + goto out; } for (bool more_services = true; more_services;) { DWORD service_status_size = 0, service_status_count = 0; - if (EnumServicesStatusEx( - scm, - SC_ENUM_PROCESS_INFO, - SERVICE_WIN32, - SERVICE_STATE_ALL, - (LPBYTE)service_status, - ENUM_SERVICE_STATUS_PROCESS_SIZE, - &service_status_size, - &service_status_count, - &service_status_resume, - NULL)) + if (EnumServicesStatusEx(scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)service_status, + SERVICE_STATUS_PROCESS_SIZE, &service_status_size, &service_status_count, + &service_status_resume, NULL)) more_services = false; else { ret = GetLastError(); if (ret != ERROR_MORE_DATA) { - log_errorf(installer, ret, TEXT("%1!hs!: EnumServicesStatusEx failed"), log_argv); + log_errorf(installer, LOG_LEVEL_ERR, ret, TEXT("EnumServicesStatusEx failed")); break; } } - for (DWORD i = 0; i < service_status_count; i++) { - if (_tcsnicmp(service_status[i].lpServiceName, TUNNEL_SERVICE_PREFIX, _countof(TUNNEL_SERVICE_PREFIX) - 1) == 0) { - const TCHAR *tunnel_name = service_status[i].lpServiceName + _countof(TUNNEL_SERVICE_PREFIX) - 1; - if (is_valid_tunnel_name(tunnel_name)) - insert_service_control( - installer, - view, - service_status[i].lpServiceName, - service_status[i].ServiceStatusProcess.dwCurrentState != SERVICE_STOPPED && service_status[i].ServiceStatusProcess.dwCurrentState != SERVICE_STOP_PENDING); - } + for (DWORD i = 0; i < service_status_count; ++i) { + if (_tcsicmp(service_status[i].lpServiceName, MANAGER_SERVICE_NAME) && + _tcsnicmp(service_status[i].lpServiceName, TUNNEL_SERVICE_PREFIX, _countof(TUNNEL_SERVICE_PREFIX) - 1)) + continue; + insert_service_control(installer, view, service_status[i].lpServiceName, + service_status[i].ServiceStatusProcess.dwCurrentState != SERVICE_STOPPED && + service_status[i].ServiceStatusProcess.dwCurrentState != SERVICE_STOP_PENDING); } } - ret = ERROR_SUCCESS; -cleanup: - if (service_status) - LocalFree(service_status); +out: + LocalFree(service_status); if (scm) CloseServiceHandle(scm); if (view) @@ -379,25 +249,28 @@ cleanup: MsiCloseHandle(db); if (is_com_initialized) CoUninitialize(); - return ret == ERROR_SUCCESS ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; + return ret == ERROR_SUCCESS ? ret : ERROR_INSTALL_FAILURE; } __declspec(dllexport) UINT __stdcall RemoveConfigFolder(MSIHANDLE installer) { - LSTATUS result; + LSTATUS ret; TCHAR path[MAX_PATH]; + bool is_com_initialized = SUCCEEDED(CoInitialize(NULL)); - result = SHRegGetPath( - HKEY_LOCAL_MACHINE, - TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\S-1-5-18"), - TEXT("ProfileImagePath"), - path, - 0); - if (result != ERROR_SUCCESS) { - log_errorf(installer, result, TEXT("%1!hs!: SHRegGetPath failed"), (DWORD_PTR[]){ (DWORD_PTR)__FUNCTION__ }); - return ERROR_SUCCESS; + ret = SHRegGetPath(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\S-1-5-18"), + TEXT("ProfileImagePath"), path, 0); + if (ret != ERROR_SUCCESS) { + log_errorf(installer, LOG_LEVEL_WARN, ret, TEXT("SHRegGetPath failed")); + goto out; } - PathAppend(path, TEXT("AppData\\Local\\WireGuard")); - remove_folder(installer, path); + if (!PathAppend(path, TEXT("AppData\\Local\\WireGuard"))) { + log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("PathAppend(\"%1\", \"AppData\\Local\\WireGuard\") failed"), path); + goto out; + } + remove_directory_recursive(installer, path, 10); +out: + if (is_com_initialized) + CoUninitialize(); return ERROR_SUCCESS; } -- cgit v1.2.3-59-g8ed1b