Skip to content

Commit

Permalink
feat(installer): start the Gateway service at install time (#363)
Browse files Browse the repository at this point in the history
  • Loading branch information
thenextman authored Dec 7, 2022
1 parent 8fecad2 commit b07ccd4
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 45 deletions.
200 changes: 155 additions & 45 deletions package/Windows/Actions/CustomAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ enum Errors
InvalidHost = 30000
};

constexpr auto DG_SERVICE_NAME = L"DevolutionsGateway";

/// <summary>
/// Write a message to the installer log
/// </summary>
Expand Down Expand Up @@ -346,7 +348,7 @@ UINT __stdcall BrowseForCertificate(MSIHANDLE hInstall)
er = BrowseForFile(
hInstall,
propertyName,
L"PFX Files (*.pfx, *.p12)\0*.pfx;*.p12\0Certificate Files (*.pem, *.crt)\0*.pem;*.crt\0\0"
L"PFX Files (*.pfx, *.p12)\0*.pfx;*.p12\0Certificate Files (*.pem, *.crt)\0*.pem;*.crt\0All Files\0*.*\0\0"
);

if (er != ERROR_SUCCESS)
Expand Down Expand Up @@ -386,7 +388,7 @@ UINT __stdcall BrowseForPrivateKey(MSIHANDLE hInstall)

WcaLog(LOGMSG_STANDARD, "Initialized.");

er = BrowseForFile(hInstall, L"P.CERT_PK_FILE", L"Private Key Files (*.key)\0*.key\0\0");
er = BrowseForFile(hInstall, L"P.CERT_PK_FILE", L"Private Key Files (*.key)\0*.key\0All Files\0*.*\0\0");

if (er != ERROR_SUCCESS)
{
Expand All @@ -412,7 +414,7 @@ UINT __stdcall BrowseForPublicKey(MSIHANDLE hInstall)
er = BrowseForFile(
hInstall,
L"P.PUBLIC_KEY_FILE",
L"Key Files (*.pem, *.key)\0*.pem;*.key\0All Files\0*.*\0\0"
L"Public Key Files (*.pem)\0*.pem\0Private Key Files (*.key)\0*.key\0All Files\0*.*\0\0"
);

if (er != ERROR_SUCCESS)
Expand All @@ -426,6 +428,44 @@ UINT __stdcall BrowseForPublicKey(MSIHANDLE hInstall)
return WcaFinalize(er);
}

HRESULT __stdcall OpenServiceManagerX(MSIHANDLE hInstall, DWORD dwDesiredAccess, SC_HANDLE* lpHandle)
{
HRESULT hr = S_OK;
SC_HANDLE hSCM = NULL;

hSCM = OpenSCManagerW(NULL, NULL, dwDesiredAccess);

if (hSCM == NULL)
{
DWORD dwError = GetLastError();
LogGLE(hInstall, L"OpenSCManager failed", dwError);
hr = HRESULT_FROM_WIN32(dwError);
}

*lpHandle = hSCM;

return hr;
}

HRESULT __stdcall OpenServiceX(MSIHANDLE hInstall, SC_HANDLE hSCManager, LPCWSTR lpServiceName, DWORD dwDesiredAccess, SC_HANDLE* lpHandle)
{
HRESULT hr = S_OK;
SC_HANDLE hService = NULL;

hService = OpenServiceW(hSCManager, lpServiceName, dwDesiredAccess);

if (hService == NULL)
{
DWORD dwError = GetLastError();
LogGLE(hInstall, L"OpenService failed", dwError);
hr = HRESULT_FROM_WIN32(dwError);
}

*lpHandle = hService;

return hr;
}

UINT __stdcall SetGatewayStartupType(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
Expand Down Expand Up @@ -472,25 +512,13 @@ UINT __stdcall SetGatewayStartupType(MSIHANDLE hInstall)
goto LExit;
}

hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);

if (hSCM == NULL)
if (OpenServiceManagerX(hInstall, SC_MANAGER_ALL_ACCESS, &hSCM) != S_OK)
{
DWORD dwError = GetLastError();
LogGLE(hInstall, L"OpenSCManager failed", dwError);
hr = HRESULT_FROM_WIN32(dwError);

goto LExit;
}

hService = OpenServiceW(hSCM, L"DevolutionsGateway", SERVICE_CHANGE_CONFIG);

