From 2a6e08690223fd15bd5cb261efe9b997fa2d6026 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 21 Dec 2021 12:24:35 +0100 Subject: MDEV-27335 Windows, MSI - Bring the datadir location into the instance config UI --- win/packaging/ca/CustomAction.cpp | 122 ++++++++++++++++++++++++-------------- win/packaging/ca/CustomAction.def | 2 +- win/packaging/extra.wxs.in | 29 +++++---- 3 files changed, 93 insertions(+), 60 deletions(-) (limited to 'win/packaging') diff --git a/win/packaging/ca/CustomAction.cpp b/win/packaging/ca/CustomAction.cpp index ccb83c7b0c6..cbef4d2ee41 100644 --- a/win/packaging/ca/CustomAction.cpp +++ b/win/packaging/ca/CustomAction.cpp @@ -161,70 +161,100 @@ static void EscapeCommandLine(const wchar_t *in, wchar_t *out, size_t buflen) } out[pos++]= 0; } + +bool IsDirectoryEmptyOrNonExisting(const wchar_t *dir) { + wchar_t wildcard[MAX_PATH+3]; + WIN32_FIND_DATAW data; + HANDLE h; + wcscpy_s(wildcard, MAX_PATH, dir); + wcscat_s(wildcard, MAX_PATH, L"*.*"); + bool empty= true; + h= FindFirstFile(wildcard, &data); + if (h != INVALID_HANDLE_VALUE) + { + for (;;) + { + if (wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) + { + empty= false; + break; + } + if (!FindNextFile(h, &data)) + break; + } + FindClose(h); + } + return empty; +} + /* - Check for if directory is empty during install, - sets "_NOT_EMPTY" otherise + Check for valid data directory is empty during install + A valid data directory is non-existing, or empty. + + In addition, it must be different from any directories that + are going to be installed. This is required. because the full + directory is removed on a feature uninstall, and we do not want + it to be lib or bin. */ -extern "C" UINT __stdcall CheckDirectoryEmpty(MSIHANDLE hInstall, - const wchar_t *PropertyName) +extern "C" UINT __stdcall CheckDataDirectory(MSIHANDLE hInstall) { - HRESULT hr = S_OK; - UINT er = ERROR_SUCCESS; - wchar_t buf[MAX_PATH]; - DWORD len = MAX_PATH; - WIN32_FIND_DATAW data; - HANDLE h; + HRESULT hr= S_OK; + UINT er= ERROR_SUCCESS; + wchar_t datadir[MAX_PATH]; + DWORD len= MAX_PATH; bool empty; + wchar_t *path= 0; - hr = WcaInitialize(hInstall, __FUNCTION__); + MsiGetPropertyW(hInstall, L"DATADIR", datadir, &len); + hr= WcaInitialize(hInstall, __FUNCTION__); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); - MsiGetPropertyW(hInstall, PropertyName, buf, &len); - wcscat_s(buf, MAX_PATH, L"*.*"); + WcaLog(LOGMSG_STANDARD, "Checking files in %S", datadir); + empty= IsDirectoryEmptyOrNonExisting(datadir); + if (empty) + WcaLog(LOGMSG_STANDARD, "DATADIR is empty or non-existent"); + else + WcaLog(LOGMSG_STANDARD, "DATADIR is NOT empty"); + + if (!empty) + { + WcaSetProperty(L"DATADIRERROR", L"data directory exist and not empty"); + goto LExit; + } + WcaSetProperty(L"DATADIRERROR", L""); - WcaLog(LOGMSG_STANDARD, "Checking files in %S", buf); - h= FindFirstFile(buf, &data); - if (h != INVALID_HANDLE_VALUE) + WcaGetFormattedString(L"[INSTALLDIR]",&path); + if (path && !wcsicmp(datadir, path)) { - empty= true; - for(;;) - { - if (wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) - { - empty= false; - break; - } - if (!FindNextFile(h, &data)) - break; - } - FindClose(h); + WcaSetProperty(L"DATADIRERROR", L"data directory can not be " + L"installation root directory"); + ReleaseStr(path); + goto LExit; } - else + for (auto dir : + {L"[INSTALLDIR]bin\\", L"[INSTALLDIR]include\\", + L"[INSTALLDIR]lib\\", L"[INSTALLDIR]share\\"}) { - /* Non-existent directory, we handle it as empty */ - empty = true; + WcaGetFormattedString(dir, &path); + if (path && !wcsnicmp(datadir, path, wcslen(path))) + { + const wchar_t *subdir= dir + sizeof("[INSTALLDIR]") - 1; + wchar_t msg[MAX_PATH]= L"data directory conflicts with '"; + wcsncat_s(msg, subdir, wcslen(subdir) - 1); + wcscat_s(msg, L"' directory, which is part of this installation"); + WcaSetProperty(L"DATADIRERROR", msg); + ReleaseStr(path); + goto LExit; + } + ReleaseStr(path); + path= 0; } - - if(empty) - WcaLog(LOGMSG_STANDARD, "Directory %S is empty or non-existent", - PropertyName); - else - WcaLog(LOGMSG_STANDARD, "Directory %S is NOT empty", PropertyName); - - wcscpy_s(buf, MAX_PATH, PropertyName); - wcscat_s(buf, L"NOTEMPTY"); - WcaSetProperty(buf, empty? L"":L"1"); - LExit: return WcaFinalize(er); } -extern "C" UINT __stdcall CheckDataDirectoryEmpty(MSIHANDLE hInstall) -{ - return CheckDirectoryEmpty(hInstall, L"DATADIR"); -} bool CheckServiceExists(const wchar_t *name) { diff --git a/win/packaging/ca/CustomAction.def b/win/packaging/ca/CustomAction.def index 0be77a97a08..aed69cf7827 100644 --- a/win/packaging/ca/CustomAction.def +++ b/win/packaging/ca/CustomAction.def @@ -5,6 +5,6 @@ PresetDatabaseProperties RemoveDataDirectory CreateDatabaseRollback CheckDatabaseProperties -CheckDataDirectoryEmpty +CheckDataDirectory CheckDBInUse CheckServiceUpgrades diff --git a/win/packaging/extra.wxs.in b/win/packaging/extra.wxs.in index e886ed87d06..d003cea26d6 100644 --- a/win/packaging/extra.wxs.in +++ b/win/packaging/extra.wxs.in @@ -230,12 +230,22 @@ {\Font1}Use UTF8 as default server's character set - + + + + + 1 + 1 + 1 + 1 + + DATADIRERROR + RootPasswordConfirm]]> ""]]> NOT SERVICENAME AND NOT WarningText @@ -335,7 +345,7 @@ - + @@ -355,13 +365,6 @@ NOT Installed AND UpgradableServiceFound - - - - DATADIRNOTEMPTY - - WarningText @@ -634,13 +637,13 @@ Property="FailureProgram" Execute="deferred" /> - + - + - DATADIRNOTEMPTY + DATADIRERROR SERVICENAME -- cgit v1.2.1