aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Util/ca/RestartManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Util/ca/RestartManager.cpp')
-rw-r--r--src/ext/Util/ca/RestartManager.cpp185
1 files changed, 185 insertions, 0 deletions
diff --git a/src/ext/Util/ca/RestartManager.cpp b/src/ext/Util/ca/RestartManager.cpp
new file mode 100644
index 00000000..c31819c1
--- /dev/null
+++ b/src/ext/Util/ca/RestartManager.cpp
@@ -0,0 +1,185 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4#include <restartmanager.h>
5
6// Include space for the terminating null.
7#define CCH_SESSION_KEY CCH_RM_SESSION_KEY + 1
8
9enum eRmuResourceType
10{
11 etInvalid,
12 etFilename,
13 etApplication,
14 etServiceName,
15
16 // Mask types from Attributes.
17 etTypeMask = 0xf,
18};
19
20LPCWSTR vcsRestartResourceQuery =
21 L"SELECT `Wix4RestartResource`.`Wix4RestartResource`, `Wix4RestartResource`.`Component_`, `Wix4RestartResource`.`Resource`, `Wix4RestartResource`.`Attributes` "
22 L"FROM `Wix4RestartResource`";
23enum eRestartResourceQuery { rrqRestartResource = 1, rrqComponent, rrqResource, rrqAttributes };
24
25/********************************************************************
26WixRegisterRestartResources - Immediate CA to register resources with RM.
27
28Enumerates components before InstallValidate and registers resources
29to be restarted by Restart Manager if the component action
30is anything other than None.
31
32Do not disable file system redirection.
33
34********************************************************************/
35extern "C" UINT __stdcall WixRegisterRestartResources(
36 __in MSIHANDLE hInstall
37 )
38{
39 HRESULT hr = S_OK;
40 UINT er = ERROR_SUCCESS;
41
42 PMSIHANDLE hView = NULL;
43 PMSIHANDLE hRec = NULL;
44
45 LPWSTR wzSessionKey = NULL;
46 size_t cchSessionKey = 0;
47 PRMU_SESSION pSession = NULL;
48
49 LPWSTR wzRestartResource = NULL;
50 LPWSTR wzComponent = NULL;
51 LPWSTR wzResource = NULL;
52 int iAttributes = NULL;
53 BOOL fIsComponentNull = FALSE;
54 WCA_TODO todo = WCA_TODO_UNKNOWN;
55 int iType = etInvalid;
56
57 hr = WcaInitialize(hInstall, "WixRegisterRestartResources");
58 ExitOnFailure(hr, "Failed to initialize.");
59
60 // Skip if the table doesn't exist.
61 if (S_OK != WcaTableExists(L"Wix4RestartResource"))
62 {
63 WcaLog(LOGMSG_STANDARD, "The Wix4RestartResource table does not exist; there are no resources to register with Restart Manager.");
64 ExitFunction();
65 }
66
67 // Get the existing Restart Manager session if available.
68 hr = WcaGetProperty(L"MsiRestartManagerSessionKey", &wzSessionKey);
69 ExitOnFailure(hr, "Failed to get the MsiRestartManagerSessionKey property.");
70
71 hr = ::StringCchLengthW(wzSessionKey, CCH_SESSION_KEY, &cchSessionKey);
72 ExitOnFailure(hr, "Failed to get the MsiRestartManagerSessionKey string length.");
73
74 // Skip if the property doesn't exist.
75 if (0 == cchSessionKey)
76 {
77 WcaLog(LOGMSG_STANDARD, "The MsiRestartManagerSessionKey property is not available to join.");
78 ExitFunction();
79 }
80
81 // Join the existing Restart Manager session if supported.
82 hr = RmuJoinSession(&pSession, wzSessionKey);
83 if (E_MODNOTFOUND == hr)
84 {
85 WcaLog(LOGMSG_STANDARD, "The Restart Manager is not supported on this platform. Skipping.");
86 ExitFunction1(hr = S_OK);
87 }
88 else if (FAILED(hr))
89 {
90 WcaLog(LOGMSG_STANDARD, "Failed to join the existing Restart Manager session %ls.", wzSessionKey);
91 ExitFunction1(hr = S_OK);
92 }
93
94 // Loop through each record in the table.
95 hr = WcaOpenExecuteView(vcsRestartResourceQuery, &hView);
96 ExitOnFailure(hr, "Failed to open a view on the RestartResource table.");
97
98 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
99 {
100 hr = WcaGetRecordString(hRec, rrqRestartResource, &wzRestartResource);
101 ExitOnFailure(hr, "Failed to get the RestartResource field value.");
102
103 hr = WcaGetRecordString(hRec, rrqComponent, &wzComponent);
104 ExitOnFailure(hr, "Failed to get the Component_ field value.");
105
106 hr = WcaGetRecordFormattedString(hRec, rrqResource, &wzResource);
107 ExitOnFailure(hr, "Failed to get the Resource formatted field value.");
108
109 hr = WcaGetRecordInteger(hRec, rrqAttributes, &iAttributes);
110 ExitOnFailure(hr, "Failed to get the Attributes field value.");
111
112 fIsComponentNull = ::MsiRecordIsNull(hRec, rrqComponent);
113 todo = WcaGetComponentToDo(wzComponent);
114
115 // Only register resources for components that are null, or being installed, reinstalled, or uninstalled.
116 if (!fIsComponentNull && WCA_TODO_UNKNOWN == todo)
117 {
118 WcaLog(LOGMSG_VERBOSE, "Skipping resource %ls.", wzRestartResource);
119 continue;
120 }
121
122 // Get the type from Attributes and add to the Restart Manager.
123 iType = iAttributes & etTypeMask;
124 switch (iType)
125 {
126 case etFilename:
127 WcaLog(LOGMSG_VERBOSE, "Registering file name %ls with the Restart Manager.", wzResource);
128 hr = RmuAddFile(pSession, wzResource);
129 ExitOnFailure(hr, "Failed to register the file name with the Restart Manager session.");
130 break;
131
132 case etApplication:
133 WcaLog(LOGMSG_VERBOSE, "Registering process name %ls with the Restart Manager.", wzResource);
134 hr = RmuAddProcessesByName(pSession, wzResource);
135 if (E_NOTFOUND == hr)
136 {
137 // ERROR_ACCESS_DENIED was returned when trying to register this process.
138 // Since other instances may have been registered, log a message and continue the setup rather than failing.
139 WcaLog(LOGMSG_STANDARD, "The process, %ls, could not be registered with the Restart Manager (probably because the setup is not elevated and the process is in another user context). A reboot may be requested later.", wzResource);
140 hr = S_OK;
141 }
142 else
143 {
144 ExitOnFailure(hr, "Failed to register the process name with the Restart Manager session.");
145 }
146 break;
147
148 case etServiceName:
149 WcaLog(LOGMSG_VERBOSE, "Registering service name %ls with the Restart Manager.", wzResource);
150 hr = RmuAddService(pSession, wzResource);
151 ExitOnFailure(hr, "Failed to register the service name with the Restart Manager session.");
152 break;
153
154 default:
155 WcaLog(LOGMSG_VERBOSE, "The resource type %d for %ls is not supported and will not be registered.", iType, wzRestartResource);
156 break;
157 }
158 }
159
160 if (E_NOMOREITEMS == hr)
161 {
162 hr = S_OK;
163 }
164 ExitOnFailure(hr, "Failed while looping through all rows to register resources.");
165
166 // Register the resources and unjoin the session.
167 hr = RmuEndSession(pSession);
168 if (FAILED(hr))
169 {
170 WcaLog(LOGMSG_VERBOSE, "Failed to register the resources with the Restart Manager.");
171 ExitFunction1(hr = S_OK);
172 }
173
174LExit:
175 ReleaseStr(wzRestartResource);
176 ReleaseStr(wzComponent);
177 ReleaseStr(wzResource);
178
179 if (FAILED(hr))
180 {
181 er = ERROR_INSTALL_FAILURE;
182 }
183
184 return WcaFinalize(er);
185}