if (hService == NULL)
if (OpenServiceX(hInstall, hSCM, DG_SERVICE_NAME, SERVICE_CHANGE_CONFIG, &hService) != S_OK)
{
DWORD dwError = GetLastError();
LogGLE(hInstall, L"OpenService failed", dwError);
hr = HRESULT_FROM_WIN32(dwError);

goto LExit;
}

Expand Down Expand Up @@ -519,45 +547,27 @@ UINT __stdcall SetGatewayStartupType(MSIHANDLE hInstall)
return WcaFinalize(er);
}

UINT __stdcall QueryGatewayStartupType(MSIHANDLE hInstall)
HRESULT __stdcall GetGatewayStartupType(MSIHANDLE hInstall, DWORD* pStartupType)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
HRESULT hr = E_FAIL;
SC_HANDLE hSCM = NULL;
SC_HANDLE hService = NULL;
LPQUERY_SERVICE_CONFIG lpsc;
LPQUERY_SERVICE_CONFIG lpsc = { 0 };
DWORD dwBytesNeeded;
DWORD cbBufSize = 0;
DWORD dwError;

hr = WcaInitialize(hInstall, "QueryGatewayStartupType");
ExitOnFailure(hr, "Failed to initialize");

WcaLog(LOGMSG_STANDARD, "Initialized.");

hSCM = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT);

if (hSCM == NULL)
if (OpenServiceManagerX(hInstall, SC_MANAGER_CONNECT, &hSCM) != S_OK)
{
DWORD dwError = GetLastError();
LogGLE(hInstall, L"OpenSCManager failed", dwError);
hr = HRESULT_FROM_WIN32(dwError);

goto LExit;
}

hService = OpenServiceW(hSCM, L"DevolutionsGateway", SERVICE_QUERY_CONFIG);

if (hService == NULL)
if (OpenServiceX(hInstall, hSCM, DG_SERVICE_NAME, SERVICE_QUERY_CONFIG, &hService) != S_OK)
{
DWORD dwError = GetLastError();
LogGLE(hInstall, L"OpenService failed", dwError);
hr = HRESULT_FROM_WIN32(dwError);

goto LExit;
}

if (!QueryServiceConfig(hService, NULL, 0, &dwBytesNeeded))
if (!QueryServiceConfigW(hService, NULL, 0, &dwBytesNeeded))
{
dwError = GetLastError();

Expand All @@ -582,18 +592,118 @@ UINT __stdcall QueryGatewayStartupType(MSIHANDLE hInstall)
}
}

if (!QueryServiceConfig(hService, lpsc, cbBufSize, &dwBytesNeeded))
if (!QueryServiceConfigW(hService, lpsc, cbBufSize, &dwBytesNeeded))
{
dwError = GetLastError();
LogGLE(hInstall, L"QueryServiceConfig failed", dwError);
hr = HRESULT_FROM_WIN32(dwError);

LocalFree(lpsc);

goto LExit;
}

hr = WcaSetIntProperty(L"P.SERVICE_START", lpsc->dwStartType == SERVICE_DISABLED ? SERVICE_DEMAND_START : lpsc->dwStartType);
ExitOnFailure(hr, "The expected property was not found.");
hr = S_OK;
*pStartupType = lpsc->dwStartType;

LocalFree(lpsc);

LExit:
if (hService != NULL)
{
CloseServiceHandle(hService);
}

if (hSCM != NULL)
{
CloseServiceHandle(hSCM);
}

return hr;
}

UINT __stdcall QueryGatewayStartupType(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
DWORD dwStartType = 0;
UINT er = ERROR_SUCCESS;

hr = WcaInitialize(hInstall, "QueryGatewayStartupType");
ExitOnFailure(hr, "Failed to initialize");

WcaLog(LOGMSG_STANDARD, "Initialized.");

Log(hInstall, L"Looking for existing Devolutions Gateway service");

hr = GetGatewayStartupType(hInstall, &dwStartType);

if (hr == S_OK)
{
hr = WcaSetIntProperty(L"P.SERVICE_START", dwStartType == SERVICE_DISABLED ? SERVICE_DEMAND_START : dwStartType);
ExitOnFailure(hr, "The expected property was not found.");
}

LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}

