diff options
Diffstat (limited to 'src/ext/ComPlus/ca/cppartroleexec.cpp')
-rw-r--r-- | src/ext/ComPlus/ca/cppartroleexec.cpp | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/src/ext/ComPlus/ca/cppartroleexec.cpp b/src/ext/ComPlus/ca/cppartroleexec.cpp new file mode 100644 index 00000000..4a503c79 --- /dev/null +++ b/src/ext/ComPlus/ca/cppartroleexec.cpp | |||
@@ -0,0 +1,397 @@ | |||
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 | |||
5 | |||
6 | // private structs | ||
7 | |||
8 | struct CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES | ||
9 | { | ||
10 | int iActionType; | ||
11 | int iActionCost; | ||
12 | LPWSTR pwzKey; | ||
13 | LPWSTR pwzRoleName; | ||
14 | LPWSTR pwzAccount; | ||
15 | LPWSTR pwzPartID; | ||
16 | }; | ||
17 | |||
18 | |||
19 | // prototypes for private helper functions | ||
20 | |||
21 | static HRESULT ReadUserInPartitionRoleAttributes( | ||
22 | LPWSTR* ppwzData, | ||
23 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
24 | ); | ||
25 | static void FreeUserInPartitionRoleAttributes( | ||
26 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
27 | ); | ||
28 | static HRESULT CreateUserInPartitionRole( | ||
29 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
30 | ); | ||
31 | static HRESULT RemoveUserInPartitionRole( | ||
32 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
33 | ); | ||
34 | |||
35 | |||
36 | // function definitions | ||
37 | |||
38 | HRESULT CpiConfigureUsersInPartitionRoles( | ||
39 | LPWSTR* ppwzData, | ||
40 | HANDLE hRollbackFile | ||
41 | ) | ||
42 | { | ||
43 | HRESULT hr = S_OK; | ||
44 | |||
45 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES attrs; | ||
46 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
47 | |||
48 | // read action text | ||
49 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
50 | ExitOnFailure(hr, "Failed to send action start message"); | ||
51 | |||
52 | // ger count | ||
53 | int iCnt = 0; | ||
54 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
55 | ExitOnFailure(hr, "Failed to read count"); | ||
56 | |||
57 | // write count to rollback file | ||
58 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
59 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
60 | |||
61 | for (int i = 0; i < iCnt; i++) | ||
62 | { | ||
63 | // read attributes from CustomActionData | ||
64 | hr = ReadUserInPartitionRoleAttributes(ppwzData, &attrs); | ||
65 | ExitOnFailure(hr, "Failed to read attributes"); | ||
66 | |||
67 | // progress message | ||
68 | hr = CpiActionDataMessage(1, attrs.pwzRoleName); | ||
69 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
70 | |||
71 | if (S_FALSE == hr) | ||
72 | ExitFunction(); | ||
73 | |||
74 | // write key to rollback file | ||
75 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
76 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
77 | |||
78 | // action | ||
79 | switch (attrs.iActionType) | ||
80 | { | ||
81 | case atCreate: | ||
82 | hr = CreateUserInPartitionRole(&attrs); | ||
83 | ExitOnFailure(hr, "Failed to add user to partition role, key: %S", attrs.pwzKey); | ||
84 | break; | ||
85 | case atRemove: | ||
86 | hr = RemoveUserInPartitionRole(&attrs); | ||
87 | ExitOnFailure(hr, "Failed to remove user from partition role, key: %S", attrs.pwzKey); | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | // write completion status to rollback file | ||
92 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
93 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
94 | |||
95 | // progress | ||
96 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
97 | ExitOnFailure(hr, "Failed to update progress"); | ||
98 | } | ||
99 | |||
100 | hr = S_OK; | ||
101 | |||
102 | LExit: | ||
103 | // clean up | ||
104 | FreeUserInPartitionRoleAttributes(&attrs); | ||
105 | |||
106 | return hr; | ||
107 | } | ||
108 | |||
109 | HRESULT CpiRollbackConfigureUsersInPartitionRoles( | ||
110 | LPWSTR* ppwzData, | ||
111 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
112 | ) | ||
113 | { | ||
114 | HRESULT hr = S_OK; | ||
115 | |||
116 | int iRollbackStatus; | ||
117 | |||
118 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES attrs; | ||
119 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
120 | |||
121 | // read action text | ||
122 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
123 | ExitOnFailure(hr, "Failed to send action start message"); | ||
124 | |||
125 | // get count | ||
126 | int iCnt = 0; | ||
127 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
128 | ExitOnFailure(hr, "Failed to read count"); | ||
129 | |||
130 | for (int i = 0; i < iCnt; i++) | ||
131 | { | ||
132 | // read attributes from CustomActionData | ||
133 | hr = ReadUserInPartitionRoleAttributes(ppwzData, &attrs); | ||
134 | ExitOnFailure(hr, "Failed to read attributes"); | ||
135 | |||
136 | // rollback status | ||
137 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
138 | |||
139 | if (S_FALSE == hr) | ||
140 | continue; // not found, nothing to rollback | ||
141 | |||
142 | // progress message | ||
143 | hr = CpiActionDataMessage(1, attrs.pwzRoleName); | ||
144 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
145 | |||
146 | if (S_FALSE == hr) | ||
147 | ExitFunction(); | ||
148 | |||
149 | // action | ||
150 | switch (attrs.iActionType) | ||
151 | { | ||
152 | case atCreate: | ||
153 | hr = CreateUserInPartitionRole(&attrs); | ||
154 | if (FAILED(hr)) | ||
155 | WcaLog(LOGMSG_STANDARD, "Failed to add user to partition role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
156 | break; | ||
157 | case atRemove: | ||
158 | hr = RemoveUserInPartitionRole(&attrs); | ||
159 | if (FAILED(hr)) | ||
160 | WcaLog(LOGMSG_STANDARD, "Failed to remove user from partition role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
161 | break; | ||
162 | } | ||
163 | |||
164 | // check rollback status | ||
165 | if (0 == iRollbackStatus) | ||
166 | continue; // operation did not complete, skip progress | ||
167 | |||
168 | // progress | ||
169 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
170 | ExitOnFailure(hr, "Failed to update progress"); | ||
171 | } | ||
172 | |||
173 | hr = S_OK; | ||
174 | |||
175 | LExit: | ||
176 | // clean up | ||
177 | FreeUserInPartitionRoleAttributes(&attrs); | ||
178 | |||
179 | return hr; | ||
180 | } | ||
181 | |||
182 | |||
183 | // helper function definitions | ||
184 | |||
185 | static HRESULT ReadUserInPartitionRoleAttributes( | ||
186 | LPWSTR* ppwzData, | ||
187 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
188 | ) | ||
189 | { | ||
190 | HRESULT hr = S_OK; | ||
191 | |||
192 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
193 | ExitOnFailure(hr, "Failed to read action type"); | ||
194 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
195 | ExitOnFailure(hr, "Failed to read action cost"); | ||
196 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
197 | ExitOnFailure(hr, "Failed to read key"); | ||
198 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzRoleName); | ||
199 | ExitOnFailure(hr, "Failed to read role name"); | ||
200 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount); | ||
201 | ExitOnFailure(hr, "Failed to read account name"); | ||
202 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
203 | ExitOnFailure(hr, "Failed to read partition id"); | ||
204 | |||
205 | hr = S_OK; | ||
206 | |||
207 | LExit: | ||
208 | return hr; | ||
209 | } | ||
210 | |||
211 | static void FreeUserInPartitionRoleAttributes( | ||
212 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
213 | ) | ||
214 | { | ||
215 | ReleaseStr(pAttrs->pwzKey); | ||
216 | ReleaseStr(pAttrs->pwzRoleName); | ||
217 | ReleaseStr(pAttrs->pwzAccount); | ||
218 | ReleaseStr(pAttrs->pwzPartID); | ||
219 | } | ||
220 | |||
221 | static HRESULT CreateUserInPartitionRole( | ||
222 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
223 | ) | ||
224 | { | ||
225 | HRESULT hr = S_OK; | ||
226 | UINT er = ERROR_SUCCESS; | ||
227 | |||
228 | ICatalogCollection* piUsrInRoleColl = NULL; | ||
229 | ICatalogObject* piUsrInRoleObj = NULL; | ||
230 | |||
231 | PSID pSid = NULL; | ||
232 | long lChanges = 0; | ||
233 | |||
234 | // log | ||
235 | WcaLog(LOGMSG_VERBOSE, "Adding user to partition role, key: %S", pAttrs->pwzKey); | ||
236 | |||
237 | // get users in partition role collection | ||
238 | hr = CpiGetUsersInPartitionRoleCollection(pAttrs->pwzPartID, pAttrs->pwzRoleName, &piUsrInRoleColl); | ||
239 | if (S_FALSE == hr) | ||
240 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
241 | ExitOnFailure(hr, "Failed to get users in partition role collection"); | ||
242 | |||
243 | // get SID for account | ||
244 | do { | ||
245 | er = ERROR_SUCCESS; | ||
246 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
247 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
248 | { | ||
249 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
250 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
251 | switch (er) | ||
252 | { | ||
253 | case IDABORT: | ||
254 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
255 | case IDRETRY: | ||
256 | break; | ||
257 | case IDIGNORE: | ||
258 | default: | ||
259 | ExitFunction1(hr = S_OK); | ||
260 | } | ||
261 | } | ||
262 | else | ||
263 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
264 | } while (IDRETRY == er); | ||
265 | |||
266 | // find any existing entry | ||
267 | hr = CpiFindUserCollectionObject(piUsrInRoleColl, pSid, NULL); | ||
268 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
269 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
270 | else | ||
271 | ExitOnFailure(hr, "Failed to find user in partition role"); | ||
272 | |||
273 | if (S_OK == hr) | ||
274 | { | ||
275 | WcaLog(LOGMSG_VERBOSE, "User already assigned to partition role, key: %S", pAttrs->pwzKey); | ||
276 | ExitFunction(); // exit with hr = S_OK | ||
277 | } | ||
278 | |||
279 | // convert SID back to account name | ||
280 | hr = CpiSidToAccountName(pSid, &pAttrs->pwzAccount); | ||
281 | ExitOnFailure(hr, "Failed to convert SID to account name"); | ||
282 | |||
283 | // add user | ||
284 | hr = CpiAddCollectionObject(piUsrInRoleColl, &piUsrInRoleObj); | ||
285 | ExitOnFailure(hr, "Failed to add user in role to collection"); | ||
286 | |||
287 | hr = CpiPutCollectionObjectValue(piUsrInRoleObj, L"User", pAttrs->pwzAccount); | ||
288 | ExitOnFailure(hr, "Failed to set role name property"); | ||
289 | |||
290 | // save changes | ||
291 | hr = piUsrInRoleColl->SaveChanges(&lChanges); | ||
292 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
293 | CpiLogCatalogErrorInfo(); | ||
294 | ExitOnFailure(hr, "Failed to save changes"); | ||
295 | |||
296 | // log | ||
297 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
298 | |||
299 | hr = S_OK; | ||
300 | |||
301 | LExit: | ||
302 | // clean up | ||
303 | ReleaseObject(piUsrInRoleColl); | ||
304 | ReleaseObject(piUsrInRoleObj); | ||
305 | |||
306 | if (pSid) | ||
307 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
308 | |||
309 | return hr; | ||
310 | } | ||
311 | |||
312 | static HRESULT RemoveUserInPartitionRole( | ||
313 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
314 | ) | ||
315 | { | ||
316 | HRESULT hr = S_OK; | ||
317 | UINT er = ERROR_SUCCESS; | ||
318 | |||
319 | ICatalogCollection* piUsrInRoleColl = NULL; | ||
320 | |||
321 | PSID pSid = NULL; | ||
322 | long lChanges = 0; | ||
323 | |||
324 | // log | ||
325 | WcaLog(LOGMSG_VERBOSE, "Removing user from partition role, key: %S", pAttrs->pwzKey); | ||
326 | |||
327 | // get users in partition role collection | ||
328 | hr = CpiGetUsersInPartitionRoleCollection(pAttrs->pwzPartID, pAttrs->pwzRoleName, &piUsrInRoleColl); | ||
329 | ExitOnFailure(hr, "Failed to get users in partition role collection"); | ||
330 | |||
331 | if (S_FALSE == hr) | ||
332 | { | ||
333 | // users in role collection not found | ||
334 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve users in partition role collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
335 | ExitFunction1(hr = S_OK); | ||
336 | } | ||
337 | |||
338 | // get SID for account | ||
339 | do { | ||
340 | er = ERROR_SUCCESS; | ||
341 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
342 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
343 | { | ||
344 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
345 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
346 | switch (er) | ||
347 | { | ||
348 | case IDABORT: | ||
349 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
350 | case IDRETRY: | ||
351 | break; | ||
352 | case IDIGNORE: | ||
353 | default: | ||
354 | ExitFunction1(hr = S_OK); | ||
355 | } | ||
356 | } | ||
357 | else | ||
358 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
359 | } while (IDRETRY == er); | ||
360 | |||
361 | // remove | ||
362 | hr = CpiRemoveUserCollectionObject(piUsrInRoleColl, pSid); | ||
363 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
364 | { | ||
365 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
366 | hr = S_FALSE; | ||
367 | } | ||
368 | else | ||
369 | ExitOnFailure(hr, "Failed to remove user"); | ||
370 | |||
371 | if (S_FALSE == hr) | ||
372 | { | ||
373 | // role not found | ||
374 | WcaLog(LOGMSG_VERBOSE, "User not found for partition role, nothing to delete, key: %S", pAttrs->pwzKey); | ||
375 | ExitFunction1(hr = S_OK); | ||
376 | } | ||
377 | |||
378 | // save changes | ||
379 | hr = piUsrInRoleColl->SaveChanges(&lChanges); | ||
380 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
381 | CpiLogCatalogErrorInfo(); | ||
382 | ExitOnFailure(hr, "Failed to save changes"); | ||
383 | |||
384 | // log | ||
385 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
386 | |||
387 | hr = S_OK; | ||
388 | |||
389 | LExit: | ||
390 | // clean up | ||
391 | ReleaseObject(piUsrInRoleColl); | ||
392 | |||
393 | if (pSid) | ||
394 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
395 | |||
396 | return hr; | ||
397 | } | ||