UINT __stdcall StartGatewayIfNeeded(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
DWORD dwStartType = 0;
SC_HANDLE hSCM = NULL;
SC_HANDLE hService = NULL;
UINT er = ERROR_SUCCESS;

hr = WcaInitialize(hInstall, "StartGatewayIfNeeded");
ExitOnFailure(hr, "Failed to initialize");

WcaLog(LOGMSG_STANDARD, "Initialized.");

hr = GetGatewayStartupType(hInstall, &dwStartType);

if (hr == S_OK)
{
if (dwStartType == SERVICE_AUTO_START)
{
Log(hInstall, L"Trying to start the Devolutions Gateway service");

if (OpenServiceManagerX(hInstall, SC_MANAGER_CONNECT, &hSCM) != S_OK)
{
goto LExit;
}

if (OpenServiceX(hInstall, hSCM, DG_SERVICE_NAME, SERVICE_START, &hService) != S_OK)
{
goto LExit;
}

if (StartServiceW(hService, 0, NULL))
{
Log(hInstall, L"Successfully asked the Devolutions Gateway service to start");
}
else
{
DWORD dwError = GetLastError();

if (dwError == ERROR_SERVICE_ALREADY_RUNNING)
{
Log(hInstall, L"Devolutions Gateway service is already running");

goto LExit;
}

LogGLE(hInstall, L"StartService failed", dwError);
hr = HRESULT_FROM_WIN32(dwError);
}
}
else
{
Log(hInstall, L"Devolutions Gateway service is not SERVICE_AUTO_START, nothing to do");
}
}

LExit:
if (hService != NULL)
{
Expand Down Expand Up @@ -831,7 +941,7 @@ UINT __stdcall ValidateCertificate(MSIHANDLE hInstall)

for (int i = 0; i < lstrlenW(szCertPass); i++)
{
szValBuf[i] = L'•';
szValBuf[i] = L'';
}

szValBuf[lstrlenW(szCertPass)] = L'\0';
Expand Down
1 change: 1 addition & 0 deletions package/Windows/Actions/CustomAction.def
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ EXPORTS
BrowseForPublicKey
SetGatewayStartupType
QueryGatewayStartupType
StartGatewayIfNeeded
ValidateAccessUri
ValidateListeners
ValidateCertificate
Expand Down
5 changes: 5 additions & 0 deletions package/Windows/DevolutionsGateway.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
<RegistrySearch Id="DetermineInstallLocation" Type="raw" Root="HKLM" Key="Software\$(var.VendorName)\InstalledProducts\$(var.ProductName)" Name="InstallLocation" />
</Property>

<!-- Public properties (supported) -->
<Property Id="P.DGW.NO_START_SERVICE" Secure="yes" />

<!-- Properties to support Gateway configuration via Installer UI-->
<Property Id="P.CONFIGURE" Value="1" />
<Property Id="P.ERROR" Secure="yes" />
Expand Down Expand Up @@ -120,6 +123,7 @@
<CustomAction Id="CA.BrowseForPublicKey" BinaryKey="B.HELPER" DllEntry="BrowseForPublicKey" Execute="immediate" Return="ignore" />
<CustomAction Id="CA.QueryGatewayStartupType" BinaryKey="B.HELPER" DllEntry="QueryGatewayStartupType" Execute="immediate" Return="ignore" />
<CustomAction Id="CA.SetGatewayStartupType" BinaryKey="B.HELPER" DllEntry="SetGatewayStartupType" Execute="deferred" Impersonate="no" Return="ignore" />
<CustomAction Id="CA.StartGatewayIfNeeded" BinaryKey="B.HELPER" DllEntry="StartGatewayIfNeeded" Execute="deferred" Impersonate="no" Return="ignore" />
<CustomAction Id="CA.ConfigHostname" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="deferred" Impersonate="no" Return="check"/>
<CustomAction Id="CA.ConfigListeners" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="deferred" Impersonate="no" Return="check"/>
<CustomAction Id="CA.ConfigCert" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="deferred" Impersonate="no" Return="check" HideTarget="yes" />
Expand All @@ -141,6 +145,7 @@
<Custom Action="CA.ConfigListeners" Before="StartServices">(NOT Installed OR REINSTALL) AND (P.CONFIGURE = "0")</Custom>
<Custom Action="CA.ConfigCert" Before="StartServices">(NOT Installed OR REINSTALL) AND (P.CONFIGURE = "0")</Custom>
<Custom Action="CA.ConfigPk" Before="StartServices">(NOT Installed OR REINSTALL) AND (P.CONFIGURE = "0")</Custom>
<Custom Action="CA.StartGatewayIfNeeded" After="StartServices">(NOT Uninstalling) AND (NOT P.DGW.NO_START_SERVICE)</Custom>
</InstallExecuteSequence>

<Media Id="1" Cabinet="dgateway.cab" EmbedCab="yes" />
Expand Down

0 comments on commit b07ccd4

Please sign in to comment.