diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2019-02-04 20:05:54 -0600 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2019-02-04 20:05:54 -0600 |
commit | cbc09b6cd6d0d0b8bf095a88d4d8333616637f71 (patch) | |
tree | a0893e8b8772765747630052018312a2d77f97e4 | |
parent | c94f50e3d8dc958f8a0b9540e63e920a079c1779 (diff) | |
download | wix-cbc09b6cd6d0d0b8bf095a88d4d8333616637f71.tar.gz wix-cbc09b6cd6d0d0b8bf095a88d4d8333616637f71.tar.bz2 wix-cbc09b6cd6d0d0b8bf095a88d4d8333616637f71.zip |
Import code from old v4 repo
44 files changed, 21074 insertions, 0 deletions
diff --git a/src/ca/cpappexec.cpp b/src/ca/cpappexec.cpp new file mode 100644 index 00000000..43d6cd6d --- /dev/null +++ b/src/ca/cpappexec.cpp | |||
@@ -0,0 +1,344 @@ | |||
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_APPLICATION_ATTRIBUTES | ||
9 | { | ||
10 | int iActionType; | ||
11 | int iActionCost; | ||
12 | LPWSTR pwzKey; | ||
13 | LPWSTR pwzID; | ||
14 | LPWSTR pwzName; | ||
15 | LPWSTR pwzPartID; | ||
16 | CPI_PROPERTY* pPropList; | ||
17 | }; | ||
18 | |||
19 | |||
20 | // prototypes for private helper functions | ||
21 | |||
22 | static HRESULT ReadApplicationAttributes( | ||
23 | LPWSTR* ppwzData, | ||
24 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
25 | ); | ||
26 | static void FreeApplicationAttributes( | ||
27 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
28 | ); | ||
29 | static HRESULT CreateApplication( | ||
30 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
31 | ); | ||
32 | static HRESULT RemoveApplication( | ||
33 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
34 | ); | ||
35 | |||
36 | |||
37 | // function definitions | ||
38 | |||
39 | HRESULT CpiConfigureApplications( | ||
40 | LPWSTR* ppwzData, | ||
41 | HANDLE hRollbackFile | ||
42 | ) | ||
43 | { | ||
44 | HRESULT hr = S_OK; | ||
45 | |||
46 | CPI_APPLICATION_ATTRIBUTES attrs; | ||
47 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
48 | |||
49 | // read action text | ||
50 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
51 | ExitOnFailure(hr, "Failed to send action start message"); | ||
52 | |||
53 | // get count | ||
54 | int iCnt = 0; | ||
55 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
56 | ExitOnFailure(hr, "Failed to read count"); | ||
57 | |||
58 | // write count to rollback file | ||
59 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
60 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
61 | |||
62 | for (int i = 0; i < iCnt; i++) | ||
63 | { | ||
64 | // read attributes from CustomActionData | ||
65 | hr = ReadApplicationAttributes(ppwzData, &attrs); | ||
66 | ExitOnFailure(hr, "Failed to read attributes"); | ||
67 | |||
68 | // progress message | ||
69 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
70 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
71 | |||
72 | if (S_FALSE == hr) | ||
73 | ExitFunction(); | ||
74 | |||
75 | // write key to rollback file | ||
76 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
77 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
78 | |||
79 | // action | ||
80 | switch (attrs.iActionType) | ||
81 | { | ||
82 | case atCreate: | ||
83 | hr = CreateApplication(&attrs); | ||
84 | ExitOnFailure(hr, "Failed to create application, key: %S", attrs.pwzKey); | ||
85 | break; | ||
86 | case atRemove: | ||
87 | hr = RemoveApplication(&attrs); | ||
88 | ExitOnFailure(hr, "Failed to remove application, key: %S", attrs.pwzKey); | ||
89 | break; | ||
90 | } | ||
91 | |||
92 | // write completion status to rollback file | ||
93 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
94 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
95 | |||
96 | // progress | ||
97 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
98 | ExitOnFailure(hr, "Failed to update progress"); | ||
99 | } | ||
100 | |||
101 | hr = S_OK; | ||
102 | |||
103 | LExit: | ||
104 | // clean up | ||
105 | FreeApplicationAttributes(&attrs); | ||
106 | |||
107 | return hr; | ||
108 | } | ||
109 | |||
110 | HRESULT CpiRollbackConfigureApplications( | ||
111 | LPWSTR* ppwzData, | ||
112 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
113 | ) | ||
114 | { | ||
115 | HRESULT hr = S_OK; | ||
116 | |||
117 | int iRollbackStatus; | ||
118 | |||
119 | CPI_APPLICATION_ATTRIBUTES attrs; | ||
120 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
121 | |||
122 | // read action text | ||
123 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
124 | ExitOnFailure(hr, "Failed to send action start message"); | ||
125 | |||
126 | // get count | ||
127 | int iCnt = 0; | ||
128 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
129 | ExitOnFailure(hr, "Failed to read count"); | ||
130 | |||
131 | for (int i = 0; i < iCnt; i++) | ||
132 | { | ||
133 | // read attributes from CustomActionData | ||
134 | hr = ReadApplicationAttributes(ppwzData, &attrs); | ||
135 | ExitOnFailure(hr, "Failed to read attributes"); | ||
136 | |||
137 | // rollback status | ||
138 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
139 | |||
140 | if (S_FALSE == hr) | ||
141 | continue; // not found, nothing to rollback | ||
142 | |||
143 | // progress message | ||
144 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
145 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
146 | |||
147 | if (S_FALSE == hr) | ||
148 | ExitFunction(); | ||
149 | |||
150 | // action | ||
151 | switch (attrs.iActionType) | ||
152 | { | ||
153 | case atCreate: | ||
154 | hr = CreateApplication(&attrs); | ||
155 | if (FAILED(hr)) | ||
156 | WcaLog(LOGMSG_STANDARD, "Failed to create application, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
157 | break; | ||
158 | case atRemove: | ||
159 | hr = RemoveApplication(&attrs); | ||
160 | if (FAILED(hr)) | ||
161 | WcaLog(LOGMSG_STANDARD, "Failed to remove application, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
162 | break; | ||
163 | } | ||
164 | |||
165 | // check rollback status | ||
166 | if (0 == iRollbackStatus) | ||
167 | continue; // operation did not complete, skip progress | ||
168 | |||
169 | // progress | ||
170 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
171 | ExitOnFailure(hr, "Failed to update progress"); | ||
172 | } | ||
173 | |||
174 | hr = S_OK; | ||
175 | |||
176 | LExit: | ||
177 | // clean up | ||
178 | FreeApplicationAttributes(&attrs); | ||
179 | |||
180 | return hr; | ||
181 | } | ||
182 | |||
183 | |||
184 | // helper function definitions | ||
185 | |||
186 | static HRESULT ReadApplicationAttributes( | ||
187 | LPWSTR* ppwzData, | ||
188 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
189 | ) | ||
190 | { | ||
191 | HRESULT hr = S_OK; | ||
192 | |||
193 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
194 | ExitOnFailure(hr, "Failed to read action type"); | ||
195 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
196 | ExitOnFailure(hr, "Failed to read action cost"); | ||
197 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
198 | ExitOnFailure(hr, "Failed to read key"); | ||
199 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzID); | ||
200 | ExitOnFailure(hr, "Failed to read id"); | ||
201 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName); | ||
202 | ExitOnFailure(hr, "Failed to read name"); | ||
203 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
204 | ExitOnFailure(hr, "Failed to read partition id"); | ||
205 | hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList); | ||
206 | ExitOnFailure(hr, "Failed to read properties"); | ||
207 | |||
208 | hr = S_OK; | ||
209 | |||
210 | LExit: | ||
211 | return hr; | ||
212 | } | ||
213 | |||
214 | static void FreeApplicationAttributes( | ||
215 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
216 | ) | ||
217 | { | ||
218 | ReleaseStr(pAttrs->pwzKey); | ||
219 | ReleaseStr(pAttrs->pwzID); | ||
220 | ReleaseStr(pAttrs->pwzName); | ||
221 | ReleaseStr(pAttrs->pwzPartID); | ||
222 | |||
223 | if (pAttrs->pPropList) | ||
224 | CpiFreePropertyList(pAttrs->pPropList); | ||
225 | } | ||
226 | |||
227 | static HRESULT CreateApplication( | ||
228 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
229 | ) | ||
230 | { | ||
231 | HRESULT hr = S_OK; | ||
232 | |||
233 | ICatalogCollection* piAppColl = NULL; | ||
234 | ICatalogObject* piAppObj = NULL; | ||
235 | |||
236 | long lChanges = 0; | ||
237 | |||
238 | // log | ||
239 | WcaLog(LOGMSG_VERBOSE, "Creating application, key: %S", pAttrs->pwzKey); | ||
240 | |||
241 | // get applications collection | ||
242 | hr = CpiGetApplicationsCollection(pAttrs->pwzPartID, &piAppColl); | ||
243 | if (S_FALSE == hr) | ||
244 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
245 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
246 | |||
247 | // check if application exists | ||
248 | hr = CpiFindCollectionObjectByStringKey(piAppColl, pAttrs->pwzID, &piAppObj); | ||
249 | ExitOnFailure(hr, "Failed to find application"); | ||
250 | |||
251 | if (S_FALSE == hr) | ||
252 | { | ||
253 | // create application | ||
254 | hr = CpiAddCollectionObject(piAppColl, &piAppObj); | ||
255 | ExitOnFailure(hr, "Failed to add application to collection"); | ||
256 | |||
257 | hr = CpiPutCollectionObjectValue(piAppObj, L"ID", pAttrs->pwzID); | ||
258 | ExitOnFailure(hr, "Failed to set application id property"); | ||
259 | |||
260 | hr = CpiPutCollectionObjectValue(piAppObj, L"Name", pAttrs->pwzName); | ||
261 | ExitOnFailure(hr, "Failed to set application name property"); | ||
262 | |||
263 | // save changes | ||
264 | hr = piAppColl->SaveChanges(&lChanges); | ||
265 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
266 | CpiLogCatalogErrorInfo(); | ||
267 | ExitOnFailure(hr, "Failed to add application"); | ||
268 | } | ||
269 | |||
270 | // properties | ||
271 | hr = CpiPutCollectionObjectValues(piAppObj, pAttrs->pPropList); | ||
272 | ExitOnFailure(hr, "Failed to write properties"); | ||
273 | |||
274 | // save changes | ||
275 | hr = piAppColl->SaveChanges(&lChanges); | ||
276 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
277 | CpiLogCatalogErrorInfo(); | ||
278 | ExitOnFailure(hr, "Failed to save changes"); | ||
279 | |||
280 | // log | ||
281 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
282 | |||
283 | hr = S_OK; | ||
284 | |||
285 | LExit: | ||
286 | // clean up | ||
287 | ReleaseObject(piAppColl); | ||
288 | ReleaseObject(piAppObj); | ||
289 | |||
290 | return hr; | ||
291 | } | ||
292 | |||
293 | static HRESULT RemoveApplication( | ||
294 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
295 | ) | ||
296 | { | ||
297 | HRESULT hr = S_OK; | ||
298 | |||
299 | ICatalogCollection* piAppColl = NULL; | ||
300 | |||
301 | long lChanges = 0; | ||
302 | |||
303 | // log | ||
304 | WcaLog(LOGMSG_VERBOSE, "Removing application, key: %S", pAttrs->pwzKey); | ||
305 | |||
306 | // get applications collection | ||
307 | hr = CpiGetApplicationsCollection(pAttrs->pwzPartID, &piAppColl); | ||
308 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
309 | |||
310 | if (S_FALSE == hr) | ||
311 | { | ||
312 | // applications collection not found | ||
313 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve applications collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
314 | ExitFunction1(hr = S_OK); | ||
315 | } | ||
316 | |||
317 | // remove | ||
318 | hr = CpiRemoveCollectionObject(piAppColl, pAttrs->pwzID, NULL, TRUE); | ||
319 | ExitOnFailure(hr, "Failed to remove application"); | ||
320 | |||
321 | if (S_FALSE == hr) | ||
322 | { | ||
323 | // application not found | ||
324 | WcaLog(LOGMSG_VERBOSE, "Application not found, nothing to delete, key: %S", pAttrs->pwzKey); | ||
325 | ExitFunction1(hr = S_OK); | ||
326 | } | ||
327 | |||
328 | // save changes | ||
329 | hr = piAppColl->SaveChanges(&lChanges); | ||
330 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
331 | CpiLogCatalogErrorInfo(); | ||
332 | ExitOnFailure(hr, "Failed to save changes"); | ||
333 | |||
334 | // log | ||
335 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
336 | |||
337 | hr = S_OK; | ||
338 | |||
339 | LExit: | ||
340 | // clean up | ||
341 | ReleaseObject(piAppColl); | ||
342 | |||
343 | return hr; | ||
344 | } | ||
diff --git a/src/ca/cpappexec.h b/src/ca/cpappexec.h new file mode 100644 index 00000000..5003b046 --- /dev/null +++ b/src/ca/cpappexec.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | HRESULT CpiConfigureApplications( | ||
6 | LPWSTR* ppwzData, | ||
7 | HANDLE hRollbackFile | ||
8 | ); | ||
9 | HRESULT CpiRollbackConfigureApplications( | ||
10 | LPWSTR* ppwzData, | ||
11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
12 | ); | ||
diff --git a/src/ca/cpapproleexec.cpp b/src/ca/cpapproleexec.cpp new file mode 100644 index 00000000..e3b71e93 --- /dev/null +++ b/src/ca/cpapproleexec.cpp | |||
@@ -0,0 +1,720 @@ | |||
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_APPLICATION_ROLE_ATTRIBUTES | ||
9 | { | ||
10 | int iActionType; | ||
11 | int iActionCost; | ||
12 | LPWSTR pwzKey; | ||
13 | LPWSTR pwzName; | ||
14 | LPWSTR pwzAppID; | ||
15 | LPWSTR pwzPartID; | ||
16 | CPI_PROPERTY* pPropList; | ||
17 | }; | ||
18 | |||
19 | struct CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES | ||
20 | { | ||
21 | int iActionType; | ||
22 | int iActionCost; | ||
23 | LPWSTR pwzKey; | ||
24 | LPWSTR pwzRoleName; | ||
25 | LPWSTR pwzAccount; | ||
26 | LPWSTR pwzAppID; | ||
27 | LPWSTR pwzPartID; | ||
28 | }; | ||
29 | |||
30 | |||
31 | // prototypes for private helper functions | ||
32 | |||
33 | static HRESULT ReadApplicationRoleAttributes( | ||
34 | LPWSTR* ppwzData, | ||
35 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
36 | ); | ||
37 | static void FreeApplicationRoleAttributes( | ||
38 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
39 | ); | ||
40 | static HRESULT CreateApplicationRole( | ||
41 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
42 | ); | ||
43 | static HRESULT RemoveApplicationRole( | ||
44 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
45 | ); | ||
46 | static HRESULT ReadUsersInApplicationRoleAttributes( | ||
47 | LPWSTR* ppwzData, | ||
48 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
49 | ); | ||
50 | static void FreeUsersInApplicationRoleAttributes( | ||
51 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
52 | ); | ||
53 | static HRESULT CreateUsersInApplicationRole( | ||
54 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
55 | ); | ||
56 | static HRESULT RemoveUsersInApplicationRole( | ||
57 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
58 | ); | ||
59 | |||
60 | |||
61 | // function definitions | ||
62 | |||
63 | HRESULT CpiConfigureApplicationRoles( | ||
64 | LPWSTR* ppwzData, | ||
65 | HANDLE hRollbackFile | ||
66 | ) | ||
67 | { | ||
68 | HRESULT hr = S_OK; | ||
69 | |||
70 | CPI_APPLICATION_ROLE_ATTRIBUTES attrs; | ||
71 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
72 | |||
73 | // read action text | ||
74 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
75 | ExitOnFailure(hr, "Failed to send action start message"); | ||
76 | |||
77 | // ger count | ||
78 | int iCnt = 0; | ||
79 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
80 | ExitOnFailure(hr, "Failed to read count"); | ||
81 | |||
82 | // write count to rollback file | ||
83 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
84 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
85 | |||
86 | for (int i = 0; i < iCnt; i++) | ||
87 | { | ||
88 | // read attributes from CustomActionData | ||
89 | hr = ReadApplicationRoleAttributes(ppwzData, &attrs); | ||
90 | ExitOnFailure(hr, "Failed to read attributes"); | ||
91 | |||
92 | // progress message | ||
93 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
94 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
95 | |||
96 | if (S_FALSE == hr) | ||
97 | ExitFunction(); | ||
98 | |||
99 | // write key to rollback file | ||
100 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
101 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
102 | |||
103 | // action | ||
104 | switch (attrs.iActionType) | ||
105 | { | ||
106 | case atCreate: | ||
107 | hr = CreateApplicationRole(&attrs); | ||
108 | ExitOnFailure(hr, "Failed to create application role, key: %S", attrs.pwzKey); | ||
109 | break; | ||
110 | case atRemove: | ||
111 | hr = RemoveApplicationRole(&attrs); | ||
112 | ExitOnFailure(hr, "Failed to remove application role, key: %S", attrs.pwzKey); | ||
113 | break; | ||
114 | } | ||
115 | |||
116 | // write completion status to rollback file | ||
117 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
118 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
119 | |||
120 | // progress | ||
121 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
122 | ExitOnFailure(hr, "Failed to update progress"); | ||
123 | } | ||
124 | |||
125 | hr = S_OK; | ||
126 | |||
127 | LExit: | ||
128 | // clean up | ||
129 | FreeApplicationRoleAttributes(&attrs); | ||
130 | |||
131 | return hr; | ||
132 | } | ||
133 | |||
134 | HRESULT CpiRollbackConfigureApplicationRoles( | ||
135 | LPWSTR* ppwzData, | ||
136 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
137 | ) | ||
138 | { | ||
139 | HRESULT hr = S_OK; | ||
140 | |||
141 | int iRollbackStatus; | ||
142 | |||
143 | CPI_APPLICATION_ROLE_ATTRIBUTES attrs; | ||
144 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
145 | |||
146 | // read action text | ||
147 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
148 | ExitOnFailure(hr, "Failed to send action start message"); | ||
149 | |||
150 | // get count | ||
151 | int iCnt = 0; | ||
152 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
153 | ExitOnFailure(hr, "Failed to read count"); | ||
154 | |||
155 | for (int i = 0; i < iCnt; i++) | ||
156 | { | ||
157 | // read attributes from CustomActionData | ||
158 | hr = ReadApplicationRoleAttributes(ppwzData, &attrs); | ||
159 | ExitOnFailure(hr, "Failed to read attributes"); | ||
160 | |||
161 | // rollback status | ||
162 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
163 | |||
164 | if (S_FALSE == hr) | ||
165 | continue; // not found, nothing to rollback | ||
166 | |||
167 | // progress message | ||
168 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
169 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
170 | |||
171 | if (S_FALSE == hr) | ||
172 | ExitFunction(); | ||
173 | |||
174 | // action | ||
175 | switch (attrs.iActionType) | ||
176 | { | ||
177 | case atCreate: | ||
178 | hr = CreateApplicationRole(&attrs); | ||
179 | if (FAILED(hr)) | ||
180 | WcaLog(LOGMSG_STANDARD, "Failed to create application role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
181 | break; | ||
182 | case atRemove: | ||
183 | hr = RemoveApplicationRole(&attrs); | ||
184 | if (FAILED(hr)) | ||
185 | WcaLog(LOGMSG_STANDARD, "Failed to remove application role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
186 | break; | ||
187 | } | ||
188 | |||
189 | // check rollback status | ||
190 | if (0 == iRollbackStatus) | ||
191 | continue; // operation did not complete, skip progress | ||
192 | |||
193 | // progress | ||
194 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
195 | ExitOnFailure(hr, "Failed to update progress"); | ||
196 | } | ||
197 | |||
198 | hr = S_OK; | ||
199 | |||
200 | LExit: | ||
201 | // clean up | ||
202 | FreeApplicationRoleAttributes(&attrs); | ||
203 | |||
204 | return hr; | ||
205 | } | ||
206 | |||
207 | HRESULT CpiConfigureUsersInApplicationRoles( | ||
208 | LPWSTR* ppwzData, | ||
209 | HANDLE hRollbackFile | ||
210 | ) | ||
211 | { | ||
212 | HRESULT hr = S_OK; | ||
213 | |||
214 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES attrs; | ||
215 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
216 | |||
217 | // read action text | ||
218 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
219 | ExitOnFailure(hr, "Failed to send action start message"); | ||
220 | |||
221 | // ger count | ||
222 | int iCnt = 0; | ||
223 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
224 | ExitOnFailure(hr, "Failed to read count"); | ||
225 | |||
226 | // write count to rollback file | ||
227 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
228 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
229 | |||
230 | for (int i = 0; i < iCnt; i++) | ||
231 | { | ||
232 | // read attributes from CustomActionData | ||
233 | hr = ReadUsersInApplicationRoleAttributes(ppwzData, &attrs); | ||
234 | ExitOnFailure(hr, "Failed to read attributes"); | ||
235 | |||
236 | // progress message | ||
237 | hr = CpiActionDataMessage(1, attrs.pwzRoleName); | ||
238 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
239 | |||
240 | if (S_FALSE == hr) | ||
241 | ExitFunction(); | ||
242 | |||
243 | // write key to rollback file | ||
244 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
245 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
246 | |||
247 | // action | ||
248 | switch (attrs.iActionType) | ||
249 | { | ||
250 | case atCreate: | ||
251 | hr = CreateUsersInApplicationRole(&attrs); | ||
252 | ExitOnFailure(hr, "Failed to create user in application role, key: %S", attrs.pwzKey); | ||
253 | break; | ||
254 | case atRemove: | ||
255 | hr = RemoveUsersInApplicationRole(&attrs); | ||
256 | ExitOnFailure(hr, "Failed to remove user from application role, key: %S", attrs.pwzKey); | ||
257 | break; | ||
258 | } | ||
259 | |||
260 | // write completion status to rollback file | ||
261 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
262 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
263 | |||
264 | // progress | ||
265 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
266 | ExitOnFailure(hr, "Failed to update progress"); | ||
267 | } | ||
268 | |||
269 | hr = S_OK; | ||
270 | |||
271 | LExit: | ||
272 | // clean up | ||
273 | FreeUsersInApplicationRoleAttributes(&attrs); | ||
274 | |||
275 | return hr; | ||
276 | } | ||
277 | |||
278 | HRESULT CpiRollbackConfigureUsersInApplicationRoles( | ||
279 | LPWSTR* ppwzData, | ||
280 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
281 | ) | ||
282 | { | ||
283 | HRESULT hr = S_OK; | ||
284 | |||
285 | int iRollbackStatus; | ||
286 | |||
287 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES attrs; | ||
288 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
289 | |||
290 | // read action text | ||
291 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
292 | ExitOnFailure(hr, "Failed to send action start message"); | ||
293 | |||
294 | // get count | ||
295 | int iCnt = 0; | ||
296 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
297 | ExitOnFailure(hr, "Failed to read count"); | ||
298 | |||
299 | for (int i = 0; i < iCnt; i++) | ||
300 | { | ||
301 | // read attributes from CustomActionData | ||
302 | hr = ReadUsersInApplicationRoleAttributes(ppwzData, &attrs); | ||
303 | ExitOnFailure(hr, "Failed to read attributes"); | ||
304 | |||
305 | // rollback status | ||
306 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
307 | |||
308 | if (S_FALSE == hr) | ||
309 | continue; // not found, nothing to rollback | ||
310 | |||
311 | // progress message | ||
312 | hr = CpiActionDataMessage(1, attrs.pwzRoleName); | ||
313 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
314 | |||
315 | if (S_FALSE == hr) | ||
316 | ExitFunction(); | ||
317 | |||
318 | // action | ||
319 | switch (attrs.iActionType) | ||
320 | { | ||
321 | case atCreate: | ||
322 | hr = CreateUsersInApplicationRole(&attrs); | ||
323 | if (FAILED(hr)) | ||
324 | WcaLog(LOGMSG_STANDARD, "Failed to add user to application role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
325 | break; | ||
326 | case atRemove: | ||
327 | hr = RemoveUsersInApplicationRole(&attrs); | ||
328 | if (FAILED(hr)) | ||
329 | WcaLog(LOGMSG_STANDARD, "Failed to remove user from application role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
330 | break; | ||
331 | } | ||
332 | |||
333 | // check rollback status | ||
334 | if (0 == iRollbackStatus) | ||
335 | continue; // operation did not complete, skip progress | ||
336 | |||
337 | // progress | ||
338 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
339 | ExitOnFailure(hr, "Failed to update progress"); | ||
340 | } | ||
341 | |||
342 | hr = S_OK; | ||
343 | |||
344 | LExit: | ||
345 | // clean up | ||
346 | FreeUsersInApplicationRoleAttributes(&attrs); | ||
347 | |||
348 | return hr; | ||
349 | } | ||
350 | |||
351 | |||
352 | // helper function definitions | ||
353 | |||
354 | static HRESULT ReadApplicationRoleAttributes( | ||
355 | LPWSTR* ppwzData, | ||
356 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
357 | ) | ||
358 | { | ||
359 | HRESULT hr = S_OK; | ||
360 | |||
361 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
362 | ExitOnFailure(hr, "Failed to read action type"); | ||
363 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
364 | ExitOnFailure(hr, "Failed to read action cost"); | ||
365 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
366 | ExitOnFailure(hr, "Failed to read key"); | ||
367 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName); | ||
368 | ExitOnFailure(hr, "Failed to read name"); | ||
369 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
370 | ExitOnFailure(hr, "Failed to read application id"); | ||
371 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
372 | ExitOnFailure(hr, "Failed to read partition id"); | ||
373 | hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList); | ||
374 | ExitOnFailure(hr, "Failed to read properties"); | ||
375 | |||
376 | hr = S_OK; | ||
377 | |||
378 | LExit: | ||
379 | return hr; | ||
380 | } | ||
381 | |||
382 | static void FreeApplicationRoleAttributes( | ||
383 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
384 | ) | ||
385 | { | ||
386 | ReleaseStr(pAttrs->pwzKey); | ||
387 | ReleaseStr(pAttrs->pwzName); | ||
388 | ReleaseStr(pAttrs->pwzAppID); | ||
389 | ReleaseStr(pAttrs->pwzPartID); | ||
390 | |||
391 | if (pAttrs->pPropList) | ||
392 | CpiFreePropertyList(pAttrs->pPropList); | ||
393 | } | ||
394 | |||
395 | static HRESULT CreateApplicationRole( | ||
396 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
397 | ) | ||
398 | { | ||
399 | HRESULT hr = S_OK; | ||
400 | |||
401 | ICatalogCollection* piRolesColl = NULL; | ||
402 | ICatalogObject* piRoleObj = NULL; | ||
403 | |||
404 | long lChanges = 0; | ||
405 | |||
406 | // log | ||
407 | WcaLog(LOGMSG_VERBOSE, "Creating application role, key: %S", pAttrs->pwzKey); | ||
408 | |||
409 | // get roles collection | ||
410 | hr = CpiGetRolesCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piRolesColl); | ||
411 | if (S_FALSE == hr) | ||
412 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
413 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
414 | |||
415 | // check if role exists | ||
416 | hr = CpiFindCollectionObjectByName(piRolesColl, pAttrs->pwzName, &piRoleObj); | ||
417 | ExitOnFailure(hr, "Failed to find role"); | ||
418 | |||
419 | if (S_FALSE == hr) | ||
420 | { | ||
421 | // create role | ||
422 | hr = CpiAddCollectionObject(piRolesColl, &piRoleObj); | ||
423 | ExitOnFailure(hr, "Failed to add role to collection"); | ||
424 | |||
425 | hr = CpiPutCollectionObjectValue(piRoleObj, L"Name", pAttrs->pwzName); | ||
426 | ExitOnFailure(hr, "Failed to set role name property"); | ||
427 | } | ||
428 | |||
429 | // properties | ||
430 | hr = CpiPutCollectionObjectValues(piRoleObj, pAttrs->pPropList); | ||
431 | ExitOnFailure(hr, "Failed to write properties"); | ||
432 | |||
433 | // save changes | ||
434 | hr = piRolesColl->SaveChanges(&lChanges); | ||
435 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
436 | CpiLogCatalogErrorInfo(); | ||
437 | ExitOnFailure(hr, "Failed to save changes"); | ||
438 | |||
439 | // log | ||
440 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
441 | |||
442 | hr = S_OK; | ||
443 | |||
444 | LExit: | ||
445 | // clean up | ||
446 | ReleaseObject(piRolesColl); | ||
447 | ReleaseObject(piRoleObj); | ||
448 | |||
449 | return hr; | ||
450 | } | ||
451 | |||
452 | static HRESULT RemoveApplicationRole( | ||
453 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
454 | ) | ||
455 | { | ||
456 | HRESULT hr = S_OK; | ||
457 | |||
458 | ICatalogCollection* piRolesColl = NULL; | ||
459 | |||
460 | long lChanges = 0; | ||
461 | |||
462 | // log | ||
463 | WcaLog(LOGMSG_VERBOSE, "Removing application role, key: %S", pAttrs->pwzKey); | ||
464 | |||
465 | // get roles collection | ||
466 | hr = CpiGetRolesCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piRolesColl); | ||
467 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
468 | |||
469 | if (S_FALSE == hr) | ||
470 | { | ||
471 | // roles collection not found | ||
472 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve roles collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
473 | ExitFunction1(hr = S_OK); | ||
474 | } | ||
475 | |||
476 | // remove | ||
477 | hr = CpiRemoveCollectionObject(piRolesColl, NULL, pAttrs->pwzName, FALSE); | ||
478 | ExitOnFailure(hr, "Failed to remove role"); | ||
479 | |||
480 | if (S_FALSE == hr) | ||
481 | { | ||
482 | // role not found | ||
483 | WcaLog(LOGMSG_VERBOSE, "Role not found, nothing to delete, key: %S", pAttrs->pwzKey); | ||
484 | ExitFunction1(hr = S_OK); | ||
485 | } | ||
486 | |||
487 | // save changes | ||
488 | hr = piRolesColl->SaveChanges(&lChanges); | ||
489 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
490 | CpiLogCatalogErrorInfo(); | ||
491 | ExitOnFailure(hr, "Failed to save changes"); | ||
492 | |||
493 | // log | ||
494 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
495 | |||
496 | hr = S_OK; | ||
497 | |||
498 | LExit: | ||
499 | // clean up | ||
500 | ReleaseObject(piRolesColl); | ||
501 | |||
502 | return hr; | ||
503 | } | ||
504 | |||
505 | static HRESULT ReadUsersInApplicationRoleAttributes( | ||
506 | LPWSTR* ppwzData, | ||
507 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
508 | ) | ||
509 | { | ||
510 | HRESULT hr = S_OK; | ||
511 | |||
512 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
513 | ExitOnFailure(hr, "Failed to read action type"); | ||
514 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
515 | ExitOnFailure(hr, "Failed to read action cost"); | ||
516 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
517 | ExitOnFailure(hr, "Failed to read key"); | ||
518 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzRoleName); | ||
519 | ExitOnFailure(hr, "Failed to read role name"); | ||
520 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount); | ||
521 | ExitOnFailure(hr, "Failed to read account name"); | ||
522 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
523 | ExitOnFailure(hr, "Failed to read application id"); | ||
524 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
525 | ExitOnFailure(hr, "Failed to read partition id"); | ||
526 | |||
527 | hr = S_OK; | ||
528 | |||
529 | LExit: | ||
530 | return hr; | ||
531 | } | ||
532 | |||
533 | static void FreeUsersInApplicationRoleAttributes( | ||
534 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
535 | ) | ||
536 | { | ||
537 | ReleaseStr(pAttrs->pwzKey); | ||
538 | ReleaseStr(pAttrs->pwzRoleName); | ||
539 | ReleaseStr(pAttrs->pwzAccount); | ||
540 | ReleaseStr(pAttrs->pwzAppID); | ||
541 | ReleaseStr(pAttrs->pwzPartID); | ||
542 | } | ||
543 | |||
544 | static HRESULT CreateUsersInApplicationRole( | ||
545 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
546 | ) | ||
547 | { | ||
548 | HRESULT hr = S_OK; | ||
549 | UINT er = ERROR_SUCCESS; | ||
550 | |||
551 | ICatalogCollection* piUsrInRoleColl = NULL; | ||
552 | ICatalogObject* piUsrInRoleObj = NULL; | ||
553 | |||
554 | PSID pSid = NULL; | ||
555 | long lChanges = 0; | ||
556 | |||
557 | // log | ||
558 | WcaLog(LOGMSG_VERBOSE, "Adding user to application role, key: %S", pAttrs->pwzKey); | ||
559 | |||
560 | // get users in role collection | ||
561 | hr = CpiGetUsersInRoleCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzRoleName, &piUsrInRoleColl); | ||
562 | if (S_FALSE == hr) | ||
563 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
564 | ExitOnFailure(hr, "Failed to get users in role collection"); | ||
565 | |||
566 | // get SID for account | ||
567 | do { | ||
568 | er = ERROR_SUCCESS; | ||
569 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
570 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
571 | { | ||
572 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
573 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
574 | switch (er) | ||
575 | { | ||
576 | case IDABORT: | ||
577 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
578 | case IDRETRY: | ||
579 | break; | ||
580 | case IDIGNORE: | ||
581 | default: | ||
582 | ExitFunction1(hr = S_OK); | ||
583 | } | ||
584 | } | ||
585 | else | ||
586 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
587 | } while (IDRETRY == er); | ||
588 | |||
589 | // find any existing entry | ||
590 | hr = CpiFindUserCollectionObject(piUsrInRoleColl, pSid, NULL); | ||
591 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
592 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
593 | else | ||
594 | ExitOnFailure(hr, "Failed to find user in application role"); | ||
595 | |||
596 | if (S_OK == hr) | ||
597 | { | ||
598 | WcaLog(LOGMSG_VERBOSE, "User already assigned to application role, key: %S", pAttrs->pwzKey); | ||
599 | ExitFunction(); // exit with hr = S_OK | ||
600 | } | ||
601 | |||
602 | // convert SID back to account name | ||
603 | hr = CpiSidToAccountName(pSid, &pAttrs->pwzAccount); | ||
604 | ExitOnFailure(hr, "Failed to convert SID to account name"); | ||
605 | |||
606 | // add user | ||
607 | hr = CpiAddCollectionObject(piUsrInRoleColl, &piUsrInRoleObj); | ||
608 | ExitOnFailure(hr, "Failed to add user in role to collection"); | ||
609 | |||
610 | hr = CpiPutCollectionObjectValue(piUsrInRoleObj, L"User", pAttrs->pwzAccount); | ||
611 | ExitOnFailure(hr, "Failed to set role name property"); | ||
612 | |||
613 | // save changes | ||
614 | hr = piUsrInRoleColl->SaveChanges(&lChanges); | ||
615 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
616 | CpiLogCatalogErrorInfo(); | ||
617 | ExitOnFailure(hr, "Failed to save changes"); | ||
618 | |||
619 | // log | ||
620 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
621 | |||
622 | hr = S_OK; | ||
623 | |||
624 | LExit: | ||
625 | // clean up | ||
626 | ReleaseObject(piUsrInRoleColl); | ||
627 | ReleaseObject(piUsrInRoleObj); | ||
628 | |||
629 | if (pSid) | ||
630 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
631 | |||
632 | return hr; | ||
633 | } | ||
634 | |||
635 | static HRESULT RemoveUsersInApplicationRole( | ||
636 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
637 | ) | ||
638 | { | ||
639 | HRESULT hr = S_OK; | ||
640 | UINT er = ERROR_SUCCESS; | ||
641 | |||
642 | ICatalogCollection* piUsrInRoleColl = NULL; | ||
643 | |||
644 | PSID pSid = NULL; | ||
645 | long lChanges = 0; | ||
646 | |||
647 | // log | ||
648 | WcaLog(LOGMSG_VERBOSE, "Removing user from application role, key: %S", pAttrs->pwzKey); | ||
649 | |||
650 | // get users in role collection | ||
651 | hr = CpiGetUsersInRoleCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzRoleName, &piUsrInRoleColl); | ||
652 | ExitOnFailure(hr, "Failed to get users in role collection"); | ||
653 | |||
654 | if (S_FALSE == hr) | ||
655 | { | ||
656 | // users in role collection not found | ||
657 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve users in role collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
658 | ExitFunction1(hr = S_OK); | ||
659 | } | ||
660 | |||
661 | // get SID for account | ||
662 | do { | ||
663 | er = ERROR_SUCCESS; | ||
664 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
665 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
666 | { | ||
667 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
668 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
669 | switch (er) | ||
670 | { | ||
671 | case IDABORT: | ||
672 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
673 | case IDRETRY: | ||
674 | break; | ||
675 | case IDIGNORE: | ||
676 | default: | ||
677 | ExitFunction1(hr = S_OK); | ||
678 | } | ||
679 | } | ||
680 | else | ||
681 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
682 | } while (IDRETRY == er); | ||
683 | |||
684 | // remove | ||
685 | hr = CpiRemoveUserCollectionObject(piUsrInRoleColl, pSid); | ||
686 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
687 | { | ||
688 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
689 | hr = S_FALSE; | ||
690 | } | ||
691 | else | ||
692 | ExitOnFailure(hr, "Failed to remove user"); | ||
693 | |||
694 | if (S_FALSE == hr) | ||
695 | { | ||
696 | // role not found | ||
697 | WcaLog(LOGMSG_VERBOSE, "User not found for application role, nothing to delete, key: %S", pAttrs->pwzKey); | ||
698 | ExitFunction1(hr = S_OK); | ||
699 | } | ||
700 | |||
701 | // save changes | ||
702 | hr = piUsrInRoleColl->SaveChanges(&lChanges); | ||
703 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
704 | CpiLogCatalogErrorInfo(); | ||
705 | ExitOnFailure(hr, "Failed to save changes"); | ||
706 | |||
707 | // log | ||
708 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
709 | |||
710 | hr = S_OK; | ||
711 | |||
712 | LExit: | ||
713 | // clean up | ||
714 | ReleaseObject(piUsrInRoleColl); | ||
715 | |||
716 | if (pSid) | ||
717 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
718 | |||
719 | return hr; | ||
720 | } | ||
diff --git a/src/ca/cpapproleexec.h b/src/ca/cpapproleexec.h new file mode 100644 index 00000000..1251cbdb --- /dev/null +++ b/src/ca/cpapproleexec.h | |||
@@ -0,0 +1,20 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | HRESULT CpiConfigureApplicationRoles( | ||
6 | LPWSTR* ppwzData, | ||
7 | HANDLE hRollbackFile | ||
8 | ); | ||
9 | HRESULT CpiRollbackConfigureApplicationRoles( | ||
10 | LPWSTR* ppwzData, | ||
11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
12 | ); | ||
13 | HRESULT CpiConfigureUsersInApplicationRoles( | ||
14 | LPWSTR* ppwzData, | ||
15 | HANDLE hRollbackFile | ||
16 | ); | ||
17 | HRESULT CpiRollbackConfigureUsersInApplicationRoles( | ||
18 | LPWSTR* ppwzData, | ||
19 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
20 | ); | ||
diff --git a/src/ca/cpapprolesched.cpp b/src/ca/cpapprolesched.cpp new file mode 100644 index 00000000..a268d156 --- /dev/null +++ b/src/ca/cpapprolesched.cpp | |||
@@ -0,0 +1,843 @@ | |||
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 | // sql queries | ||
7 | |||
8 | LPCWSTR vcsApplicationRoleQuery = | ||
9 | L"SELECT `ApplicationRole`, `Application_`, `Component_`, `Name` FROM `ComPlusApplicationRole`"; | ||
10 | enum eApplicationRoleQuery { arqApplicationRole = 1, arqApplication, arqComponent, arqName }; | ||
11 | |||
12 | LPCWSTR vcsUserInApplicationRoleQuery = | ||
13 | L"SELECT `UserInApplicationRole`, `ApplicationRole_`, `ComPlusUserInApplicationRole`.`Component_`, `Domain`, `Name` FROM `ComPlusUserInApplicationRole`, `User` WHERE `User_` = `User`"; | ||
14 | LPCWSTR vcsGroupInApplicationRoleQuery = | ||
15 | L"SELECT `GroupInApplicationRole`, `ApplicationRole_`, `ComPlusGroupInApplicationRole`.`Component_`, `Domain`, `Name` FROM `ComPlusGroupInApplicationRole`, `Group` WHERE `Group_` = `Group`"; | ||
16 | enum eTrusteeInApplicationRoleQuery { tiarqUserInApplicationRole = 1, tiarqApplicationRole, tiarqComponent, tiarqDomain, tiarqName }; | ||
17 | |||
18 | LPCWSTR vcsApplicationRolePropertyQuery = | ||
19 | L"SELECT `Name`, `Value` FROM `ComPlusApplicationRoleProperty` WHERE `ApplicationRole_` = ?"; | ||
20 | |||
21 | |||
22 | // property definitions | ||
23 | |||
24 | CPI_PROPERTY_DEFINITION pdlApplicationRoleProperties[] = | ||
25 | { | ||
26 | {L"Description", cpptString, 500}, | ||
27 | {NULL, cpptNone, 0} | ||
28 | }; | ||
29 | |||
30 | |||
31 | // prototypes for private helper functions | ||
32 | |||
33 | static HRESULT TrusteesInApplicationRolesRead( | ||
34 | LPCWSTR pwzQuery, | ||
35 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
36 | CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList | ||
37 | ); | ||
38 | static void FreeApplicationRole( | ||
39 | CPI_APPLICATION_ROLE* pItm | ||
40 | ); | ||
41 | static void FreeUserInApplicationRole( | ||
42 | CPI_USER_IN_APPLICATION_ROLE* pItm | ||
43 | ); | ||
44 | //static HRESULT GetUsersCollForApplicationRole( | ||
45 | // CPI_APPLICATION_ROLE* pAppRole, | ||
46 | // ICatalogCollection** ppiUsersColl | ||
47 | // ); | ||
48 | static HRESULT FindObjectForApplicationRole( | ||
49 | CPI_APPLICATION_ROLE* pItm, | ||
50 | ICatalogObject** ppiRoleObj | ||
51 | ); | ||
52 | static HRESULT AddApplicationRoleToActionData( | ||
53 | CPI_APPLICATION_ROLE* pItm, | ||
54 | int iActionType, | ||
55 | int iActionCost, | ||
56 | LPWSTR* ppwzActionData | ||
57 | ); | ||
58 | static HRESULT AddUserInApplicationRoleToActionData( | ||
59 | CPI_USER_IN_APPLICATION_ROLE* pItm, | ||
60 | int iActionType, | ||
61 | int iActionCost, | ||
62 | LPWSTR* ppwzActionData | ||
63 | ); | ||
64 | |||
65 | |||
66 | // function definitions | ||
67 | |||
68 | void CpiApplicationRoleListFree( | ||
69 | CPI_APPLICATION_ROLE_LIST* pList | ||
70 | ) | ||
71 | { | ||
72 | CPI_APPLICATION_ROLE* pItm = pList->pFirst; | ||
73 | |||
74 | while (pItm) | ||
75 | { | ||
76 | CPI_APPLICATION_ROLE* pDelete = pItm; | ||
77 | pItm = pItm->pNext; | ||
78 | FreeApplicationRole(pDelete); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | HRESULT CpiApplicationRolesRead( | ||
83 | CPI_APPLICATION_LIST* pAppList, | ||
84 | CPI_APPLICATION_ROLE_LIST* pAppRoleList | ||
85 | ) | ||
86 | { | ||
87 | HRESULT hr = S_OK; | ||
88 | UINT er = ERROR_SUCCESS; | ||
89 | |||
90 | PMSIHANDLE hView, hRec; | ||
91 | |||
92 | CPI_APPLICATION_ROLE* pItm = NULL; | ||
93 | LPWSTR pwzData = NULL; | ||
94 | BOOL fMatchingArchitecture = FALSE; | ||
95 | |||
96 | // loop through all application roles | ||
97 | hr = WcaOpenExecuteView(vcsApplicationRoleQuery, &hView); | ||
98 | ExitOnFailure(hr, "Failed to execute view on ComPlusApplicationRole table"); | ||
99 | |||
100 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
101 | { | ||
102 | // get component | ||
103 | hr = WcaGetRecordString(hRec, arqComponent, &pwzData); | ||
104 | ExitOnFailure(hr, "Failed to get component"); | ||
105 | |||
106 | // check if the component is our processor architecture | ||
107 | if (pwzData && *pwzData) | ||
108 | { | ||
109 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
110 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
111 | |||
112 | if (!fMatchingArchitecture) | ||
113 | { | ||
114 | continue; // not the same architecture, ignore | ||
115 | } | ||
116 | } | ||
117 | |||
118 | // create entry | ||
119 | pItm = (CPI_APPLICATION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_APPLICATION_ROLE)); | ||
120 | if (!pItm) | ||
121 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
122 | |||
123 | // get component install state | ||
124 | if (pwzData && *pwzData) | ||
125 | { | ||
126 | pItm->fHasComponent = TRUE; | ||
127 | |||
128 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
129 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
130 | } | ||
131 | |||
132 | // get key | ||
133 | hr = WcaGetRecordString(hRec, arqApplicationRole, &pwzData); | ||
134 | ExitOnFailure(hr, "Failed to get key"); | ||
135 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
136 | |||
137 | // get application | ||
138 | hr = WcaGetRecordString(hRec, arqApplication, &pwzData); | ||
139 | ExitOnFailure(hr, "Failed to get application"); | ||
140 | |||
141 | hr = CpiApplicationFindByKey(pAppList, pwzData, &pItm->pApplication); | ||
142 | if (S_FALSE == hr) | ||
143 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
144 | ExitOnFailure(hr, "Failed to find application, key: %S", pwzData); | ||
145 | |||
146 | // get name | ||
147 | hr = WcaGetRecordFormattedString(hRec, arqName, &pwzData); | ||
148 | ExitOnFailure(hr, "Failed to get name"); | ||
149 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
150 | |||
151 | // get properties | ||
152 | if (CpiTableExists(cptComPlusApplicationRoleProperty)) | ||
153 | { | ||
154 | hr = CpiPropertiesRead(vcsApplicationRolePropertyQuery, pItm->wzKey, pdlApplicationRoleProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
155 | ExitOnFailure(hr, "Failed to get properties"); | ||
156 | } | ||
157 | |||
158 | // set references & increment counters | ||
159 | if (pItm->fHasComponent) | ||
160 | { | ||
161 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
162 | { | ||
163 | CpiApplicationAddReferenceInstall(pItm->pApplication); | ||
164 | pAppRoleList->iInstallCount++; | ||
165 | } | ||
166 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
167 | { | ||
168 | CpiApplicationAddReferenceUninstall(pItm->pApplication); | ||
169 | pAppRoleList->iUninstallCount++; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | // add entry | ||
174 | if (pAppRoleList->pFirst) | ||
175 | pItm->pNext = pAppRoleList->pFirst; | ||
176 | pAppRoleList->pFirst = pItm; | ||
177 | pItm = NULL; | ||
178 | } | ||
179 | |||
180 | if (E_NOMOREITEMS == hr) | ||
181 | hr = S_OK; | ||
182 | |||
183 | LExit: | ||
184 | // clean up | ||
185 | if (pItm) | ||
186 | FreeApplicationRole(pItm); | ||
187 | |||
188 | ReleaseStr(pwzData); | ||
189 | |||
190 | return hr; | ||
191 | } | ||
192 | |||
193 | HRESULT CpiApplicationRolesVerifyInstall( | ||
194 | CPI_APPLICATION_ROLE_LIST* pList | ||
195 | ) | ||
196 | { | ||
197 | HRESULT hr = S_OK; | ||
198 | UINT er = ERROR_SUCCESS; | ||
199 | |||
200 | ICatalogObject* piRoleObj = NULL; | ||
201 | |||
202 | for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
203 | { | ||
204 | // referenced locaters or roles that are being installed | ||
205 | if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction))) | ||
206 | continue; | ||
207 | |||
208 | // if the role is referensed and is not a locater, it must be installed | ||
209 | if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction)) | ||
210 | MessageExitOnFailure(hr = E_FAIL, msierrComPlusApplicationRoleDependency, "An application role is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey); | ||
211 | |||
212 | // role is a locater | ||
213 | if (!pItm->fHasComponent) | ||
214 | { | ||
215 | // get collection object for role | ||
216 | hr = FindObjectForApplicationRole(pItm, &piRoleObj); | ||
217 | ExitOnFailure(hr, "Failed to find collection object for role"); | ||
218 | |||
219 | // if the role was not found | ||
220 | if (S_FALSE == hr) | ||
221 | MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusApplicationRoleNotFound, "An application role required by this installation was not found, key: %S", pItm->wzKey); | ||
222 | } | ||
223 | |||
224 | // role is supposed to be created | ||
225 | else if (!CpiIsInstalled(pItm->isInstalled)) | ||
226 | { | ||
227 | do { | ||
228 | // find roles with conflicting name or id | ||
229 | hr = FindObjectForApplicationRole(pItm, NULL); | ||
230 | ExitOnFailure(hr, "Failed to find collection object for role"); | ||
231 | |||
232 | if (S_OK == hr) | ||
233 | { | ||
234 | er = WcaErrorMessage(msierrComPlusApplicationRoleConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
235 | switch (er) | ||
236 | { | ||
237 | case IDABORT: | ||
238 | ExitOnFailure(hr = E_FAIL, "An application with a conflictiong name exists, key: %S", pItm->wzKey); | ||
239 | break; | ||
240 | case IDRETRY: | ||
241 | break; | ||
242 | case IDIGNORE: | ||
243 | default: | ||
244 | hr = S_FALSE; // indicate that this is not a conflict | ||
245 | } | ||
246 | } | ||
247 | } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts | ||
248 | } | ||
249 | |||
250 | // clean up | ||
251 | ReleaseNullObject(piRoleObj); | ||
252 | } | ||
253 | |||
254 | hr = S_OK; | ||
255 | |||
256 | LExit: | ||
257 | // clean up | ||
258 | ReleaseObject(piRoleObj); | ||
259 | |||
260 | return hr; | ||
261 | } | ||
262 | |||
263 | HRESULT CpiApplicationRolesVerifyUninstall( | ||
264 | CPI_APPLICATION_ROLE_LIST* pList | ||
265 | ) | ||
266 | { | ||
267 | HRESULT hr = S_OK; | ||
268 | |||
269 | for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
270 | { | ||
271 | // referenced locaters or roles that are being installed | ||
272 | if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction))) | ||
273 | continue; | ||
274 | |||
275 | // get collection object for role | ||
276 | hr = FindObjectForApplicationRole(pItm, NULL); | ||
277 | ExitOnFailure(hr, "Failed to find collection object for role"); | ||
278 | |||
279 | // if the role was not found | ||
280 | if (S_FALSE == hr) | ||
281 | { | ||
282 | pItm->fObjectNotFound = TRUE; | ||
283 | if (pItm->fHasComponent) | ||
284 | pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall | ||
285 | } | ||
286 | } | ||
287 | |||
288 | hr = S_OK; | ||
289 | |||
290 | LExit: | ||
291 | return hr; | ||
292 | } | ||
293 | |||
294 | void CpiApplicationRoleAddReferenceInstall( | ||
295 | CPI_APPLICATION_ROLE* pItm | ||
296 | ) | ||
297 | { | ||
298 | pItm->fReferencedForInstall = TRUE; | ||
299 | CpiApplicationAddReferenceInstall(pItm->pApplication); | ||
300 | } | ||
301 | |||
302 | void CpiApplicationRoleAddReferenceUninstall( | ||
303 | CPI_APPLICATION_ROLE* pItm | ||
304 | ) | ||
305 | { | ||
306 | pItm->fReferencedForUninstall = TRUE; | ||
307 | CpiApplicationAddReferenceUninstall(pItm->pApplication); | ||
308 | } | ||
309 | |||
310 | HRESULT CpiApplicationRolesInstall( | ||
311 | CPI_APPLICATION_ROLE_LIST* pList, | ||
312 | int iRunMode, | ||
313 | LPWSTR* ppwzActionData, | ||
314 | int* piProgress | ||
315 | ) | ||
316 | { | ||
317 | HRESULT hr = S_OK; | ||
318 | |||
319 | int iActionType; | ||
320 | |||
321 | // add action text | ||
322 | hr = CpiAddActionTextToActionData(L"CreateComPlusApplicationRoles", ppwzActionData); | ||
323 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
324 | |||
325 | // add count to action data | ||
326 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
327 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
328 | |||
329 | // add roles to custom action data | ||
330 | for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
331 | { | ||
332 | // roles that are being installed only | ||
333 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
334 | continue; | ||
335 | |||
336 | // action type | ||
337 | if (rmRollback == iRunMode) | ||
338 | { | ||
339 | if (CpiIsInstalled(pItm->isInstalled)) | ||
340 | iActionType = atNoOp; | ||
341 | else | ||
342 | iActionType = atRemove; | ||
343 | } | ||
344 | else | ||
345 | iActionType = atCreate; | ||
346 | |||
347 | // add to action data | ||
348 | hr = AddApplicationRoleToActionData(pItm, iActionType, COST_APPLICATION_ROLE_CREATE, ppwzActionData); | ||
349 | ExitOnFailure(hr, "Failed to add application role to custom action data, key: %S", pItm->wzKey); | ||
350 | } | ||
351 | |||
352 | // add progress tics | ||
353 | if (piProgress) | ||
354 | *piProgress += COST_APPLICATION_ROLE_CREATE * pList->iInstallCount; | ||
355 | |||
356 | hr = S_OK; | ||
357 | |||
358 | LExit: | ||
359 | return hr; | ||
360 | } | ||
361 | |||
362 | HRESULT CpiApplicationRolesUninstall( | ||
363 | CPI_APPLICATION_ROLE_LIST* pList, | ||
364 | int iRunMode, | ||
365 | LPWSTR* ppwzActionData, | ||
366 | int* piProgress | ||
367 | ) | ||
368 | { | ||
369 | HRESULT hr = S_OK; | ||
370 | |||
371 | int iActionType; | ||
372 | |||
373 | // add action text | ||
374 | hr = CpiAddActionTextToActionData(L"RemoveComPlusApplicationRoles", ppwzActionData); | ||
375 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
376 | |||
377 | // add count to action data | ||
378 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
379 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
380 | |||
381 | // add roles to custom action data | ||
382 | for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
383 | { | ||
384 | // roles that are being uninstalled only | ||
385 | if (pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
386 | continue; | ||
387 | |||
388 | // action type | ||
389 | if (rmRollback == iRunMode) | ||
390 | iActionType = atCreate; | ||
391 | else | ||
392 | iActionType = atRemove; | ||
393 | |||
394 | // add to action data | ||
395 | hr = AddApplicationRoleToActionData(pItm, iActionType, COST_APPLICATION_ROLE_DELETE, ppwzActionData); | ||
396 | ExitOnFailure(hr, "Failed to add application role to custom action data, key: %S", pItm->wzKey); | ||
397 | } | ||
398 | |||
399 | // add progress tics | ||
400 | if (piProgress) | ||
401 | *piProgress += COST_APPLICATION_ROLE_DELETE * pList->iUninstallCount; | ||
402 | |||
403 | hr = S_OK; | ||
404 | |||
405 | LExit: | ||
406 | return hr; | ||
407 | } | ||
408 | |||
409 | HRESULT CpiApplicationRoleFindByKey( | ||
410 | CPI_APPLICATION_ROLE_LIST* pList, | ||
411 | LPCWSTR pwzKey, | ||
412 | CPI_APPLICATION_ROLE** ppAppRole | ||
413 | ) | ||
414 | { | ||
415 | for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
416 | { | ||
417 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
418 | { | ||
419 | *ppAppRole = pItm; | ||
420 | return S_OK; | ||
421 | } | ||
422 | } | ||
423 | |||
424 | return S_FALSE; | ||
425 | } | ||
426 | |||
427 | void CpiUserInApplicationRoleListFree( | ||
428 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList | ||
429 | ) | ||
430 | { | ||
431 | CPI_USER_IN_APPLICATION_ROLE* pItm = pList->pFirst; | ||
432 | |||
433 | while (pItm) | ||
434 | { | ||
435 | CPI_USER_IN_APPLICATION_ROLE* pDelete = pItm; | ||
436 | pItm = pItm->pNext; | ||
437 | FreeUserInApplicationRole(pDelete); | ||
438 | } | ||
439 | } | ||
440 | |||
441 | HRESULT CpiUsersInApplicationRolesRead( | ||
442 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
443 | CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList | ||
444 | ) | ||
445 | { | ||
446 | HRESULT hr = S_OK; | ||
447 | |||
448 | // read users in application roles | ||
449 | if (CpiTableExists(cptComPlusUserInApplicationRole)) | ||
450 | { | ||
451 | hr = TrusteesInApplicationRolesRead(vcsUserInApplicationRoleQuery, pAppRoleList, pUsrInAppRoleList); | ||
452 | ExitOnFailure(hr, "Failed to read users in application roles"); | ||
453 | } | ||
454 | |||
455 | // read groups in application roles | ||
456 | if (CpiTableExists(cptComPlusGroupInApplicationRole)) | ||
457 | { | ||
458 | hr = TrusteesInApplicationRolesRead(vcsGroupInApplicationRoleQuery, pAppRoleList, pUsrInAppRoleList); | ||
459 | ExitOnFailure(hr, "Failed to read groups in application roles"); | ||
460 | } | ||
461 | |||
462 | hr = S_OK; | ||
463 | |||
464 | LExit: | ||
465 | return hr; | ||
466 | } | ||
467 | |||
468 | HRESULT CpiUsersInApplicationRolesInstall( | ||
469 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList, | ||
470 | int iRunMode, | ||
471 | LPWSTR* ppwzActionData, | ||
472 | int* piProgress | ||
473 | ) | ||
474 | { | ||
475 | HRESULT hr = S_OK; | ||
476 | |||
477 | int iActionType; | ||
478 | |||
479 | // add action text | ||
480 | hr = CpiAddActionTextToActionData(L"AddUsersToComPlusApplicationRoles", ppwzActionData); | ||
481 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
482 | |||
483 | // add count to action data | ||
484 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
485 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
486 | |||
487 | // add roles to custom action data | ||
488 | for (CPI_USER_IN_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
489 | { | ||
490 | // roles that are being installed only | ||
491 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
492 | continue; | ||
493 | |||
494 | // action type | ||
495 | if (rmRollback == iRunMode) | ||
496 | { | ||
497 | if (CpiIsInstalled(pItm->isInstalled)) | ||
498 | iActionType = atNoOp; | ||
499 | else | ||
500 | iActionType = atRemove; | ||
501 | } | ||
502 | else | ||
503 | iActionType = atCreate; | ||
504 | |||
505 | // add to action data | ||
506 | hr = AddUserInApplicationRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_CREATE, ppwzActionData); | ||
507 | ExitOnFailure(hr, "Failed to add user in application role to custom action data, key: %S", pItm->wzKey); | ||
508 | } | ||
509 | |||
510 | // add progress tics | ||
511 | if (piProgress) | ||
512 | *piProgress += COST_USER_IN_APPLICATION_ROLE_CREATE * pList->iInstallCount; | ||
513 | |||
514 | hr = S_OK; | ||
515 | |||
516 | LExit: | ||
517 | return hr; | ||
518 | } | ||
519 | |||
520 | HRESULT CpiUsersInApplicationRolesUninstall( | ||
521 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList, | ||
522 | int iRunMode, | ||
523 | LPWSTR* ppwzActionData, | ||
524 | int* piProgress | ||
525 | ) | ||
526 | { | ||
527 | HRESULT hr = S_OK; | ||
528 | |||
529 | int iActionType; | ||
530 | |||
531 | // add action text | ||
532 | hr = CpiAddActionTextToActionData(L"RemoveUsersFromComPlusAppRoles", ppwzActionData); | ||
533 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
534 | |||
535 | // add count to action data | ||
536 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
537 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
538 | |||
539 | // add roles to custom action data | ||
540 | for (CPI_USER_IN_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
541 | { | ||
542 | // roles that are being uninstalled only | ||
543 | if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
544 | continue; | ||
545 | |||
546 | // action type | ||
547 | if (rmRollback == iRunMode) | ||
548 | iActionType = atCreate; | ||
549 | else | ||
550 | iActionType = atRemove; | ||
551 | |||
552 | // add to action data | ||
553 | hr = AddUserInApplicationRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_DELETE, ppwzActionData); | ||
554 | ExitOnFailure(hr, "Failed to add user in application role to custom action data, key: %S", pItm->wzKey); | ||
555 | } | ||
556 | |||
557 | // add progress tics | ||
558 | if (piProgress) | ||
559 | *piProgress += COST_USER_IN_APPLICATION_ROLE_DELETE * pList->iUninstallCount; | ||
560 | |||
561 | hr = S_OK; | ||
562 | |||
563 | LExit: | ||
564 | return hr; | ||
565 | } | ||
566 | |||
567 | |||
568 | // helper function definitions | ||
569 | |||
570 | static HRESULT TrusteesInApplicationRolesRead( | ||
571 | LPCWSTR pwzQuery, | ||
572 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
573 | CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList | ||
574 | ) | ||
575 | { | ||
576 | HRESULT hr = S_OK; | ||
577 | UINT er = ERROR_SUCCESS; | ||
578 | |||
579 | PMSIHANDLE hView, hRec; | ||
580 | |||
581 | CPI_USER_IN_APPLICATION_ROLE* pItm = NULL; | ||
582 | LPWSTR pwzData = NULL; | ||
583 | LPWSTR pwzDomain = NULL; | ||
584 | LPWSTR pwzName = NULL; | ||
585 | BOOL fMatchingArchitecture = FALSE; | ||
586 | |||
587 | // loop through all application roles | ||
588 | hr = WcaOpenExecuteView(pwzQuery, &hView); | ||
589 | ExitOnFailure(hr, "Failed to execute view on table"); | ||
590 | |||
591 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
592 | { | ||
593 | // get component | ||
594 | hr = WcaGetRecordString(hRec, tiarqComponent, &pwzData); | ||
595 | ExitOnFailure(hr, "Failed to get component"); | ||
596 | |||
597 | // check if the component is our processor architecture | ||
598 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
599 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
600 | |||
601 | if (!fMatchingArchitecture) | ||
602 | { | ||
603 | continue; // not the same architecture, ignore | ||
604 | } | ||
605 | |||
606 | // create entry | ||
607 | pItm = (CPI_USER_IN_APPLICATION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_USER_IN_APPLICATION_ROLE)); | ||
608 | if (!pItm) | ||
609 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
610 | |||
611 | // get component install state | ||
612 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
613 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
614 | |||
615 | // get key | ||
616 | hr = WcaGetRecordString(hRec, tiarqUserInApplicationRole, &pwzData); | ||
617 | ExitOnFailure(hr, "Failed to get key"); | ||
618 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
619 | |||
620 | // get application role | ||
621 | hr = WcaGetRecordString(hRec, tiarqApplicationRole, &pwzData); | ||
622 | ExitOnFailure(hr, "Failed to get application role"); | ||
623 | |||
624 | hr = CpiApplicationRoleFindByKey(pAppRoleList, pwzData, &pItm->pApplicationRole); | ||
625 | if (S_FALSE == hr) | ||
626 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
627 | ExitOnFailure(hr, "Failed to find application role, key: %S", pwzData); | ||
628 | |||
629 | // get user domain | ||
630 | hr = WcaGetRecordFormattedString(hRec, tiarqDomain, &pwzDomain); | ||
631 | ExitOnFailure(hr, "Failed to get domain"); | ||
632 | |||
633 | // get user name | ||
634 | hr = WcaGetRecordFormattedString(hRec, tiarqName, &pwzName); | ||
635 | ExitOnFailure(hr, "Failed to get name"); | ||
636 | |||
637 | // build account name | ||
638 | hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount); | ||
639 | ExitOnFailure(hr, "Failed to build account name"); | ||
640 | |||
641 | // set references & increment counters | ||
642 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
643 | { | ||
644 | CpiApplicationRoleAddReferenceInstall(pItm->pApplicationRole); | ||
645 | pUsrInAppRoleList->iInstallCount++; | ||
646 | } | ||
647 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
648 | { | ||
649 | CpiApplicationRoleAddReferenceUninstall(pItm->pApplicationRole); | ||
650 | pUsrInAppRoleList->iUninstallCount++; | ||
651 | } | ||
652 | |||
653 | // add entry | ||
654 | if (pUsrInAppRoleList->pFirst) | ||
655 | pItm->pNext = pUsrInAppRoleList->pFirst; | ||
656 | pUsrInAppRoleList->pFirst = pItm; | ||
657 | pItm = NULL; | ||
658 | } | ||
659 | |||
660 | if (E_NOMOREITEMS == hr) | ||
661 | hr = S_OK; | ||
662 | |||
663 | LExit: | ||
664 | // clean up | ||
665 | if (pItm) | ||
666 | FreeUserInApplicationRole(pItm); | ||
667 | |||
668 | ReleaseStr(pwzData); | ||
669 | ReleaseStr(pwzDomain); | ||
670 | ReleaseStr(pwzName); | ||
671 | |||
672 | return hr; | ||
673 | } | ||
674 | |||
675 | static void FreeApplicationRole( | ||
676 | CPI_APPLICATION_ROLE* pItm | ||
677 | ) | ||
678 | { | ||
679 | if (pItm->pProperties) | ||
680 | CpiPropertiesFreeList(pItm->pProperties); | ||
681 | |||
682 | ReleaseObject(pItm->piUsersColl); | ||
683 | |||
684 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
685 | } | ||
686 | |||
687 | static void FreeUserInApplicationRole( | ||
688 | CPI_USER_IN_APPLICATION_ROLE* pItm | ||
689 | ) | ||
690 | { | ||
691 | ReleaseStr(pItm->pwzAccount); | ||
692 | |||
693 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
694 | } | ||
695 | |||
696 | //static HRESULT GetUsersCollForApplicationRole( | ||
697 | // CPI_APPLICATION_ROLE* pAppRole, | ||
698 | // ICatalogCollection** ppiUsersColl | ||
699 | // ) | ||
700 | //{ | ||
701 | // HRESULT hr = S_OK; | ||
702 | // | ||
703 | // ICatalogCollection* piRoleColl = NULL; | ||
704 | // ICatalogObject* piRoleObj = NULL; | ||
705 | // | ||
706 | // // if a previous attempt to locate the collection object failed | ||
707 | // if (pAppRole->fObjectNotFound) | ||
708 | // ExitFunction1(hr = S_FALSE); | ||
709 | // | ||
710 | // // get applications collection | ||
711 | // if (!pAppRole->piUsersColl) | ||
712 | // { | ||
713 | // // get collection object for role | ||
714 | // hr = FindObjectForApplicationRole(pAppRole, &piRoleObj); | ||
715 | // ExitOnFailure(hr, "Failed to find collection object for role"); | ||
716 | // | ||
717 | // if (S_FALSE == hr) | ||
718 | // ExitFunction(); // exit with hr = S_FALSE | ||
719 | // | ||
720 | // // get users collection | ||
721 | // hr = CpiGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInRole", &pAppRole->piUsersColl); | ||
722 | // ExitOnFailure(hr, "Failed to get users in role collection"); | ||
723 | // } | ||
724 | // | ||
725 | // // return value | ||
726 | // *ppiUsersColl = pAppRole->piUsersColl; | ||
727 | // (*ppiUsersColl)->AddRef(); | ||
728 | // | ||
729 | // hr = S_OK; | ||
730 | // | ||
731 | //LExit: | ||
732 | // // clean up | ||
733 | // ReleaseObject(piRoleColl); | ||
734 | // ReleaseObject(piRoleObj); | ||
735 | // | ||
736 | // return hr; | ||
737 | //} | ||
738 | |||
739 | static HRESULT FindObjectForApplicationRole( | ||
740 | CPI_APPLICATION_ROLE* pItm, | ||
741 | ICatalogObject** ppiRoleObj | ||
742 | ) | ||
743 | { | ||
744 | HRESULT hr = S_OK; | ||
745 | |||
746 | ICatalogCollection* piRoleColl = NULL; | ||
747 | |||
748 | // get roles collection | ||
749 | hr = CpiGetRolesCollForApplication(pItm->pApplication, &piRoleColl); | ||
750 | ExitOnFailure(hr, "Failed to get collection"); | ||
751 | |||
752 | if (S_FALSE == hr) | ||
753 | ExitFunction(); // exit with hr = S_FALSE | ||
754 | |||
755 | // find role object | ||
756 | hr = CpiFindCollectionObject(piRoleColl, NULL, pItm->wzName, ppiRoleObj); | ||
757 | ExitOnFailure(hr, "Failed to find object"); | ||
758 | |||
759 | // exit with hr from CpiFindCollectionObject() | ||
760 | |||
761 | LExit: | ||
762 | // clean up | ||
763 | ReleaseObject(piRoleColl); | ||
764 | |||
765 | return hr; | ||
766 | } | ||
767 | |||
768 | static HRESULT AddApplicationRoleToActionData( | ||
769 | CPI_APPLICATION_ROLE* pItm, | ||
770 | int iActionType, | ||
771 | int iActionCost, | ||
772 | LPWSTR* ppwzActionData | ||
773 | ) | ||
774 | { | ||
775 | HRESULT hr = S_OK; | ||
776 | |||
777 | // add action information to custom action data | ||
778 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
779 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
780 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
781 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
782 | |||
783 | // add application role information to custom action data | ||
784 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
785 | ExitOnFailure(hr, "Failed to add application role key to custom action data"); | ||
786 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
787 | ExitOnFailure(hr, "Failed to add application role name to custom action data"); | ||
788 | |||
789 | // add application information to custom action data | ||
790 | hr = WcaWriteStringToCaData(pItm->pApplication->wzID, ppwzActionData); | ||
791 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
792 | |||
793 | // add partition information to custom action data | ||
794 | hr = WcaWriteStringToCaData(pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L"", ppwzActionData); | ||
795 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
796 | |||
797 | // add properties to custom action data | ||
798 | hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
799 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
800 | |||
801 | hr = S_OK; | ||
802 | |||
803 | LExit: | ||
804 | return hr; | ||
805 | } | ||
806 | |||
807 | static HRESULT AddUserInApplicationRoleToActionData( | ||
808 | CPI_USER_IN_APPLICATION_ROLE* pItm, | ||
809 | int iActionType, | ||
810 | int iActionCost, | ||
811 | LPWSTR* ppwzActionData | ||
812 | ) | ||
813 | { | ||
814 | HRESULT hr = S_OK; | ||
815 | |||
816 | // add action information to custom action data | ||
817 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
818 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
819 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
820 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
821 | |||
822 | // add application role information to custom action data | ||
823 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
824 | ExitOnFailure(hr, "Failed to add key to custom action data"); | ||
825 | hr = WcaWriteStringToCaData(pItm->pApplicationRole->wzName, ppwzActionData); | ||
826 | ExitOnFailure(hr, "Failed to add role name to custom action data"); | ||
827 | hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData); | ||
828 | ExitOnFailure(hr, "Failed to add user account to custom action data"); | ||
829 | |||
830 | // add application information to custom action data | ||
831 | CPI_APPLICATION* pApplication = pItm->pApplicationRole->pApplication; | ||
832 | hr = WcaWriteStringToCaData(pApplication->wzID, ppwzActionData); | ||
833 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
834 | |||
835 | // add partition information to custom action data | ||
836 | hr = WcaWriteStringToCaData(pApplication->pPartition ? pApplication->pPartition->wzID : L"", ppwzActionData); | ||
837 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
838 | |||
839 | hr = S_OK; | ||
840 | |||
841 | LExit: | ||
842 | return hr; | ||
843 | } | ||
diff --git a/src/ca/cpapprolesched.h b/src/ca/cpapprolesched.h new file mode 100644 index 00000000..02852eef --- /dev/null +++ b/src/ca/cpapprolesched.h | |||
@@ -0,0 +1,112 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | struct CPI_APPLICATION_ROLE | ||
6 | { | ||
7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
8 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
9 | |||
10 | int iPropertyCount; | ||
11 | CPI_PROPERTY* pProperties; | ||
12 | |||
13 | BOOL fHasComponent; | ||
14 | BOOL fReferencedForInstall; | ||
15 | BOOL fReferencedForUninstall; | ||
16 | BOOL fObjectNotFound; | ||
17 | |||
18 | INSTALLSTATE isInstalled, isAction; | ||
19 | |||
20 | CPI_APPLICATION* pApplication; | ||
21 | |||
22 | ICatalogCollection* piUsersColl; | ||
23 | |||
24 | CPI_APPLICATION_ROLE* pNext; | ||
25 | }; | ||
26 | |||
27 | struct CPI_APPLICATION_ROLE_LIST | ||
28 | { | ||
29 | CPI_APPLICATION_ROLE* pFirst; | ||
30 | |||
31 | int iInstallCount; | ||
32 | int iUninstallCount; | ||
33 | }; | ||
34 | |||
35 | struct CPI_USER_IN_APPLICATION_ROLE | ||
36 | { | ||
37 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
38 | LPWSTR pwzAccount; | ||
39 | |||
40 | INSTALLSTATE isInstalled, isAction; | ||
41 | |||
42 | CPI_APPLICATION_ROLE* pApplicationRole; | ||
43 | |||
44 | CPI_USER_IN_APPLICATION_ROLE* pNext; | ||
45 | }; | ||
46 | |||
47 | struct CPI_USER_IN_APPLICATION_ROLE_LIST | ||
48 | { | ||
49 | CPI_USER_IN_APPLICATION_ROLE* pFirst; | ||
50 | |||
51 | int iInstallCount; | ||
52 | int iUninstallCount; | ||
53 | }; | ||
54 | |||
55 | |||
56 | // function prototypes | ||
57 | |||
58 | void CpiApplicationRoleListFree( | ||
59 | CPI_APPLICATION_ROLE_LIST* pList | ||
60 | ); | ||
61 | HRESULT CpiApplicationRolesRead( | ||
62 | CPI_APPLICATION_LIST* pAppList, | ||
63 | CPI_APPLICATION_ROLE_LIST* pAppRoleList | ||
64 | ); | ||
65 | HRESULT CpiApplicationRolesVerifyInstall( | ||
66 | CPI_APPLICATION_ROLE_LIST* pList | ||
67 | ); | ||
68 | HRESULT CpiApplicationRolesVerifyUninstall( | ||
69 | CPI_APPLICATION_ROLE_LIST* pList | ||
70 | ); | ||
71 | void CpiApplicationRoleAddReferenceInstall( | ||
72 | CPI_APPLICATION_ROLE* pItm | ||
73 | ); | ||
74 | void CpiApplicationRoleAddReferenceUninstall( | ||
75 | CPI_APPLICATION_ROLE* pItm | ||
76 | ); | ||
77 | HRESULT CpiApplicationRolesInstall( | ||
78 | CPI_APPLICATION_ROLE_LIST* pList, | ||
79 | int iRunMode, | ||
80 | LPWSTR* ppwzActionData, | ||
81 | int* piProgress | ||
82 | ); | ||
83 | HRESULT CpiApplicationRolesUninstall( | ||
84 | CPI_APPLICATION_ROLE_LIST* pList, | ||
85 | int iRunMode, | ||
86 | LPWSTR* ppwzActionData, | ||
87 | int* piProgress | ||
88 | ); | ||
89 | HRESULT CpiApplicationRoleFindByKey( | ||
90 | CPI_APPLICATION_ROLE_LIST* pList, | ||
91 | LPCWSTR pwzKey, | ||
92 | CPI_APPLICATION_ROLE** ppAppRole | ||
93 | ); | ||
94 | void CpiUserInApplicationRoleListFree( | ||
95 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList | ||
96 | ); | ||
97 | HRESULT CpiUsersInApplicationRolesRead( | ||
98 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
99 | CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList | ||
100 | ); | ||
101 | HRESULT CpiUsersInApplicationRolesInstall( | ||
102 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList, | ||
103 | int iRunMode, | ||
104 | LPWSTR* ppwzActionData, | ||
105 | int* piProgress | ||
106 | ); | ||
107 | HRESULT CpiUsersInApplicationRolesUninstall( | ||
108 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList, | ||
109 | int iRunMode, | ||
110 | LPWSTR* ppwzActionData, | ||
111 | int* piProgress | ||
112 | ); | ||
diff --git a/src/ca/cpappsched.cpp b/src/ca/cpappsched.cpp new file mode 100644 index 00000000..cec99794 --- /dev/null +++ b/src/ca/cpappsched.cpp | |||
@@ -0,0 +1,752 @@ | |||
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 | // sql queries | ||
7 | |||
8 | LPCWSTR vcsApplicationQuery = | ||
9 | L"SELECT `Application`, `Component_`, `Partition_`, `Id`, `Name` FROM `ComPlusApplication`"; | ||
10 | enum eApplicationQuery { aqApplication = 1, aqComponent, aqPartition, aqID, aqName }; | ||
11 | |||
12 | LPCWSTR vcsApplicationPropertyQuery = | ||
13 | L"SELECT `Name`, `Value` FROM `ComPlusApplicationProperty` WHERE `Application_` = ?"; | ||
14 | |||
15 | |||
16 | // property definitions | ||
17 | |||
18 | CPI_PROPERTY_DEFINITION pdlApplicationProperties[] = | ||
19 | { | ||
20 | {L"3GigSupportEnabled", cpptBoolean, 500}, | ||
21 | {L"AccessChecksLevel", cpptInteger, 500}, | ||
22 | {L"Activation", cpptInteger, 500}, | ||
23 | {L"ApplicationAccessChecksEnabled", cpptBoolean, 500}, | ||
24 | {L"ApplicationDirectory", cpptString, 501}, | ||
25 | {L"Authentication", cpptInteger, 500}, | ||
26 | {L"AuthenticationCapability", cpptInteger, 500}, | ||
27 | {L"Changeable", cpptBoolean, 500}, | ||
28 | {L"CommandLine", cpptString, 500}, | ||
29 | {L"ConcurrentApps", cpptInteger, 501}, | ||
30 | {L"CreatedBy", cpptString, 500}, | ||
31 | {L"CRMEnabled", cpptBoolean, 500}, | ||
32 | {L"CRMLogFile", cpptString, 500}, | ||
33 | {L"Deleteable", cpptBoolean, 500}, | ||
34 | {L"Description", cpptString, 500}, | ||
35 | {L"DumpEnabled", cpptBoolean, 501}, | ||
36 | {L"DumpOnException", cpptBoolean, 501}, | ||
37 | {L"DumpOnFailfast", cpptBoolean, 501}, | ||
38 | {L"DumpPath", cpptString, 501}, | ||
39 | {L"EventsEnabled", cpptBoolean, 500}, | ||
40 | {L"Identity", cpptString, 500}, | ||
41 | {L"ImpersonationLevel", cpptInteger, 500}, | ||
42 | {L"IsEnabled", cpptBoolean, 501}, | ||
43 | {L"MaxDumpCount", cpptInteger, 501}, | ||
44 | {L"Password", cpptString, 500}, | ||
45 | {L"QCAuthenticateMsgs", cpptInteger, 501}, | ||
46 | {L"QCListenerMaxThreads", cpptInteger, 501}, | ||
47 | {L"QueueListenerEnabled", cpptBoolean, 500}, | ||
48 | {L"QueuingEnabled", cpptBoolean, 500}, | ||
49 | {L"RecycleActivationLimit", cpptInteger, 501}, | ||
50 | {L"RecycleCallLimit", cpptInteger, 501}, | ||
51 | {L"RecycleExpirationTimeout", cpptInteger, 501}, | ||
52 | {L"RecycleLifetimeLimit", cpptInteger, 501}, | ||
53 | {L"RecycleMemoryLimit", cpptInteger, 501}, | ||
54 | {L"Replicable", cpptBoolean, 501}, | ||
55 | {L"RunForever", cpptBoolean, 500}, | ||
56 | {L"ShutdownAfter", cpptInteger, 500}, | ||
57 | {L"SoapActivated", cpptBoolean, 502}, | ||
58 | {L"SoapBaseUrl", cpptString, 502}, | ||
59 | {L"SoapMailTo", cpptString, 502}, | ||
60 | {L"SoapVRoot", cpptString, 502}, | ||
61 | {L"SRPEnabled", cpptBoolean, 501}, | ||
62 | {L"SRPTrustLevel", cpptInteger, 501}, | ||
63 | {NULL, cpptNone, 0} | ||
64 | }; | ||
65 | |||
66 | |||
67 | // prototypes for private helper functions | ||
68 | |||
69 | static void FreeApplication( | ||
70 | CPI_APPLICATION* pItm | ||
71 | ); | ||
72 | static HRESULT FindObjectForApplication( | ||
73 | CPI_APPLICATION* pItm, | ||
74 | BOOL fFindId, | ||
75 | BOOL fFindName, | ||
76 | ICatalogObject** ppiAppObj | ||
77 | ); | ||
78 | static HRESULT AddApplicationToActionData( | ||
79 | CPI_APPLICATION* pItm, | ||
80 | int iActionType, | ||
81 | int iActionCost, | ||
82 | LPWSTR* ppwzActionData | ||
83 | ); | ||
84 | |||
85 | |||
86 | // function definitions | ||
87 | |||
88 | void CpiApplicationListFree( | ||
89 | CPI_APPLICATION_LIST* pList | ||
90 | ) | ||
91 | { | ||
92 | CPI_APPLICATION* pItm = pList->pFirst; | ||
93 | |||
94 | while (pItm) | ||
95 | { | ||
96 | CPI_APPLICATION* pDelete = pItm; | ||
97 | pItm = pItm->pNext; | ||
98 | FreeApplication(pDelete); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | HRESULT CpiApplicationsRead( | ||
103 | CPI_PARTITION_LIST* pPartList, | ||
104 | CPI_APPLICATION_LIST* pAppList | ||
105 | ) | ||
106 | { | ||
107 | HRESULT hr = S_OK; | ||
108 | UINT er = ERROR_SUCCESS; | ||
109 | |||
110 | int iVersionNT = 0; | ||
111 | |||
112 | PMSIHANDLE hView, hRec; | ||
113 | |||
114 | CPI_APPLICATION* pItm = NULL; | ||
115 | LPWSTR pwzData = NULL; | ||
116 | BOOL fMatchingArchitecture = FALSE; | ||
117 | |||
118 | // get NT version | ||
119 | hr = WcaGetIntProperty(L"VersionNT", &iVersionNT); | ||
120 | ExitOnFailure(hr, "Failed to get VersionNT property"); | ||
121 | |||
122 | // loop through all applications | ||
123 | hr = WcaOpenExecuteView(vcsApplicationQuery, &hView); | ||
124 | ExitOnFailure(hr, "Failed to execute view on ComPlusApplication table"); | ||
125 | |||
126 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
127 | { | ||
128 | // get component | ||
129 | hr = WcaGetRecordString(hRec, aqComponent, &pwzData); | ||
130 | ExitOnFailure(hr, "Failed to get component"); | ||
131 | |||
132 | // check if the component is our processor architecture | ||
133 | if (pwzData && *pwzData) | ||
134 | { | ||
135 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
136 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
137 | |||
138 | if (!fMatchingArchitecture) | ||
139 | { | ||
140 | continue; // not the same architecture, ignore | ||
141 | } | ||
142 | } | ||
143 | |||
144 | // create entry | ||
145 | pItm = (CPI_APPLICATION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_APPLICATION)); | ||
146 | if (!pItm) | ||
147 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
148 | |||
149 | // get component install state | ||
150 | if (pwzData && *pwzData) | ||
151 | { | ||
152 | pItm->fHasComponent = TRUE; | ||
153 | |||
154 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
155 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
156 | } | ||
157 | |||
158 | // get key | ||
159 | hr = WcaGetRecordString(hRec, aqApplication, &pwzData); | ||
160 | ExitOnFailure(hr, "Failed to get key"); | ||
161 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
162 | |||
163 | // get partition | ||
164 | if (502 <= iVersionNT) | ||
165 | { | ||
166 | hr = WcaGetRecordString(hRec, aqPartition, &pwzData); | ||
167 | ExitOnFailure(hr, "Failed to get partition"); | ||
168 | |||
169 | if (pwzData && *pwzData) | ||
170 | { | ||
171 | hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition); | ||
172 | ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | // get id | ||
177 | hr = WcaGetRecordFormattedString(hRec, aqID, &pwzData); | ||
178 | ExitOnFailure(hr, "Failed to get id"); | ||
179 | |||
180 | if (pwzData && *pwzData) | ||
181 | { | ||
182 | hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID)); | ||
183 | ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData); | ||
184 | } | ||
185 | |||
186 | // get name | ||
187 | hr = WcaGetRecordFormattedString(hRec, aqName, &pwzData); | ||
188 | ExitOnFailure(hr, "Failed to get name"); | ||
189 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
190 | |||
191 | // if application is a locater, either an id or a name must be provided | ||
192 | if (!pItm->fHasComponent && !*pItm->wzID && !*pItm->wzName) | ||
193 | ExitOnFailure(hr = E_FAIL, "An application locater must have either an id or a name associated, key: %S", pItm->wzKey); | ||
194 | |||
195 | // if application is not a locater, an name must be provided | ||
196 | if (pItm->fHasComponent && !*pItm->wzName) | ||
197 | ExitOnFailure(hr = E_FAIL, "An application must have a name associated, key: %S", pItm->wzKey); | ||
198 | |||
199 | // get properties | ||
200 | if (CpiTableExists(cptComPlusApplicationProperty) && pItm->fHasComponent) | ||
201 | { | ||
202 | hr = CpiPropertiesRead(vcsApplicationPropertyQuery, pItm->wzKey, pdlApplicationProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
203 | ExitOnFailure(hr, "Failed to get properties"); | ||
204 | } | ||
205 | |||
206 | // set references & increment counters | ||
207 | if (pItm->fHasComponent) | ||
208 | { | ||
209 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
210 | { | ||
211 | if (pItm->pPartition) | ||
212 | CpiPartitionAddReferenceInstall(pItm->pPartition); | ||
213 | pAppList->iInstallCount++; | ||
214 | } | ||
215 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
216 | { | ||
217 | if (pItm->pPartition) | ||
218 | CpiPartitionAddReferenceUninstall(pItm->pPartition); | ||
219 | pAppList->iUninstallCount++; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | // add entry | ||
224 | if (pAppList->pFirst) | ||
225 | pItm->pNext = pAppList->pFirst; | ||
226 | pAppList->pFirst = pItm; | ||
227 | pItm = NULL; | ||
228 | } | ||
229 | |||
230 | if (E_NOMOREITEMS == hr) | ||
231 | hr = S_OK; | ||
232 | |||
233 | LExit: | ||
234 | // clean up | ||
235 | if (pItm) | ||
236 | FreeApplication(pItm); | ||
237 | |||
238 | ReleaseStr(pwzData); | ||
239 | |||
240 | return hr; | ||
241 | } | ||
242 | |||
243 | HRESULT CpiApplicationsVerifyInstall( | ||
244 | CPI_APPLICATION_LIST* pList | ||
245 | ) | ||
246 | { | ||
247 | HRESULT hr = S_OK; | ||
248 | UINT er = ERROR_SUCCESS; | ||
249 | |||
250 | ICatalogObject* piAppObj = NULL; | ||
251 | |||
252 | for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
253 | { | ||
254 | // referenced locaters or applications that are being installed | ||
255 | if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction))) | ||
256 | continue; | ||
257 | |||
258 | // if the application is referensed and is not a locater, it must be installed | ||
259 | if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction)) | ||
260 | MessageExitOnFailure(hr = E_FAIL, msierrComPlusApplicationDependency, "An application is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey); | ||
261 | |||
262 | // application is supposed to exist | ||
263 | if (!pItm->fHasComponent || CpiIsInstalled(pItm->isInstalled)) | ||
264 | { | ||
265 | // get collection object for application | ||
266 | hr = FindObjectForApplication(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piAppObj); | ||
267 | ExitOnFailure(hr, "Failed to find collection object for application"); | ||
268 | |||
269 | // if the application was found | ||
270 | if (S_OK == hr) | ||
271 | { | ||
272 | // if we don't have an id, copy id from object | ||
273 | if (!*pItm->wzID) | ||
274 | { | ||
275 | hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID)); | ||
276 | ExitOnFailure(hr, "Failed to get id"); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | // if the application was not found | ||
281 | else | ||
282 | { | ||
283 | // if the application is a locater, this is an error | ||
284 | if (!pItm->fHasComponent) | ||
285 | MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusApplicationNotFound, "An application required by this installation was not found, key: %S", pItm->wzKey); | ||
286 | |||
287 | // create a new id if one is missing | ||
288 | if (!*pItm->wzID) | ||
289 | { | ||
290 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
291 | ExitOnFailure(hr, "Failed to create id"); | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | // application is supposed to be created | ||
297 | else | ||
298 | { | ||
299 | // check for conflicts | ||
300 | do { | ||
301 | if (*pItm->wzID) | ||
302 | { | ||
303 | // find applications with conflicting id | ||
304 | hr = FindObjectForApplication(pItm, TRUE, FALSE, &piAppObj); | ||
305 | ExitOnFailure(hr, "Failed to find collection object for application"); | ||
306 | |||
307 | if (S_FALSE == hr) | ||
308 | { | ||
309 | // find applications with conflicting name | ||
310 | hr = FindObjectForApplication(pItm, FALSE, TRUE, &piAppObj); | ||
311 | ExitOnFailure(hr, "Failed to find collection object for application"); | ||
312 | |||
313 | if (S_OK == hr) | ||
314 | // "A application with a conflictiong name exists. retry cancel" | ||
315 | er = WcaErrorMessage(msierrComPlusApplicationNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0); | ||
316 | else | ||
317 | break; // no conflicting entry found, break loop | ||
318 | } | ||
319 | else | ||
320 | // "A application with a conflicting id exists. abort retry ignore" | ||
321 | er = WcaErrorMessage(msierrComPlusApplicationIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
322 | } | ||
323 | else | ||
324 | { | ||
325 | // find applications with conflicting name | ||
326 | hr = FindObjectForApplication(pItm, FALSE, TRUE, &piAppObj); | ||
327 | ExitOnFailure(hr, "Failed to find collection object for application"); | ||
328 | |||
329 | if (S_OK == hr) | ||
330 | // "A subscription with a conflictiong name exists. abort retry ignore" | ||
331 | er = WcaErrorMessage(msierrComPlusApplicationNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
332 | else | ||
333 | break; // no conflicting entry found, break loop | ||
334 | } | ||
335 | |||
336 | switch (er) | ||
337 | { | ||
338 | case IDCANCEL: | ||
339 | case IDABORT: | ||
340 | ExitOnFailure(hr = E_FAIL, "An application with a conflictiong name or id exists, key: %S", pItm->wzKey); | ||
341 | break; | ||
342 | case IDRETRY: | ||
343 | break; | ||
344 | case IDIGNORE: | ||
345 | default: | ||
346 | // if we don't have an id, copy id from object | ||
347 | if (!*pItm->wzID) | ||
348 | { | ||
349 | hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID)); | ||
350 | ExitOnFailure(hr, "Failed to get id"); | ||
351 | } | ||
352 | hr = S_FALSE; // indicate that this is not a conflict | ||
353 | } | ||
354 | } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts | ||
355 | |||
356 | // create a new id if one is missing | ||
357 | if (!*pItm->wzID) | ||
358 | { | ||
359 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
360 | ExitOnFailure(hr, "Failed to create id"); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | // clean up | ||
365 | ReleaseNullObject(piAppObj); | ||
366 | } | ||
367 | |||
368 | hr = S_OK; | ||
369 | |||
370 | LExit: | ||
371 | // clean up | ||
372 | ReleaseObject(piAppObj); | ||
373 | |||
374 | return hr; | ||
375 | } | ||
376 | |||
377 | HRESULT CpiApplicationsVerifyUninstall( | ||
378 | CPI_APPLICATION_LIST* pList | ||
379 | ) | ||
380 | { | ||
381 | HRESULT hr = S_OK; | ||
382 | ICatalogObject* piAppObj = NULL; | ||
383 | |||
384 | for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
385 | { | ||
386 | // referenced locaters or applications that are being installed | ||
387 | if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction))) | ||
388 | continue; | ||
389 | |||
390 | // get collection object for application | ||
391 | hr = FindObjectForApplication(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piAppObj); | ||
392 | ExitOnFailure(hr, "Failed to find collection object for application"); | ||
393 | |||
394 | // if the application was found | ||
395 | if (S_OK == hr) | ||
396 | { | ||
397 | // if we don't have an id, copy id from object | ||
398 | if (!*pItm->wzID) | ||
399 | { | ||
400 | hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID)); | ||
401 | ExitOnFailure(hr, "Failed to get id"); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | // if the application was not found | ||
406 | else | ||
407 | { | ||
408 | pItm->fObjectNotFound = TRUE; | ||
409 | if (pItm->fHasComponent) | ||
410 | pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall | ||
411 | } | ||
412 | |||
413 | // clean up | ||
414 | ReleaseNullObject(piAppObj); | ||
415 | } | ||
416 | |||
417 | hr = S_OK; | ||
418 | |||
419 | LExit: | ||
420 | // clean up | ||
421 | ReleaseObject(piAppObj); | ||
422 | |||
423 | return hr; | ||
424 | } | ||
425 | |||
426 | void CpiApplicationAddReferenceInstall( | ||
427 | CPI_APPLICATION* pItm | ||
428 | ) | ||
429 | { | ||
430 | pItm->fReferencedForInstall = TRUE; | ||
431 | if (pItm->pPartition) | ||
432 | CpiPartitionAddReferenceInstall(pItm->pPartition); | ||
433 | } | ||
434 | |||
435 | void CpiApplicationAddReferenceUninstall( | ||
436 | CPI_APPLICATION* pItm | ||
437 | ) | ||
438 | { | ||
439 | pItm->fReferencedForUninstall = TRUE; | ||
440 | if (pItm->pPartition) | ||
441 | CpiPartitionAddReferenceUninstall(pItm->pPartition); | ||
442 | } | ||
443 | |||
444 | HRESULT CpiApplicationsInstall( | ||
445 | CPI_APPLICATION_LIST* pList, | ||
446 | int iRunMode, | ||
447 | LPWSTR* ppwzActionData, | ||
448 | int* piProgress | ||
449 | ) | ||
450 | { | ||
451 | HRESULT hr = S_OK; | ||
452 | |||
453 | int iActionType; | ||
454 | |||
455 | // add action text | ||
456 | hr = CpiAddActionTextToActionData(L"CreateComPlusApplications", ppwzActionData); | ||
457 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
458 | |||
459 | // add applicaton count to action data | ||
460 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
461 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
462 | |||
463 | // add applications to custom action data | ||
464 | for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
465 | { | ||
466 | // applications that are being installed only | ||
467 | if (!pItm->fHasComponent || !WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
468 | continue; | ||
469 | |||
470 | // action type | ||
471 | if (rmRollback == iRunMode) | ||
472 | { | ||
473 | if (CpiIsInstalled(pItm->isInstalled)) | ||
474 | iActionType = atNoOp; | ||
475 | else | ||
476 | iActionType = atRemove; | ||
477 | } | ||
478 | else | ||
479 | iActionType = atCreate; | ||
480 | |||
481 | // add to action data | ||
482 | hr = AddApplicationToActionData(pItm, iActionType, COST_APPLICATION_CREATE, ppwzActionData); | ||
483 | ExitOnFailure(hr, "Failed to add applicaton to custom action data, key: %S", pItm->wzKey); | ||
484 | } | ||
485 | |||
486 | // add progress tics | ||
487 | if (piProgress) | ||
488 | *piProgress += COST_APPLICATION_CREATE * pList->iInstallCount; | ||
489 | |||
490 | hr = S_OK; | ||
491 | |||
492 | LExit: | ||
493 | return hr; | ||
494 | } | ||
495 | |||
496 | HRESULT CpiApplicationsUninstall( | ||
497 | CPI_APPLICATION_LIST* pList, | ||
498 | int iRunMode, | ||
499 | LPWSTR* ppwzActionData, | ||
500 | int* piProgress | ||
501 | ) | ||
502 | { | ||
503 | HRESULT hr = S_OK; | ||
504 | |||
505 | int iActionType; | ||
506 | |||
507 | // add action text | ||
508 | hr = CpiAddActionTextToActionData(L"RemoveComPlusApplications", ppwzActionData); | ||
509 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
510 | |||
511 | // add applicaton count to action data | ||
512 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
513 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
514 | |||
515 | // add applications to custom action data | ||
516 | for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
517 | { | ||
518 | // applications that are being uninstalled only | ||
519 | if (!pItm->fHasComponent || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
520 | continue; | ||
521 | |||
522 | // action type | ||
523 | if (rmRollback == iRunMode) | ||
524 | iActionType = atCreate; | ||
525 | else | ||
526 | iActionType = atRemove; | ||
527 | |||
528 | // add to action data | ||
529 | hr = AddApplicationToActionData(pItm, iActionType, COST_APPLICATION_DELETE, ppwzActionData); | ||
530 | ExitOnFailure(hr, "Failed to add applicaton to custom action data, key: %S", pItm->wzKey); | ||
531 | } | ||
532 | |||
533 | // add progress tics | ||
534 | if (piProgress) | ||
535 | *piProgress += COST_APPLICATION_DELETE * pList->iUninstallCount; | ||
536 | |||
537 | hr = S_OK; | ||
538 | |||
539 | LExit: | ||
540 | return hr; | ||
541 | } | ||
542 | |||
543 | HRESULT CpiApplicationFindByKey( | ||
544 | CPI_APPLICATION_LIST* pList, | ||
545 | LPCWSTR pwzKey, | ||
546 | CPI_APPLICATION** ppApp | ||
547 | ) | ||
548 | { | ||
549 | for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
550 | { | ||
551 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
552 | { | ||
553 | *ppApp = pItm; | ||
554 | return S_OK; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | return S_FALSE; | ||
559 | } | ||
560 | |||
561 | HRESULT CpiGetRolesCollForApplication( | ||
562 | CPI_APPLICATION* pApp, | ||
563 | ICatalogCollection** ppiRolesColl | ||
564 | ) | ||
565 | { | ||
566 | HRESULT hr = S_OK; | ||
567 | |||
568 | ICatalogCollection* piAppColl = NULL; | ||
569 | ICatalogObject* piAppObj = NULL; | ||
570 | |||
571 | // if a previous attempt to locate the collection object failed | ||
572 | if (pApp->fObjectNotFound) | ||
573 | ExitFunction1(hr = S_FALSE); | ||
574 | |||
575 | // get applications collection | ||
576 | if (!pApp->piRolesColl) | ||
577 | { | ||
578 | // get applications collection | ||
579 | if (pApp->pPartition) | ||
580 | hr = CpiGetApplicationsCollForPartition(pApp->pPartition, &piAppColl); | ||
581 | else | ||
582 | hr = CpiGetApplicationsCollection(&piAppColl); | ||
583 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
584 | |||
585 | if (S_FALSE == hr) | ||
586 | ExitFunction(); // exit with hr = S_FALSE | ||
587 | |||
588 | // find application object | ||
589 | hr = CpiFindCollectionObject(piAppColl, pApp->wzID, *pApp->wzID ? NULL : pApp->wzName, &piAppObj); | ||
590 | ExitOnFailure(hr, "Failed to find application object"); | ||
591 | |||
592 | if (S_FALSE == hr) | ||
593 | ExitFunction(); // exit with hr = S_FALSE | ||
594 | |||
595 | // get roles collection | ||
596 | hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Roles", &pApp->piRolesColl); | ||
597 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
598 | } | ||
599 | |||
600 | // return value | ||
601 | *ppiRolesColl = pApp->piRolesColl; | ||
602 | (*ppiRolesColl)->AddRef(); | ||
603 | |||
604 | hr = S_OK; | ||
605 | |||
606 | LExit: | ||
607 | // clean up | ||
608 | ReleaseObject(piAppColl); | ||
609 | ReleaseObject(piAppObj); | ||
610 | |||
611 | return hr; | ||
612 | } | ||
613 | |||
614 | HRESULT CpiGetComponentsCollForApplication( | ||
615 | CPI_APPLICATION* pApp, | ||
616 | ICatalogCollection** ppiCompsColl | ||
617 | ) | ||
618 | { | ||
619 | HRESULT hr = S_OK; | ||
620 | |||
621 | ICatalogCollection* piAppColl = NULL; | ||
622 | ICatalogObject* piAppObj = NULL; | ||
623 | |||
624 | // if a previous attempt to locate the collection object failed | ||
625 | if (pApp->fObjectNotFound) | ||
626 | ExitFunction1(hr = S_FALSE); | ||
627 | |||
628 | // get applications collection | ||
629 | if (!pApp->piCompsColl) | ||
630 | { | ||
631 | // get applications collection | ||
632 | if (pApp->pPartition) | ||
633 | hr = CpiGetApplicationsCollForPartition(pApp->pPartition, &piAppColl); | ||
634 | else | ||
635 | hr = CpiGetApplicationsCollection(&piAppColl); | ||
636 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
637 | |||
638 | if (S_FALSE == hr) | ||
639 | ExitFunction(); // exit with hr = S_FALSE | ||
640 | |||
641 | // find application object | ||
642 | hr = CpiFindCollectionObject(piAppColl, pApp->wzID, *pApp->wzID ? NULL : pApp->wzName, &piAppObj); | ||
643 | ExitOnFailure(hr, "Failed to find application object"); | ||
644 | |||
645 | if (S_FALSE == hr) | ||
646 | ExitFunction(); // exit with hr = S_FALSE | ||
647 | |||
648 | // get roles collection | ||
649 | hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Components", &pApp->piCompsColl); | ||
650 | ExitOnFailure(hr, "Failed to get components collection"); | ||
651 | } | ||
652 | |||
653 | // return value | ||
654 | *ppiCompsColl = pApp->piCompsColl; | ||
655 | (*ppiCompsColl)->AddRef(); | ||
656 | |||
657 | hr = S_OK; | ||
658 | |||
659 | LExit: | ||
660 | // clean up | ||
661 | ReleaseObject(piAppColl); | ||
662 | ReleaseObject(piAppObj); | ||
663 | |||
664 | return hr; | ||
665 | } | ||
666 | |||
667 | |||
668 | // helper function definitions | ||
669 | |||
670 | static void FreeApplication( | ||
671 | CPI_APPLICATION* pItm | ||
672 | ) | ||
673 | { | ||
674 | if (pItm->pProperties) | ||
675 | CpiPropertiesFreeList(pItm->pProperties); | ||
676 | |||
677 | ReleaseObject(pItm->piRolesColl); | ||
678 | ReleaseObject(pItm->piCompsColl); | ||
679 | |||
680 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
681 | } | ||
682 | |||
683 | static HRESULT FindObjectForApplication( | ||
684 | CPI_APPLICATION* pItm, | ||
685 | BOOL fFindId, | ||
686 | BOOL fFindName, | ||
687 | ICatalogObject** ppiAppObj | ||
688 | ) | ||
689 | { | ||
690 | HRESULT hr = S_OK; | ||
691 | |||
692 | ICatalogCollection* piAppColl = NULL; | ||
693 | |||
694 | // get applications collection | ||
695 | if (pItm->pPartition) | ||
696 | hr = CpiGetApplicationsCollForPartition(pItm->pPartition, &piAppColl); | ||
697 | else | ||
698 | hr = CpiGetApplicationsCollection(&piAppColl); | ||
699 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
700 | |||
701 | if (S_FALSE == hr) | ||
702 | ExitFunction(); // exit with hr = S_FALSE | ||
703 | |||
704 | // find application object | ||
705 | hr = CpiFindCollectionObject(piAppColl, fFindId ? pItm->wzID : NULL, fFindName ? pItm->wzName : NULL, ppiAppObj); | ||
706 | ExitOnFailure(hr, "Failed to find application object"); | ||
707 | |||
708 | // exit with hr from CpiFindCollectionObject() | ||
709 | |||
710 | LExit: | ||
711 | // clean up | ||
712 | ReleaseObject(piAppColl); | ||
713 | |||
714 | return hr; | ||
715 | } | ||
716 | |||
717 | static HRESULT AddApplicationToActionData( | ||
718 | CPI_APPLICATION* pItm, | ||
719 | int iActionType, | ||
720 | int iActionCost, | ||
721 | LPWSTR* ppwzActionData | ||
722 | ) | ||
723 | { | ||
724 | HRESULT hr = S_OK; | ||
725 | |||
726 | // add action information to custom action data | ||
727 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
728 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
729 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
730 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
731 | |||
732 | // add application information to custom action data | ||
733 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
734 | ExitOnFailure(hr, "Failed to add application key to custom action data"); | ||
735 | hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData); | ||
736 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
737 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
738 | ExitOnFailure(hr, "Failed to add application name to custom action data"); | ||
739 | |||
740 | // add partition information to custom action data | ||
741 | hr = WcaWriteStringToCaData(pItm->pPartition ? pItm->pPartition->wzID : L"", ppwzActionData); | ||
742 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
743 | |||
744 | // add properties to custom action data | ||
745 | hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
746 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
747 | |||
748 | hr = S_OK; | ||
749 | |||
750 | LExit: | ||
751 | return hr; | ||
752 | } | ||
diff --git a/src/ca/cpappsched.h b/src/ca/cpappsched.h new file mode 100644 index 00000000..2cd6a0ee --- /dev/null +++ b/src/ca/cpappsched.h | |||
@@ -0,0 +1,83 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | struct CPI_APPLICATION | ||
6 | { | ||
7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
8 | WCHAR wzID[CPI_MAX_GUID + 1]; | ||
9 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
10 | |||
11 | int iPropertyCount; | ||
12 | CPI_PROPERTY* pProperties; | ||
13 | |||
14 | BOOL fHasComponent; | ||
15 | BOOL fReferencedForInstall; | ||
16 | BOOL fReferencedForUninstall; | ||
17 | BOOL fObjectNotFound; | ||
18 | |||
19 | INSTALLSTATE isInstalled, isAction; | ||
20 | |||
21 | CPI_PARTITION* pPartition; | ||
22 | |||
23 | ICatalogCollection* piRolesColl; | ||
24 | ICatalogCollection* piCompsColl; | ||
25 | |||
26 | CPI_APPLICATION* pNext; | ||
27 | }; | ||
28 | |||
29 | struct CPI_APPLICATION_LIST | ||
30 | { | ||
31 | CPI_APPLICATION* pFirst; | ||
32 | |||
33 | int iInstallCount; | ||
34 | int iUninstallCount; | ||
35 | }; | ||
36 | |||
37 | |||
38 | // function prototypes | ||
39 | |||
40 | void CpiApplicationListFree( | ||
41 | CPI_APPLICATION_LIST* pList | ||
42 | ); | ||
43 | HRESULT CpiApplicationsRead( | ||
44 | CPI_PARTITION_LIST* pPartList, | ||
45 | CPI_APPLICATION_LIST* pAppList | ||
46 | ); | ||
47 | HRESULT CpiApplicationsVerifyInstall( | ||
48 | CPI_APPLICATION_LIST* pList | ||
49 | ); | ||
50 | HRESULT CpiApplicationsVerifyUninstall( | ||
51 | CPI_APPLICATION_LIST* pList | ||
52 | ); | ||
53 | void CpiApplicationAddReferenceInstall( | ||
54 | CPI_APPLICATION* pItm | ||
55 | ); | ||
56 | void CpiApplicationAddReferenceUninstall( | ||
57 | CPI_APPLICATION* pItm | ||
58 | ); | ||
59 | HRESULT CpiApplicationsInstall( | ||
60 | CPI_APPLICATION_LIST* pList, | ||
61 | int iRunMode, | ||
62 | LPWSTR* ppwzActionData, | ||
63 | int* piProgress | ||
64 | ); | ||
65 | HRESULT CpiApplicationsUninstall( | ||
66 | CPI_APPLICATION_LIST* pList, | ||
67 | int iRunMode, | ||
68 | LPWSTR* ppwzActionData, | ||
69 | int* piProgress | ||
70 | ); | ||
71 | HRESULT CpiApplicationFindByKey( | ||
72 | CPI_APPLICATION_LIST* pList, | ||
73 | LPCWSTR pwzKey, | ||
74 | CPI_APPLICATION** ppApp | ||
75 | ); | ||
76 | HRESULT CpiGetRolesCollForApplication( | ||
77 | CPI_APPLICATION* pApp, | ||
78 | ICatalogCollection** ppiRolesColl | ||
79 | ); | ||
80 | HRESULT CpiGetComponentsCollForApplication( | ||
81 | CPI_APPLICATION* pApp, | ||
82 | ICatalogCollection** ppiCompsColl | ||
83 | ); | ||
diff --git a/src/ca/cpasmexec.cpp b/src/ca/cpasmexec.cpp new file mode 100644 index 00000000..339c08e1 --- /dev/null +++ b/src/ca/cpasmexec.cpp | |||
@@ -0,0 +1,1888 @@ | |||
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 | // GAC related declarations | ||
7 | |||
8 | typedef struct _FUSION_INSTALL_REFERENCE_ | ||
9 | { | ||
10 | DWORD cbSize; | ||
11 | DWORD dwFlags; | ||
12 | GUID guidScheme; | ||
13 | LPCWSTR szIdentifier; | ||
14 | LPCWSTR szNonCannonicalData; | ||
15 | } FUSION_INSTALL_REFERENCE; | ||
16 | |||
17 | typedef struct _FUSION_INSTALL_REFERENCE_ *LPFUSION_INSTALL_REFERENCE; | ||
18 | |||
19 | typedef const FUSION_INSTALL_REFERENCE *LPCFUSION_INSTALL_REFERENCE; | ||
20 | |||
21 | typedef struct _ASSEMBLY_INFO | ||
22 | { | ||
23 | ULONG cbAssemblyInfo; | ||
24 | DWORD dwAssemblyFlags; | ||
25 | ULARGE_INTEGER uliAssemblySizeInKB; | ||
26 | LPWSTR pszCurrentAssemblyPathBuf; | ||
27 | ULONG cchBuf; | ||
28 | } ASSEMBLY_INFO; | ||
29 | |||
30 | typedef interface IAssemblyCacheItem IAssemblyCacheItem; | ||
31 | |||
32 | MIDL_INTERFACE("e707dcde-d1cd-11d2-bab9-00c04f8eceae") | ||
33 | IAssemblyCache : public IUnknown | ||
34 | { | ||
35 | public: | ||
36 | virtual HRESULT STDMETHODCALLTYPE UninstallAssembly( | ||
37 | /* [in] */ DWORD dwFlags, | ||
38 | /* [in] */ LPCWSTR pszAssemblyName, | ||
39 | /* [in] */ LPCFUSION_INSTALL_REFERENCE pRefData, | ||
40 | /* [optional][out] */ ULONG *pulDisposition) = 0; | ||
41 | |||
42 | virtual HRESULT STDMETHODCALLTYPE QueryAssemblyInfo( | ||
43 | /* [in] */ DWORD dwFlags, | ||
44 | /* [in] */ LPCWSTR pszAssemblyName, | ||
45 | /* [out][in] */ ASSEMBLY_INFO *pAsmInfo) = 0; | ||
46 | |||
47 | virtual HRESULT STDMETHODCALLTYPE CreateAssemblyCacheItem( | ||
48 | /* [in] */ DWORD dwFlags, | ||
49 | /* [in] */ PVOID pvReserved, | ||
50 | /* [out] */ IAssemblyCacheItem **ppAsmItem, | ||
51 | /* [optional][in] */ LPCWSTR pszAssemblyName) = 0; | ||
52 | |||
53 | virtual HRESULT STDMETHODCALLTYPE CreateAssemblyScavenger( | ||
54 | /* [out] */ IUnknown **ppUnkReserved) = 0; | ||
55 | |||
56 | virtual HRESULT STDMETHODCALLTYPE InstallAssembly( | ||
57 | /* [in] */ DWORD dwFlags, | ||
58 | /* [in] */ LPCWSTR pszManifestFilePath, | ||
59 | /* [in] */ LPCFUSION_INSTALL_REFERENCE pRefData) = 0; | ||
60 | }; | ||
61 | |||
62 | typedef HRESULT (__stdcall *LoadLibraryShimFunc)(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll); | ||
63 | typedef HRESULT (__stdcall *CreateAssemblyCacheFunc)(IAssemblyCache **ppAsmCache, DWORD dwReserved); | ||
64 | |||
65 | |||
66 | // RegistrationHelper related declarations | ||
67 | |||
68 | static const GUID CLSID_RegistrationHelper = | ||
69 | { 0x89a86e7b, 0xc229, 0x4008, { 0x9b, 0xaa, 0x2f, 0x5c, 0x84, 0x11, 0xd7, 0xe0 } }; | ||
70 | |||
71 | enum eInstallationFlags { | ||
72 | ifConfigureComponentsOnly = 16, | ||
73 | ifFindOrCreateTargetApplication = 4, | ||
74 | ifExpectExistingTypeLib = 1 | ||
75 | }; | ||
76 | |||
77 | |||
78 | // private constants | ||
79 | |||
80 | enum eAssemblyAttributes | ||
81 | { | ||
82 | aaEventClass = (1 << 0), | ||
83 | aaDotNetAssembly = (1 << 1), | ||
84 | aaPathFromGAC = (1 << 2), | ||
85 | aaRunInCommit = (1 << 3) | ||
86 | }; | ||
87 | |||
88 | |||
89 | // private structs | ||
90 | |||
91 | struct CPI_ROLE_ASSIGNMENT | ||
92 | { | ||
93 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
94 | WCHAR wzRoleName[MAX_DARWIN_COLUMN + 1]; | ||
95 | |||
96 | CPI_ROLE_ASSIGNMENT* pNext; | ||
97 | }; | ||
98 | |||
99 | struct CPI_METHOD | ||
100 | { | ||
101 | WCHAR wzIndex[11 + 1]; | ||
102 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
103 | |||
104 | CPI_PROPERTY* pPropertyList; | ||
105 | CPI_ROLE_ASSIGNMENT* pRoleAssignmentList; | ||
106 | |||
107 | CPI_METHOD* pNext; | ||
108 | }; | ||
109 | |||
110 | struct CPI_INTERFACE | ||
111 | { | ||
112 | WCHAR wzIID[CPI_MAX_GUID + 1]; | ||
113 | |||
114 | CPI_PROPERTY* pPropertyList; | ||
115 | CPI_ROLE_ASSIGNMENT* pRoleAssignmentList; | ||
116 | CPI_METHOD* pMethodList; | ||
117 | |||
118 | CPI_INTERFACE* pNext; | ||
119 | }; | ||
120 | |||
121 | struct CPI_COMPONENT | ||
122 | { | ||
123 | WCHAR wzCLSID[CPI_MAX_GUID + 1]; | ||
124 | |||
125 | CPI_PROPERTY* pPropertyList; | ||
126 | CPI_ROLE_ASSIGNMENT* pRoleAssignmentList; | ||
127 | CPI_INTERFACE* pInterfaceList; | ||
128 | |||
129 | CPI_COMPONENT* pNext; | ||
130 | }; | ||
131 | |||
132 | struct CPI_ASSEMBLY_ATTRIBUTES | ||
133 | { | ||
134 | int iActionType; | ||
135 | int iActionCost; | ||
136 | LPWSTR pwzKey; | ||
137 | LPWSTR pwzAssemblyName; | ||
138 | LPWSTR pwzDllPath; | ||
139 | LPWSTR pwzTlbPath; | ||
140 | LPWSTR pwzPSDllPath; | ||
141 | LPWSTR pwzAppID; | ||
142 | LPWSTR pwzPartID; | ||
143 | int iAttributes; | ||
144 | CPI_COMPONENT* pCompList; | ||
145 | }; | ||
146 | |||
147 | struct CPI_ROLE_ASSIGNMENTS_ATTRIBUTES | ||
148 | { | ||
149 | int iActionType; | ||
150 | int iActionCost; | ||
151 | LPWSTR pwzKey; | ||
152 | LPWSTR pwzAppID; | ||
153 | LPWSTR pwzPartID; | ||
154 | int iRoleCount; | ||
155 | CPI_COMPONENT* pCompList; | ||
156 | }; | ||
157 | |||
158 | |||
159 | // prototypes for private helper functions | ||
160 | |||
161 | static HRESULT RegisterAssembly( | ||
162 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
163 | ); | ||
164 | static HRESULT UnregisterAssembly( | ||
165 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
166 | ); | ||
167 | static void InitAssemblyExec(); | ||
168 | static void UninitAssemblyExec(); | ||
169 | static HRESULT GetRegistrationHelper( | ||
170 | IDispatch** ppiRegHlp | ||
171 | ); | ||
172 | static HRESULT GetAssemblyCacheObject( | ||
173 | IAssemblyCache** ppAssemblyCache | ||
174 | ); | ||
175 | static HRESULT GetAssemblyPathFromGAC( | ||
176 | LPCWSTR pwzAssemblyName, | ||
177 | LPWSTR* ppwzAssemblyPath | ||
178 | ); | ||
179 | static HRESULT RegisterDotNetAssembly( | ||
180 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
181 | ); | ||
182 | static HRESULT RegisterNativeAssembly( | ||
183 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
184 | ); | ||
185 | static HRESULT UnregisterDotNetAssembly( | ||
186 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
187 | ); | ||
188 | static HRESULT RemoveComponents( | ||
189 | ICatalogCollection* piCompColl, | ||
190 | CPI_COMPONENT* pCompList | ||
191 | ); | ||
192 | static HRESULT ReadAssemblyAttributes( | ||
193 | LPWSTR* ppwzData, | ||
194 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
195 | ); | ||
196 | static void FreeAssemblyAttributes( | ||
197 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
198 | ); | ||
199 | static HRESULT ReadRoleAssignmentsAttributes( | ||
200 | LPWSTR* ppwzData, | ||
201 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
202 | ); | ||
203 | static void FreeRoleAssignmentsAttributes( | ||
204 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
205 | ); | ||
206 | static HRESULT ConfigureComponents( | ||
207 | LPCWSTR pwzPartID, | ||
208 | LPCWSTR pwzAppID, | ||
209 | CPI_COMPONENT* pCompList, | ||
210 | BOOL fCreate, | ||
211 | BOOL fProgress | ||
212 | ); | ||
213 | static HRESULT ConfigureInterfaces( | ||
214 | ICatalogCollection* piCompColl, | ||
215 | ICatalogObject* piCompObj, | ||
216 | CPI_INTERFACE* pIntfList, | ||
217 | BOOL fCreate | ||
218 | ); | ||
219 | static HRESULT ConfigureMethods( | ||
220 | ICatalogCollection* piIntfColl, | ||
221 | ICatalogObject* piIntfObj, | ||
222 | CPI_METHOD* pMethList, | ||
223 | BOOL fCreate | ||
224 | ); | ||
225 | static HRESULT ConfigureRoleAssignments( | ||
226 | LPCWSTR pwzCollName, | ||
227 | ICatalogCollection* piCompColl, | ||
228 | ICatalogObject* piCompObj, | ||
229 | CPI_ROLE_ASSIGNMENT* pRoleList, | ||
230 | BOOL fCreate | ||
231 | ); | ||
232 | static HRESULT ReadComponentList( | ||
233 | LPWSTR* ppwzData, | ||
234 | CPI_COMPONENT** ppCompList | ||
235 | ); | ||
236 | static HRESULT ReadInterfaceList( | ||
237 | LPWSTR* ppwzData, | ||
238 | CPI_INTERFACE** ppIntfList | ||
239 | ); | ||
240 | static HRESULT ReadMethodList( | ||
241 | LPWSTR* ppwzData, | ||
242 | CPI_METHOD** ppMethList | ||
243 | ); | ||
244 | static HRESULT ReadRoleAssignmentList( | ||
245 | LPWSTR* ppwzData, | ||
246 | CPI_ROLE_ASSIGNMENT** ppRoleList | ||
247 | ); | ||
248 | static void FreeComponentList( | ||
249 | CPI_COMPONENT* pList | ||
250 | ); | ||
251 | static void FreeInterfaceList( | ||
252 | CPI_INTERFACE* pList | ||
253 | ); | ||
254 | static void FreeMethodList( | ||
255 | CPI_METHOD* pList | ||
256 | ); | ||
257 | static void FreeRoleAssignmentList( | ||
258 | CPI_ROLE_ASSIGNMENT* pList | ||
259 | ); | ||
260 | |||
261 | |||
262 | // variables | ||
263 | |||
264 | static IDispatch* gpiRegHlp; | ||
265 | static IAssemblyCache* gpAssemblyCache; | ||
266 | static HMODULE ghMscoree; | ||
267 | static HMODULE ghFusion; | ||
268 | |||
269 | |||
270 | // function definitions | ||
271 | |||
272 | HRESULT CpiConfigureAssemblies( | ||
273 | LPWSTR* ppwzData, | ||
274 | HANDLE hRollbackFile | ||
275 | ) | ||
276 | { | ||
277 | HRESULT hr = S_OK; | ||
278 | |||
279 | CPI_ASSEMBLY_ATTRIBUTES attrs; | ||
280 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
281 | |||
282 | // initialize | ||
283 | InitAssemblyExec(); | ||
284 | |||
285 | // read action text | ||
286 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
287 | ExitOnFailure(hr, "Failed to send action start message"); | ||
288 | |||
289 | // get count | ||
290 | int iCnt = 0; | ||
291 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
292 | ExitOnFailure(hr, "Failed to read count"); | ||
293 | |||
294 | // write count to rollback file | ||
295 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
296 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
297 | |||
298 | for (int i = 0; i < iCnt; i++) | ||
299 | { | ||
300 | // read attributes from CustomActionData | ||
301 | hr = ReadAssemblyAttributes(ppwzData, &attrs); | ||
302 | ExitOnFailure(hr, "Failed to read assembly attributes"); | ||
303 | |||
304 | // write key to rollback file | ||
305 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
306 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
307 | |||
308 | // action | ||
309 | switch (attrs.iActionType) | ||
310 | { | ||
311 | case atCreate: | ||
312 | hr = RegisterAssembly(&attrs); | ||
313 | ExitOnFailure(hr, "Failed to register assembly, key: %S", attrs.pwzKey); | ||
314 | break; | ||
315 | case atRemove: | ||
316 | hr = UnregisterAssembly(&attrs); | ||
317 | ExitOnFailure(hr, "Failed to unregister assembly, key: %S", attrs.pwzKey); | ||
318 | break; | ||
319 | default: | ||
320 | hr = S_OK; | ||
321 | break; | ||
322 | } | ||
323 | |||
324 | if (S_FALSE == hr) | ||
325 | ExitFunction(); // aborted by user | ||
326 | |||
327 | // write completion status to rollback file | ||
328 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
329 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
330 | |||
331 | // progress | ||
332 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
333 | ExitOnFailure(hr, "Failed to update progress"); | ||
334 | } | ||
335 | |||
336 | hr = S_OK; | ||
337 | |||
338 | LExit: | ||
339 | // clean up | ||
340 | FreeAssemblyAttributes(&attrs); | ||
341 | |||
342 | // uninitialize | ||
343 | UninitAssemblyExec(); | ||
344 | |||
345 | return hr; | ||
346 | } | ||
347 | |||
348 | HRESULT CpiRollbackConfigureAssemblies( | ||
349 | LPWSTR* ppwzData, | ||
350 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
351 | ) | ||
352 | { | ||
353 | HRESULT hr = S_OK; | ||
354 | |||
355 | int iRollbackStatus; | ||
356 | |||
357 | CPI_ASSEMBLY_ATTRIBUTES attrs; | ||
358 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
359 | |||
360 | // initialize | ||
361 | InitAssemblyExec(); | ||
362 | |||
363 | // read action text | ||
364 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
365 | ExitOnFailure(hr, "Failed to send action start message"); | ||
366 | |||
367 | // get count | ||
368 | int iCnt = 0; | ||
369 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
370 | ExitOnFailure(hr, "Failed to read count"); | ||
371 | |||
372 | for (int i = 0; i < iCnt; i++) | ||
373 | { | ||
374 | // read attributes from CustomActionData | ||
375 | hr = ReadAssemblyAttributes(ppwzData, &attrs); | ||
376 | ExitOnFailure(hr, "Failed to read assembly attributes"); | ||
377 | |||
378 | // rollback status | ||
379 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
380 | |||
381 | if (S_FALSE == hr) | ||
382 | continue; // not found, nothing to rollback | ||
383 | |||
384 | // action | ||
385 | switch (attrs.iActionType) | ||
386 | { | ||
387 | case atCreate: | ||
388 | hr = RegisterAssembly(&attrs); | ||
389 | if (FAILED(hr)) | ||
390 | WcaLog(LOGMSG_STANDARD, "Failed to register assembly, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
391 | break; | ||
392 | case atRemove: | ||
393 | hr = UnregisterAssembly(&attrs); | ||
394 | if (FAILED(hr)) | ||
395 | WcaLog(LOGMSG_STANDARD, "Failed to unregister assembly, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
396 | break; | ||
397 | } | ||
398 | |||
399 | // check rollback status | ||
400 | if (0 == iRollbackStatus) | ||
401 | continue; // operation did not complete, skip progress | ||
402 | |||
403 | // progress | ||
404 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
405 | ExitOnFailure(hr, "Failed to update progress"); | ||
406 | } | ||
407 | |||
408 | hr = S_OK; | ||
409 | |||
410 | LExit: | ||
411 | // clean up | ||
412 | FreeAssemblyAttributes(&attrs); | ||
413 | |||
414 | // uninitialize | ||
415 | UninitAssemblyExec(); | ||
416 | |||
417 | return hr; | ||
418 | } | ||
419 | |||
420 | HRESULT CpiConfigureRoleAssignments( | ||
421 | LPWSTR* ppwzData, | ||
422 | HANDLE hRollbackFile | ||
423 | ) | ||
424 | { | ||
425 | HRESULT hr = S_OK; | ||
426 | |||
427 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES attrs; | ||
428 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
429 | |||
430 | // read action text | ||
431 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
432 | ExitOnFailure(hr, "Failed to send action start message"); | ||
433 | |||
434 | // get count | ||
435 | int iCnt = 0; | ||
436 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
437 | ExitOnFailure(hr, "Failed to read count"); | ||
438 | |||
439 | // write count to rollback file | ||
440 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
441 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
442 | |||
443 | for (int i = 0; i < iCnt; i++) | ||
444 | { | ||
445 | // read attributes from CustomActionData | ||
446 | hr = ReadRoleAssignmentsAttributes(ppwzData, &attrs); | ||
447 | ExitOnFailure(hr, "Failed to read role assignments attributes"); | ||
448 | |||
449 | // write key to rollback file | ||
450 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
451 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
452 | |||
453 | // action | ||
454 | if (atNoOp != attrs.iActionType) | ||
455 | { | ||
456 | hr = ConfigureComponents(attrs.pwzPartID, attrs.pwzAppID, attrs.pCompList, atCreate == attrs.iActionType, TRUE); | ||
457 | ExitOnFailure(hr, "Failed to configure components"); | ||
458 | |||
459 | if (S_FALSE == hr) | ||
460 | ExitFunction(); // aborted by user | ||
461 | } | ||
462 | |||
463 | // write completion status to rollback file | ||
464 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
465 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
466 | |||
467 | // progress | ||
468 | hr = WcaProgressMessage(attrs.iActionCost * attrs.iRoleCount, FALSE); | ||
469 | ExitOnFailure(hr, "Failed to update progress"); | ||
470 | } | ||
471 | |||
472 | hr = S_OK; | ||
473 | |||
474 | LExit: | ||
475 | // clean up | ||
476 | FreeRoleAssignmentsAttributes(&attrs); | ||
477 | |||
478 | return hr; | ||
479 | } | ||
480 | |||
481 | HRESULT CpiRollbackConfigureRoleAssignments( | ||
482 | LPWSTR* ppwzData, | ||
483 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
484 | ) | ||
485 | { | ||
486 | HRESULT hr = S_OK; | ||
487 | |||
488 | int iRollbackStatus; | ||
489 | |||
490 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES attrs; | ||
491 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
492 | |||
493 | // read action text | ||
494 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
495 | ExitOnFailure(hr, "Failed to send action start message"); | ||
496 | |||
497 | // get count | ||
498 | int iCnt = 0; | ||
499 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
500 | ExitOnFailure(hr, "Failed to read count"); | ||
501 | |||
502 | for (int i = 0; i < iCnt; i++) | ||
503 | { | ||
504 | // read attributes from CustomActionData | ||
505 | hr = ReadRoleAssignmentsAttributes(ppwzData, &attrs); | ||
506 | ExitOnFailure(hr, "Failed to read role assignments attributes"); | ||
507 | |||
508 | // rollback status | ||
509 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
510 | |||
511 | if (S_FALSE == hr) | ||
512 | continue; // not found, nothing to rollback | ||
513 | |||
514 | // action | ||
515 | if (atNoOp != attrs.iActionType) | ||
516 | { | ||
517 | hr = ConfigureComponents(attrs.pwzPartID, attrs.pwzAppID, attrs.pCompList, atCreate == attrs.iActionType, TRUE); | ||
518 | ExitOnFailure(hr, "Failed to configure components"); | ||
519 | |||
520 | if (S_FALSE == hr) | ||
521 | ExitFunction(); // aborted by user | ||
522 | } | ||
523 | |||
524 | // check rollback status | ||
525 | if (0 == iRollbackStatus) | ||
526 | continue; // operation did not complete, skip progress | ||
527 | |||
528 | // progress | ||
529 | hr = WcaProgressMessage(attrs.iActionCost * attrs.iRoleCount, FALSE); | ||
530 | ExitOnFailure(hr, "Failed to update progress"); | ||
531 | } | ||
532 | |||
533 | hr = S_OK; | ||
534 | |||
535 | LExit: | ||
536 | // clean up | ||
537 | FreeRoleAssignmentsAttributes(&attrs); | ||
538 | |||
539 | return hr; | ||
540 | } | ||
541 | |||
542 | |||
543 | // helper function definitions | ||
544 | |||
545 | static HRESULT RegisterAssembly( | ||
546 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
547 | ) | ||
548 | { | ||
549 | HRESULT hr = S_OK; | ||
550 | |||
551 | // progress message | ||
552 | hr = CpiActionDataMessage(1, (pAttrs->iAttributes & aaPathFromGAC) ? pAttrs->pwzAssemblyName : pAttrs->pwzDllPath); | ||
553 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
554 | |||
555 | if (S_FALSE == hr) | ||
556 | ExitFunction(); // aborted by user | ||
557 | |||
558 | // log | ||
559 | WcaLog(LOGMSG_VERBOSE, "Registering assembly, key: %S", pAttrs->pwzKey); | ||
560 | |||
561 | // extract path from GAC | ||
562 | if (pAttrs->iAttributes & aaPathFromGAC) | ||
563 | { | ||
564 | hr = GetAssemblyPathFromGAC(pAttrs->pwzAssemblyName, &pAttrs->pwzDllPath); | ||
565 | if (S_FALSE == hr) | ||
566 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
567 | ExitOnFailure(hr, "Failed to get path for assembly from GAC"); | ||
568 | |||
569 | // log | ||
570 | WcaLog(LOGMSG_VERBOSE, "Assembly path extracted from GAC, key: %S, path: '%S'", pAttrs->pwzKey, pAttrs->pwzDllPath); | ||
571 | } | ||
572 | |||
573 | // .net assembly | ||
574 | if (pAttrs->iAttributes & aaDotNetAssembly) | ||
575 | { | ||
576 | hr = RegisterDotNetAssembly(pAttrs); | ||
577 | ExitOnFailure(hr, "Failed to register .NET assembly"); | ||
578 | } | ||
579 | |||
580 | // native assembly | ||
581 | else | ||
582 | { | ||
583 | hr = RegisterNativeAssembly(pAttrs); | ||
584 | ExitOnFailure(hr, "Failed to register native assembly"); | ||
585 | } | ||
586 | |||
587 | // configure components | ||
588 | if (pAttrs->pCompList) | ||
589 | { | ||
590 | hr = ConfigureComponents(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pCompList, TRUE, FALSE); | ||
591 | ExitOnFailure(hr, "Failed to configure components"); | ||
592 | } | ||
593 | |||
594 | hr = S_OK; | ||
595 | |||
596 | LExit: | ||
597 | return hr; | ||
598 | } | ||
599 | |||
600 | static HRESULT UnregisterAssembly( | ||
601 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
602 | ) | ||
603 | { | ||
604 | HRESULT hr = S_OK; | ||
605 | |||
606 | long lChanges = 0; | ||
607 | |||
608 | ICatalogCollection* piColl = NULL; | ||
609 | ICatalogObject* piObj = NULL; | ||
610 | |||
611 | // progress message | ||
612 | hr = CpiActionDataMessage(1, (pAttrs->iAttributes & aaPathFromGAC) ? pAttrs->pwzAssemblyName : pAttrs->pwzDllPath); | ||
613 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
614 | |||
615 | if (S_FALSE == hr) | ||
616 | ExitFunction(); // aborted by user | ||
617 | |||
618 | // log | ||
619 | WcaLog(LOGMSG_VERBOSE, "Unregistering assembly, key: %S", pAttrs->pwzKey); | ||
620 | |||
621 | // extract path from GAC | ||
622 | if (pAttrs->iAttributes & aaPathFromGAC) | ||
623 | { | ||
624 | hr = GetAssemblyPathFromGAC(pAttrs->pwzAssemblyName, &pAttrs->pwzDllPath); | ||
625 | ExitOnFailure(hr, "Failed to get path for assembly from GAC"); | ||
626 | |||
627 | if (S_FALSE == hr) | ||
628 | { | ||
629 | WcaLog(LOGMSG_VERBOSE, "Unable to locate assembly in GAC, assembly will not be unregistered from COM+, key: %S", pAttrs->pwzKey); | ||
630 | ExitFunction1(hr = S_OK); | ||
631 | } | ||
632 | |||
633 | // log | ||
634 | WcaLog(LOGMSG_VERBOSE, "Assembly path extracted from GAC, key: %S, path: '%S'", pAttrs->pwzKey, pAttrs->pwzDllPath); | ||
635 | } | ||
636 | |||
637 | // .NET assembly | ||
638 | if (pAttrs->iAttributes & aaDotNetAssembly) | ||
639 | { | ||
640 | if (pAttrs->pwzAppID && *pAttrs->pwzAppID) | ||
641 | { | ||
642 | // When unregistering a .net assembly using the RegistrationHelper class, and the application is | ||
643 | // left empty after all components in the assembly are removed, the RegistrationHelper class also | ||
644 | // attempts to remove the application for some reason. However, it does not handle the situation | ||
645 | // when the application has its deleteable property set to false, and will simply fail if this is | ||
646 | // the case. This is the reason we are clearing the deleatable property of the application here. | ||
647 | // | ||
648 | // TODO: handle rollbacks | ||
649 | |||
650 | // get applications collection | ||
651 | hr = CpiGetApplicationsCollection(pAttrs->pwzPartID, &piColl); | ||
652 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
653 | |||
654 | if (S_FALSE == hr) | ||
655 | { | ||
656 | // applications collection not found | ||
657 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve applications collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
658 | ExitFunction1(hr = S_OK); | ||
659 | } | ||
660 | |||
661 | // find application object | ||
662 | hr = CpiFindCollectionObjectByStringKey(piColl, pAttrs->pwzAppID, &piObj); | ||
663 | ExitOnFailure(hr, "Failed to find application object"); | ||
664 | |||
665 | if (S_FALSE == hr) | ||
666 | { | ||
667 | // application not found | ||
668 | WcaLog(LOGMSG_VERBOSE, "Unable to find application object, nothing to delete, key: %S", pAttrs->pwzKey); | ||
669 | ExitFunction1(hr = S_OK); | ||
670 | } | ||
671 | |||
672 | // reset deleteable property | ||
673 | hr = CpiResetObjectProperty(piColl, piObj, L"Deleteable"); | ||
674 | ExitOnFailure(hr, "Failed to reset deleteable property"); | ||
675 | } | ||
676 | |||
677 | // unregister assembly | ||
678 | hr = UnregisterDotNetAssembly(pAttrs); | ||
679 | ExitOnFailure(hr, "Failed to unregister .NET assembly"); | ||
680 | } | ||
681 | |||
682 | // native assembly | ||
683 | else | ||
684 | { | ||
685 | // get components collection | ||
686 | hr = CpiGetComponentsCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piColl); | ||
687 | ExitOnFailure(hr, "Failed to get components collection"); | ||
688 | |||
689 | if (S_FALSE == hr) | ||
690 | { | ||
691 | // components collection not found | ||
692 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve components collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
693 | ExitFunction1(hr = S_OK); | ||
694 | } | ||
695 | |||
696 | // remove components | ||
697 | hr = RemoveComponents(piColl, pAttrs->pCompList); | ||
698 | ExitOnFailure(hr, "Failed to get remove components"); | ||
699 | |||
700 | // save changes | ||
701 | hr = piColl->SaveChanges(&lChanges); | ||
702 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
703 | CpiLogCatalogErrorInfo(); | ||
704 | ExitOnFailure(hr, "Failed to save changes"); | ||
705 | } | ||
706 | |||
707 | hr = S_OK; | ||
708 | |||
709 | LExit: | ||
710 | // clean up | ||
711 | ReleaseObject(piColl); | ||
712 | ReleaseObject(piObj); | ||
713 | |||
714 | return hr; | ||
715 | } | ||
716 | |||
717 | static void InitAssemblyExec() | ||
718 | { | ||
719 | gpiRegHlp = NULL; | ||
720 | gpAssemblyCache = NULL; | ||
721 | ghMscoree = NULL; | ||
722 | ghFusion = NULL; | ||
723 | } | ||
724 | |||
725 | static void UninitAssemblyExec() | ||
726 | { | ||
727 | ReleaseObject(gpiRegHlp); | ||
728 | ReleaseObject(gpAssemblyCache); | ||
729 | if (ghFusion) | ||
730 | ::FreeLibrary(ghFusion); | ||
731 | if (ghMscoree) | ||
732 | ::FreeLibrary(ghMscoree); | ||
733 | } | ||
734 | |||
735 | static HRESULT GetRegistrationHelper( | ||
736 | IDispatch** ppiRegHlp | ||
737 | ) | ||
738 | { | ||
739 | HRESULT hr = S_OK; | ||
740 | |||
741 | if (!gpiRegHlp) | ||
742 | { | ||
743 | // create registration helper object | ||
744 | hr = ::CoCreateInstance(CLSID_RegistrationHelper, NULL, CLSCTX_ALL, IID_IDispatch, (void**)&gpiRegHlp); | ||
745 | ExitOnFailure(hr, "Failed to create registration helper object"); | ||
746 | } | ||
747 | |||
748 | gpiRegHlp->AddRef(); | ||
749 | *ppiRegHlp = gpiRegHlp; | ||
750 | |||
751 | hr = S_OK; | ||
752 | |||
753 | LExit: | ||
754 | return hr; | ||
755 | } | ||
756 | |||
757 | static HRESULT GetAssemblyCacheObject( | ||
758 | IAssemblyCache** ppAssemblyCache | ||
759 | ) | ||
760 | { | ||
761 | HRESULT hr = S_OK; | ||
762 | |||
763 | if (!gpAssemblyCache) | ||
764 | { | ||
765 | // mscoree.dll | ||
766 | if (!ghMscoree) | ||
767 | { | ||
768 | // load mscoree.dll | ||
769 | ghMscoree = ::LoadLibraryW(L"mscoree.dll"); | ||
770 | ExitOnNull(ghMscoree, hr, E_FAIL, "Failed to load mscoree.dll"); | ||
771 | } | ||
772 | |||
773 | // fusion.dll | ||
774 | if (!ghFusion) | ||
775 | { | ||
776 | // get LoadLibraryShim function address | ||
777 | LoadLibraryShimFunc pfnLoadLibraryShim = (LoadLibraryShimFunc)::GetProcAddress(ghMscoree, "LoadLibraryShim"); | ||
778 | ExitOnNull(pfnLoadLibraryShim, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for LoadLibraryShim() function"); | ||
779 | |||
780 | // load fusion.dll | ||
781 | hr = pfnLoadLibraryShim(L"fusion.dll", NULL, NULL, &ghFusion); | ||
782 | ExitOnFailure(hr, "Failed to load fusion.dll"); | ||
783 | } | ||
784 | |||
785 | // get CreateAssemblyCache function address | ||
786 | CreateAssemblyCacheFunc pfnCreateAssemblyCache = (CreateAssemblyCacheFunc)::GetProcAddress(ghFusion, "CreateAssemblyCache"); | ||
787 | ExitOnNull(pfnCreateAssemblyCache, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for CreateAssemblyCache() function"); | ||
788 | |||
789 | // create AssemblyCache object | ||
790 | hr = pfnCreateAssemblyCache(&gpAssemblyCache, 0); | ||
791 | ExitOnFailure(hr, "Failed to create AssemblyCache object"); | ||
792 | } | ||
793 | |||
794 | gpAssemblyCache->AddRef(); | ||
795 | *ppAssemblyCache = gpAssemblyCache; | ||
796 | |||
797 | hr = S_OK; | ||
798 | |||
799 | LExit: | ||
800 | return hr; | ||
801 | } | ||
802 | |||
803 | static HRESULT GetAssemblyPathFromGAC( | ||
804 | LPCWSTR pwzAssemblyName, | ||
805 | LPWSTR* ppwzAssemblyPath | ||
806 | ) | ||
807 | { | ||
808 | HRESULT hr = S_OK; | ||
809 | |||
810 | IAssemblyCache* pAssemblyCache = NULL; | ||
811 | |||
812 | ASSEMBLY_INFO assemblyInfo; | ||
813 | WCHAR wzPathBuf[MAX_PATH]; | ||
814 | |||
815 | ::ZeroMemory(&assemblyInfo, sizeof(ASSEMBLY_INFO)); | ||
816 | ::ZeroMemory(wzPathBuf, countof(wzPathBuf)); | ||
817 | |||
818 | // get AssemblyCache object | ||
819 | hr = GetAssemblyCacheObject(&pAssemblyCache); | ||
820 | ExitOnFailure(hr, "Failed to get AssemblyCache object"); | ||
821 | |||
822 | // get assembly info | ||
823 | assemblyInfo.cbAssemblyInfo = sizeof(ASSEMBLY_INFO); | ||
824 | assemblyInfo.pszCurrentAssemblyPathBuf = wzPathBuf; | ||
825 | assemblyInfo.cchBuf = countof(wzPathBuf); | ||
826 | |||
827 | hr = pAssemblyCache->QueryAssemblyInfo(0, pwzAssemblyName, &assemblyInfo); | ||
828 | if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
829 | ExitFunction1(hr = S_FALSE); | ||
830 | ExitOnFailure(hr, "Failed to get assembly info"); | ||
831 | |||
832 | // copy assembly path | ||
833 | hr = StrAllocString(ppwzAssemblyPath, wzPathBuf, 0); | ||
834 | ExitOnFailure(hr, "Failed to copy assembly path"); | ||
835 | |||
836 | hr = S_OK; | ||
837 | |||
838 | LExit: | ||
839 | // clean up | ||
840 | ReleaseObject(pAssemblyCache); | ||
841 | |||
842 | return hr; | ||
843 | } | ||
844 | |||
845 | static HRESULT RegisterDotNetAssembly( | ||
846 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
847 | ) | ||
848 | { | ||
849 | HRESULT hr = S_OK; | ||
850 | |||
851 | IDispatch* piRegHlp = NULL; | ||
852 | |||
853 | DISPID dispid; | ||
854 | BSTR bstrMember = NULL; | ||
855 | |||
856 | long lInstallationFlags = 0; | ||
857 | |||
858 | VARIANTARG rgvarg[5]; | ||
859 | DISPPARAMS dispparams; | ||
860 | EXCEPINFO excepInfo; | ||
861 | |||
862 | BSTR bstrPartName = NULL; | ||
863 | BSTR bstrAppName = NULL; | ||
864 | BSTR bstrDllPath = NULL; | ||
865 | BSTR bstrTlbPath = NULL; | ||
866 | |||
867 | ::ZeroMemory(rgvarg, sizeof(rgvarg)); | ||
868 | ::ZeroMemory(&dispparams, sizeof(dispparams)); | ||
869 | ::ZeroMemory(&excepInfo, sizeof(excepInfo)); | ||
870 | |||
871 | bstrMember = ::SysAllocString(L"InstallAssembly_2"); | ||
872 | ExitOnNull(bstrMember, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for method name"); | ||
873 | |||
874 | // create BSTRs for parameters | ||
875 | if (pAttrs->pwzPartID && *pAttrs->pwzPartID) | ||
876 | { | ||
877 | bstrPartName = ::SysAllocString(pAttrs->pwzPartID); | ||
878 | ExitOnNull(bstrPartName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id"); | ||
879 | } | ||
880 | |||
881 | if (pAttrs->pwzAppID && *pAttrs->pwzAppID) | ||
882 | { | ||
883 | bstrAppName = ::SysAllocString(pAttrs->pwzAppID); | ||
884 | ExitOnNull(bstrAppName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id"); | ||
885 | } | ||
886 | |||
887 | bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath); | ||
888 | ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path"); | ||
889 | |||
890 | if (pAttrs->pwzTlbPath && *pAttrs->pwzTlbPath) | ||
891 | { | ||
892 | bstrTlbPath = ::SysAllocString(pAttrs->pwzTlbPath); | ||
893 | ExitOnNull(bstrTlbPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path"); | ||
894 | } | ||
895 | |||
896 | // get registration helper object | ||
897 | hr = GetRegistrationHelper(&piRegHlp); | ||
898 | ExitOnFailure(hr, "Failed to get registration helper object"); | ||
899 | |||
900 | // get dispatch id of InstallAssembly() method | ||
901 | hr = piRegHlp->GetIDsOfNames(IID_NULL, &bstrMember, 1, LOCALE_USER_DEFAULT, &dispid); | ||
902 | ExitOnFailure(hr, "Failed to get dispatch id of InstallAssembly() method"); | ||
903 | |||
904 | // set installation flags | ||
905 | lInstallationFlags = ifExpectExistingTypeLib; | ||
906 | |||
907 | if (!bstrAppName) | ||
908 | lInstallationFlags |= ifFindOrCreateTargetApplication; | ||
909 | |||
910 | // invoke InstallAssembly() method | ||
911 | rgvarg[0].vt = VT_I4; | ||
912 | rgvarg[0].lVal = lInstallationFlags; | ||
913 | rgvarg[1].vt = VT_BYREF|VT_BSTR; | ||
914 | rgvarg[1].pbstrVal = &bstrTlbPath; | ||
915 | rgvarg[2].vt = VT_BSTR; | ||
916 | rgvarg[2].bstrVal = bstrPartName; | ||
917 | rgvarg[3].vt = VT_BYREF|VT_BSTR; | ||
918 | rgvarg[3].pbstrVal = &bstrAppName; | ||
919 | rgvarg[4].vt = VT_BSTR; | ||
920 | rgvarg[4].bstrVal = bstrDllPath; | ||
921 | dispparams.rgvarg = rgvarg; | ||
922 | dispparams.cArgs = 5; | ||
923 | dispparams.cNamedArgs = 0; | ||
924 | |||
925 | hr = piRegHlp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, NULL, &excepInfo, NULL); | ||
926 | if (DISP_E_EXCEPTION == hr) | ||
927 | { | ||
928 | // log exception information | ||
929 | if (!excepInfo.pfnDeferredFillIn || (excepInfo.pfnDeferredFillIn && SUCCEEDED(excepInfo.pfnDeferredFillIn(&excepInfo)))) | ||
930 | { | ||
931 | WcaLog(LOGMSG_STANDARD, "ExceptionInfo: Code='%hu', Source='%S', Description='%S', HelpFile='%S', HelpContext='%u'", | ||
932 | excepInfo.wCode, excepInfo.bstrSource, | ||
933 | excepInfo.bstrDescription ? excepInfo.bstrDescription : L"", | ||
934 | excepInfo.bstrHelpFile ? excepInfo.bstrHelpFile : L"", | ||
935 | excepInfo.dwHelpContext); | ||
936 | } | ||
937 | } | ||
938 | ExitOnFailure(hr, "Failed to invoke RegistrationHelper.InstallAssembly() method"); | ||
939 | |||
940 | hr = S_OK; | ||
941 | |||
942 | LExit: | ||
943 | // clean up | ||
944 | ReleaseObject(piRegHlp); | ||
945 | |||
946 | ReleaseBSTR(bstrMember); | ||
947 | |||
948 | ReleaseBSTR(excepInfo.bstrSource); | ||
949 | ReleaseBSTR(excepInfo.bstrDescription); | ||
950 | ReleaseBSTR(excepInfo.bstrHelpFile); | ||
951 | |||
952 | ReleaseBSTR(bstrPartName); | ||
953 | ReleaseBSTR(bstrAppName); | ||
954 | ReleaseBSTR(bstrDllPath); | ||
955 | ReleaseBSTR(bstrTlbPath); | ||
956 | |||
957 | return hr; | ||
958 | } | ||
959 | |||
960 | static HRESULT RegisterNativeAssembly( | ||
961 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
962 | ) | ||
963 | { | ||
964 | HRESULT hr = S_OK; | ||
965 | |||
966 | ICOMAdminCatalog* piCatalog = NULL; | ||
967 | ICOMAdminCatalog2* piCatalog2 = NULL; | ||
968 | BSTR bstrGlobPartID = NULL; | ||
969 | |||
970 | BSTR bstrPartID = NULL; | ||
971 | BSTR bstrAppID = NULL; | ||
972 | BSTR bstrDllPath = NULL; | ||
973 | BSTR bstrTlbPath = NULL; | ||
974 | BSTR bstrPSDllPath = NULL; | ||
975 | |||
976 | // create BSTRs for parameters | ||
977 | if (pAttrs->pwzPartID && *pAttrs->pwzPartID) | ||
978 | { | ||
979 | bstrPartID = ::SysAllocString(pAttrs->pwzPartID); | ||
980 | ExitOnNull(bstrPartID, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id"); | ||
981 | } | ||
982 | |||
983 | bstrAppID = ::SysAllocString(pAttrs->pwzAppID); | ||
984 | ExitOnNull(bstrAppID, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id"); | ||
985 | |||
986 | bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath); | ||
987 | ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path"); | ||
988 | |||
989 | bstrTlbPath = ::SysAllocString(pAttrs->pwzTlbPath ? pAttrs->pwzTlbPath : L""); | ||
990 | ExitOnNull(bstrTlbPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path"); | ||
991 | |||
992 | bstrPSDllPath = ::SysAllocString(pAttrs->pwzPSDllPath ? pAttrs->pwzPSDllPath : L""); | ||
993 | ExitOnNull(bstrPSDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path"); | ||
994 | |||
995 | // get catalog | ||
996 | hr = CpiGetAdminCatalog(&piCatalog); | ||
997 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
998 | |||
999 | // get ICOMAdminCatalog2 interface | ||
1000 | hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2); | ||
1001 | |||
1002 | // COM+ 1.5 or later | ||
1003 | if (E_NOINTERFACE != hr) | ||
1004 | { | ||
1005 | ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface"); | ||
1006 | |||
1007 | // partition id | ||
1008 | if (!bstrPartID) | ||
1009 | { | ||
1010 | // get global partition id | ||
1011 | hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID); | ||
1012 | ExitOnFailure(hr, "Failed to get global partition id"); | ||
1013 | } | ||
1014 | |||
1015 | // set current partition | ||
1016 | hr = piCatalog2->put_CurrentPartition(bstrPartID ? bstrPartID : bstrGlobPartID); | ||
1017 | ExitOnFailure(hr, "Failed to set current partition"); | ||
1018 | } | ||
1019 | |||
1020 | // COM+ pre 1.5 | ||
1021 | else | ||
1022 | { | ||
1023 | // this version of COM+ does not support partitions, make sure a partition was not specified | ||
1024 | if (bstrPartID) | ||
1025 | ExitOnFailure(hr = E_FAIL, "Partitions are not supported by this version of COM+"); | ||
1026 | } | ||
1027 | |||
1028 | // install event classes | ||
1029 | if (pAttrs->iAttributes & aaEventClass) | ||
1030 | { | ||
1031 | hr = piCatalog->InstallEventClass(bstrAppID, bstrDllPath, bstrTlbPath, bstrPSDllPath); | ||
1032 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1033 | CpiLogCatalogErrorInfo(); | ||
1034 | ExitOnFailure(hr, "Failed to install event classes"); | ||
1035 | } | ||
1036 | |||
1037 | // install components | ||
1038 | else | ||
1039 | { | ||
1040 | hr = piCatalog->InstallComponent(bstrAppID, bstrDllPath, bstrTlbPath, bstrPSDllPath); | ||
1041 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1042 | CpiLogCatalogErrorInfo(); | ||
1043 | ExitOnFailure(hr, "Failed to install components"); | ||
1044 | } | ||
1045 | |||
1046 | hr = S_OK; | ||
1047 | |||
1048 | LExit: | ||
1049 | // clean up | ||
1050 | ReleaseObject(piCatalog); | ||
1051 | ReleaseObject(piCatalog2); | ||
1052 | ReleaseBSTR(bstrGlobPartID); | ||
1053 | |||
1054 | ReleaseBSTR(bstrPartID); | ||
1055 | ReleaseBSTR(bstrAppID); | ||
1056 | ReleaseBSTR(bstrDllPath); | ||
1057 | ReleaseBSTR(bstrTlbPath); | ||
1058 | ReleaseBSTR(bstrPSDllPath); | ||
1059 | |||
1060 | return hr; | ||
1061 | } | ||
1062 | |||
1063 | static HRESULT UnregisterDotNetAssembly( | ||
1064 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
1065 | ) | ||
1066 | { | ||
1067 | HRESULT hr = S_OK; | ||
1068 | |||
1069 | IDispatch* piRegHlp = NULL; | ||
1070 | |||
1071 | DISPID dispid; | ||
1072 | BSTR bstrMember = NULL; | ||
1073 | |||
1074 | VARIANTARG rgvarg[3]; | ||
1075 | DISPPARAMS dispparams; | ||
1076 | EXCEPINFO excepInfo; | ||
1077 | |||
1078 | BSTR bstrPartName = NULL; | ||
1079 | BSTR bstrAppName = NULL; | ||
1080 | BSTR bstrDllPath = NULL; | ||
1081 | |||
1082 | ::ZeroMemory(rgvarg, sizeof(rgvarg)); | ||
1083 | ::ZeroMemory(&dispparams, sizeof(dispparams)); | ||
1084 | ::ZeroMemory(&excepInfo, sizeof(excepInfo)); | ||
1085 | |||
1086 | bstrMember = ::SysAllocString(L"UninstallAssembly_2"); | ||
1087 | ExitOnNull(bstrMember, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for method name"); | ||
1088 | |||
1089 | // create BSTRs for parameters | ||
1090 | if (pAttrs->pwzPartID && *pAttrs->pwzPartID) | ||
1091 | { | ||
1092 | bstrPartName = ::SysAllocString(pAttrs->pwzPartID); | ||
1093 | ExitOnNull(bstrPartName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id"); | ||
1094 | } | ||
1095 | |||
1096 | bstrAppName = ::SysAllocString(pAttrs->pwzAppID); | ||
1097 | ExitOnNull(bstrAppName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id"); | ||
1098 | |||
1099 | bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath); | ||
1100 | ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path"); | ||
1101 | |||
1102 | // get registration helper object | ||
1103 | hr = GetRegistrationHelper(&piRegHlp); | ||
1104 | ExitOnFailure(hr, "Failed to get registration helper object"); | ||
1105 | |||
1106 | // get dispatch id of UninstallAssembly() method | ||
1107 | hr = piRegHlp->GetIDsOfNames(IID_NULL, &bstrMember, 1, LOCALE_USER_DEFAULT, &dispid); | ||
1108 | ExitOnFailure(hr, "Failed to get dispatch id of UninstallAssembly() method"); | ||
1109 | |||
1110 | // invoke UninstallAssembly() method | ||
1111 | rgvarg[0].vt = VT_BSTR; | ||
1112 | rgvarg[0].bstrVal = bstrPartName; | ||
1113 | rgvarg[1].vt = VT_BSTR; | ||
1114 | rgvarg[1].bstrVal = bstrAppName; | ||
1115 | rgvarg[2].vt = VT_BSTR; | ||
1116 | rgvarg[2].bstrVal = bstrDllPath; | ||
1117 | dispparams.rgvarg = rgvarg; | ||
1118 | dispparams.cArgs = 3; | ||
1119 | dispparams.cNamedArgs = 0; | ||
1120 | |||
1121 | hr = piRegHlp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, NULL, &excepInfo, NULL); | ||
1122 | if (DISP_E_EXCEPTION == hr) | ||
1123 | { | ||
1124 | // log exception information | ||
1125 | if (!excepInfo.pfnDeferredFillIn || (excepInfo.pfnDeferredFillIn && SUCCEEDED(excepInfo.pfnDeferredFillIn(&excepInfo)))) | ||
1126 | { | ||
1127 | WcaLog(LOGMSG_STANDARD, "ExceptionInfo: Code='%hu', Source='%S', Description='%S', HelpFile='%S', HelpContext='%u'", | ||
1128 | excepInfo.wCode, excepInfo.bstrSource, | ||
1129 | excepInfo.bstrDescription ? excepInfo.bstrDescription : L"", | ||
1130 | excepInfo.bstrHelpFile ? excepInfo.bstrHelpFile : L"", | ||
1131 | excepInfo.dwHelpContext); | ||
1132 | } | ||
1133 | } | ||
1134 | ExitOnFailure(hr, "Failed to invoke RegistrationHelper.UninstallAssembly() method"); | ||
1135 | |||
1136 | hr = S_OK; | ||
1137 | |||
1138 | LExit: | ||
1139 | // clean up | ||
1140 | ReleaseObject(piRegHlp); | ||
1141 | |||
1142 | ReleaseBSTR(bstrMember); | ||
1143 | |||
1144 | ReleaseBSTR(excepInfo.bstrSource); | ||
1145 | ReleaseBSTR(excepInfo.bstrDescription); | ||
1146 | ReleaseBSTR(excepInfo.bstrHelpFile); | ||
1147 | |||
1148 | ReleaseBSTR(bstrPartName); | ||
1149 | ReleaseBSTR(bstrAppName); | ||
1150 | ReleaseBSTR(bstrDllPath); | ||
1151 | |||
1152 | return hr; | ||
1153 | } | ||
1154 | |||
1155 | static HRESULT RemoveComponents( | ||
1156 | ICatalogCollection* piCompColl, | ||
1157 | CPI_COMPONENT* pCompList | ||
1158 | ) | ||
1159 | { | ||
1160 | HRESULT hr = S_OK; | ||
1161 | |||
1162 | for (CPI_COMPONENT* pItm = pCompList; pItm; pItm = pItm->pNext) | ||
1163 | { | ||
1164 | // remove | ||
1165 | hr = CpiRemoveCollectionObject(piCompColl, pItm->wzCLSID, NULL, FALSE); | ||
1166 | ExitOnFailure(hr, "Failed to remove component"); | ||
1167 | |||
1168 | if (S_FALSE == hr) | ||
1169 | WcaLog(LOGMSG_VERBOSE, "Component not found, nothing to delete, key: %S", pItm->wzCLSID); | ||
1170 | } | ||
1171 | |||
1172 | hr = S_OK; | ||
1173 | |||
1174 | LExit: | ||
1175 | return hr; | ||
1176 | } | ||
1177 | |||
1178 | static HRESULT ReadAssemblyAttributes( | ||
1179 | LPWSTR* ppwzData, | ||
1180 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
1181 | ) | ||
1182 | { | ||
1183 | HRESULT hr = S_OK; | ||
1184 | |||
1185 | // read attributes | ||
1186 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
1187 | ExitOnFailure(hr, "Failed to read action type"); | ||
1188 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
1189 | ExitOnFailure(hr, "Failed to read action cost"); | ||
1190 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
1191 | ExitOnFailure(hr, "Failed to read key"); | ||
1192 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAssemblyName); | ||
1193 | ExitOnFailure(hr, "Failed to read assembly name"); | ||
1194 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzDllPath); | ||
1195 | ExitOnFailure(hr, "Failed to read dll path"); | ||
1196 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzTlbPath); | ||
1197 | ExitOnFailure(hr, "Failed to read tlb path"); | ||
1198 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPSDllPath); | ||
1199 | ExitOnFailure(hr, "Failed to read proxy-stub dll path"); | ||
1200 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iAttributes); | ||
1201 | ExitOnFailure(hr, "Failed to read attributes"); | ||
1202 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
1203 | ExitOnFailure(hr, "Failed to read application id"); | ||
1204 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
1205 | ExitOnFailure(hr, "Failed to read partition id"); | ||
1206 | |||
1207 | // free existing component list | ||
1208 | if (pAttrs->pCompList) | ||
1209 | { | ||
1210 | FreeComponentList(pAttrs->pCompList); | ||
1211 | pAttrs->pCompList = NULL; | ||
1212 | } | ||
1213 | |||
1214 | // read components | ||
1215 | hr = ReadComponentList(ppwzData, &pAttrs->pCompList); | ||
1216 | ExitOnFailure(hr, "Failed to read components"); | ||
1217 | |||
1218 | hr = S_OK; | ||
1219 | |||
1220 | LExit: | ||
1221 | return hr; | ||
1222 | } | ||
1223 | |||
1224 | static void FreeAssemblyAttributes( | ||
1225 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
1226 | ) | ||
1227 | { | ||
1228 | ReleaseStr(pAttrs->pwzKey); | ||
1229 | ReleaseStr(pAttrs->pwzAssemblyName); | ||
1230 | ReleaseStr(pAttrs->pwzDllPath); | ||
1231 | ReleaseStr(pAttrs->pwzTlbPath); | ||
1232 | ReleaseStr(pAttrs->pwzPSDllPath); | ||
1233 | ReleaseStr(pAttrs->pwzAppID); | ||
1234 | ReleaseStr(pAttrs->pwzPartID); | ||
1235 | |||
1236 | if (pAttrs->pCompList) | ||
1237 | FreeComponentList(pAttrs->pCompList); | ||
1238 | } | ||
1239 | |||
1240 | static HRESULT ReadRoleAssignmentsAttributes( | ||
1241 | LPWSTR* ppwzData, | ||
1242 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
1243 | ) | ||
1244 | { | ||
1245 | HRESULT hr = S_OK; | ||
1246 | |||
1247 | // read attributes | ||
1248 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
1249 | ExitOnFailure(hr, "Failed to read action type"); | ||
1250 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
1251 | ExitOnFailure(hr, "Failed to read action cost"); | ||
1252 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
1253 | ExitOnFailure(hr, "Failed to read key"); | ||
1254 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iRoleCount); | ||
1255 | ExitOnFailure(hr, "Failed to read role assignments count"); | ||
1256 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
1257 | ExitOnFailure(hr, "Failed to read application id"); | ||
1258 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
1259 | ExitOnFailure(hr, "Failed to read partition id"); | ||
1260 | |||
1261 | // free existing component list | ||
1262 | if (pAttrs->pCompList) | ||
1263 | { | ||
1264 | FreeComponentList(pAttrs->pCompList); | ||
1265 | pAttrs->pCompList = NULL; | ||
1266 | } | ||
1267 | |||
1268 | // read components | ||
1269 | hr = ReadComponentList(ppwzData, &pAttrs->pCompList); | ||
1270 | ExitOnFailure(hr, "Failed to read components"); | ||
1271 | |||
1272 | hr = S_OK; | ||
1273 | |||
1274 | LExit: | ||
1275 | return hr; | ||
1276 | } | ||
1277 | |||
1278 | static void FreeRoleAssignmentsAttributes( | ||
1279 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
1280 | ) | ||
1281 | { | ||
1282 | ReleaseStr(pAttrs->pwzKey); | ||
1283 | ReleaseStr(pAttrs->pwzAppID); | ||
1284 | ReleaseStr(pAttrs->pwzPartID); | ||
1285 | |||
1286 | if (pAttrs->pCompList) | ||
1287 | FreeComponentList(pAttrs->pCompList); | ||
1288 | } | ||
1289 | |||
1290 | |||
1291 | static HRESULT ConfigureComponents( | ||
1292 | LPCWSTR pwzPartID, | ||
1293 | LPCWSTR pwzAppID, | ||
1294 | CPI_COMPONENT* pCompList, | ||
1295 | BOOL fCreate, | ||
1296 | BOOL fProgress | ||
1297 | ) | ||
1298 | { | ||
1299 | HRESULT hr = S_OK; | ||
1300 | |||
1301 | ICatalogCollection* piCompColl = NULL; | ||
1302 | ICatalogObject* piCompObj = NULL; | ||
1303 | |||
1304 | long lChanges = 0; | ||
1305 | |||
1306 | // get components collection | ||
1307 | hr = CpiGetComponentsCollection(pwzPartID, pwzAppID, &piCompColl); | ||
1308 | if (S_FALSE == hr) | ||
1309 | if (fCreate) | ||
1310 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1311 | else | ||
1312 | ExitFunction1(hr = S_OK); | ||
1313 | ExitOnFailure(hr, "Failed to get components collection"); | ||
1314 | |||
1315 | // read components | ||
1316 | for (CPI_COMPONENT* pItm = pCompList; pItm; pItm = pItm->pNext) | ||
1317 | { | ||
1318 | // progress message | ||
1319 | if (fProgress) | ||
1320 | { | ||
1321 | hr = CpiActionDataMessage(1, pItm->wzCLSID); | ||
1322 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
1323 | |||
1324 | if (S_FALSE == hr) | ||
1325 | ExitFunction(); // aborted by user | ||
1326 | } | ||
1327 | |||
1328 | // find component | ||
1329 | hr = CpiFindCollectionObjectByStringKey(piCompColl, pItm->wzCLSID, &piCompObj); | ||
1330 | if (S_FALSE == hr) | ||
1331 | if (fCreate) | ||
1332 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1333 | else | ||
1334 | continue; | ||
1335 | ExitOnFailure(hr, "Failed to find component object"); | ||
1336 | |||
1337 | // properties | ||
1338 | hr = CpiPutCollectionObjectValues(piCompObj, pItm->pPropertyList); | ||
1339 | ExitOnFailure(hr, "Failed to write properties"); | ||
1340 | |||
1341 | // read roles | ||
1342 | if (pItm->pRoleAssignmentList) | ||
1343 | { | ||
1344 | hr = ConfigureRoleAssignments(L"RolesForComponent", piCompColl, piCompObj, pItm->pRoleAssignmentList, fCreate); | ||
1345 | ExitOnFailure(hr, "Failed to read roles"); | ||
1346 | } | ||
1347 | |||
1348 | // read interfaces | ||
1349 | if (pItm->pInterfaceList) | ||
1350 | { | ||
1351 | hr = ConfigureInterfaces(piCompColl, piCompObj, pItm->pInterfaceList, fCreate); | ||
1352 | ExitOnFailure(hr, "Failed to read interfaces"); | ||
1353 | } | ||
1354 | |||
1355 | // clean up | ||
1356 | ReleaseNullObject(piCompObj); | ||
1357 | } | ||
1358 | |||
1359 | // save changes | ||
1360 | hr = piCompColl->SaveChanges(&lChanges); | ||
1361 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1362 | CpiLogCatalogErrorInfo(); | ||
1363 | ExitOnFailure(hr, "Failed to save changes"); | ||
1364 | |||
1365 | hr = S_OK; | ||
1366 | |||
1367 | LExit: | ||
1368 | // clean up | ||
1369 | ReleaseObject(piCompColl); | ||
1370 | ReleaseObject(piCompObj); | ||
1371 | |||
1372 | return hr; | ||
1373 | } | ||
1374 | |||
1375 | static HRESULT ConfigureInterfaces( | ||
1376 | ICatalogCollection* piCompColl, | ||
1377 | ICatalogObject* piCompObj, | ||
1378 | CPI_INTERFACE* pIntfList, | ||
1379 | BOOL fCreate | ||
1380 | ) | ||
1381 | { | ||
1382 | HRESULT hr = S_OK; | ||
1383 | |||
1384 | ICatalogCollection* piIntfColl = NULL; | ||
1385 | ICatalogObject* piIntfObj = NULL; | ||
1386 | |||
1387 | long lChanges = 0; | ||
1388 | |||
1389 | // get interfaces collection | ||
1390 | hr = CpiGetInterfacesCollection(piCompColl, piCompObj, &piIntfColl); | ||
1391 | if (S_FALSE == hr) | ||
1392 | if (fCreate) | ||
1393 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1394 | else | ||
1395 | ExitFunction1(hr = S_OK); | ||
1396 | ExitOnFailure(hr, "Failed to get interfaces collection"); | ||
1397 | |||
1398 | // read interfaces | ||
1399 | for (CPI_INTERFACE* pItm = pIntfList; pItm; pItm = pItm->pNext) | ||
1400 | { | ||
1401 | // find interface | ||
1402 | hr = CpiFindCollectionObjectByStringKey(piIntfColl, pItm->wzIID, &piIntfObj); | ||
1403 | if (S_FALSE == hr) | ||
1404 | if (fCreate) | ||
1405 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1406 | else | ||
1407 | continue; | ||
1408 | ExitOnFailure(hr, "Failed to find interface object"); | ||
1409 | |||
1410 | // properties | ||
1411 | hr = CpiPutCollectionObjectValues(piIntfObj, pItm->pPropertyList); | ||
1412 | ExitOnFailure(hr, "Failed to write properties"); | ||
1413 | |||
1414 | // read roles | ||
1415 | if (pItm->pRoleAssignmentList) | ||
1416 | { | ||
1417 | hr = ConfigureRoleAssignments(L"RolesForInterface", piIntfColl, piIntfObj, pItm->pRoleAssignmentList, fCreate); | ||
1418 | ExitOnFailure(hr, "Failed to read roles"); | ||
1419 | } | ||
1420 | |||
1421 | // read methods | ||
1422 | if (pItm->pMethodList) | ||
1423 | { | ||
1424 | hr = ConfigureMethods(piIntfColl, piIntfObj, pItm->pMethodList, fCreate); | ||
1425 | ExitOnFailure(hr, "Failed to read methods"); | ||
1426 | } | ||
1427 | |||
1428 | // clean up | ||
1429 | ReleaseNullObject(piIntfObj); | ||
1430 | } | ||
1431 | |||
1432 | // save changes | ||
1433 | hr = piIntfColl->SaveChanges(&lChanges); | ||
1434 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1435 | CpiLogCatalogErrorInfo(); | ||
1436 | ExitOnFailure(hr, "Failed to save changes"); | ||
1437 | |||
1438 | hr = S_OK; | ||
1439 | |||
1440 | LExit: | ||
1441 | // clean up | ||
1442 | ReleaseObject(piIntfColl); | ||
1443 | ReleaseObject(piIntfObj); | ||
1444 | |||
1445 | return hr; | ||
1446 | } | ||
1447 | |||
1448 | static HRESULT ConfigureMethods( | ||
1449 | ICatalogCollection* piIntfColl, | ||
1450 | ICatalogObject* piIntfObj, | ||
1451 | CPI_METHOD* pMethList, | ||
1452 | BOOL fCreate | ||
1453 | ) | ||
1454 | { | ||
1455 | HRESULT hr = S_OK; | ||
1456 | |||
1457 | ICatalogCollection* piMethColl = NULL; | ||
1458 | ICatalogObject* piMethObj = NULL; | ||
1459 | |||
1460 | long lChanges = 0; | ||
1461 | |||
1462 | // get methods collection | ||
1463 | hr = CpiGetMethodsCollection(piIntfColl, piIntfObj, &piMethColl); | ||
1464 | if (S_FALSE == hr) | ||
1465 | if (fCreate) | ||
1466 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1467 | else | ||
1468 | ExitFunction1(hr = S_OK); | ||
1469 | ExitOnFailure(hr, "Failed to get methods collection"); | ||
1470 | |||
1471 | // read methods | ||
1472 | for (CPI_METHOD* pItm = pMethList; pItm; pItm = pItm->pNext) | ||
1473 | { | ||
1474 | // find method | ||
1475 | if (*pItm->wzIndex) | ||
1476 | hr = CpiFindCollectionObjectByIntegerKey(piMethColl, _wtol(pItm->wzIndex), &piMethObj); | ||
1477 | else | ||
1478 | hr = CpiFindCollectionObjectByName(piMethColl, pItm->wzName, &piMethObj); | ||
1479 | |||
1480 | if (S_FALSE == hr) | ||
1481 | if (fCreate) | ||
1482 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1483 | else | ||
1484 | continue; | ||
1485 | ExitOnFailure(hr, "Failed to find method object"); | ||
1486 | |||
1487 | // properties | ||
1488 | hr = CpiPutCollectionObjectValues(piMethObj, pItm->pPropertyList); | ||
1489 | ExitOnFailure(hr, "Failed to write properties"); | ||
1490 | |||
1491 | // read roles | ||
1492 | if (pItm->pRoleAssignmentList) | ||
1493 | { | ||
1494 | hr = ConfigureRoleAssignments(L"RolesForMethod", piMethColl, piMethObj, pItm->pRoleAssignmentList, fCreate); | ||
1495 | ExitOnFailure(hr, "Failed to read roles"); | ||
1496 | } | ||
1497 | |||
1498 | // clean up | ||
1499 | ReleaseNullObject(piMethObj); | ||
1500 | } | ||
1501 | |||
1502 | // save changes | ||
1503 | hr = piMethColl->SaveChanges(&lChanges); | ||
1504 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1505 | CpiLogCatalogErrorInfo(); | ||
1506 | ExitOnFailure(hr, "Failed to save changes"); | ||
1507 | |||
1508 | hr = S_OK; | ||
1509 | |||
1510 | LExit: | ||
1511 | // clean up | ||
1512 | ReleaseObject(piMethColl); | ||
1513 | ReleaseObject(piMethObj); | ||
1514 | |||
1515 | return hr; | ||
1516 | } | ||
1517 | |||
1518 | static HRESULT ConfigureRoleAssignments( | ||
1519 | LPCWSTR pwzCollName, | ||
1520 | ICatalogCollection* piCompColl, | ||
1521 | ICatalogObject* piCompObj, | ||
1522 | CPI_ROLE_ASSIGNMENT* pRoleList, | ||
1523 | BOOL fCreate | ||
1524 | ) | ||
1525 | { | ||
1526 | HRESULT hr = S_OK; | ||
1527 | |||
1528 | ICatalogCollection* piRoleColl = NULL; | ||
1529 | ICatalogObject* piRoleObj = NULL; | ||
1530 | |||
1531 | long lChanges = 0; | ||
1532 | |||
1533 | // get roles collection | ||
1534 | hr = CpiGetCatalogCollection(piCompColl, piCompObj, pwzCollName, &piRoleColl); | ||
1535 | if (S_FALSE == hr) | ||
1536 | if (fCreate) | ||
1537 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1538 | else | ||
1539 | ExitFunction1(hr = S_OK); | ||
1540 | ExitOnFailure(hr, "Failed to get role assignments collection"); | ||
1541 | |||
1542 | // read roles | ||
1543 | for (CPI_ROLE_ASSIGNMENT* pItm = pRoleList; pItm; pItm = pItm->pNext) | ||
1544 | { | ||
1545 | if (fCreate) | ||
1546 | { | ||
1547 | // find existing role | ||
1548 | hr = CpiFindCollectionObjectByName(piRoleColl, pItm->wzRoleName, NULL); | ||
1549 | ExitOnFailure(hr, "Failed to find role, key: %S", pItm->wzKey); | ||
1550 | |||
1551 | if (S_OK == hr) | ||
1552 | continue; // role already exists | ||
1553 | |||
1554 | // add object | ||
1555 | hr = CpiAddCollectionObject(piRoleColl, &piRoleObj); | ||
1556 | ExitOnFailure(hr, "Failed to add role assignment to collection"); | ||
1557 | |||
1558 | // role name | ||
1559 | hr = CpiPutCollectionObjectValue(piRoleObj, L"Name", pItm->wzRoleName); | ||
1560 | ExitOnFailure(hr, "Failed to set role name property, key: %S", pItm->wzKey); | ||
1561 | |||
1562 | // clean up | ||
1563 | ReleaseNullObject(piRoleObj); | ||
1564 | } | ||
1565 | else | ||
1566 | { | ||
1567 | // remove role | ||
1568 | hr = CpiRemoveCollectionObject(piRoleColl, NULL, pItm->wzRoleName, FALSE); | ||
1569 | ExitOnFailure(hr, "Failed to remove role, key: %S", pItm->wzKey); | ||
1570 | } | ||
1571 | } | ||
1572 | |||
1573 | // save changes | ||
1574 | hr = piRoleColl->SaveChanges(&lChanges); | ||
1575 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
1576 | CpiLogCatalogErrorInfo(); | ||
1577 | ExitOnFailure(hr, "Failed to save changes"); | ||
1578 | |||
1579 | hr = S_OK; | ||
1580 | |||
1581 | LExit: | ||
1582 | // clean up | ||
1583 | ReleaseObject(piRoleColl); | ||
1584 | ReleaseObject(piRoleObj); | ||
1585 | |||
1586 | return hr; | ||
1587 | } | ||
1588 | |||
1589 | static HRESULT ReadComponentList( | ||
1590 | LPWSTR* ppwzData, | ||
1591 | CPI_COMPONENT** ppCompList | ||
1592 | ) | ||
1593 | { | ||
1594 | HRESULT hr = S_OK; | ||
1595 | |||
1596 | LPWSTR pwzData = NULL; | ||
1597 | |||
1598 | CPI_COMPONENT* pItm = NULL; | ||
1599 | |||
1600 | int iCnt = 0; | ||
1601 | |||
1602 | // read count | ||
1603 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
1604 | ExitOnFailure(hr, "Failed to read count"); | ||
1605 | |||
1606 | // read components | ||
1607 | for (int i = 0; i < iCnt; i++) | ||
1608 | { | ||
1609 | pItm = (CPI_COMPONENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_COMPONENT)); | ||
1610 | if (!pItm) | ||
1611 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1612 | |||
1613 | // read clsid | ||
1614 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1615 | ExitOnFailure(hr, "Failed to read clsid"); | ||
1616 | StringCchCopyW(pItm->wzCLSID, countof(pItm->wzCLSID), pwzData); | ||
1617 | |||
1618 | // read properties | ||
1619 | hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList); | ||
1620 | ExitOnFailure(hr, "Failed to read properties"); | ||
1621 | |||
1622 | // read role assignments | ||
1623 | hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList); | ||
1624 | ExitOnFailure(hr, "Failed to read role assignments"); | ||
1625 | |||
1626 | // read interfaces | ||
1627 | hr = ReadInterfaceList(ppwzData, &pItm->pInterfaceList); | ||
1628 | ExitOnFailure(hr, "Failed to read interfaces"); | ||
1629 | |||
1630 | // add to list | ||
1631 | if (*ppCompList) | ||
1632 | pItm->pNext = *ppCompList; | ||
1633 | *ppCompList = pItm; | ||
1634 | pItm = NULL; | ||
1635 | } | ||
1636 | |||
1637 | hr = S_OK; | ||
1638 | |||
1639 | LExit: | ||
1640 | // clean up | ||
1641 | ReleaseStr(pwzData); | ||
1642 | |||
1643 | if (pItm) | ||
1644 | FreeComponentList(pItm); | ||
1645 | |||
1646 | return hr; | ||
1647 | } | ||
1648 | |||
1649 | static HRESULT ReadInterfaceList( | ||
1650 | LPWSTR* ppwzData, | ||
1651 | CPI_INTERFACE** ppIntfList | ||
1652 | ) | ||
1653 | { | ||
1654 | HRESULT hr = S_OK; | ||
1655 | |||
1656 | LPWSTR pwzData = NULL; | ||
1657 | |||
1658 | CPI_INTERFACE* pItm = NULL; | ||
1659 | |||
1660 | int iCnt = 0; | ||
1661 | |||
1662 | // read count | ||
1663 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
1664 | ExitOnFailure(hr, "Failed to read count"); | ||
1665 | |||
1666 | // read interfaces | ||
1667 | for (int i = 0; i < iCnt; i++) | ||
1668 | { | ||
1669 | pItm = (CPI_INTERFACE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_INTERFACE)); | ||
1670 | if (!pItm) | ||
1671 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1672 | |||
1673 | // read iid | ||
1674 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1675 | ExitOnFailure(hr, "Failed to read iid"); | ||
1676 | StringCchCopyW(pItm->wzIID, countof(pItm->wzIID), pwzData); | ||
1677 | |||
1678 | // read properties | ||
1679 | hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList); | ||
1680 | ExitOnFailure(hr, "Failed to read properties"); | ||
1681 | |||
1682 | // read role assignments | ||
1683 | hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList); | ||
1684 | ExitOnFailure(hr, "Failed to read role assignments"); | ||
1685 | |||
1686 | // read methods | ||
1687 | hr = ReadMethodList(ppwzData, &pItm->pMethodList); | ||
1688 | ExitOnFailure(hr, "Failed to read methods"); | ||
1689 | |||
1690 | // add to list | ||
1691 | if (*ppIntfList) | ||
1692 | pItm->pNext = *ppIntfList; | ||
1693 | *ppIntfList = pItm; | ||
1694 | pItm = NULL; | ||
1695 | } | ||
1696 | |||
1697 | hr = S_OK; | ||
1698 | |||
1699 | LExit: | ||
1700 | // clean up | ||
1701 | ReleaseStr(pwzData); | ||
1702 | |||
1703 | if (pItm) | ||
1704 | FreeInterfaceList(pItm); | ||
1705 | |||
1706 | return hr; | ||
1707 | } | ||
1708 | |||
1709 | static HRESULT ReadMethodList( | ||
1710 | LPWSTR* ppwzData, | ||
1711 | CPI_METHOD** ppMethList | ||
1712 | ) | ||
1713 | { | ||
1714 | HRESULT hr = S_OK; | ||
1715 | |||
1716 | LPWSTR pwzData = NULL; | ||
1717 | |||
1718 | CPI_METHOD* pItm = NULL; | ||
1719 | |||
1720 | int iCnt = 0; | ||
1721 | |||
1722 | // read count | ||
1723 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
1724 | ExitOnFailure(hr, "Failed to read count"); | ||
1725 | |||
1726 | // read methods | ||
1727 | for (int i = 0; i < iCnt; i++) | ||
1728 | { | ||
1729 | pItm = (CPI_METHOD*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_METHOD)); | ||
1730 | if (!pItm) | ||
1731 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1732 | |||
1733 | // read index | ||
1734 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1735 | ExitOnFailure(hr, "Failed to read index"); | ||
1736 | StringCchCopyW(pItm->wzIndex, countof(pItm->wzIndex), pwzData); | ||
1737 | |||
1738 | // read name | ||
1739 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1740 | ExitOnFailure(hr, "Failed to read name"); | ||
1741 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
1742 | |||
1743 | // read properties | ||
1744 | hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList); | ||
1745 | ExitOnFailure(hr, "Failed to read properties"); | ||
1746 | |||
1747 | // read role assignments | ||
1748 | hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList); | ||
1749 | ExitOnFailure(hr, "Failed to read role assignments"); | ||
1750 | |||
1751 | // add to list | ||
1752 | if (*ppMethList) | ||
1753 | pItm->pNext = *ppMethList; | ||
1754 | *ppMethList = pItm; | ||
1755 | pItm = NULL; | ||
1756 | } | ||
1757 | |||
1758 | hr = S_OK; | ||
1759 | |||
1760 | LExit: | ||
1761 | // clean up | ||
1762 | ReleaseStr(pwzData); | ||
1763 | |||
1764 | if (pItm) | ||
1765 | FreeMethodList(pItm); | ||
1766 | |||
1767 | return hr; | ||
1768 | } | ||
1769 | |||
1770 | static HRESULT ReadRoleAssignmentList( | ||
1771 | LPWSTR* ppwzData, | ||
1772 | CPI_ROLE_ASSIGNMENT** ppRoleList | ||
1773 | ) | ||
1774 | { | ||
1775 | HRESULT hr = S_OK; | ||
1776 | |||
1777 | LPWSTR pwzData = NULL; | ||
1778 | |||
1779 | CPI_ROLE_ASSIGNMENT* pItm = NULL; | ||
1780 | |||
1781 | int iCnt = 0; | ||
1782 | |||
1783 | // read role count | ||
1784 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
1785 | ExitOnFailure(hr, "Failed to read role assignments count"); | ||
1786 | |||
1787 | // read roles | ||
1788 | for (int i = 0; i < iCnt; i++) | ||
1789 | { | ||
1790 | pItm = (CPI_ROLE_ASSIGNMENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLE_ASSIGNMENT)); | ||
1791 | if (!pItm) | ||
1792 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1793 | |||
1794 | // read key | ||
1795 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1796 | ExitOnFailure(hr, "Failed to read key"); | ||
1797 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
1798 | |||
1799 | // read role name | ||
1800 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
1801 | ExitOnFailure(hr, "Failed to read role name"); | ||
1802 | StringCchCopyW(pItm->wzRoleName, countof(pItm->wzRoleName), pwzData); | ||
1803 | |||
1804 | // add to list | ||
1805 | if (*ppRoleList) | ||
1806 | pItm->pNext = *ppRoleList; | ||
1807 | *ppRoleList = pItm; | ||
1808 | pItm = NULL; | ||
1809 | } | ||
1810 | |||
1811 | hr = S_OK; | ||
1812 | |||
1813 | LExit: | ||
1814 | // clean up | ||
1815 | ReleaseStr(pwzData); | ||
1816 | |||
1817 | if (pItm) | ||
1818 | FreeRoleAssignmentList(pItm); | ||
1819 | |||
1820 | return hr; | ||
1821 | } | ||
1822 | |||
1823 | static void FreeComponentList( | ||
1824 | CPI_COMPONENT* pList | ||
1825 | ) | ||
1826 | { | ||
1827 | while (pList) | ||
1828 | { | ||
1829 | if (pList->pPropertyList) | ||
1830 | CpiFreePropertyList(pList->pPropertyList); | ||
1831 | if (pList->pRoleAssignmentList) | ||
1832 | FreeRoleAssignmentList(pList->pRoleAssignmentList); | ||
1833 | if (pList->pInterfaceList) | ||
1834 | FreeInterfaceList(pList->pInterfaceList); | ||
1835 | |||
1836 | CPI_COMPONENT* pDelete = pList; | ||
1837 | pList = pList->pNext; | ||
1838 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
1839 | } | ||
1840 | } | ||
1841 | |||
1842 | static void FreeInterfaceList( | ||
1843 | CPI_INTERFACE* pList | ||
1844 | ) | ||
1845 | { | ||
1846 | while (pList) | ||
1847 | { | ||
1848 | if (pList->pPropertyList) | ||
1849 | CpiFreePropertyList(pList->pPropertyList); | ||
1850 | if (pList->pRoleAssignmentList) | ||
1851 | FreeRoleAssignmentList(pList->pRoleAssignmentList); | ||
1852 | if (pList->pMethodList) | ||
1853 | FreeMethodList(pList->pMethodList); | ||
1854 | |||
1855 | CPI_INTERFACE* pDelete = pList; | ||
1856 | pList = pList->pNext; | ||
1857 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
1858 | } | ||
1859 | } | ||
1860 | |||
1861 | static void FreeMethodList( | ||
1862 | CPI_METHOD* pList | ||
1863 | ) | ||
1864 | { | ||
1865 | while (pList) | ||
1866 | { | ||
1867 | if (pList->pPropertyList) | ||
1868 | CpiFreePropertyList(pList->pPropertyList); | ||
1869 | if (pList->pRoleAssignmentList) | ||
1870 | FreeRoleAssignmentList(pList->pRoleAssignmentList); | ||
1871 | |||
1872 | CPI_METHOD* pDelete = pList; | ||
1873 | pList = pList->pNext; | ||
1874 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
1875 | } | ||
1876 | } | ||
1877 | |||
1878 | static void FreeRoleAssignmentList( | ||
1879 | CPI_ROLE_ASSIGNMENT* pList | ||
1880 | ) | ||
1881 | { | ||
1882 | while (pList) | ||
1883 | { | ||
1884 | CPI_ROLE_ASSIGNMENT* pDelete = pList; | ||
1885 | pList = pList->pNext; | ||
1886 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
1887 | } | ||
1888 | } | ||
diff --git a/src/ca/cpasmexec.h b/src/ca/cpasmexec.h new file mode 100644 index 00000000..56184c01 --- /dev/null +++ b/src/ca/cpasmexec.h | |||
@@ -0,0 +1,20 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | HRESULT CpiConfigureAssemblies( | ||
6 | LPWSTR* ppwzData, | ||
7 | HANDLE hRollbackFile | ||
8 | ); | ||
9 | HRESULT CpiRollbackConfigureAssemblies( | ||
10 | LPWSTR* ppwzData, | ||
11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
12 | ); | ||
13 | HRESULT CpiConfigureRoleAssignments( | ||
14 | LPWSTR* ppwzData, | ||
15 | HANDLE hRollbackFile | ||
16 | ); | ||
17 | HRESULT CpiRollbackConfigureRoleAssignments( | ||
18 | LPWSTR* ppwzData, | ||
19 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
20 | ); | ||
diff --git a/src/ca/cpasmsched.cpp b/src/ca/cpasmsched.cpp new file mode 100644 index 00000000..97ecff61 --- /dev/null +++ b/src/ca/cpasmsched.cpp | |||
@@ -0,0 +1,2135 @@ | |||
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 | // sql queries | ||
7 | |||
8 | LPCWSTR vcsMsiAssemblyNameQuery = | ||
9 | L"SELECT `Name`, `Value` FROM `MsiAssemblyName` WHERE `Component_` = ?"; | ||
10 | enum eMsiAssemblyNameQuery { manqName = 1, manqValue }; | ||
11 | |||
12 | LPCWSTR vcsModuleQuery = | ||
13 | L"SELECT `ModuleID` FROM `ModuleSignature`"; | ||
14 | enum eModuleQuery { mqModule = 1 }; | ||
15 | |||
16 | LPCWSTR vcsAssemblyQuery = | ||
17 | L"SELECT `Assembly`, `Component_`, `Application_`, `AssemblyName`, `DllPath`, `TlbPath`, `PSDllPath`, `Attributes` FROM `ComPlusAssembly`"; | ||
18 | enum eAssemblyQuery { aqAssembly = 1, aqComponent, aqApplication, aqAssemblyName, aqDllPath, aqTlbPath, aqPSDllPath, aqAttributes }; | ||
19 | |||
20 | LPCWSTR vcsComponentQuery = | ||
21 | L"SELECT `ComPlusComponent`, `CLSID` FROM `ComPlusComponent` WHERE `Assembly_` = ?"; | ||
22 | enum eComponentQuery { cqComponent = 1, cqCLSID }; | ||
23 | |||
24 | LPCWSTR vcsComponentPropertyQuery = | ||
25 | L"SELECT `Name`, `Value` FROM `ComPlusComponentProperty` WHERE `ComPlusComponent_` = ?"; | ||
26 | |||
27 | LPCWSTR vcsInterfaceQuery = | ||
28 | L"SELECT `Interface`, `IID` FROM `ComPlusInterface` WHERE `ComPlusComponent_` = ?"; | ||
29 | enum eInterfaceQuery { iqInterface = 1, iqIID }; | ||
30 | |||
31 | LPCWSTR vcsInterfacePropertyQuery = | ||
32 | L"SELECT `Name`, `Value` FROM `ComPlusInterfaceProperty` WHERE `Interface_` = ?"; | ||
33 | |||
34 | LPCWSTR vcsMethodQuery = | ||
35 | L"SELECT `Method`, `Index`, `Name` FROM `ComPlusMethod` WHERE `Interface_` = ?"; | ||
36 | enum eMethodQuery { mqMethod = 1, mqIndex, mqName }; | ||
37 | |||
38 | LPCWSTR vcsMethodPropertyQuery = | ||
39 | L"SELECT `Name`, `Value` FROM `ComPlusMethodProperty` WHERE `Method_` = ?"; | ||
40 | |||
41 | LPCWSTR vcsRoleForComponentQuery = | ||
42 | L"SELECT `RoleForComponent`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForComponent` WHERE `ComPlusComponent_` = ?"; | ||
43 | LPCWSTR vcsRoleForInterfaceQuery = | ||
44 | L"SELECT `RoleForInterface`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForInterface` WHERE `Interface_` = ?"; | ||
45 | LPCWSTR vcsRoleForMethodQuery = | ||
46 | L"SELECT `RoleForMethod`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForMethod` WHERE `Method_` = ?"; | ||
47 | |||
48 | enum eRoleAssignmentQuery { raqKey = 1, raqApplicationRole, raqComponent }; | ||
49 | |||
50 | LPCWSTR vcsModuleComponentsQuery = | ||
51 | L"SELECT `Component`, `ModuleID` FROM `ModuleComponents`"; | ||
52 | LPCWSTR vcsModuleDependencyQuery = | ||
53 | L"SELECT `ModuleID`, `RequiredID` FROM `ModuleDependency`"; | ||
54 | LPCWSTR vcsAssemblyDependencyQuery = | ||
55 | L"SELECT `Assembly_`, `RequiredAssembly_` FROM `ComPlusAssemblyDependency`"; | ||
56 | |||
57 | enum eKeyPairQuery { kpqFirstKey = 1, kpqSecondKey }; | ||
58 | |||
59 | |||
60 | // private structs | ||
61 | |||
62 | struct CPI_KEY_PAIR | ||
63 | { | ||
64 | WCHAR wzFirstKey[MAX_DARWIN_KEY + 1]; | ||
65 | WCHAR wzSecondKey[MAX_DARWIN_KEY + 1]; | ||
66 | |||
67 | CPI_KEY_PAIR* pNext; | ||
68 | }; | ||
69 | |||
70 | struct CPI_DEPENDENCY_CHAIN | ||
71 | { | ||
72 | LPCWSTR pwzKey; | ||
73 | |||
74 | CPI_DEPENDENCY_CHAIN* pPrev; | ||
75 | }; | ||
76 | |||
77 | struct CPI_MODULE | ||
78 | { | ||
79 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
80 | |||
81 | CPI_MODULE* pPrev; | ||
82 | CPI_MODULE* pNext; | ||
83 | }; | ||
84 | |||
85 | struct CPI_MODULE_LIST | ||
86 | { | ||
87 | CPI_MODULE* pFirst; | ||
88 | CPI_MODULE* pLast; | ||
89 | }; | ||
90 | |||
91 | |||
92 | // property definitions | ||
93 | |||
94 | CPI_PROPERTY_DEFINITION pdlComponentProperties[] = | ||
95 | { | ||
96 | {L"AllowInprocSubscribers", cpptBoolean, 500}, | ||
97 | {L"ComponentAccessChecksEnabled", cpptBoolean, 500}, | ||
98 | {L"ComponentTransactionTimeout", cpptInteger, 500}, | ||
99 | {L"ComponentTransactionTimeoutEnabled", cpptBoolean, 500}, | ||
100 | {L"COMTIIntrinsics", cpptBoolean, 500}, | ||
101 | {L"ConstructionEnabled", cpptBoolean, 500}, | ||
102 | {L"ConstructorString", cpptString, 500}, | ||
103 | {L"CreationTimeout", cpptInteger, 500}, | ||
104 | {L"Description", cpptString, 500}, | ||
105 | {L"EventTrackingEnabled", cpptBoolean, 500}, | ||
106 | {L"ExceptionClass", cpptString, 500}, | ||
107 | {L"FireInParallel", cpptBoolean, 500}, | ||
108 | {L"IISIntrinsics", cpptBoolean, 500}, | ||
109 | {L"InitializesServerApplication", cpptBoolean, 500}, | ||
110 | {L"IsEnabled", cpptBoolean, 501}, | ||
111 | {L"IsPrivateComponent", cpptBoolean, 501}, | ||
112 | {L"JustInTimeActivation", cpptBoolean, 500}, | ||
113 | {L"LoadBalancingSupported", cpptBoolean, 500}, | ||
114 | {L"MaxPoolSize", cpptInteger, 500}, | ||
115 | {L"MinPoolSize", cpptInteger, 500}, | ||
116 | {L"MultiInterfacePublisherFilterCLSID", cpptString, 500}, | ||
117 | {L"MustRunInClientContext", cpptBoolean, 500}, | ||
118 | {L"MustRunInDefaultContext", cpptBoolean, 501}, | ||
119 | {L"ObjectPoolingEnabled", cpptBoolean, 500}, | ||
120 | {L"PublisherID", cpptString, 500}, | ||
121 | {L"SoapAssemblyName", cpptString, 502}, | ||
122 | {L"SoapTypeName", cpptString, 502}, | ||
123 | {L"Synchronization", cpptInteger, 500}, | ||
124 | {L"Transaction", cpptInteger, 500}, | ||
125 | {L"TxIsolationLevel", cpptInteger, 501}, | ||
126 | {NULL, cpptNone, 0} | ||
127 | }; | ||
128 | |||
129 | CPI_PROPERTY_DEFINITION pdlInterfaceProperties[] = | ||
130 | { | ||
131 | {L"Description", cpptString, 500}, | ||
132 | {L"QueuingEnabled", cpptBoolean, 500}, | ||
133 | {NULL, cpptNone, 0} | ||
134 | }; | ||
135 | |||
136 | CPI_PROPERTY_DEFINITION pdlMethodProperties[] = | ||
137 | { | ||
138 | {L"AutoComplete", cpptBoolean, 500}, | ||
139 | {L"Description", cpptString, 500}, | ||
140 | {NULL, cpptNone, 0} | ||
141 | }; | ||
142 | |||
143 | |||
144 | // prototypes for private helper functions | ||
145 | |||
146 | static HRESULT GetAssemblyName( | ||
147 | LPCWSTR pwzComponent, | ||
148 | LPWSTR* ppwzAssemblyName | ||
149 | ); | ||
150 | static HRESULT KeyPairsRead( | ||
151 | LPCWSTR pwzQuery, | ||
152 | CPI_KEY_PAIR** ppKeyPairList | ||
153 | ); | ||
154 | static HRESULT ModulesRead( | ||
155 | CPI_MODULE_LIST* pModList | ||
156 | ); | ||
157 | static HRESULT AssembliesRead( | ||
158 | CPI_KEY_PAIR* pModCompList, | ||
159 | CPI_APPLICATION_LIST* pAppList, | ||
160 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
161 | CPI_ASSEMBLY_LIST* pAsmList | ||
162 | ); | ||
163 | static HRESULT ComponentsRead( | ||
164 | LPCWSTR pwzAsmKey, | ||
165 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
166 | CPI_ASSEMBLY* pAsm | ||
167 | ); | ||
168 | static HRESULT InterfacesRead( | ||
169 | LPCWSTR pwzCompKey, | ||
170 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
171 | CPI_ASSEMBLY* pAsm, | ||
172 | CPI_COMPONENT* pComp | ||
173 | ); | ||
174 | static HRESULT MethodsRead( | ||
175 | LPCWSTR pwzIntfKey, | ||
176 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
177 | CPI_ASSEMBLY* pAsm, | ||
178 | CPI_INTERFACE* pIntf | ||
179 | ); | ||
180 | static HRESULT RoleAssignmentsRead( | ||
181 | LPCWSTR pwzQuery, | ||
182 | LPCWSTR pwzKey, | ||
183 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
184 | CPI_ROLE_ASSIGNMENT** ppRoleList, | ||
185 | int* piInstallCount, | ||
186 | int* piUninstallCount | ||
187 | ); | ||
188 | static HRESULT TopSortModuleList( | ||
189 | CPI_KEY_PAIR* pDepList, | ||
190 | CPI_MODULE_LIST* pList | ||
191 | ); | ||
192 | static HRESULT SwapDependentModules( | ||
193 | CPI_DEPENDENCY_CHAIN* pdcPrev, | ||
194 | CPI_KEY_PAIR* pDepList, | ||
195 | CPI_MODULE_LIST* pList, | ||
196 | CPI_MODULE* pRoot, | ||
197 | CPI_MODULE* pItm | ||
198 | ); | ||
199 | static HRESULT ModuleFindByKey( | ||
200 | CPI_MODULE* pItm, | ||
201 | LPCWSTR pwzKey, | ||
202 | BOOL fReverse, | ||
203 | CPI_MODULE** ppItm | ||
204 | ); | ||
205 | static void SortAssemblyListByModule( | ||
206 | CPI_MODULE_LIST* pModList, | ||
207 | CPI_ASSEMBLY_LIST* pAsmList | ||
208 | ); | ||
209 | static HRESULT TopSortAssemblyList( | ||
210 | CPI_KEY_PAIR* pDepList, | ||
211 | CPI_ASSEMBLY_LIST* pList | ||
212 | ); | ||
213 | static HRESULT SwapDependentAssemblies( | ||
214 | CPI_DEPENDENCY_CHAIN* pdcPrev, | ||
215 | CPI_KEY_PAIR* pDepList, | ||
216 | CPI_ASSEMBLY_LIST* pList, | ||
217 | CPI_ASSEMBLY* pRoot, | ||
218 | CPI_ASSEMBLY* pItm | ||
219 | ); | ||
220 | static HRESULT AssemblyFindByKey( | ||
221 | CPI_ASSEMBLY* pItm, | ||
222 | LPCWSTR pwzKey, | ||
223 | BOOL fReverse, | ||
224 | CPI_ASSEMBLY** ppItm | ||
225 | ); | ||
226 | static HRESULT AddAssemblyToActionData( | ||
227 | CPI_ASSEMBLY* pItm, | ||
228 | BOOL fInstall, | ||
229 | int iActionType, | ||
230 | int iActionCost, | ||
231 | LPWSTR* ppwzActionData | ||
232 | ); | ||
233 | static HRESULT AddRoleAssignmentsToActionData( | ||
234 | CPI_ASSEMBLY* pItm, | ||
235 | BOOL fInstall, | ||
236 | int iActionType, | ||
237 | int iActionCost, | ||
238 | LPWSTR* ppwzActionData | ||
239 | ); | ||
240 | static HRESULT AddComponentToActionData( | ||
241 | CPI_COMPONENT* pItm, | ||
242 | BOOL fInstall, | ||
243 | BOOL fProps, | ||
244 | BOOL fRoles, | ||
245 | LPWSTR* ppwzActionData | ||
246 | ); | ||
247 | static HRESULT AddInterfaceToActionData( | ||
248 | CPI_INTERFACE* pItm, | ||
249 | BOOL fInstall, | ||
250 | BOOL fProps, | ||
251 | BOOL fRoles, | ||
252 | LPWSTR* ppwzActionData | ||
253 | ); | ||
254 | static HRESULT AddMethodToActionData( | ||
255 | CPI_METHOD* pItm, | ||
256 | BOOL fInstall, | ||
257 | BOOL fProps, | ||
258 | BOOL fRoles, | ||
259 | LPWSTR* ppwzActionData | ||
260 | ); | ||
261 | static HRESULT AddRolesToActionData( | ||
262 | int iRoleInstallCount, | ||
263 | int iRoleUninstallCount, | ||
264 | CPI_ROLE_ASSIGNMENT* pRoleList, | ||
265 | BOOL fInstall, | ||
266 | BOOL fRoles, | ||
267 | LPWSTR* ppwzActionData | ||
268 | ); | ||
269 | static HRESULT KeyPairFindByFirstKey( | ||
270 | CPI_KEY_PAIR* pList, | ||
271 | LPCWSTR pwzKey, | ||
272 | CPI_KEY_PAIR** ppItm | ||
273 | ); | ||
274 | static void AssemblyFree( | ||
275 | CPI_ASSEMBLY* pItm | ||
276 | ); | ||
277 | static void KeyPairsFreeList( | ||
278 | CPI_KEY_PAIR* pList | ||
279 | ); | ||
280 | void ModuleListFree( | ||
281 | CPI_MODULE_LIST* pList | ||
282 | ); | ||
283 | static void ModuleFree( | ||
284 | CPI_MODULE* pItm | ||
285 | ); | ||
286 | static void ComponentsFreeList( | ||
287 | CPI_COMPONENT* pList | ||
288 | ); | ||
289 | static void InterfacesFreeList( | ||
290 | CPI_INTERFACE* pList | ||
291 | ); | ||
292 | static void MethodsFreeList( | ||
293 | CPI_METHOD* pList | ||
294 | ); | ||
295 | static void RoleAssignmentsFreeList( | ||
296 | CPI_ROLE_ASSIGNMENT* pList | ||
297 | ); | ||
298 | |||
299 | |||
300 | // function definitions | ||
301 | |||
302 | void CpiAssemblyListFree( | ||
303 | CPI_ASSEMBLY_LIST* pList | ||
304 | ) | ||
305 | { | ||
306 | CPI_ASSEMBLY* pItm = pList->pFirst; | ||
307 | |||
308 | while (pItm) | ||
309 | { | ||
310 | CPI_ASSEMBLY* pDelete = pItm; | ||
311 | pItm = pItm->pNext; | ||
312 | AssemblyFree(pDelete); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | HRESULT CpiAssembliesRead( | ||
317 | CPI_APPLICATION_LIST* pAppList, | ||
318 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
319 | CPI_ASSEMBLY_LIST* pAsmList | ||
320 | ) | ||
321 | { | ||
322 | HRESULT hr = S_OK; | ||
323 | CPI_MODULE_LIST modList; | ||
324 | CPI_KEY_PAIR* pModCompList = NULL; | ||
325 | CPI_KEY_PAIR* pModDepList = NULL; | ||
326 | CPI_KEY_PAIR* pAsmDepList = NULL; | ||
327 | |||
328 | ::ZeroMemory(&modList, sizeof(CPI_MODULE_LIST)); | ||
329 | |||
330 | BOOL fModuleSignatureTable = (S_OK == WcaTableExists(L"ModuleSignature")); | ||
331 | BOOL fModuleComponentsTable = (S_OK == WcaTableExists(L"ModuleComponents")); | ||
332 | BOOL fModuleDependencyTable = (S_OK == WcaTableExists(L"ModuleDependency")); | ||
333 | |||
334 | // read modules | ||
335 | if (fModuleSignatureTable) | ||
336 | { | ||
337 | hr = ModulesRead(&modList); | ||
338 | ExitOnFailure(hr, "Failed to read ModuleSignature table"); | ||
339 | } | ||
340 | |||
341 | // read module components | ||
342 | if (fModuleComponentsTable) | ||
343 | { | ||
344 | hr = KeyPairsRead(vcsModuleComponentsQuery, &pModCompList); | ||
345 | ExitOnFailure(hr, "Failed to read ModuleComponents table"); | ||
346 | } | ||
347 | |||
348 | // read module dependencies | ||
349 | if (fModuleDependencyTable) | ||
350 | { | ||
351 | hr = KeyPairsRead(vcsModuleDependencyQuery, &pModDepList); | ||
352 | ExitOnFailure(hr, "Failed to read ModuleDependency table"); | ||
353 | } | ||
354 | |||
355 | // read assemblies | ||
356 | hr = AssembliesRead(pModCompList, pAppList, pAppRoleList, pAsmList); | ||
357 | ExitOnFailure(hr, "Failed to read ComPlusAssembly table"); | ||
358 | |||
359 | // read assembly dependencies | ||
360 | if (CpiTableExists(cptComPlusAssemblyDependency)) | ||
361 | { | ||
362 | hr = KeyPairsRead(vcsAssemblyDependencyQuery, &pAsmDepList); | ||
363 | ExitOnFailure(hr, "Failed to read ComPlusAssemblyDependency table"); | ||
364 | } | ||
365 | |||
366 | // sort modules | ||
367 | if (modList.pFirst && pModDepList) | ||
368 | { | ||
369 | hr = TopSortModuleList(pModDepList, &modList); | ||
370 | ExitOnFailure(hr, "Failed to sort modules"); | ||
371 | } | ||
372 | |||
373 | // sort assemblies by module | ||
374 | if (pAsmList->pFirst && modList.pFirst && pModDepList) | ||
375 | SortAssemblyListByModule(&modList, pAsmList); | ||
376 | |||
377 | // sort assemblies by dependency | ||
378 | if (pAsmList->pFirst && pAsmDepList) | ||
379 | { | ||
380 | hr = TopSortAssemblyList(pAsmDepList, pAsmList); | ||
381 | ExitOnFailure(hr, "Failed to sort assemblies"); | ||
382 | } | ||
383 | |||
384 | hr = S_OK; | ||
385 | |||
386 | LExit: | ||
387 | // clean up | ||
388 | ModuleListFree(&modList); | ||
389 | if (pModCompList) | ||
390 | KeyPairsFreeList(pModCompList); | ||
391 | if (pModDepList) | ||
392 | KeyPairsFreeList(pModDepList); | ||
393 | if (pAsmDepList) | ||
394 | KeyPairsFreeList(pAsmDepList); | ||
395 | |||
396 | return hr; | ||
397 | } | ||
398 | |||
399 | HRESULT CpiAssembliesVerifyInstall( | ||
400 | CPI_ASSEMBLY_LIST* pList | ||
401 | ) | ||
402 | { | ||
403 | HRESULT hr = S_OK; | ||
404 | |||
405 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
406 | { | ||
407 | // assemblies that are being installed | ||
408 | if (!pItm->fReferencedForInstall && !pItm->iRoleAssignmentsInstallCount && !WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
409 | continue; | ||
410 | |||
411 | // if the assembly is referensed, it must be installed | ||
412 | if ((pItm->fReferencedForInstall || pItm->iRoleAssignmentsInstallCount) && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction)) | ||
413 | MessageExitOnFailure(hr = E_FAIL, msierrComPlusAssemblyDependency, "An assembly is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey); | ||
414 | } | ||
415 | |||
416 | hr = S_OK; | ||
417 | |||
418 | LExit: | ||
419 | return hr; | ||
420 | } | ||
421 | |||
422 | HRESULT CpiAssembliesVerifyUninstall( | ||
423 | CPI_ASSEMBLY_LIST* pList | ||
424 | ) | ||
425 | { | ||
426 | HRESULT hr = S_OK; | ||
427 | |||
428 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
429 | { | ||
430 | // assemblies that are being uninstalled | ||
431 | if (!pItm->fReferencedForUninstall && !pItm->iRoleAssignmentsUninstallCount && (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction) && !WcaIsReInstalling(pItm->isInstalled, pItm->isAction))) | ||
432 | continue; | ||
433 | |||
434 | // if the application is not present, there is no need to remove the components | ||
435 | if (pItm->pApplication && pItm->pApplication->fObjectNotFound) | ||
436 | { | ||
437 | pItm->fIgnore = TRUE; | ||
438 | pList->iUninstallCount--; // elements with the fIgnore flag set will not be scheduled for uninstall | ||
439 | pList->iRoleUninstallCount--; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | hr = S_OK; | ||
444 | |||
445 | //LExit: | ||
446 | return hr; | ||
447 | } | ||
448 | |||
449 | HRESULT CpiAssembliesInstall( | ||
450 | CPI_ASSEMBLY_LIST* pList, | ||
451 | int iRunMode, | ||
452 | LPWSTR* ppwzActionData, | ||
453 | int* piProgress | ||
454 | ) | ||
455 | { | ||
456 | HRESULT hr = S_OK; | ||
457 | |||
458 | int iActionType; | ||
459 | int iCount = 0; | ||
460 | |||
461 | // add action text | ||
462 | hr = CpiAddActionTextToActionData(L"RegisterComPlusAssemblies", ppwzActionData); | ||
463 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
464 | |||
465 | // assembly count | ||
466 | switch (iRunMode) | ||
467 | { | ||
468 | case rmDeferred: | ||
469 | iCount = pList->iInstallCount - pList->iCommitCount; | ||
470 | break; | ||
471 | case rmCommit: | ||
472 | iCount = pList->iCommitCount; | ||
473 | break; | ||
474 | case rmRollback: | ||
475 | iCount = pList->iInstallCount; | ||
476 | break; | ||
477 | } | ||
478 | |||
479 | // add assembly count to action data | ||
480 | hr = WcaWriteIntegerToCaData(iCount, ppwzActionData); | ||
481 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
482 | |||
483 | // add assemblies to custom action data in forward order | ||
484 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
485 | { | ||
486 | // assemblies that are being installed, or contains roll assignments to install | ||
487 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
488 | continue; | ||
489 | |||
490 | // assemblies that are being installed must be scheduled during the right type of action | ||
491 | BOOL fRunInCommit = 0 != (pItm->iAttributes & aaRunInCommit); | ||
492 | if (((rmCommit == iRunMode && !fRunInCommit) || (rmDeferred == iRunMode && fRunInCommit))) | ||
493 | continue; | ||
494 | |||
495 | // action type | ||
496 | if (rmRollback == iRunMode) | ||
497 | { | ||
498 | if (CpiIsInstalled(pItm->isInstalled)) | ||
499 | iActionType = atNoOp; | ||
500 | else | ||
501 | iActionType = atRemove; | ||
502 | } | ||
503 | else | ||
504 | iActionType = atCreate; | ||
505 | |||
506 | // add to action data | ||
507 | hr = AddAssemblyToActionData(pItm, TRUE, iActionType, COST_ASSEMBLY_REGISTER, ppwzActionData); | ||
508 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
509 | } | ||
510 | |||
511 | // add progress tics | ||
512 | if (piProgress) | ||
513 | *piProgress += COST_ASSEMBLY_REGISTER * iCount; | ||
514 | |||
515 | hr = S_OK; | ||
516 | |||
517 | LExit: | ||
518 | return hr; | ||
519 | } | ||
520 | |||
521 | HRESULT CpiAssembliesUninstall( | ||
522 | CPI_ASSEMBLY_LIST* pList, | ||
523 | int iRunMode, | ||
524 | LPWSTR* ppwzActionData, | ||
525 | int* piProgress | ||
526 | ) | ||
527 | { | ||
528 | HRESULT hr = S_OK; | ||
529 | |||
530 | int iActionType; | ||
531 | |||
532 | // add action text | ||
533 | hr = CpiAddActionTextToActionData(L"UnregisterComPlusAssemblies", ppwzActionData); | ||
534 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
535 | |||
536 | // add assembly count to action data | ||
537 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
538 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
539 | |||
540 | // add assemblies to custom action data in reverse order | ||
541 | for (CPI_ASSEMBLY* pItm = pList->pLast; pItm; pItm = pItm->pPrev) | ||
542 | { | ||
543 | // assemblies that are being uninstalled | ||
544 | if (pItm->fIgnore || (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction) && !WcaIsReInstalling(pItm->isInstalled, pItm->isAction))) | ||
545 | continue; | ||
546 | |||
547 | // action type | ||
548 | if (rmRollback == iRunMode) | ||
549 | iActionType = atCreate; | ||
550 | else | ||
551 | iActionType = atRemove; | ||
552 | |||
553 | // add to action data | ||
554 | hr = AddAssemblyToActionData(pItm, FALSE, iActionType, COST_ASSEMBLY_UNREGISTER, ppwzActionData); | ||
555 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
556 | } | ||
557 | |||
558 | // add progress tics | ||
559 | if (piProgress) | ||
560 | *piProgress += COST_ASSEMBLY_UNREGISTER * pList->iUninstallCount; | ||
561 | |||
562 | hr = S_OK; | ||
563 | |||
564 | LExit: | ||
565 | return hr; | ||
566 | } | ||
567 | |||
568 | HRESULT CpiRoleAssignmentsInstall( | ||
569 | CPI_ASSEMBLY_LIST* pList, | ||
570 | int iRunMode, | ||
571 | LPWSTR* ppwzActionData, | ||
572 | int* piProgress | ||
573 | ) | ||
574 | { | ||
575 | HRESULT hr = S_OK; | ||
576 | |||
577 | int iActionType; | ||
578 | int iCount = 0; | ||
579 | |||
580 | // add action text | ||
581 | hr = CpiAddActionTextToActionData(L"AddComPlusRoleAssignments", ppwzActionData); | ||
582 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
583 | |||
584 | // assembly count | ||
585 | switch (iRunMode) | ||
586 | { | ||
587 | case rmDeferred: | ||
588 | iCount = pList->iRoleInstallCount - pList->iRoleCommitCount; | ||
589 | break; | ||
590 | case rmCommit: | ||
591 | iCount = pList->iRoleCommitCount; | ||
592 | break; | ||
593 | case rmRollback: | ||
594 | iCount = pList->iRoleInstallCount; | ||
595 | break; | ||
596 | } | ||
597 | |||
598 | // add assembly count to action data | ||
599 | hr = WcaWriteIntegerToCaData(iCount, ppwzActionData); | ||
600 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
601 | |||
602 | // add assemblies to custom action data in forward order | ||
603 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
604 | { | ||
605 | // assemblies that are being installed, or contains roll assignments to install | ||
606 | if (!pItm->iRoleAssignmentsInstallCount) | ||
607 | continue; | ||
608 | |||
609 | // assemblies that are being installed must be scheduled during the right type of action | ||
610 | BOOL fRunInCommit = 0 != (pItm->iAttributes & aaRunInCommit); | ||
611 | if (((rmCommit == iRunMode && !fRunInCommit) || (rmDeferred == iRunMode && fRunInCommit))) | ||
612 | continue; | ||
613 | |||
614 | // action type | ||
615 | if (rmRollback == iRunMode) | ||
616 | { | ||
617 | if (CpiIsInstalled(pItm->isInstalled)) | ||
618 | iActionType = atNoOp; | ||
619 | else | ||
620 | iActionType = atRemove; | ||
621 | } | ||
622 | else | ||
623 | iActionType = atCreate; | ||
624 | |||
625 | // add to action data | ||
626 | hr = AddRoleAssignmentsToActionData(pItm, TRUE, iActionType, COST_ROLLASSIGNMENT_CREATE, ppwzActionData); | ||
627 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
628 | |||
629 | // add progress tics | ||
630 | if (piProgress) | ||
631 | *piProgress += COST_ROLLASSIGNMENT_CREATE * pItm->iRoleAssignmentsInstallCount; | ||
632 | } | ||
633 | |||
634 | hr = S_OK; | ||
635 | |||
636 | LExit: | ||
637 | return hr; | ||
638 | } | ||
639 | |||
640 | HRESULT CpiRoleAssignmentsUninstall( | ||
641 | CPI_ASSEMBLY_LIST* pList, | ||
642 | int iRunMode, | ||
643 | LPWSTR* ppwzActionData, | ||
644 | int* piProgress | ||
645 | ) | ||
646 | { | ||
647 | HRESULT hr = S_OK; | ||
648 | |||
649 | int iActionType; | ||
650 | |||
651 | // add action text | ||
652 | hr = CpiAddActionTextToActionData(L"RemoveComPlusRoleAssignments", ppwzActionData); | ||
653 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
654 | |||
655 | // add assembly count to action data | ||
656 | hr = WcaWriteIntegerToCaData(pList->iRoleUninstallCount, ppwzActionData); | ||
657 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
658 | |||
659 | // add assemblies to custom action data in reverse order | ||
660 | for (CPI_ASSEMBLY* pItm = pList->pLast; pItm; pItm = pItm->pPrev) | ||
661 | { | ||
662 | // assemblies that are being uninstalled | ||
663 | if (pItm->fIgnore || !pItm->iRoleAssignmentsUninstallCount) | ||
664 | continue; | ||
665 | |||
666 | // action type | ||
667 | if (rmRollback == iRunMode) | ||
668 | iActionType = atCreate; | ||
669 | else | ||
670 | iActionType = atRemove; | ||
671 | |||
672 | // add to action data | ||
673 | hr = AddRoleAssignmentsToActionData(pItm, FALSE, iActionType, COST_ROLLASSIGNMENT_DELETE, ppwzActionData); | ||
674 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
675 | |||
676 | // add progress tics | ||
677 | if (piProgress) | ||
678 | *piProgress += COST_ROLLASSIGNMENT_DELETE * pItm->iRoleAssignmentsUninstallCount; | ||
679 | } | ||
680 | |||
681 | hr = S_OK; | ||
682 | |||
683 | LExit: | ||
684 | return hr; | ||
685 | } | ||
686 | |||
687 | HRESULT CpiGetSubscriptionsCollForComponent( | ||
688 | CPI_ASSEMBLY* pAsm, | ||
689 | CPI_COMPONENT* pComp, | ||
690 | ICatalogCollection** ppiSubsColl | ||
691 | ) | ||
692 | { | ||
693 | HRESULT hr = S_OK; | ||
694 | |||
695 | ICatalogCollection* piCompColl = NULL; | ||
696 | ICatalogObject* piCompObj = NULL; | ||
697 | |||
698 | // get applications collection | ||
699 | if (!pComp->piSubsColl) | ||
700 | { | ||
701 | // get components collection for application | ||
702 | hr = CpiGetComponentsCollForApplication(pAsm->pApplication, &piCompColl); | ||
703 | ExitOnFailure(hr, "Failed to get components collection for application"); | ||
704 | |||
705 | if (S_FALSE == hr) | ||
706 | ExitFunction(); // exit with hr = S_FALSE | ||
707 | |||
708 | // find component object | ||
709 | hr = CpiFindCollectionObject(piCompColl, pComp->wzCLSID, NULL, &piCompObj); | ||
710 | ExitOnFailure(hr, "Failed to find component object"); | ||
711 | |||
712 | if (S_FALSE == hr) | ||
713 | ExitFunction(); // exit with hr = S_FALSE | ||
714 | |||
715 | // get roles collection | ||
716 | hr = CpiGetCatalogCollection(piCompColl, piCompObj, L"SubscriptionsForComponent", &pComp->piSubsColl); | ||
717 | ExitOnFailure(hr, "Failed to get subscriptions collection"); | ||
718 | } | ||
719 | |||
720 | // return value | ||
721 | *ppiSubsColl = pComp->piSubsColl; | ||
722 | (*ppiSubsColl)->AddRef(); | ||
723 | |||
724 | hr = S_OK; | ||
725 | |||
726 | LExit: | ||
727 | // clean up | ||
728 | ReleaseObject(piCompColl); | ||
729 | ReleaseObject(piCompObj); | ||
730 | |||
731 | return hr; | ||
732 | } | ||
733 | |||
734 | |||
735 | // helper function definitions | ||
736 | |||
737 | static HRESULT GetAssemblyName( | ||
738 | LPCWSTR pwzComponent, | ||
739 | LPWSTR* ppwzAssemblyName | ||
740 | ) | ||
741 | { | ||
742 | HRESULT hr = S_OK; | ||
743 | |||
744 | PMSIHANDLE hView, hRecKey, hRec; | ||
745 | |||
746 | LPWSTR pwzKey = NULL; | ||
747 | |||
748 | LPWSTR pwzName = NULL; | ||
749 | LPWSTR pwzVersion = NULL; | ||
750 | LPWSTR pwzCulture = NULL; | ||
751 | LPWSTR pwzPublicKeyToken = NULL; | ||
752 | |||
753 | // create parameter record | ||
754 | hRecKey = ::MsiCreateRecord(1); | ||
755 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
756 | hr = WcaSetRecordString(hRecKey, 1, pwzComponent); | ||
757 | ExitOnFailure(hr, "Failed to set record string"); | ||
758 | |||
759 | // open view | ||
760 | hr = WcaOpenView(vcsMsiAssemblyNameQuery, &hView); | ||
761 | ExitOnFailure(hr, "Failed to open view on MsiAssemblyName table"); | ||
762 | hr = WcaExecuteView(hView, hRecKey); | ||
763 | ExitOnFailure(hr, "Failed to execute view on MsiAssemblyName table"); | ||
764 | |||
765 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
766 | { | ||
767 | // read key | ||
768 | hr = WcaGetRecordString(hRec, manqName, &pwzKey); | ||
769 | ExitOnFailure(hr, "Failed to get name"); | ||
770 | |||
771 | // read value | ||
772 | if (0 == lstrcmpiW(L"name", pwzKey)) | ||
773 | hr = WcaGetRecordString(hRec, manqValue, &pwzName); | ||
774 | else if (0 == lstrcmpiW(L"version", pwzKey)) | ||
775 | hr = WcaGetRecordString(hRec, manqValue, &pwzVersion); | ||
776 | else if (0 == lstrcmpiW(L"culture", pwzKey)) | ||
777 | hr = WcaGetRecordString(hRec, manqValue, &pwzCulture); | ||
778 | else if (0 == lstrcmpiW(L"publicKeyToken", pwzKey)) | ||
779 | hr = WcaGetRecordString(hRec, manqValue, &pwzPublicKeyToken); | ||
780 | else | ||
781 | { | ||
782 | WcaLog(LOGMSG_VERBOSE, "Unknown name in MsiAssemblyName table: %S, %S", pwzComponent, pwzKey); | ||
783 | hr = S_OK; | ||
784 | } | ||
785 | |||
786 | ExitOnFailure(hr, "Failed to get value"); | ||
787 | } | ||
788 | |||
789 | if (E_NOMOREITEMS != hr) | ||
790 | ExitOnFailure(hr, "Failed to fetch record"); | ||
791 | |||
792 | // verify | ||
793 | if (!(pwzName && *pwzName) || !(pwzVersion && *pwzVersion)) | ||
794 | ExitOnFailure(hr = E_FAIL, "Incomplete assembly name"); | ||
795 | |||
796 | // build name string | ||
797 | hr = StrAllocFormatted(ppwzAssemblyName, L"%s, Version=%s, Culture=%s, PublicKeyToken=%s", | ||
798 | pwzName, pwzVersion, | ||
799 | pwzCulture && *pwzCulture ? pwzCulture : L"Neutral", | ||
800 | pwzPublicKeyToken && *pwzPublicKeyToken ? pwzPublicKeyToken : L"null"); | ||
801 | ExitOnFailure(hr, "Failed to build assembly name string"); | ||
802 | |||
803 | hr = S_OK; | ||
804 | |||
805 | LExit: | ||
806 | // clean up | ||
807 | ReleaseStr(pwzKey); | ||
808 | ReleaseStr(pwzName); | ||
809 | ReleaseStr(pwzVersion); | ||
810 | ReleaseStr(pwzCulture); | ||
811 | ReleaseStr(pwzPublicKeyToken); | ||
812 | |||
813 | return hr; | ||
814 | } | ||
815 | |||
816 | static HRESULT KeyPairsRead( | ||
817 | LPCWSTR pwzQuery, | ||
818 | CPI_KEY_PAIR** ppKeyPairList | ||
819 | ) | ||
820 | { | ||
821 | HRESULT hr = S_OK; | ||
822 | |||
823 | PMSIHANDLE hView, hRec; | ||
824 | |||
825 | CPI_KEY_PAIR* pItm = NULL; | ||
826 | LPWSTR pwzData = NULL; | ||
827 | |||
828 | // loop through all dependencies | ||
829 | hr = WcaOpenExecuteView(pwzQuery, &hView); | ||
830 | ExitOnFailure(hr, "Failed to execute view on table"); | ||
831 | |||
832 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
833 | { | ||
834 | // create entry | ||
835 | pItm = (CPI_KEY_PAIR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_KEY_PAIR)); | ||
836 | if (!pItm) | ||
837 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
838 | |||
839 | // get key | ||
840 | hr = WcaGetRecordString(hRec, kpqFirstKey, &pwzData); | ||
841 | ExitOnFailure(hr, "Failed to get first key"); | ||
842 | StringCchCopyW(pItm->wzFirstKey, countof(pItm->wzFirstKey), pwzData); | ||
843 | |||
844 | // get key | ||
845 | hr = WcaGetRecordString(hRec, kpqSecondKey, &pwzData); | ||
846 | ExitOnFailure(hr, "Failed to get second key"); | ||
847 | StringCchCopyW(pItm->wzSecondKey, countof(pItm->wzSecondKey), pwzData); | ||
848 | |||
849 | // add entry | ||
850 | if (*ppKeyPairList) | ||
851 | pItm->pNext = *ppKeyPairList; | ||
852 | *ppKeyPairList = pItm; | ||
853 | pItm = NULL; | ||
854 | } | ||
855 | |||
856 | if (E_NOMOREITEMS == hr) | ||
857 | hr = S_OK; | ||
858 | |||
859 | LExit: | ||
860 | // clean up | ||
861 | if (pItm) | ||
862 | KeyPairsFreeList(pItm); | ||
863 | |||
864 | ReleaseStr(pwzData); | ||
865 | |||
866 | return hr; | ||
867 | } | ||
868 | |||
869 | static HRESULT ModulesRead( | ||
870 | CPI_MODULE_LIST* pModList | ||
871 | ) | ||
872 | { | ||
873 | HRESULT hr = S_OK; | ||
874 | |||
875 | PMSIHANDLE hView, hRec; | ||
876 | |||
877 | CPI_MODULE* pItm = NULL; | ||
878 | LPWSTR pwzData = NULL; | ||
879 | |||
880 | // loop through all modules | ||
881 | hr = WcaOpenExecuteView(vcsModuleQuery, &hView); | ||
882 | ExitOnFailure(hr, "Failed to execute view on ModuleSignature table"); | ||
883 | |||
884 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
885 | { | ||
886 | // create entry | ||
887 | pItm = (CPI_MODULE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_MODULE)); | ||
888 | if (!pItm) | ||
889 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
890 | |||
891 | // get key | ||
892 | hr = WcaGetRecordString(hRec, mqModule, &pwzData); | ||
893 | ExitOnFailure(hr, "Failed to get key"); | ||
894 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
895 | |||
896 | // add entry | ||
897 | if (pModList->pLast) | ||
898 | { | ||
899 | pModList->pLast->pNext = pItm; | ||
900 | pItm->pPrev = pModList->pLast; | ||
901 | } | ||
902 | else | ||
903 | pModList->pFirst = pItm; | ||
904 | pModList->pLast = pItm; | ||
905 | pItm = NULL; | ||
906 | } | ||
907 | |||
908 | if (E_NOMOREITEMS == hr) | ||
909 | hr = S_OK; | ||
910 | |||
911 | LExit: | ||
912 | // clean up | ||
913 | if (pItm) | ||
914 | ModuleFree(pItm); | ||
915 | |||
916 | ReleaseStr(pwzData); | ||
917 | |||
918 | return hr; | ||
919 | } | ||
920 | |||
921 | static HRESULT AssembliesRead( | ||
922 | CPI_KEY_PAIR* pModCompList, | ||
923 | CPI_APPLICATION_LIST* pAppList, | ||
924 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
925 | CPI_ASSEMBLY_LIST* pAsmList | ||
926 | ) | ||
927 | { | ||
928 | HRESULT hr = S_OK; | ||
929 | UINT er = ERROR_SUCCESS; | ||
930 | |||
931 | PMSIHANDLE hView, hRec; | ||
932 | |||
933 | CPI_ASSEMBLY* pItm = NULL; | ||
934 | CPI_KEY_PAIR* pModComp; | ||
935 | LPWSTR pwzData = NULL; | ||
936 | LPWSTR pwzComponent = NULL; | ||
937 | BOOL fMatchingArchitecture = FALSE; | ||
938 | |||
939 | // loop through all assemblies | ||
940 | hr = WcaOpenExecuteView(vcsAssemblyQuery, &hView); | ||
941 | ExitOnFailure(hr, "Failed to execute view on ComPlusAssembly table"); | ||
942 | |||
943 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
944 | { | ||
945 | // get component | ||
946 | hr = WcaGetRecordString(hRec, aqComponent, &pwzComponent); | ||
947 | ExitOnFailure(hr, "Failed to get component"); | ||
948 | |||
949 | // check if the component is our processor architecture | ||
950 | hr = CpiVerifyComponentArchitecure(pwzComponent, &fMatchingArchitecture); | ||
951 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
952 | |||
953 | if (!fMatchingArchitecture) | ||
954 | { | ||
955 | continue; // not the same architecture, ignore | ||
956 | } | ||
957 | |||
958 | // create entry | ||
959 | pItm = (CPI_ASSEMBLY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ASSEMBLY)); | ||
960 | if (!pItm) | ||
961 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
962 | |||
963 | // get component install state | ||
964 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &pItm->isInstalled, &pItm->isAction); | ||
965 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
966 | |||
967 | // get key | ||
968 | hr = WcaGetRecordString(hRec, aqAssembly, &pwzData); | ||
969 | ExitOnFailure(hr, "Failed to get key"); | ||
970 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
971 | |||
972 | // get attributes | ||
973 | hr = WcaGetRecordInteger(hRec, aqAttributes, &pItm->iAttributes); | ||
974 | ExitOnFailure(hr, "Failed to get attributes"); | ||
975 | |||
976 | // get assembly name | ||
977 | hr = WcaGetRecordFormattedString(hRec, aqAssemblyName, &pItm->pwzAssemblyName); | ||
978 | ExitOnFailure(hr, "Failed to get assembly name"); | ||
979 | |||
980 | if (!*pItm->pwzAssemblyName && (pItm->iAttributes & aaPathFromGAC)) | ||
981 | { | ||
982 | // get assembly name for component | ||
983 | hr = GetAssemblyName(pwzComponent, &pItm->pwzAssemblyName); | ||
984 | ExitOnFailure(hr, "Failed to get assembly name for component"); | ||
985 | } | ||
986 | |||
987 | // get dll path | ||
988 | hr = WcaGetRecordFormattedString(hRec, aqDllPath, &pItm->pwzDllPath); | ||
989 | ExitOnFailure(hr, "Failed to get assembly dll path"); | ||
990 | |||
991 | // get module | ||
992 | // TODO: if there is a very large number of components belonging to modules, this search might be slow | ||
993 | hr = KeyPairFindByFirstKey(pModCompList, pwzData, &pModComp); | ||
994 | |||
995 | if (S_OK == hr) | ||
996 | StringCchCopyW(pItm->wzModule, countof(pItm->wzModule), pModComp->wzSecondKey); | ||
997 | |||
998 | // get application | ||
999 | hr = WcaGetRecordString(hRec, aqApplication, &pwzData); | ||
1000 | ExitOnFailure(hr, "Failed to get application"); | ||
1001 | |||
1002 | if (pwzData && *pwzData) | ||
1003 | { | ||
1004 | hr = CpiApplicationFindByKey(pAppList, pwzData, &pItm->pApplication); | ||
1005 | if (S_FALSE == hr) | ||
1006 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1007 | ExitOnFailure(hr, "Failed to find application, key: %S", pwzData); | ||
1008 | } | ||
1009 | |||
1010 | // get tlb path | ||
1011 | hr = WcaGetRecordFormattedString(hRec, aqTlbPath, &pItm->pwzTlbPath); | ||
1012 | ExitOnFailure(hr, "Failed to get assembly tlb path"); | ||
1013 | |||
1014 | // get proxy-stub dll path | ||
1015 | hr = WcaGetRecordFormattedString(hRec, aqPSDllPath, &pItm->pwzPSDllPath); | ||
1016 | ExitOnFailure(hr, "Failed to get assembly proxy-stub DLL path"); | ||
1017 | |||
1018 | // read components | ||
1019 | if (CpiTableExists(cptComPlusComponent)) | ||
1020 | { | ||
1021 | hr = ComponentsRead(pItm->wzKey, pAppRoleList, pItm); | ||
1022 | ExitOnFailure(hr, "Failed to read components for assembly"); | ||
1023 | } | ||
1024 | |||
1025 | // set references & increment counters | ||
1026 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
1027 | { | ||
1028 | pAsmList->iInstallCount++; | ||
1029 | if (pItm->iAttributes & aaRunInCommit) | ||
1030 | pAsmList->iCommitCount++; | ||
1031 | } | ||
1032 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction) || WcaIsReInstalling(pItm->isInstalled, pItm->isAction)) | ||
1033 | pAsmList->iUninstallCount++; | ||
1034 | |||
1035 | if (pItm->iRoleAssignmentsInstallCount) | ||
1036 | { | ||
1037 | pAsmList->iRoleInstallCount++; | ||
1038 | if (pItm->iAttributes & aaRunInCommit) | ||
1039 | pAsmList->iRoleCommitCount++; | ||
1040 | } | ||
1041 | if (pItm->iRoleAssignmentsUninstallCount) | ||
1042 | pAsmList->iRoleUninstallCount++; | ||
1043 | |||
1044 | if (pItm->pApplication) | ||
1045 | { | ||
1046 | if (pItm->iRoleAssignmentsInstallCount || WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
1047 | CpiApplicationAddReferenceInstall(pItm->pApplication); | ||
1048 | if (pItm->iRoleAssignmentsUninstallCount || WcaIsUninstalling(pItm->isInstalled, pItm->isAction) || WcaIsReInstalling(pItm->isInstalled, pItm->isAction)) | ||
1049 | CpiApplicationAddReferenceUninstall(pItm->pApplication); | ||
1050 | } | ||
1051 | |||
1052 | // add entry | ||
1053 | if (pAsmList->pLast) | ||
1054 | { | ||
1055 | pAsmList->pLast->pNext = pItm; | ||
1056 | pItm->pPrev = pAsmList->pLast; | ||
1057 | } | ||
1058 | else | ||
1059 | pAsmList->pFirst = pItm; | ||
1060 | pAsmList->pLast = pItm; | ||
1061 | pItm = NULL; | ||
1062 | } | ||
1063 | |||
1064 | if (E_NOMOREITEMS == hr) | ||
1065 | hr = S_OK; | ||
1066 | |||
1067 | LExit: | ||
1068 | // clean up | ||
1069 | if (pItm) | ||
1070 | AssemblyFree(pItm); | ||
1071 | |||
1072 | ReleaseStr(pwzData); | ||
1073 | ReleaseStr(pwzComponent); | ||
1074 | |||
1075 | return hr; | ||
1076 | } | ||
1077 | |||
1078 | static HRESULT TopSortModuleList( | ||
1079 | CPI_KEY_PAIR* pDepList, | ||
1080 | CPI_MODULE_LIST* pList | ||
1081 | ) | ||
1082 | { | ||
1083 | HRESULT hr = S_OK; | ||
1084 | |||
1085 | // top sort list | ||
1086 | for (CPI_MODULE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
1087 | { | ||
1088 | // append module | ||
1089 | hr = SwapDependentModules(NULL, pDepList, pList, pItm, pItm); | ||
1090 | ExitOnFailure(hr, "Failed to swap dependent modules"); | ||
1091 | } | ||
1092 | |||
1093 | hr = S_OK; | ||
1094 | |||
1095 | LExit: | ||
1096 | return hr; | ||
1097 | } | ||
1098 | |||
1099 | static HRESULT SwapDependentModules( | ||
1100 | CPI_DEPENDENCY_CHAIN* pdcPrev, // list containing the entire dependency chain | ||
1101 | CPI_KEY_PAIR* pDepList, // module dependency list | ||
1102 | CPI_MODULE_LIST* pList, // module list being sorted | ||
1103 | CPI_MODULE* pRoot, // first module in the chain | ||
1104 | CPI_MODULE* pItm // current module to test for dependencies | ||
1105 | ) | ||
1106 | { | ||
1107 | HRESULT hr = S_OK; | ||
1108 | |||
1109 | CPI_MODULE* pDepItm; | ||
1110 | |||
1111 | // find dependencies | ||
1112 | for (CPI_KEY_PAIR* pDep = pDepList; pDep; pDep = pDep->pNext) | ||
1113 | { | ||
1114 | if (0 == lstrcmpW(pItm->wzKey, pDep->wzFirstKey)) | ||
1115 | { | ||
1116 | CPI_DEPENDENCY_CHAIN dcItm; | ||
1117 | dcItm.pwzKey = pItm->wzKey; | ||
1118 | dcItm.pPrev = pdcPrev; | ||
1119 | |||
1120 | // check for circular dependencies | ||
1121 | for (CPI_DEPENDENCY_CHAIN* pdcItm = &dcItm; pdcItm; pdcItm = pdcItm->pPrev) | ||
1122 | { | ||
1123 | if (0 == lstrcmpW(pdcItm->pwzKey, pDep->wzSecondKey)) | ||
1124 | { | ||
1125 | // circular dependency found | ||
1126 | ExitOnFailure(hr = E_FAIL, "Circular module dependency found, key: %S", pDep->wzSecondKey); | ||
1127 | } | ||
1128 | } | ||
1129 | |||
1130 | // make sure the item is not already in the list | ||
1131 | hr = ModuleFindByKey(pRoot->pPrev, pDep->wzSecondKey, TRUE, &pDepItm); // find in reverse order | ||
1132 | |||
1133 | if (S_OK == hr) | ||
1134 | continue; // item found, move on | ||
1135 | |||
1136 | // find item in the list | ||
1137 | hr = ModuleFindByKey(pRoot->pNext, pDep->wzSecondKey, FALSE, &pDepItm); // find in forward order | ||
1138 | |||
1139 | if (S_FALSE == hr) | ||
1140 | { | ||
1141 | // not found | ||
1142 | ExitOnFailure(hr = E_FAIL, "Module dependency not found, key: %S", pDep->wzSecondKey); | ||
1143 | } | ||
1144 | |||
1145 | // if this item in turn has dependencies, they have to be swaped first | ||
1146 | hr = SwapDependentModules(&dcItm, pDepList, pList, pRoot, pDepItm); | ||
1147 | ExitOnFailure(hr, "Failed to swap dependent module"); | ||
1148 | |||
1149 | // remove item from its current position | ||
1150 | pDepItm->pPrev->pNext = pDepItm->pNext; // pDepItm can never be the first item, no need to check pPrev | ||
1151 | if (pDepItm->pNext) | ||
1152 | pDepItm->pNext->pPrev = pDepItm->pPrev; | ||
1153 | else | ||
1154 | { | ||
1155 | pList->pLast = pDepItm->pPrev; | ||
1156 | pList->pLast->pNext = NULL; | ||
1157 | } | ||
1158 | |||
1159 | // insert before the current item | ||
1160 | if (pRoot->pPrev) | ||
1161 | pRoot->pPrev->pNext = pDepItm; | ||
1162 | else | ||
1163 | pList->pFirst = pDepItm; | ||
1164 | pDepItm->pPrev = pRoot->pPrev; | ||
1165 | pRoot->pPrev = pDepItm; | ||
1166 | pDepItm->pNext = pRoot; | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | hr = S_OK; | ||
1171 | |||
1172 | LExit: | ||
1173 | return hr; | ||
1174 | } | ||
1175 | |||
1176 | static HRESULT ModuleFindByKey( | ||
1177 | CPI_MODULE* pItm, | ||
1178 | LPCWSTR pwzKey, | ||
1179 | BOOL fReverse, | ||
1180 | CPI_MODULE** ppItm | ||
1181 | ) | ||
1182 | { | ||
1183 | for (; pItm; pItm = fReverse ? pItm->pPrev : pItm->pNext) | ||
1184 | { | ||
1185 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
1186 | { | ||
1187 | *ppItm = pItm; | ||
1188 | return S_OK; | ||
1189 | } | ||
1190 | } | ||
1191 | |||
1192 | return S_FALSE; | ||
1193 | } | ||
1194 | |||
1195 | static void SortAssemblyListByModule( | ||
1196 | CPI_MODULE_LIST* pModList, | ||
1197 | CPI_ASSEMBLY_LIST* pAsmList | ||
1198 | ) | ||
1199 | { | ||
1200 | CPI_ASSEMBLY* pMoved = NULL; // first moved item | ||
1201 | |||
1202 | // loop modules in reverse order | ||
1203 | for (CPI_MODULE* pMod = pModList->pLast; pMod; pMod = pMod->pPrev) | ||
1204 | { | ||
1205 | // loop assemblies in forward order, starting with the first unmoved item | ||
1206 | CPI_ASSEMBLY* pAsm = pMoved ? pMoved->pNext : pAsmList->pFirst; | ||
1207 | while (pAsm) | ||
1208 | { | ||
1209 | CPI_ASSEMBLY* pNext = pAsm->pNext; | ||
1210 | |||
1211 | // check if assembly belongs to the current module | ||
1212 | if (0 == lstrcmpW(pMod->wzKey, pAsm->wzModule)) | ||
1213 | { | ||
1214 | // if the item is not already first in the list | ||
1215 | if (pAsm->pPrev) | ||
1216 | { | ||
1217 | // remove item from it's current position | ||
1218 | pAsm->pPrev->pNext = pAsm->pNext; | ||
1219 | if (pAsm->pNext) | ||
1220 | pAsm->pNext->pPrev = pAsm->pPrev; | ||
1221 | else | ||
1222 | pAsmList->pLast = pAsm->pPrev; | ||
1223 | |||
1224 | // insert item first in the list | ||
1225 | pAsmList->pFirst->pPrev = pAsm; | ||
1226 | pAsm->pNext = pAsmList->pFirst; | ||
1227 | pAsm->pPrev = NULL; | ||
1228 | pAsmList->pFirst = pAsm; | ||
1229 | } | ||
1230 | |||
1231 | // if we haven't moved any items yet, this is the first moved item | ||
1232 | if (!pMoved) | ||
1233 | pMoved = pAsm; | ||
1234 | } | ||
1235 | |||
1236 | pAsm = pNext; | ||
1237 | } | ||
1238 | } | ||
1239 | } | ||
1240 | |||
1241 | static HRESULT TopSortAssemblyList( | ||
1242 | CPI_KEY_PAIR* pDepList, | ||
1243 | CPI_ASSEMBLY_LIST* pList | ||
1244 | ) | ||
1245 | { | ||
1246 | HRESULT hr = S_OK; | ||
1247 | |||
1248 | // top sort list | ||
1249 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
1250 | { | ||
1251 | // append module | ||
1252 | hr = SwapDependentAssemblies(NULL, pDepList, pList, pItm, pItm); | ||
1253 | ExitOnFailure(hr, "Failed to swap dependent assemblies"); | ||
1254 | } | ||
1255 | |||
1256 | hr = S_OK; | ||
1257 | |||
1258 | LExit: | ||
1259 | return hr; | ||
1260 | } | ||
1261 | |||
1262 | static HRESULT SwapDependentAssemblies( | ||
1263 | CPI_DEPENDENCY_CHAIN* pdcPrev, // list containing the entire dependency chain | ||
1264 | CPI_KEY_PAIR* pDepList, // assembly dependency list | ||
1265 | CPI_ASSEMBLY_LIST* pList, // assembly list being sorted | ||
1266 | CPI_ASSEMBLY* pRoot, // first assembly in the chain | ||
1267 | CPI_ASSEMBLY* pItm // current assembly to test for dependencies | ||
1268 | ) | ||
1269 | { | ||
1270 | HRESULT hr = S_OK; | ||
1271 | |||
1272 | CPI_ASSEMBLY* pDepItm; | ||
1273 | |||
1274 | // find dependencies | ||
1275 | for (CPI_KEY_PAIR* pDep = pDepList; pDep; pDep = pDep->pNext) | ||
1276 | { | ||
1277 | if (0 == lstrcmpW(pItm->wzKey, pDep->wzFirstKey)) | ||
1278 | { | ||
1279 | CPI_DEPENDENCY_CHAIN dcItm; | ||
1280 | dcItm.pwzKey = pItm->wzKey; | ||
1281 | dcItm.pPrev = pdcPrev; | ||
1282 | |||
1283 | // check for circular dependencies | ||
1284 | for (CPI_DEPENDENCY_CHAIN* pdcItm = &dcItm; pdcItm; pdcItm = pdcItm->pPrev) | ||
1285 | { | ||
1286 | if (0 == lstrcmpW(pdcItm->pwzKey, pDep->wzSecondKey)) | ||
1287 | { | ||
1288 | // circular dependency found | ||
1289 | ExitOnFailure(hr = E_FAIL, "Circular assembly dependency found, key: %S", pDep->wzSecondKey); | ||
1290 | } | ||
1291 | } | ||
1292 | |||
1293 | // make sure the item is not already in the list | ||
1294 | hr = AssemblyFindByKey(pRoot->pPrev, pDep->wzSecondKey, TRUE, &pDepItm); // find in reverse order | ||
1295 | |||
1296 | if (S_OK == hr) | ||
1297 | continue; // item found, move on | ||
1298 | |||
1299 | // find item in the list | ||
1300 | hr = AssemblyFindByKey(pRoot->pNext, pDep->wzSecondKey, FALSE, &pDepItm); // find in forward order | ||
1301 | |||
1302 | if (S_FALSE == hr) | ||
1303 | { | ||
1304 | // not found | ||
1305 | ExitOnFailure(hr = E_FAIL, "Assembly dependency not found, key: %S", pDep->wzSecondKey); | ||
1306 | } | ||
1307 | |||
1308 | // if the root item belongs to a module, this item must also belong to the same module | ||
1309 | if (*pItm->wzModule) | ||
1310 | { | ||
1311 | if (0 != lstrcmpW(pDepItm->wzModule, pItm->wzModule)) | ||
1312 | ExitOnFailure(hr = E_FAIL, "An assembly dependency can only exist between two assemblies not belonging to modules, or belonging to the same module. assembly: %S, required assembly: %S", pItm->wzKey, pDepItm->wzKey); | ||
1313 | } | ||
1314 | |||
1315 | // if this item in turn has dependencies, they have to be swaped first | ||
1316 | hr = SwapDependentAssemblies(&dcItm, pDepList, pList, pRoot, pDepItm); | ||
1317 | ExitOnFailure(hr, "Failed to swap dependent assemblies"); | ||
1318 | |||
1319 | // remove item from its current position | ||
1320 | pDepItm->pPrev->pNext = pDepItm->pNext; // pDepItm can never be the first item, no need to check pPrev | ||
1321 | if (pDepItm->pNext) | ||
1322 | pDepItm->pNext->pPrev = pDepItm->pPrev; | ||
1323 | else | ||
1324 | { | ||
1325 | pList->pLast = pDepItm->pPrev; | ||
1326 | pList->pLast->pNext = NULL; | ||
1327 | } | ||
1328 | |||
1329 | // insert before the current item | ||
1330 | if (pRoot->pPrev) | ||
1331 | pRoot->pPrev->pNext = pDepItm; | ||
1332 | else | ||
1333 | pList->pFirst = pDepItm; | ||
1334 | pDepItm->pPrev = pRoot->pPrev; | ||
1335 | pRoot->pPrev = pDepItm; | ||
1336 | pDepItm->pNext = pRoot; | ||
1337 | } | ||
1338 | } | ||
1339 | |||
1340 | hr = S_OK; | ||
1341 | |||
1342 | LExit: | ||
1343 | return hr; | ||
1344 | } | ||
1345 | |||
1346 | static HRESULT AssemblyFindByKey( | ||
1347 | CPI_ASSEMBLY* pItm, | ||
1348 | LPCWSTR pwzKey, | ||
1349 | BOOL fReverse, | ||
1350 | CPI_ASSEMBLY** ppItm | ||
1351 | ) | ||
1352 | { | ||
1353 | for (; pItm; pItm = fReverse ? pItm->pPrev : pItm->pNext) | ||
1354 | { | ||
1355 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
1356 | { | ||
1357 | *ppItm = pItm; | ||
1358 | return S_OK; | ||
1359 | } | ||
1360 | } | ||
1361 | |||
1362 | return S_FALSE; | ||
1363 | } | ||
1364 | |||
1365 | static HRESULT ComponentsRead( | ||
1366 | LPCWSTR pwzAsmKey, | ||
1367 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
1368 | CPI_ASSEMBLY* pAsm | ||
1369 | ) | ||
1370 | { | ||
1371 | HRESULT hr = S_OK; | ||
1372 | PMSIHANDLE hView; | ||
1373 | PMSIHANDLE hRec; | ||
1374 | PMSIHANDLE hRecKey; | ||
1375 | CPI_COMPONENT* pItm = NULL; | ||
1376 | LPWSTR pwzData = NULL; | ||
1377 | |||
1378 | // create parameter record | ||
1379 | hRecKey = ::MsiCreateRecord(1); | ||
1380 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
1381 | hr = WcaSetRecordString(hRecKey, 1, pwzAsmKey); | ||
1382 | ExitOnFailure(hr, "Failed to set record string"); | ||
1383 | |||
1384 | // open view | ||
1385 | hr = WcaOpenView(vcsComponentQuery, &hView); | ||
1386 | ExitOnFailure(hr, "Failed to open view on ComPlusComponent table"); | ||
1387 | hr = WcaExecuteView(hView, hRecKey); | ||
1388 | ExitOnFailure(hr, "Failed to execute view on ComPlusComponent table"); | ||
1389 | |||
1390 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
1391 | { | ||
1392 | // create entry | ||
1393 | pItm = (CPI_COMPONENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_COMPONENT)); | ||
1394 | if (!pItm) | ||
1395 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1396 | |||
1397 | // get key | ||
1398 | hr = WcaGetRecordString(hRec, cqComponent, &pwzData); | ||
1399 | ExitOnFailure(hr, "Failed to get key"); | ||
1400 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
1401 | |||
1402 | // get clsid | ||
1403 | hr = WcaGetRecordFormattedString(hRec, cqCLSID, &pwzData); | ||
1404 | ExitOnFailure(hr, "Failed to get clsid"); | ||
1405 | StringCchCopyW(pItm->wzCLSID, countof(pItm->wzCLSID), pwzData); | ||
1406 | |||
1407 | // read properties | ||
1408 | if (CpiTableExists(cptComPlusComponentProperty)) | ||
1409 | { | ||
1410 | hr = CpiPropertiesRead(vcsComponentPropertyQuery, pItm->wzKey, pdlComponentProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
1411 | ExitOnFailure(hr, "Failed to get component properties"); | ||
1412 | } | ||
1413 | |||
1414 | // read roles | ||
1415 | if (CpiTableExists(cptComPlusRoleForComponent)) | ||
1416 | { | ||
1417 | hr = RoleAssignmentsRead(vcsRoleForComponentQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount); | ||
1418 | ExitOnFailure(hr, "Failed to get roles for component"); | ||
1419 | } | ||
1420 | |||
1421 | if (pItm->iRoleInstallCount) | ||
1422 | pAsm->iRoleAssignmentsInstallCount++; | ||
1423 | if (pItm->iRoleUninstallCount) | ||
1424 | pAsm->iRoleAssignmentsUninstallCount++; | ||
1425 | |||
1426 | // read interfaces | ||
1427 | if (CpiTableExists(cptComPlusInterface)) | ||
1428 | { | ||
1429 | hr = InterfacesRead(pItm->wzKey, pAppRoleList, pAsm, pItm); | ||
1430 | ExitOnFailure(hr, "Failed to get interfaces for component"); | ||
1431 | } | ||
1432 | |||
1433 | // add entry | ||
1434 | pAsm->iComponentCount++; | ||
1435 | if (pAsm->pComponents) | ||
1436 | pItm->pNext = pAsm->pComponents; | ||
1437 | pAsm->pComponents = pItm; | ||
1438 | pItm = NULL; | ||
1439 | } | ||
1440 | |||
1441 | if (E_NOMOREITEMS == hr) | ||
1442 | hr = S_OK; | ||
1443 | |||
1444 | LExit: | ||
1445 | // clean up | ||
1446 | if (pItm) | ||
1447 | ComponentsFreeList(pItm); | ||
1448 | |||
1449 | ReleaseStr(pwzData); | ||
1450 | |||
1451 | return hr; | ||
1452 | } | ||
1453 | |||
1454 | static HRESULT InterfacesRead( | ||
1455 | LPCWSTR pwzCompKey, | ||
1456 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
1457 | CPI_ASSEMBLY* pAsm, | ||
1458 | CPI_COMPONENT* pComp | ||
1459 | ) | ||
1460 | { | ||
1461 | HRESULT hr = S_OK; | ||
1462 | PMSIHANDLE hView; | ||
1463 | PMSIHANDLE hRec; | ||
1464 | PMSIHANDLE hRecKey; | ||
1465 | CPI_INTERFACE* pItm = NULL; | ||
1466 | LPWSTR pwzData = NULL; | ||
1467 | |||
1468 | // create parameter record | ||
1469 | hRecKey = ::MsiCreateRecord(1); | ||
1470 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
1471 | hr = WcaSetRecordString(hRecKey, 1, pwzCompKey); | ||
1472 | ExitOnFailure(hr, "Failed to set record string"); | ||
1473 | |||
1474 | // open view | ||
1475 | hr = WcaOpenView(vcsInterfaceQuery, &hView); | ||
1476 | ExitOnFailure(hr, "Failed to open view on ComPlusInterface table"); | ||
1477 | hr = WcaExecuteView(hView, hRecKey); | ||
1478 | ExitOnFailure(hr, "Failed to execute view on ComPlusInterface table"); | ||
1479 | |||
1480 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
1481 | { | ||
1482 | // create entry | ||
1483 | pItm = (CPI_INTERFACE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_INTERFACE)); | ||
1484 | if (!pItm) | ||
1485 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1486 | |||
1487 | // get key | ||
1488 | hr = WcaGetRecordString(hRec, iqInterface, &pwzData); | ||
1489 | ExitOnFailure(hr, "Failed to get key"); | ||
1490 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
1491 | |||
1492 | // get iid | ||
1493 | hr = WcaGetRecordFormattedString(hRec, iqIID, &pwzData); | ||
1494 | ExitOnFailure(hr, "Failed to get iid"); | ||
1495 | StringCchCopyW(pItm->wzIID, countof(pItm->wzIID), pwzData); | ||
1496 | |||
1497 | // read properties | ||
1498 | if (CpiTableExists(cptComPlusInterfaceProperty)) | ||
1499 | { | ||
1500 | hr = CpiPropertiesRead(vcsInterfacePropertyQuery, pItm->wzKey, pdlInterfaceProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
1501 | ExitOnFailure(hr, "Failed to get interface properties"); | ||
1502 | } | ||
1503 | |||
1504 | // read roles | ||
1505 | if (CpiTableExists(cptComPlusRoleForInterface)) | ||
1506 | { | ||
1507 | hr = RoleAssignmentsRead(vcsRoleForInterfaceQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount); | ||
1508 | ExitOnFailure(hr, "Failed to get roles for interface"); | ||
1509 | } | ||
1510 | |||
1511 | if (pItm->iRoleInstallCount) | ||
1512 | pAsm->iRoleAssignmentsInstallCount++; | ||
1513 | if (pItm->iRoleUninstallCount) | ||
1514 | pAsm->iRoleAssignmentsUninstallCount++; | ||
1515 | |||
1516 | // read methods | ||
1517 | if (CpiTableExists(cptComPlusMethod)) | ||
1518 | { | ||
1519 | hr = MethodsRead(pItm->wzKey, pAppRoleList, pAsm, pItm); | ||
1520 | ExitOnFailure(hr, "Failed to get methods for interface"); | ||
1521 | } | ||
1522 | |||
1523 | // add entry | ||
1524 | pComp->iInterfaceCount++; | ||
1525 | if (pComp->pInterfaces) | ||
1526 | pItm->pNext = pComp->pInterfaces; | ||
1527 | pComp->pInterfaces = pItm; | ||
1528 | pItm = NULL; | ||
1529 | } | ||
1530 | |||
1531 | if (E_NOMOREITEMS == hr) | ||
1532 | hr = S_OK; | ||
1533 | |||
1534 | LExit: | ||
1535 | // clean up | ||
1536 | if (pItm) | ||
1537 | InterfacesFreeList(pItm); | ||
1538 | |||
1539 | ReleaseStr(pwzData); | ||
1540 | |||
1541 | return hr; | ||
1542 | } | ||
1543 | |||
1544 | static HRESULT MethodsRead( | ||
1545 | LPCWSTR pwzIntfKey, | ||
1546 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
1547 | CPI_ASSEMBLY* pAsm, | ||
1548 | CPI_INTERFACE* pIntf | ||
1549 | ) | ||
1550 | { | ||
1551 | HRESULT hr = S_OK; | ||
1552 | PMSIHANDLE hView, hRec, hRecKey; | ||
1553 | CPI_METHOD* pItm = NULL; | ||
1554 | LPWSTR pwzData = NULL; | ||
1555 | |||
1556 | // create parameter record | ||
1557 | hRecKey = ::MsiCreateRecord(1); | ||
1558 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
1559 | hr = WcaSetRecordString(hRecKey, 1, pwzIntfKey); | ||
1560 | ExitOnFailure(hr, "Failed to set record string"); | ||
1561 | |||
1562 | // open view | ||
1563 | hr = WcaOpenView(vcsMethodQuery, &hView); | ||
1564 | ExitOnFailure(hr, "Failed to open view on ComPlusMethod table"); | ||
1565 | hr = WcaExecuteView(hView, hRecKey); | ||
1566 | ExitOnFailure(hr, "Failed to execute view on ComPlusMethod table"); | ||
1567 | |||
1568 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
1569 | { | ||
1570 | // create entry | ||
1571 | pItm = (CPI_METHOD*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_METHOD)); | ||
1572 | if (!pItm) | ||
1573 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1574 | |||
1575 | // get key | ||
1576 | hr = WcaGetRecordString(hRec, iqInterface, &pwzData); | ||
1577 | ExitOnFailure(hr, "Failed to get key"); | ||
1578 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
1579 | |||
1580 | // get index | ||
1581 | hr = WcaGetRecordFormattedString(hRec, mqIndex, &pwzData); | ||
1582 | ExitOnFailure(hr, "Failed to get index"); | ||
1583 | StringCchCopyW(pItm->wzIndex, countof(pItm->wzIndex), pwzData); | ||
1584 | |||
1585 | // get name | ||
1586 | hr = WcaGetRecordFormattedString(hRec, mqName, &pwzData); | ||
1587 | ExitOnFailure(hr, "Failed to get name"); | ||
1588 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
1589 | |||
1590 | // either an index or a name must be provided | ||
1591 | if (!*pItm->wzIndex && !*pItm->wzName) | ||
1592 | ExitOnFailure(hr = E_FAIL, "A method must have either an index or a name associated, key: %S", pItm->wzKey); | ||
1593 | |||
1594 | // read properties | ||
1595 | if (CpiTableExists(cptComPlusMethodProperty)) | ||
1596 | { | ||
1597 | hr = CpiPropertiesRead(vcsMethodPropertyQuery, pItm->wzKey, pdlMethodProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
1598 | ExitOnFailure(hr, "Failed to get method properties"); | ||
1599 | } | ||
1600 | |||
1601 | // read roles | ||
1602 | if (CpiTableExists(cptComPlusRoleForMethod)) | ||
1603 | { | ||
1604 | hr = RoleAssignmentsRead(vcsRoleForMethodQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount); | ||
1605 | ExitOnFailure(hr, "Failed to get roles for method"); | ||
1606 | } | ||
1607 | |||
1608 | if (pItm->iRoleInstallCount) | ||
1609 | pAsm->iRoleAssignmentsInstallCount++; | ||
1610 | if (pItm->iRoleUninstallCount) | ||
1611 | pAsm->iRoleAssignmentsUninstallCount++; | ||
1612 | |||
1613 | // add entry | ||
1614 | pIntf->iMethodCount++; | ||
1615 | if (pIntf->pMethods) | ||
1616 | pItm->pNext = pIntf->pMethods; | ||
1617 | pIntf->pMethods = pItm; | ||
1618 | pItm = NULL; | ||
1619 | } | ||
1620 | |||
1621 | if (E_NOMOREITEMS == hr) | ||
1622 | hr = S_OK; | ||
1623 | |||
1624 | LExit: | ||
1625 | // clean up | ||
1626 | if (pItm) | ||
1627 | MethodsFreeList(pItm); | ||
1628 | |||
1629 | ReleaseStr(pwzData); | ||
1630 | |||
1631 | return hr; | ||
1632 | } | ||
1633 | |||
1634 | static HRESULT RoleAssignmentsRead( | ||
1635 | LPCWSTR pwzQuery, | ||
1636 | LPCWSTR pwzKey, | ||
1637 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
1638 | CPI_ROLE_ASSIGNMENT** ppRoleList, | ||
1639 | int* piInstallCount, | ||
1640 | int* piUninstallCount | ||
1641 | ) | ||
1642 | { | ||
1643 | HRESULT hr = S_OK; | ||
1644 | UINT er = ERROR_SUCCESS; | ||
1645 | |||
1646 | PMSIHANDLE hView, hRec, hRecKey; | ||
1647 | |||
1648 | CPI_ROLE_ASSIGNMENT* pItm = NULL; | ||
1649 | LPWSTR pwzData = NULL; | ||
1650 | BOOL fMatchingArchitecture = FALSE; | ||
1651 | |||
1652 | // create parameter record | ||
1653 | hRecKey = ::MsiCreateRecord(1); | ||
1654 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
1655 | hr = WcaSetRecordString(hRecKey, 1, pwzKey); | ||
1656 | ExitOnFailure(hr, "Failed to set record string"); | ||
1657 | |||
1658 | // open view | ||
1659 | hr = WcaOpenView(pwzQuery, &hView); | ||
1660 | ExitOnFailure(hr, "Failed to open view on role assignment table"); | ||
1661 | hr = WcaExecuteView(hView, hRecKey); | ||
1662 | ExitOnFailure(hr, "Failed to execute view on role assignment table"); | ||
1663 | |||
1664 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
1665 | { | ||
1666 | // get component | ||
1667 | hr = WcaGetRecordString(hRec, raqComponent, &pwzData); | ||
1668 | ExitOnFailure(hr, "Failed to get assembly component"); | ||
1669 | |||
1670 | // check if the component is our processor architecture | ||
1671 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
1672 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
1673 | |||
1674 | if (!fMatchingArchitecture) | ||
1675 | { | ||
1676 | continue; // not the same architecture, ignore | ||
1677 | } | ||
1678 | |||
1679 | // create entry | ||
1680 | pItm = (CPI_ROLE_ASSIGNMENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLE_ASSIGNMENT)); | ||
1681 | if (!pItm) | ||
1682 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1683 | |||
1684 | // get component install state | ||
1685 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
1686 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
1687 | |||
1688 | // get key | ||
1689 | hr = WcaGetRecordString(hRec, raqKey, &pwzData); | ||
1690 | ExitOnFailure(hr, "Failed to get key"); | ||
1691 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
1692 | |||
1693 | // get application role | ||
1694 | hr = WcaGetRecordString(hRec, raqApplicationRole, &pwzData); | ||
1695 | ExitOnFailure(hr, "Failed to get application role"); | ||
1696 | |||
1697 | hr = CpiApplicationRoleFindByKey(pAppRoleList, pwzData, &pItm->pApplicationRole); | ||
1698 | if (S_FALSE == hr) | ||
1699 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
1700 | ExitOnFailure(hr, "Failed to find application, key: %S", pwzData); | ||
1701 | |||
1702 | // set references & increment counters | ||
1703 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
1704 | { | ||
1705 | CpiApplicationRoleAddReferenceInstall(pItm->pApplicationRole); | ||
1706 | ++*piInstallCount; | ||
1707 | } | ||
1708 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
1709 | { | ||
1710 | CpiApplicationRoleAddReferenceUninstall(pItm->pApplicationRole); | ||
1711 | ++*piUninstallCount; | ||
1712 | } | ||
1713 | |||
1714 | // add entry | ||
1715 | if (*ppRoleList) | ||
1716 | pItm->pNext = *ppRoleList; | ||
1717 | *ppRoleList = pItm; | ||
1718 | pItm = NULL; | ||
1719 | } | ||
1720 | |||
1721 | if (E_NOMOREITEMS == hr) | ||
1722 | hr = S_OK; | ||
1723 | |||
1724 | LExit: | ||
1725 | // clean up | ||
1726 | if (pItm) | ||
1727 | RoleAssignmentsFreeList(pItm); | ||
1728 | |||
1729 | ReleaseStr(pwzData); | ||
1730 | |||
1731 | return hr; | ||
1732 | } | ||
1733 | |||
1734 | static HRESULT AddAssemblyToActionData( | ||
1735 | CPI_ASSEMBLY* pItm, | ||
1736 | BOOL fInstall, | ||
1737 | int iActionType, | ||
1738 | int iActionCost, | ||
1739 | LPWSTR* ppwzActionData | ||
1740 | ) | ||
1741 | { | ||
1742 | HRESULT hr = S_OK; | ||
1743 | |||
1744 | // add action information to custom action data | ||
1745 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
1746 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
1747 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
1748 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
1749 | |||
1750 | // add assembly information to custom action data | ||
1751 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
1752 | ExitOnFailure(hr, "Failed to add assembly key to custom action data"); | ||
1753 | hr = WcaWriteStringToCaData(pItm->pwzAssemblyName, ppwzActionData); | ||
1754 | ExitOnFailure(hr, "Failed to add assembly name to custom action data"); | ||
1755 | hr = WcaWriteStringToCaData(pItm->pwzDllPath, ppwzActionData); | ||
1756 | ExitOnFailure(hr, "Failed to add assembly dll path to custom action data"); | ||
1757 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pwzTlbPath : L"", ppwzActionData); | ||
1758 | ExitOnFailure(hr, "Failed to add assembly tlb path to custom action data"); | ||
1759 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pwzPSDllPath : L"", ppwzActionData); | ||
1760 | ExitOnFailure(hr, "Failed to add assembly proxy-stub dll path to custom action data"); | ||
1761 | hr = WcaWriteIntegerToCaData(pItm->iAttributes, ppwzActionData); | ||
1762 | ExitOnFailure(hr, "Failed to add assembly attributes to custom action data"); | ||
1763 | |||
1764 | // add application information to custom action data | ||
1765 | hr = WcaWriteStringToCaData(pItm->pApplication ? pItm->pApplication->wzID : L"", ppwzActionData); | ||
1766 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
1767 | |||
1768 | // add partition information to custom action data | ||
1769 | LPCWSTR pwzPartID = pItm->pApplication && pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L""; | ||
1770 | hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData); | ||
1771 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
1772 | |||
1773 | // add components to custom action data | ||
1774 | // | ||
1775 | // components are needed acording to the following table: | ||
1776 | // | ||
1777 | // Native .NET | ||
1778 | // -------------------------------------------- | ||
1779 | // NoOp | No | No | ||
1780 | // Create | Yes | Yes | ||
1781 | // Remove | Yes | No | ||
1782 | // | ||
1783 | int iCompCount = (atCreate == iActionType || (atRemove == iActionType && 0 == (pItm->iAttributes & aaDotNetAssembly))) ? pItm->iComponentCount : 0; | ||
1784 | hr = WcaWriteIntegerToCaData(iCompCount, ppwzActionData); | ||
1785 | ExitOnFailure(hr, "Failed to add component count to custom action data, key: %S", pItm->wzKey); | ||
1786 | |||
1787 | if (iCompCount) | ||
1788 | { | ||
1789 | for (CPI_COMPONENT* pComp = pItm->pComponents; pComp; pComp = pComp->pNext) | ||
1790 | { | ||
1791 | hr = AddComponentToActionData(pComp, fInstall, atCreate == iActionType, FALSE, ppwzActionData); | ||
1792 | ExitOnFailure(hr, "Failed to add component to custom action data, component: %S", pComp->wzKey); | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | hr = S_OK; | ||
1797 | |||
1798 | LExit: | ||
1799 | return hr; | ||
1800 | } | ||
1801 | |||
1802 | static HRESULT AddRoleAssignmentsToActionData( | ||
1803 | CPI_ASSEMBLY* pItm, | ||
1804 | BOOL fInstall, | ||
1805 | int iActionType, | ||
1806 | int iActionCost, | ||
1807 | LPWSTR* ppwzActionData | ||
1808 | ) | ||
1809 | { | ||
1810 | HRESULT hr = S_OK; | ||
1811 | |||
1812 | // add action information to custom action data | ||
1813 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
1814 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
1815 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
1816 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
1817 | |||
1818 | // add assembly information to custom action data | ||
1819 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
1820 | ExitOnFailure(hr, "Failed to add assembly key to custom action data"); | ||
1821 | hr = WcaWriteIntegerToCaData(fInstall ? pItm->iRoleAssignmentsInstallCount : pItm->iRoleAssignmentsUninstallCount, ppwzActionData); | ||
1822 | ExitOnFailure(hr, "Failed to add role assignments count to custom action data"); | ||
1823 | |||
1824 | // add application information to custom action data | ||
1825 | hr = WcaWriteStringToCaData(pItm->pApplication ? pItm->pApplication->wzID : L"", ppwzActionData); | ||
1826 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
1827 | |||
1828 | // add partition information to custom action data | ||
1829 | LPCWSTR pwzPartID = pItm->pApplication && pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L""; | ||
1830 | hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData); | ||
1831 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
1832 | |||
1833 | // add components to custom action data | ||
1834 | hr = WcaWriteIntegerToCaData(pItm->iComponentCount, ppwzActionData); | ||
1835 | ExitOnFailure(hr, "Failed to add component count to custom action data"); | ||
1836 | |||
1837 | for (CPI_COMPONENT* pComp = pItm->pComponents; pComp; pComp = pComp->pNext) | ||
1838 | { | ||
1839 | hr = AddComponentToActionData(pComp, fInstall, FALSE, TRUE, ppwzActionData); | ||
1840 | ExitOnFailure(hr, "Failed to add component to custom action data, component: %S", pComp->wzKey); | ||
1841 | } | ||
1842 | |||
1843 | hr = S_OK; | ||
1844 | |||
1845 | LExit: | ||
1846 | return hr; | ||
1847 | } | ||
1848 | |||
1849 | static HRESULT AddComponentToActionData( | ||
1850 | CPI_COMPONENT* pItm, | ||
1851 | BOOL fInstall, | ||
1852 | BOOL fProps, | ||
1853 | BOOL fRoles, | ||
1854 | LPWSTR* ppwzActionData | ||
1855 | ) | ||
1856 | { | ||
1857 | HRESULT hr = S_OK; | ||
1858 | |||
1859 | // add component information to custom action data | ||
1860 | hr = WcaWriteStringToCaData(pItm->wzCLSID, ppwzActionData); | ||
1861 | ExitOnFailure(hr, "Failed to add component CLSID to custom action data"); | ||
1862 | |||
1863 | // add properties to custom action data | ||
1864 | hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
1865 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
1866 | |||
1867 | // add roles to custom action data | ||
1868 | hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData); | ||
1869 | ExitOnFailure(hr, "Failed to add roles to custom action data"); | ||
1870 | |||
1871 | // add interfaces to custom action data | ||
1872 | int iIntfCount = (fProps || fRoles) ? pItm->iInterfaceCount : 0; | ||
1873 | hr = WcaWriteIntegerToCaData(iIntfCount, ppwzActionData); | ||
1874 | ExitOnFailure(hr, "Failed to add interface count to custom action data"); | ||
1875 | |||
1876 | if (iIntfCount) | ||
1877 | { | ||
1878 | for (CPI_INTERFACE* pIntf = pItm->pInterfaces; pIntf; pIntf = pIntf->pNext) | ||
1879 | { | ||
1880 | hr = AddInterfaceToActionData(pIntf, fInstall, fProps, fRoles, ppwzActionData); | ||
1881 | ExitOnFailure(hr, "Failed to add interface custom action data, interface: %S", pIntf->wzKey); | ||
1882 | } | ||
1883 | } | ||
1884 | |||
1885 | hr = S_OK; | ||
1886 | |||
1887 | LExit: | ||
1888 | return hr; | ||
1889 | } | ||
1890 | |||
1891 | static HRESULT AddInterfaceToActionData( | ||
1892 | CPI_INTERFACE* pItm, | ||
1893 | BOOL fInstall, | ||
1894 | BOOL fProps, | ||
1895 | BOOL fRoles, | ||
1896 | LPWSTR* ppwzActionData | ||
1897 | ) | ||
1898 | { | ||
1899 | HRESULT hr = S_OK; | ||
1900 | |||
1901 | // add interface information to custom action data | ||
1902 | hr = WcaWriteStringToCaData(pItm->wzIID, ppwzActionData); | ||
1903 | ExitOnFailure(hr, "Failed to add interface IID to custom action data"); | ||
1904 | |||
1905 | // add properties to custom action data | ||
1906 | hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
1907 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
1908 | |||
1909 | // add roles to custom action data | ||
1910 | hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData); | ||
1911 | ExitOnFailure(hr, "Failed to add roles to custom action data"); | ||
1912 | |||
1913 | // add methods to custom action data | ||
1914 | hr = WcaWriteIntegerToCaData(pItm->iMethodCount, ppwzActionData); | ||
1915 | ExitOnFailure(hr, "Failed to add method count to custom action data"); | ||
1916 | |||
1917 | for (CPI_METHOD* pMeth = pItm->pMethods; pMeth; pMeth = pMeth->pNext) | ||
1918 | { | ||
1919 | hr = AddMethodToActionData(pMeth, fInstall, fProps, fRoles, ppwzActionData); | ||
1920 | ExitOnFailure(hr, "Failed to add method custom action data, method: %S", pMeth->wzKey); | ||
1921 | } | ||
1922 | |||
1923 | hr = S_OK; | ||
1924 | |||
1925 | LExit: | ||
1926 | return hr; | ||
1927 | } | ||
1928 | |||
1929 | static HRESULT AddMethodToActionData( | ||
1930 | CPI_METHOD* pItm, | ||
1931 | BOOL fInstall, | ||
1932 | BOOL fProps, | ||
1933 | BOOL fRoles, | ||
1934 | LPWSTR* ppwzActionData | ||
1935 | ) | ||
1936 | { | ||
1937 | HRESULT hr = S_OK; | ||
1938 | |||
1939 | // add interface information to custom action data | ||
1940 | hr = WcaWriteStringToCaData(pItm->wzIndex, ppwzActionData); | ||
1941 | ExitOnFailure(hr, "Failed to add method index to custom action data"); | ||
1942 | |||
1943 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
1944 | ExitOnFailure(hr, "Failed to add method name to custom action data"); | ||
1945 | |||
1946 | // add properties to custom action data | ||
1947 | hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
1948 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
1949 | |||
1950 | // add roles to custom action data | ||
1951 | hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData); | ||
1952 | ExitOnFailure(hr, "Failed to add roles to custom action data"); | ||
1953 | |||
1954 | hr = S_OK; | ||
1955 | |||
1956 | LExit: | ||
1957 | return hr; | ||
1958 | } | ||
1959 | |||
1960 | static HRESULT AddRolesToActionData( | ||
1961 | int iRoleInstallCount, | ||
1962 | int iRoleUninstallCount, | ||
1963 | CPI_ROLE_ASSIGNMENT* pRoleList, | ||
1964 | BOOL fInstall, | ||
1965 | BOOL fRoles, | ||
1966 | LPWSTR* ppwzActionData | ||
1967 | ) | ||
1968 | { | ||
1969 | HRESULT hr = S_OK; | ||
1970 | |||
1971 | int iRoleCount = fRoles ? (fInstall ? iRoleInstallCount : iRoleUninstallCount) : 0; | ||
1972 | hr = WcaWriteIntegerToCaData(iRoleCount, ppwzActionData); | ||
1973 | ExitOnFailure(hr, "Failed to add role count to custom action data"); | ||
1974 | |||
1975 | if (iRoleCount) | ||
1976 | { | ||
1977 | for (CPI_ROLE_ASSIGNMENT* pRole = pRoleList; pRole; pRole = pRole->pNext) | ||
1978 | { | ||
1979 | // make sure the install state matches the create flag | ||
1980 | if (fInstall ? !WcaIsInstalling(pRole->isInstalled, pRole->isAction) : !WcaIsUninstalling(pRole->isInstalled, pRole->isAction)) | ||
1981 | continue; | ||
1982 | |||
1983 | hr = WcaWriteStringToCaData(pRole->pApplicationRole->wzKey, ppwzActionData); | ||
1984 | ExitOnFailure(hr, "Failed to add key to custom action data, role: %S", pRole->wzKey); | ||
1985 | |||
1986 | hr = WcaWriteStringToCaData(pRole->pApplicationRole->wzName, ppwzActionData); | ||
1987 | ExitOnFailure(hr, "Failed to add role name to custom action data, role: %S", pRole->wzKey); | ||
1988 | } | ||
1989 | } | ||
1990 | |||
1991 | hr = S_OK; | ||
1992 | |||
1993 | LExit: | ||
1994 | return hr; | ||
1995 | } | ||
1996 | |||
1997 | static HRESULT KeyPairFindByFirstKey( | ||
1998 | CPI_KEY_PAIR* pList, | ||
1999 | LPCWSTR pwzKey, | ||
2000 | CPI_KEY_PAIR** ppItm | ||
2001 | ) | ||
2002 | { | ||
2003 | for (; pList; pList = pList->pNext) | ||
2004 | { | ||
2005 | if (0 == lstrcmpW(pList->wzFirstKey, pwzKey)) | ||
2006 | { | ||
2007 | *ppItm = pList; | ||
2008 | return S_OK; | ||
2009 | } | ||
2010 | } | ||
2011 | |||
2012 | return S_FALSE; | ||
2013 | } | ||
2014 | |||
2015 | static void AssemblyFree( | ||
2016 | CPI_ASSEMBLY* pItm | ||
2017 | ) | ||
2018 | { | ||
2019 | ReleaseStr(pItm->pwzAssemblyName); | ||
2020 | ReleaseStr(pItm->pwzDllPath); | ||
2021 | ReleaseStr(pItm->pwzTlbPath); | ||
2022 | ReleaseStr(pItm->pwzPSDllPath); | ||
2023 | |||
2024 | if (pItm->pComponents) | ||
2025 | ComponentsFreeList(pItm->pComponents); | ||
2026 | |||
2027 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
2028 | } | ||
2029 | |||
2030 | static void KeyPairsFreeList( | ||
2031 | CPI_KEY_PAIR* pList | ||
2032 | ) | ||
2033 | { | ||
2034 | while (pList) | ||
2035 | { | ||
2036 | CPI_KEY_PAIR* pDelete = pList; | ||
2037 | pList = pList->pNext; | ||
2038 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
2039 | } | ||
2040 | } | ||
2041 | |||
2042 | void ModuleListFree( | ||
2043 | CPI_MODULE_LIST* pList | ||
2044 | ) | ||
2045 | { | ||
2046 | CPI_MODULE* pItm = pList->pFirst; | ||
2047 | |||
2048 | while (pItm) | ||
2049 | { | ||
2050 | CPI_MODULE* pDelete = pItm; | ||
2051 | pItm = pItm->pNext; | ||
2052 | ModuleFree(pDelete); | ||
2053 | } | ||
2054 | } | ||
2055 | |||
2056 | static void ModuleFree( | ||
2057 | CPI_MODULE* pItm | ||
2058 | ) | ||
2059 | { | ||
2060 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
2061 | } | ||
2062 | |||
2063 | static void ComponentsFreeList( | ||
2064 | CPI_COMPONENT* pList | ||
2065 | ) | ||
2066 | { | ||
2067 | while (pList) | ||
2068 | { | ||
2069 | if (pList->pProperties) | ||
2070 | CpiPropertiesFreeList(pList->pProperties); | ||
2071 | |||
2072 | if (pList->pRoles) | ||
2073 | RoleAssignmentsFreeList(pList->pRoles); | ||
2074 | |||
2075 | if (pList->pInterfaces) | ||
2076 | InterfacesFreeList(pList->pInterfaces); | ||
2077 | |||
2078 | ReleaseObject(pList->piSubsColl); | ||
2079 | |||
2080 | CPI_COMPONENT* pDelete = pList; | ||
2081 | pList = pList->pNext; | ||
2082 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
2083 | } | ||
2084 | } | ||
2085 | |||
2086 | static void InterfacesFreeList( | ||
2087 | CPI_INTERFACE* pList | ||
2088 | ) | ||
2089 | { | ||
2090 | while (pList) | ||
2091 | { | ||
2092 | if (pList->pProperties) | ||
2093 | CpiPropertiesFreeList(pList->pProperties); | ||
2094 | |||
2095 | if (pList->pRoles) | ||
2096 | RoleAssignmentsFreeList(pList->pRoles); | ||
2097 | |||
2098 | if (pList->pMethods) | ||
2099 | MethodsFreeList(pList->pMethods); | ||
2100 | |||
2101 | CPI_INTERFACE* pDelete = pList; | ||
2102 | pList = pList->pNext; | ||
2103 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
2104 | } | ||
2105 | } | ||
2106 | |||
2107 | static void MethodsFreeList( | ||
2108 | CPI_METHOD* pList | ||
2109 | ) | ||
2110 | { | ||
2111 | while (pList) | ||
2112 | { | ||
2113 | if (pList->pProperties) | ||
2114 | CpiPropertiesFreeList(pList->pProperties); | ||
2115 | |||
2116 | if (pList->pRoles) | ||
2117 | RoleAssignmentsFreeList(pList->pRoles); | ||
2118 | |||
2119 | CPI_METHOD* pDelete = pList; | ||
2120 | pList = pList->pNext; | ||
2121 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
2122 | } | ||
2123 | } | ||
2124 | |||
2125 | static void RoleAssignmentsFreeList( | ||
2126 | CPI_ROLE_ASSIGNMENT* pList | ||
2127 | ) | ||
2128 | { | ||
2129 | while (pList) | ||
2130 | { | ||
2131 | CPI_ROLE_ASSIGNMENT* pDelete = pList; | ||
2132 | pList = pList->pNext; | ||
2133 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
2134 | } | ||
2135 | } | ||
diff --git a/src/ca/cpasmsched.h b/src/ca/cpasmsched.h new file mode 100644 index 00000000..b5a68d7e --- /dev/null +++ b/src/ca/cpasmsched.h | |||
@@ -0,0 +1,168 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | enum eAssemblyAttributes | ||
6 | { | ||
7 | aaEventClass = (1 << 0), | ||
8 | aaDotNetAssembly = (1 << 1), | ||
9 | aaPathFromGAC = (1 << 2), | ||
10 | aaRunInCommit = (1 << 3) | ||
11 | }; | ||
12 | |||
13 | |||
14 | // structs | ||
15 | |||
16 | struct CPI_ROLE_ASSIGNMENT | ||
17 | { | ||
18 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
19 | |||
20 | INSTALLSTATE isInstalled, isAction; | ||
21 | |||
22 | CPI_APPLICATION_ROLE* pApplicationRole; | ||
23 | |||
24 | CPI_ROLE_ASSIGNMENT* pNext; | ||
25 | }; | ||
26 | |||
27 | struct CPI_METHOD | ||
28 | { | ||
29 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
30 | WCHAR wzIndex[11 + 1]; | ||
31 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
32 | |||
33 | int iPropertyCount; | ||
34 | CPI_PROPERTY* pProperties; | ||
35 | |||
36 | int iRoleInstallCount; | ||
37 | int iRoleUninstallCount; | ||
38 | CPI_ROLE_ASSIGNMENT* pRoles; | ||
39 | |||
40 | CPI_METHOD* pNext; | ||
41 | }; | ||
42 | |||
43 | struct CPI_INTERFACE | ||
44 | { | ||
45 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
46 | WCHAR wzIID[CPI_MAX_GUID + 1]; | ||
47 | |||
48 | int iPropertyCount; | ||
49 | CPI_PROPERTY* pProperties; | ||
50 | |||
51 | int iRoleInstallCount; | ||
52 | int iRoleUninstallCount; | ||
53 | CPI_ROLE_ASSIGNMENT* pRoles; | ||
54 | |||
55 | int iMethodCount; | ||
56 | CPI_METHOD* pMethods; | ||
57 | |||
58 | CPI_INTERFACE* pNext; | ||
59 | }; | ||
60 | |||
61 | struct CPI_COMPONENT | ||
62 | { | ||
63 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
64 | WCHAR wzCLSID[CPI_MAX_GUID + 1]; | ||
65 | |||
66 | int iPropertyCount; | ||
67 | CPI_PROPERTY* pProperties; | ||
68 | |||
69 | int iRoleInstallCount; | ||
70 | int iRoleUninstallCount; | ||
71 | CPI_ROLE_ASSIGNMENT* pRoles; | ||
72 | |||
73 | int iInterfaceCount; | ||
74 | CPI_INTERFACE* pInterfaces; | ||
75 | |||
76 | ICatalogCollection* piSubsColl; | ||
77 | |||
78 | CPI_COMPONENT* pNext; | ||
79 | }; | ||
80 | |||
81 | struct CPI_ASSEMBLY | ||
82 | { | ||
83 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
84 | WCHAR wzModule[MAX_DARWIN_KEY + 1]; | ||
85 | LPWSTR pwzAssemblyName; | ||
86 | LPWSTR pwzDllPath; | ||
87 | LPWSTR pwzTlbPath; | ||
88 | LPWSTR pwzPSDllPath; | ||
89 | int iAttributes; | ||
90 | |||
91 | int iComponentCount; | ||
92 | CPI_COMPONENT* pComponents; | ||
93 | |||
94 | BOOL fReferencedForInstall; | ||
95 | BOOL fReferencedForUninstall; | ||
96 | BOOL fIgnore; | ||
97 | |||
98 | int iRoleAssignmentsInstallCount; | ||
99 | int iRoleAssignmentsUninstallCount; | ||
100 | |||
101 | INSTALLSTATE isInstalled, isAction; | ||
102 | |||
103 | CPI_APPLICATION* pApplication; | ||
104 | |||
105 | CPI_ASSEMBLY* pPrev; | ||
106 | CPI_ASSEMBLY* pNext; | ||
107 | }; | ||
108 | |||
109 | struct CPI_ASSEMBLY_LIST | ||
110 | { | ||
111 | CPI_ASSEMBLY* pFirst; | ||
112 | CPI_ASSEMBLY* pLast; | ||
113 | |||
114 | int iInstallCount; | ||
115 | int iCommitCount; | ||
116 | int iUninstallCount; | ||
117 | |||
118 | int iRoleInstallCount; | ||
119 | int iRoleCommitCount; | ||
120 | int iRoleUninstallCount; | ||
121 | }; | ||
122 | |||
123 | |||
124 | // function prototypes | ||
125 | |||
126 | void CpiAssemblyListFree( | ||
127 | CPI_ASSEMBLY_LIST* pList | ||
128 | ); | ||
129 | HRESULT CpiAssembliesRead( | ||
130 | CPI_APPLICATION_LIST* pAppList, | ||
131 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
132 | CPI_ASSEMBLY_LIST* pAsmList | ||
133 | ); | ||
134 | HRESULT CpiAssembliesVerifyInstall( | ||
135 | CPI_ASSEMBLY_LIST* pList | ||
136 | ); | ||
137 | HRESULT CpiAssembliesVerifyUninstall( | ||
138 | CPI_ASSEMBLY_LIST* pList | ||
139 | ); | ||
140 | HRESULT CpiAssembliesInstall( | ||
141 | CPI_ASSEMBLY_LIST* pList, | ||
142 | int iRunMode, | ||
143 | LPWSTR* ppwzActionData, | ||
144 | int* piProgress | ||
145 | ); | ||
146 | HRESULT CpiAssembliesUninstall( | ||
147 | CPI_ASSEMBLY_LIST* pList, | ||
148 | int iRunMode, | ||
149 | LPWSTR* ppwzActionData, | ||
150 | int* piProgress | ||
151 | ); | ||
152 | HRESULT CpiRoleAssignmentsInstall( | ||
153 | CPI_ASSEMBLY_LIST* pList, | ||
154 | int iRunMode, | ||
155 | LPWSTR* ppwzActionData, | ||
156 | int* piProgress | ||
157 | ); | ||
158 | HRESULT CpiRoleAssignmentsUninstall( | ||
159 | CPI_ASSEMBLY_LIST* pList, | ||
160 | int iRunMode, | ||
161 | LPWSTR* ppwzActionData, | ||
162 | int* piProgress | ||
163 | ); | ||
164 | HRESULT CpiGetSubscriptionsCollForComponent( | ||
165 | CPI_ASSEMBLY* pAsm, | ||
166 | CPI_COMPONENT* pComp, | ||
167 | ICatalogCollection** ppiSubsColl | ||
168 | ); | ||
diff --git a/src/ca/cpcost.h b/src/ca/cpcost.h new file mode 100644 index 00000000..7a23e03b --- /dev/null +++ b/src/ca/cpcost.h | |||
@@ -0,0 +1,30 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | #define COST_PARTITION_CREATE 10000 | ||
6 | #define COST_PARTITION_DELETE 10000 | ||
7 | |||
8 | #define COST_PARTITION_USER_CREATE 10000 | ||
9 | #define COST_PARTITION_USER_DELETE 10000 | ||
10 | |||
11 | #define COST_USER_IN_PARTITION_ROLE_CREATE 10000 | ||
12 | #define COST_USER_IN_PARTITION_ROLE_DELETE 10000 | ||
13 | |||
14 | #define COST_APPLICATION_CREATE 10000 | ||
15 | #define COST_APPLICATION_DELETE 10000 | ||
16 | |||
17 | #define COST_APPLICATION_ROLE_CREATE 10000 | ||
18 | #define COST_APPLICATION_ROLE_DELETE 10000 | ||
19 | |||
20 | #define COST_USER_IN_APPLICATION_ROLE_CREATE 10000 | ||
21 | #define COST_USER_IN_APPLICATION_ROLE_DELETE 10000 | ||
22 | |||
23 | #define COST_ASSEMBLY_REGISTER 50000 | ||
24 | #define COST_ASSEMBLY_UNREGISTER 10000 | ||
25 | |||
26 | #define COST_ROLLASSIGNMENT_CREATE 10000 | ||
27 | #define COST_ROLLASSIGNMENT_DELETE 10000 | ||
28 | |||
29 | #define COST_SUBSCRIPTION_CREATE 10000 | ||
30 | #define COST_SUBSCRIPTION_DELETE 10000 | ||
diff --git a/src/ca/cpexec.cpp b/src/ca/cpexec.cpp new file mode 100644 index 00000000..fa2446d8 --- /dev/null +++ b/src/ca/cpexec.cpp | |||
@@ -0,0 +1,704 @@ | |||
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 | DllMain - standard entry point for all WiX CustomActions | ||
7 | |||
8 | ********************************************************************/ | ||
9 | extern "C" BOOL WINAPI DllMain( | ||
10 | IN HINSTANCE hInst, | ||
11 | IN ULONG ulReason, | ||
12 | IN LPVOID) | ||
13 | { | ||
14 | switch(ulReason) | ||
15 | { | ||
16 | case DLL_PROCESS_ATTACH: | ||
17 | WcaGlobalInitialize(hInst); | ||
18 | break; | ||
19 | |||
20 | case DLL_PROCESS_DETACH: | ||
21 | WcaGlobalFinalize(); | ||
22 | break; | ||
23 | } | ||
24 | |||
25 | return TRUE; | ||
26 | } | ||
27 | |||
28 | /******************************************************************** | ||
29 | ComPlusPrepare - CUSTOM ACTION ENTRY POINT | ||
30 | |||
31 | Input: deferred CustomActionData - ComPlusPrepare | ||
32 | ********************************************************************/ | ||
33 | extern "C" UINT __stdcall ComPlusPrepare(MSIHANDLE hInstall) | ||
34 | { | ||
35 | HRESULT hr = S_OK; | ||
36 | UINT er = ERROR_SUCCESS; | ||
37 | |||
38 | LPWSTR pwzCustomActionData = NULL; | ||
39 | LPWSTR pwzData = NULL; | ||
40 | |||
41 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
42 | |||
43 | // initialize | ||
44 | hr = WcaInitialize(hInstall, "ComPlusPrepare"); | ||
45 | ExitOnFailure(hr, "Failed to initialize ComPlusPrepare"); | ||
46 | |||
47 | // get custom action data | ||
48 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
49 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
50 | pwzData = pwzCustomActionData; | ||
51 | |||
52 | // create rollback file | ||
53 | hRollbackFile = ::CreateFileW(pwzData, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
54 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
55 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to create rollback file, name: %S", pwzData); | ||
56 | |||
57 | hr = S_OK; | ||
58 | |||
59 | LExit: | ||
60 | // clean up | ||
61 | ReleaseStr(pwzCustomActionData); | ||
62 | |||
63 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
64 | ::CloseHandle(hRollbackFile); | ||
65 | |||
66 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
67 | return WcaFinalize(er); | ||
68 | } | ||
69 | |||
70 | /******************************************************************** | ||
71 | ComPlusCleanup - CUSTOM ACTION ENTRY POINT | ||
72 | |||
73 | Input: deferred CustomActionData - ComPlusCleanup | ||
74 | ********************************************************************/ | ||
75 | extern "C" UINT __stdcall ComPlusCleanup(MSIHANDLE hInstall) | ||
76 | { | ||
77 | HRESULT hr = S_OK; | ||
78 | UINT er = ERROR_SUCCESS; | ||
79 | |||
80 | LPWSTR pwzCustomActionData = NULL; | ||
81 | LPWSTR pwzData = NULL; | ||
82 | |||
83 | // initialize | ||
84 | hr = WcaInitialize(hInstall, "ComPlusCleanup"); | ||
85 | ExitOnFailure(hr, "Failed to initialize ComPlusCleanup"); | ||
86 | |||
87 | // get custom action data | ||
88 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
89 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
90 | pwzData = pwzCustomActionData; | ||
91 | |||
92 | // delete rollback file | ||
93 | if (!::DeleteFileW(pwzData)) | ||
94 | { | ||
95 | // error, but not a showstopper | ||
96 | hr = HRESULT_FROM_WIN32(::GetLastError()); | ||
97 | WcaLog(LOGMSG_STANDARD, "Failed to delete rollback file, hr: 0x%x, name: %S", hr, pwzData); | ||
98 | } | ||
99 | |||
100 | hr = S_OK; | ||
101 | |||
102 | LExit: | ||
103 | // clean up | ||
104 | ReleaseStr(pwzCustomActionData); | ||
105 | |||
106 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
107 | return WcaFinalize(er); | ||
108 | } | ||
109 | |||
110 | /******************************************************************** | ||
111 | ComPlusInstallExecute - CUSTOM ACTION ENTRY POINT | ||
112 | |||
113 | Input: deferred CustomActionData - ComPlusInstallExecute | ||
114 | ********************************************************************/ | ||
115 | extern "C" UINT __stdcall ComPlusInstallExecute(MSIHANDLE hInstall) | ||
116 | { | ||
117 | HRESULT hr = S_OK; | ||
118 | UINT er = ERROR_SUCCESS; | ||
119 | |||
120 | LPWSTR pwzCustomActionData = NULL; | ||
121 | LPWSTR pwzData = NULL; | ||
122 | LPWSTR pwzRollbackFileName = NULL; | ||
123 | |||
124 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
125 | |||
126 | BOOL fInitializedCom = FALSE; | ||
127 | |||
128 | // initialize | ||
129 | hr = WcaInitialize(hInstall, "ComPlusInstallExecute"); | ||
130 | ExitOnFailure(hr, "Failed to initialize ComPlusInstallExecute"); | ||
131 | |||
132 | hr = ::CoInitialize(NULL); | ||
133 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
134 | fInitializedCom = TRUE; | ||
135 | |||
136 | CpiInitialize(); | ||
137 | |||
138 | // get custom action data | ||
139 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
140 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
141 | pwzData = pwzCustomActionData; | ||
142 | |||
143 | // open rollback file | ||
144 | hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName); | ||
145 | ExitOnFailure(hr, "Failed to read rollback file name"); | ||
146 | |||
147 | hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
148 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
149 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName); | ||
150 | |||
151 | // create partitions | ||
152 | hr = CpiConfigurePartitions(&pwzData, hRollbackFile); | ||
153 | ExitOnFailure(hr, "Failed to create partitions"); | ||
154 | if (S_FALSE == hr) ExitFunction(); | ||
155 | |||
156 | // create users in partition roles | ||
157 | hr = CpiConfigureUsersInPartitionRoles(&pwzData, hRollbackFile); | ||
158 | ExitOnFailure(hr, "Failed to create users in partition roles"); | ||
159 | if (S_FALSE == hr) ExitFunction(); | ||
160 | |||
161 | // create partition users | ||
162 | hr = CpiConfigurePartitionUsers(&pwzData, hRollbackFile); | ||
163 | ExitOnFailure(hr, "Failed to add partition users"); | ||
164 | if (S_FALSE == hr) ExitFunction(); | ||
165 | |||
166 | // create applications | ||
167 | hr = CpiConfigureApplications(&pwzData, hRollbackFile); | ||
168 | ExitOnFailure(hr, "Failed to create applications"); | ||
169 | if (S_FALSE == hr) ExitFunction(); | ||
170 | |||
171 | // create application roles | ||
172 | hr = CpiConfigureApplicationRoles(&pwzData, hRollbackFile); | ||
173 | ExitOnFailure(hr, "Failed to create application roles"); | ||
174 | if (S_FALSE == hr) ExitFunction(); | ||
175 | |||
176 | // create users in application roles | ||
177 | hr = CpiConfigureUsersInApplicationRoles(&pwzData, hRollbackFile); | ||
178 | ExitOnFailure(hr, "Failed to create users in application roles"); | ||
179 | if (S_FALSE == hr) ExitFunction(); | ||
180 | |||
181 | // register assemblies | ||
182 | hr = CpiConfigureAssemblies(&pwzData, hRollbackFile); | ||
183 | ExitOnFailure(hr, "Failed to register assemblies"); | ||
184 | if (S_FALSE == hr) ExitFunction(); | ||
185 | |||
186 | // create role assignments | ||
187 | hr = CpiConfigureRoleAssignments(&pwzData, hRollbackFile); | ||
188 | ExitOnFailure(hr, "Failed to create role assignments"); | ||
189 | if (S_FALSE == hr) ExitFunction(); | ||
190 | |||
191 | // create subscriptions | ||
192 | hr = CpiConfigureSubscriptions(&pwzData, hRollbackFile); | ||
193 | ExitOnFailure(hr, "Failed to create subscriptions"); | ||
194 | if (S_FALSE == hr) ExitFunction(); | ||
195 | |||
196 | hr = S_OK; | ||
197 | |||
198 | LExit: | ||
199 | // clean up | ||
200 | ReleaseStr(pwzCustomActionData); | ||
201 | ReleaseStr(pwzRollbackFileName); | ||
202 | |||
203 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
204 | ::CloseHandle(hRollbackFile); | ||
205 | |||
206 | // unitialize | ||
207 | CpiFinalize(); | ||
208 | |||
209 | if (fInitializedCom) | ||
210 | ::CoUninitialize(); | ||
211 | |||
212 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
213 | return WcaFinalize(er); | ||
214 | } | ||
215 | |||
216 | /******************************************************************** | ||
217 | ComPlusInstallExecuteCommit - CUSTOM ACTION ENTRY POINT | ||
218 | |||
219 | Input: deferred CustomActionData - ComPlusInstallExecuteCommit | ||
220 | ********************************************************************/ | ||
221 | extern "C" UINT __stdcall ComPlusInstallExecuteCommit(MSIHANDLE hInstall) | ||
222 | { | ||
223 | HRESULT hr = S_OK; | ||
224 | UINT er = ERROR_SUCCESS; | ||
225 | |||
226 | LPWSTR pwzCustomActionData = NULL; | ||
227 | LPWSTR pwzData = NULL; | ||
228 | LPWSTR pwzRollbackFileName = NULL; | ||
229 | |||
230 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
231 | |||
232 | BOOL fInitializedCom = FALSE; | ||
233 | |||
234 | // initialize | ||
235 | hr = WcaInitialize(hInstall, "ComPlusInstallExecuteCommit"); | ||
236 | ExitOnFailure(hr, "Failed to initialize ComPlusInstallExecuteCommit"); | ||
237 | |||
238 | hr = ::CoInitialize(NULL); | ||
239 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
240 | fInitializedCom = TRUE; | ||
241 | |||
242 | CpiInitialize(); | ||
243 | |||
244 | // get custom action data | ||
245 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
246 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
247 | pwzData = pwzCustomActionData; | ||
248 | |||
249 | // open rollback file | ||
250 | hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName); | ||
251 | ExitOnFailure(hr, "Failed to read rollback file name"); | ||
252 | |||
253 | hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
254 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
255 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName); | ||
256 | |||
257 | if (INVALID_SET_FILE_POINTER == ::SetFilePointer(hRollbackFile, 0, NULL, FILE_END)) | ||
258 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to set file pointer"); | ||
259 | |||
260 | // register assemblies | ||
261 | hr = CpiConfigureAssemblies(&pwzData, hRollbackFile); | ||
262 | ExitOnFailure(hr, "Failed to register assemblies"); | ||
263 | if (S_FALSE == hr) ExitFunction(); | ||
264 | |||
265 | // create role assignments | ||
266 | hr = CpiConfigureRoleAssignments(&pwzData, hRollbackFile); | ||
267 | ExitOnFailure(hr, "Failed to create role assignments"); | ||
268 | if (S_FALSE == hr) ExitFunction(); | ||
269 | |||
270 | // create subscriptions | ||
271 | hr = CpiConfigureSubscriptions(&pwzData, hRollbackFile); | ||
272 | ExitOnFailure(hr, "Failed to create subscriptions"); | ||
273 | if (S_FALSE == hr) ExitFunction(); | ||
274 | |||
275 | hr = S_OK; | ||
276 | |||
277 | LExit: | ||
278 | // clean up | ||
279 | ReleaseStr(pwzCustomActionData); | ||
280 | |||
281 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
282 | ::CloseHandle(hRollbackFile); | ||
283 | |||
284 | // unitialize | ||
285 | CpiFinalize(); | ||
286 | |||
287 | if (fInitializedCom) | ||
288 | ::CoUninitialize(); | ||
289 | |||
290 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
291 | return WcaFinalize(er); | ||
292 | } | ||
293 | |||
294 | /******************************************************************** | ||
295 | ComPlusRollbackInstallExecute - CUSTOM ACTION ENTRY POINT | ||
296 | |||
297 | Input: deferred CustomActionData - ComPlusRollbackInstallExecute | ||
298 | ********************************************************************/ | ||
299 | extern "C" UINT __stdcall ComPlusRollbackInstallExecute(MSIHANDLE hInstall) | ||
300 | { | ||
301 | HRESULT hr = S_OK; | ||
302 | UINT er = ERROR_SUCCESS; | ||
303 | |||
304 | LPWSTR pwzCustomActionData = NULL; | ||
305 | LPWSTR pwzData = NULL; | ||
306 | LPWSTR pwzRollbackFileName = NULL; | ||
307 | |||
308 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
309 | |||
310 | CPI_ROLLBACK_DATA* prdPartitions = NULL; | ||
311 | CPI_ROLLBACK_DATA* prdUsersInPartitionRoles = NULL; | ||
312 | CPI_ROLLBACK_DATA* prdPartitionUsers = NULL; | ||
313 | CPI_ROLLBACK_DATA* prdApplications = NULL; | ||
314 | CPI_ROLLBACK_DATA* prdApplicationRoles = NULL; | ||
315 | CPI_ROLLBACK_DATA* prdUsersApplicationRoles = NULL; | ||
316 | CPI_ROLLBACK_DATA* prdAssemblies = NULL; | ||
317 | CPI_ROLLBACK_DATA* prdRoleAssignments = NULL; | ||
318 | CPI_ROLLBACK_DATA* prdSubscriptions = NULL; | ||
319 | |||
320 | BOOL fInitializedCom = FALSE; | ||
321 | |||
322 | // initialize | ||
323 | hr = WcaInitialize(hInstall, "ComPlusRollbackInstallExecute"); | ||
324 | ExitOnFailure(hr, "Failed to initialize ComPlusRollbackInstallExecute"); | ||
325 | |||
326 | hr = ::CoInitialize(NULL); | ||
327 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
328 | fInitializedCom = TRUE; | ||
329 | |||
330 | CpiInitialize(); | ||
331 | |||
332 | // get custom action data | ||
333 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
334 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
335 | pwzData = pwzCustomActionData; | ||
336 | |||
337 | // open rollback file | ||
338 | hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName); | ||
339 | ExitOnFailure(hr, "Failed to read rollback file name"); | ||
340 | |||
341 | hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
342 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
343 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName); | ||
344 | |||
345 | // read rollback data (execute) | ||
346 | hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitions); | ||
347 | ExitOnFailure(hr, "Failed to read partitions rollback data"); | ||
348 | hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersInPartitionRoles); | ||
349 | ExitOnFailure(hr, "Failed to read users in partition roles rollback data"); | ||
350 | hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitionUsers); | ||
351 | ExitOnFailure(hr, "Failed to read partition users rollback data"); | ||
352 | hr = CpiReadRollbackDataList(hRollbackFile, &prdApplications); | ||
353 | ExitOnFailure(hr, "Failed to read applications rollback data"); | ||
354 | hr = CpiReadRollbackDataList(hRollbackFile, &prdApplicationRoles); | ||
355 | ExitOnFailure(hr, "Failed to read application roles rollback data"); | ||
356 | hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersApplicationRoles); | ||
357 | ExitOnFailure(hr, "Failed to read users in application roles rollback data"); | ||
358 | hr = CpiReadRollbackDataList(hRollbackFile, &prdAssemblies); | ||
359 | ExitOnFailure(hr, "Failed to read assemblies rollback data"); | ||
360 | hr = CpiReadRollbackDataList(hRollbackFile, &prdRoleAssignments); | ||
361 | ExitOnFailure(hr, "Failed to read role assignments rollback data"); | ||
362 | hr = CpiReadRollbackDataList(hRollbackFile, &prdSubscriptions); | ||
363 | ExitOnFailure(hr, "Failed to read subscription rollback data"); | ||
364 | |||
365 | // read rollback data (commit) | ||
366 | hr = CpiReadRollbackDataList(hRollbackFile, &prdAssemblies); | ||
367 | ExitOnFailure(hr, "Failed to read assemblies rollback data (commit)"); | ||
368 | hr = CpiReadRollbackDataList(hRollbackFile, &prdRoleAssignments); | ||
369 | ExitOnFailure(hr, "Failed to read role assignments rollback data"); | ||
370 | hr = CpiReadRollbackDataList(hRollbackFile, &prdSubscriptions); | ||
371 | ExitOnFailure(hr, "Failed to read subscription rollback data (commit)"); | ||
372 | |||
373 | ::CloseHandle(hRollbackFile); | ||
374 | hRollbackFile = INVALID_HANDLE_VALUE; | ||
375 | |||
376 | // rollback create subscriptions | ||
377 | hr = CpiRollbackConfigureSubscriptions(&pwzData, prdSubscriptions); | ||
378 | ExitOnFailure(hr, "Failed to rollback create subscriptions"); | ||
379 | |||
380 | // rollback create role assignments | ||
381 | hr = CpiRollbackConfigureRoleAssignments(&pwzData, prdRoleAssignments); | ||
382 | ExitOnFailure(hr, "Failed to rollback create role assignments"); | ||
383 | |||
384 | // rollback register assemblies | ||
385 | hr = CpiRollbackConfigureAssemblies(&pwzData, prdAssemblies); | ||
386 | ExitOnFailure(hr, "Failed to rollback register assemblies"); | ||
387 | |||
388 | // rollback create users in application roles | ||
389 | hr = CpiRollbackConfigureUsersInApplicationRoles(&pwzData, prdUsersApplicationRoles); | ||
390 | ExitOnFailure(hr, "Failed to rollback create users in application roles"); | ||
391 | |||
392 | // rollback create application roles | ||
393 | hr = CpiRollbackConfigureApplicationRoles(&pwzData, prdApplicationRoles); | ||
394 | ExitOnFailure(hr, "Failed to rollback create application roles"); | ||
395 | |||
396 | // rollback create applications | ||
397 | hr = CpiRollbackConfigureApplications(&pwzData, prdApplications); | ||
398 | ExitOnFailure(hr, "Failed to rollback create applications"); | ||
399 | |||
400 | // rollback create partition users | ||
401 | hr = CpiRollbackConfigurePartitionUsers(&pwzData, prdPartitionUsers); | ||
402 | ExitOnFailure(hr, "Failed to rollback create partition users"); | ||
403 | |||
404 | // rollback create users in partition roles | ||
405 | hr = CpiRollbackConfigureUsersInPartitionRoles(&pwzData, prdUsersInPartitionRoles); | ||
406 | ExitOnFailure(hr, "Failed to rollback create users in partition roles"); | ||
407 | |||
408 | // rollback create partitions | ||
409 | hr = CpiRollbackConfigurePartitions(&pwzData, prdPartitions); | ||
410 | ExitOnFailure(hr, "Failed to rollback create partitions"); | ||
411 | |||
412 | hr = S_OK; | ||
413 | |||
414 | LExit: | ||
415 | // clean up | ||
416 | ReleaseStr(pwzCustomActionData); | ||
417 | ReleaseStr(pwzRollbackFileName); | ||
418 | |||
419 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
420 | ::CloseHandle(hRollbackFile); | ||
421 | |||
422 | if (prdPartitions) | ||
423 | CpiFreeRollbackDataList(prdPartitions); | ||
424 | if (prdUsersInPartitionRoles) | ||
425 | CpiFreeRollbackDataList(prdUsersInPartitionRoles); | ||
426 | if (prdPartitionUsers) | ||
427 | CpiFreeRollbackDataList(prdPartitionUsers); | ||
428 | if (prdApplications) | ||
429 | CpiFreeRollbackDataList(prdApplications); | ||
430 | if (prdApplicationRoles) | ||
431 | CpiFreeRollbackDataList(prdApplicationRoles); | ||
432 | if (prdUsersApplicationRoles) | ||
433 | CpiFreeRollbackDataList(prdUsersApplicationRoles); | ||
434 | if (prdAssemblies) | ||
435 | CpiFreeRollbackDataList(prdAssemblies); | ||
436 | if (prdRoleAssignments) | ||
437 | CpiFreeRollbackDataList(prdRoleAssignments); | ||
438 | if (prdSubscriptions) | ||
439 | CpiFreeRollbackDataList(prdSubscriptions); | ||
440 | |||
441 | // unitialize | ||
442 | CpiFinalize(); | ||
443 | |||
444 | if (fInitializedCom) | ||
445 | ::CoUninitialize(); | ||
446 | |||
447 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
448 | return WcaFinalize(er); | ||
449 | } | ||
450 | |||
451 | /******************************************************************** | ||
452 | ComPlusUninstallExecute - CUSTOM ACTION ENTRY POINT | ||
453 | |||
454 | Input: deferred CustomActionData - ComPlusUninstallExecute | ||
455 | ********************************************************************/ | ||
456 | extern "C" UINT __stdcall ComPlusUninstallExecute(MSIHANDLE hInstall) | ||
457 | { | ||
458 | HRESULT hr = S_OK; | ||
459 | UINT er = ERROR_SUCCESS; | ||
460 | |||
461 | LPWSTR pwzCustomActionData = NULL; | ||
462 | LPWSTR pwzData = NULL; | ||
463 | LPWSTR pwzRollbackFileName = NULL; | ||
464 | |||
465 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
466 | |||
467 | BOOL fInitializedCom = FALSE; | ||
468 | |||
469 | // initialize | ||
470 | hr = WcaInitialize(hInstall, "ComPlusUninstallExecute"); | ||
471 | ExitOnFailure(hr, "Failed to initialize ComPlusUninstallExecute"); | ||
472 | |||
473 | hr = ::CoInitialize(NULL); | ||
474 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
475 | fInitializedCom = TRUE; | ||
476 | |||
477 | CpiInitialize(); | ||
478 | |||
479 | // get custom action data | ||
480 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
481 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
482 | pwzData = pwzCustomActionData; | ||
483 | |||
484 | // open rollback file | ||
485 | hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName); | ||
486 | ExitOnFailure(hr, "Failed to read rollback file name"); | ||
487 | |||
488 | hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
489 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
490 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName); | ||
491 | |||
492 | // delete subscriptions | ||
493 | hr = CpiConfigureSubscriptions(&pwzData, hRollbackFile); | ||
494 | ExitOnFailure(hr, "Failed to delete subscriptions"); | ||
495 | if (S_FALSE == hr) ExitFunction(); | ||
496 | |||
497 | // delete role assignments | ||
498 | hr = CpiConfigureRoleAssignments(&pwzData, hRollbackFile); | ||
499 | ExitOnFailure(hr, "Failed to delete role assignments"); | ||
500 | if (S_FALSE == hr) ExitFunction(); | ||
501 | |||
502 | // unregister assemblies | ||
503 | hr = CpiConfigureAssemblies(&pwzData, hRollbackFile); | ||
504 | ExitOnFailure(hr, "Failed to unregister assemblies"); | ||
505 | if (S_FALSE == hr) ExitFunction(); | ||
506 | |||
507 | // remove users in application roles | ||
508 | hr = CpiConfigureUsersInApplicationRoles(&pwzData, hRollbackFile); | ||
509 | ExitOnFailure(hr, "Failed to delete users in application roles"); | ||
510 | if (S_FALSE == hr) ExitFunction(); | ||
511 | |||
512 | // remove application roles | ||
513 | hr = CpiConfigureApplicationRoles(&pwzData, hRollbackFile); | ||
514 | ExitOnFailure(hr, "Failed to delete application roles"); | ||
515 | if (S_FALSE == hr) ExitFunction(); | ||
516 | |||
517 | // remove applications | ||
518 | hr = CpiConfigureApplications(&pwzData, hRollbackFile); | ||
519 | ExitOnFailure(hr, "Failed to remove applications"); | ||
520 | if (S_FALSE == hr) ExitFunction(); | ||
521 | |||
522 | // remove partition users | ||
523 | hr = CpiConfigurePartitionUsers(&pwzData, hRollbackFile); | ||
524 | ExitOnFailure(hr, "Failed to remove partition users"); | ||
525 | if (S_FALSE == hr) ExitFunction(); | ||
526 | |||
527 | // remove users in partition roles | ||
528 | hr = CpiConfigureUsersInPartitionRoles(&pwzData, hRollbackFile); | ||
529 | ExitOnFailure(hr, "Failed to delete users in partition roles"); | ||
530 | if (S_FALSE == hr) ExitFunction(); | ||
531 | |||
532 | // remove partitions | ||
533 | hr = CpiConfigurePartitions(&pwzData, hRollbackFile); | ||
534 | ExitOnFailure(hr, "Failed to delete partitions"); | ||
535 | if (S_FALSE == hr) ExitFunction(); | ||
536 | |||
537 | hr = S_OK; | ||
538 | |||
539 | LExit: | ||
540 | // clean up | ||
541 | ReleaseStr(pwzCustomActionData); | ||
542 | ReleaseStr(pwzRollbackFileName); | ||
543 | |||
544 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
545 | ::CloseHandle(hRollbackFile); | ||
546 | |||
547 | // unitialize | ||
548 | CpiFinalize(); | ||
549 | |||
550 | if (fInitializedCom) | ||
551 | ::CoUninitialize(); | ||
552 | |||
553 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
554 | return WcaFinalize(er); | ||
555 | } | ||
556 | |||
557 | /******************************************************************** | ||
558 | ComPlusRollbackUninstallExecute - CUSTOM ACTION ENTRY POINT | ||
559 | |||
560 | Input: deferred CustomActionData - ComPlusRollbackUninstallExecute | ||
561 | ********************************************************************/ | ||
562 | extern "C" UINT __stdcall ComPlusRollbackUninstallExecute(MSIHANDLE hInstall) | ||
563 | { | ||
564 | HRESULT hr = S_OK; | ||
565 | UINT er = ERROR_SUCCESS; | ||
566 | |||
567 | LPWSTR pwzCustomActionData = NULL; | ||
568 | LPWSTR pwzData = NULL; | ||
569 | LPWSTR pwzRollbackFileName = NULL; | ||
570 | |||
571 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
572 | |||
573 | CPI_ROLLBACK_DATA* prdPartitions = NULL; | ||
574 | CPI_ROLLBACK_DATA* prdUsersInPartitionRoles = NULL; | ||
575 | CPI_ROLLBACK_DATA* prdPartitionUsers = NULL; | ||
576 | CPI_ROLLBACK_DATA* prdApplications = NULL; | ||
577 | CPI_ROLLBACK_DATA* prdApplicationRoles = NULL; | ||
578 | CPI_ROLLBACK_DATA* prdUsersApplicationRoles = NULL; | ||
579 | CPI_ROLLBACK_DATA* prdAssemblies = NULL; | ||
580 | CPI_ROLLBACK_DATA* prdRoleAssignments = NULL; | ||
581 | CPI_ROLLBACK_DATA* prdSubscriptions = NULL; | ||
582 | |||
583 | BOOL fInitializedCom = FALSE; | ||
584 | |||
585 | // initialize | ||
586 | hr = WcaInitialize(hInstall, "ComPlusRollbackUninstallExecute"); | ||
587 | ExitOnFailure(hr, "Failed to initialize ComPlusRollbackUninstallExecute"); | ||
588 | |||
589 | hr = ::CoInitialize(NULL); | ||
590 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
591 | fInitializedCom = TRUE; | ||
592 | |||
593 | CpiInitialize(); | ||
594 | |||
595 | // get custom action data | ||
596 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
597 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
598 | pwzData = pwzCustomActionData; | ||
599 | |||
600 | // open rollback file | ||
601 | hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName); | ||
602 | ExitOnFailure(hr, "Failed to read rollback file name"); | ||
603 | |||
604 | hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
605 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
606 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName); | ||
607 | |||
608 | // read rollback data | ||
609 | hr = CpiReadRollbackDataList(hRollbackFile, &prdSubscriptions); | ||
610 | ExitOnFailure(hr, "Failed to read subscription rollback data"); | ||
611 | hr = CpiReadRollbackDataList(hRollbackFile, &prdRoleAssignments); | ||
612 | ExitOnFailure(hr, "Failed to read role assignments rollback data"); | ||
613 | hr = CpiReadRollbackDataList(hRollbackFile, &prdAssemblies); | ||
614 | ExitOnFailure(hr, "Failed to read assemblies rollback data"); | ||
615 | hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersApplicationRoles); | ||
616 | ExitOnFailure(hr, "Failed to read users in application roles rollback data"); | ||
617 | hr = CpiReadRollbackDataList(hRollbackFile, &prdApplicationRoles); | ||
618 | ExitOnFailure(hr, "Failed to read application roles rollback data"); | ||
619 | hr = CpiReadRollbackDataList(hRollbackFile, &prdApplications); | ||
620 | ExitOnFailure(hr, "Failed to read applications rollback data"); | ||
621 | hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitionUsers); | ||
622 | ExitOnFailure(hr, "Failed to read partition users rollback data"); | ||
623 | hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersInPartitionRoles); | ||
624 | ExitOnFailure(hr, "Failed to read users in partition roles rollback data"); | ||
625 | hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitions); | ||
626 | ExitOnFailure(hr, "Failed to read partitions rollback data"); | ||
627 | |||
628 | ::CloseHandle(hRollbackFile); | ||
629 | hRollbackFile = INVALID_HANDLE_VALUE; | ||
630 | |||
631 | // rollback remove partitions | ||
632 | hr = CpiRollbackConfigurePartitions(&pwzData, prdPartitions); | ||
633 | ExitOnFailure(hr, "Failed to rollback delete partitions"); | ||
634 | |||
635 | // rollback remove users in partition roles | ||
636 | hr = CpiRollbackConfigureUsersInPartitionRoles(&pwzData, prdUsersInPartitionRoles); | ||
637 | ExitOnFailure(hr, "Failed to rollback delete users in partition roles"); | ||
638 | |||
639 | // rollback remove partition users | ||
640 | hr = CpiRollbackConfigurePartitionUsers(&pwzData, prdPartitionUsers); | ||
641 | ExitOnFailure(hr, "Failed to rollback delete partition users"); | ||
642 | |||
643 | // rollback remove applications | ||
644 | hr = CpiRollbackConfigureApplications(&pwzData, prdApplications); | ||
645 | ExitOnFailure(hr, "Failed to rollback delete applications"); | ||
646 | |||
647 | // rollback remove application roles | ||
648 | hr = CpiRollbackConfigureApplicationRoles(&pwzData, prdApplicationRoles); | ||
649 | ExitOnFailure(hr, "Failed to rollback delete application roles"); | ||
650 | |||
651 | // rollback remove users in application roles | ||
652 | hr = CpiRollbackConfigureUsersInApplicationRoles(&pwzData, prdUsersApplicationRoles); | ||
653 | ExitOnFailure(hr, "Failed to rollback delete users in application roles"); | ||
654 | |||
655 | // rollback unregister assemblies | ||
656 | hr = CpiRollbackConfigureAssemblies(&pwzData, prdAssemblies); | ||
657 | ExitOnFailure(hr, "Failed to rollback unregister assemblies"); | ||
658 | |||
659 | // rollback delete role assignments | ||
660 | hr = CpiRollbackConfigureRoleAssignments(&pwzData, prdAssemblies); | ||
661 | ExitOnFailure(hr, "Failed to rollback delete role assignments"); | ||
662 | |||
663 | // rollback delete subscriptions | ||
664 | hr = CpiRollbackConfigureSubscriptions(&pwzData, prdSubscriptions); | ||
665 | ExitOnFailure(hr, "Failed to rollback delete subscriptions"); | ||
666 | |||
667 | hr = S_OK; | ||
668 | |||
669 | LExit: | ||
670 | // clean up | ||
671 | ReleaseStr(pwzCustomActionData); | ||
672 | ReleaseStr(pwzRollbackFileName); | ||
673 | |||
674 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
675 | ::CloseHandle(hRollbackFile); | ||
676 | |||
677 | if (prdPartitions) | ||
678 | CpiFreeRollbackDataList(prdPartitions); | ||
679 | if (prdUsersInPartitionRoles) | ||
680 | CpiFreeRollbackDataList(prdUsersInPartitionRoles); | ||
681 | if (prdPartitionUsers) | ||
682 | CpiFreeRollbackDataList(prdPartitionUsers); | ||
683 | if (prdApplications) | ||
684 | CpiFreeRollbackDataList(prdApplications); | ||
685 | if (prdApplicationRoles) | ||
686 | CpiFreeRollbackDataList(prdApplicationRoles); | ||
687 | if (prdUsersApplicationRoles) | ||
688 | CpiFreeRollbackDataList(prdUsersApplicationRoles); | ||
689 | if (prdAssemblies) | ||
690 | CpiFreeRollbackDataList(prdAssemblies); | ||
691 | if (prdRoleAssignments) | ||
692 | CpiFreeRollbackDataList(prdRoleAssignments); | ||
693 | if (prdSubscriptions) | ||
694 | CpiFreeRollbackDataList(prdSubscriptions); | ||
695 | |||
696 | // unitialize | ||
697 | CpiFinalize(); | ||
698 | |||
699 | if (fInitializedCom) | ||
700 | ::CoUninitialize(); | ||
701 | |||
702 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
703 | return WcaFinalize(er); | ||
704 | } | ||
diff --git a/src/ca/cpexec.def b/src/ca/cpexec.def new file mode 100644 index 00000000..1dad15c2 --- /dev/null +++ b/src/ca/cpexec.def | |||
@@ -0,0 +1,11 @@ | |||
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 | |||
4 | EXPORTS | ||
5 | ComPlusPrepare | ||
6 | ComPlusCleanup | ||
7 | ComPlusInstallExecute | ||
8 | ComPlusInstallExecuteCommit | ||
9 | ComPlusRollbackInstallExecute | ||
10 | ComPlusUninstallExecute | ||
11 | ComPlusRollbackUninstallExecute | ||
diff --git a/src/ca/cppartexec.cpp b/src/ca/cppartexec.cpp new file mode 100644 index 00000000..d8c30c6a --- /dev/null +++ b/src/ca/cppartexec.cpp | |||
@@ -0,0 +1,690 @@ | |||
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_PARTITION_ATTRIBUTES | ||
9 | { | ||
10 | int iActionType; | ||
11 | int iActionCost; | ||
12 | LPWSTR pwzKey; | ||
13 | LPWSTR pwzID; | ||
14 | LPWSTR pwzName; | ||
15 | CPI_PROPERTY* pPropList; | ||
16 | }; | ||
17 | |||
18 | struct CPI_PARTITION_USER_ATTRIBUTES | ||
19 | { | ||
20 | int iActionType; | ||
21 | int iActionCost; | ||
22 | LPWSTR pwzKey; | ||
23 | LPWSTR pwzAccount; | ||
24 | LPWSTR pwzPartID; | ||
25 | }; | ||
26 | |||
27 | |||
28 | // prototypes for private helper functions | ||
29 | |||
30 | static HRESULT ReadPartitionAttributes( | ||
31 | LPWSTR* ppwzData, | ||
32 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
33 | ); | ||
34 | static void FreePartitionAttributes( | ||
35 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
36 | ); | ||
37 | static HRESULT CreatePartition( | ||
38 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
39 | ); | ||
40 | static HRESULT RemovePartition( | ||
41 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
42 | ); | ||
43 | static HRESULT ReadPartitionUserAttributes( | ||
44 | LPWSTR* ppwzData, | ||
45 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
46 | ); | ||
47 | static void FreePartitionUserAttributes( | ||
48 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
49 | ); | ||
50 | static HRESULT CreatePartitionUser( | ||
51 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
52 | ); | ||
53 | static HRESULT RemovePartitionUser( | ||
54 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
55 | ); | ||
56 | |||
57 | |||
58 | // function definitions | ||
59 | |||
60 | HRESULT CpiConfigurePartitions( | ||
61 | LPWSTR* ppwzData, | ||
62 | HANDLE hRollbackFile | ||
63 | ) | ||
64 | { | ||
65 | HRESULT hr = S_OK; | ||
66 | |||
67 | CPI_PARTITION_ATTRIBUTES attrs; | ||
68 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
69 | |||
70 | // read action text | ||
71 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
72 | ExitOnFailure(hr, "Failed to send action start message"); | ||
73 | |||
74 | // ger partition count | ||
75 | int iCnt = 0; | ||
76 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
77 | ExitOnFailure(hr, "Failed to read count"); | ||
78 | |||
79 | // write count to rollback file | ||
80 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
81 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
82 | |||
83 | for (int i = 0; i < iCnt; i++) | ||
84 | { | ||
85 | // read partition attributes from CustomActionData | ||
86 | hr = ReadPartitionAttributes(ppwzData, &attrs); | ||
87 | ExitOnFailure(hr, "Failed to read attributes"); | ||
88 | |||
89 | // progress message | ||
90 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
91 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
92 | |||
93 | if (S_FALSE == hr) | ||
94 | ExitFunction(); | ||
95 | |||
96 | // write key to rollback file | ||
97 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
98 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
99 | |||
100 | // action | ||
101 | switch (attrs.iActionType) | ||
102 | { | ||
103 | case atCreate: | ||
104 | hr = CreatePartition(&attrs); | ||
105 | ExitOnFailure(hr, "Failed to create partition, key: %S", attrs.pwzKey); | ||
106 | break; | ||
107 | case atRemove: | ||
108 | hr = RemovePartition(&attrs); | ||
109 | ExitOnFailure(hr, "Failed to remove partition, key: %S", attrs.pwzKey); | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | // write completion status to rollback file | ||
114 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
115 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
116 | |||
117 | // progress | ||
118 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
119 | ExitOnFailure(hr, "Failed to update progress"); | ||
120 | } | ||
121 | |||
122 | hr = S_OK; | ||
123 | |||
124 | LExit: | ||
125 | // clean up | ||
126 | FreePartitionAttributes(&attrs); | ||
127 | |||
128 | return hr; | ||
129 | } | ||
130 | |||
131 | HRESULT CpiRollbackConfigurePartitions( | ||
132 | LPWSTR* ppwzData, | ||
133 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
134 | ) | ||
135 | { | ||
136 | HRESULT hr = S_OK; | ||
137 | |||
138 | int iRollbackStatus; | ||
139 | |||
140 | CPI_PARTITION_ATTRIBUTES attrs; | ||
141 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
142 | |||
143 | // read action text | ||
144 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
145 | ExitOnFailure(hr, "Failed to send action start message"); | ||
146 | |||
147 | // get count | ||
148 | int iCnt = 0; | ||
149 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
150 | ExitOnFailure(hr, "Failed to read count"); | ||
151 | |||
152 | for (int i = 0; i < iCnt; i++) | ||
153 | { | ||
154 | // read partition attributes from CustomActionData | ||
155 | hr = ReadPartitionAttributes(ppwzData, &attrs); | ||
156 | ExitOnFailure(hr, "Failed to read attributes"); | ||
157 | |||
158 | // rollback status | ||
159 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
160 | |||
161 | if (S_FALSE == hr) | ||
162 | continue; // not found, nothing to rollback | ||
163 | |||
164 | // progress message | ||
165 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
166 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
167 | |||
168 | if (S_FALSE == hr) | ||
169 | ExitFunction(); | ||
170 | |||
171 | // action | ||
172 | switch (attrs.iActionType) | ||
173 | { | ||
174 | case atCreate: | ||
175 | hr = CreatePartition(&attrs); | ||
176 | if (FAILED(hr)) | ||
177 | WcaLog(LOGMSG_STANDARD, "Failed to create partition, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
178 | break; | ||
179 | case atRemove: | ||
180 | hr = RemovePartition(&attrs); | ||
181 | if (FAILED(hr)) | ||
182 | WcaLog(LOGMSG_STANDARD, "Failed to remove partition, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
183 | break; | ||
184 | } | ||
185 | |||
186 | // check rollback status | ||
187 | if (0 == iRollbackStatus) | ||
188 | continue; // operation did not complete, skip progress | ||
189 | |||
190 | // progress | ||
191 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
192 | ExitOnFailure(hr, "Failed to update progress"); | ||
193 | } | ||
194 | |||
195 | hr = S_OK; | ||
196 | |||
197 | LExit: | ||
198 | // clean up | ||
199 | FreePartitionAttributes(&attrs); | ||
200 | |||
201 | return hr; | ||
202 | } | ||
203 | |||
204 | HRESULT CpiConfigurePartitionUsers( | ||
205 | LPWSTR* ppwzData, | ||
206 | HANDLE hRollbackFile | ||
207 | ) | ||
208 | { | ||
209 | HRESULT hr = S_OK; | ||
210 | |||
211 | CPI_PARTITION_USER_ATTRIBUTES attrs; | ||
212 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
213 | |||
214 | // read action text | ||
215 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
216 | ExitOnFailure(hr, "Failed to send action start message"); | ||
217 | |||
218 | // ger partition count | ||
219 | int iCnt = 0; | ||
220 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
221 | ExitOnFailure(hr, "Failed to read count"); | ||
222 | |||
223 | // write count to rollback file | ||
224 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
225 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
226 | |||
227 | for (int i = 0; i < iCnt; i++) | ||
228 | { | ||
229 | // read partition attributes from CustomActionData | ||
230 | hr = ReadPartitionUserAttributes(ppwzData, &attrs); | ||
231 | ExitOnFailure(hr, "Failed to read attributes"); | ||
232 | |||
233 | // progress message | ||
234 | hr = CpiActionDataMessage(1, attrs.pwzAccount); | ||
235 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
236 | |||
237 | if (S_FALSE == hr) | ||
238 | ExitFunction(); | ||
239 | |||
240 | // write key to rollback file | ||
241 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
242 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
243 | |||
244 | // action | ||
245 | switch (attrs.iActionType) | ||
246 | { | ||
247 | case atCreate: | ||
248 | hr = CreatePartitionUser(&attrs); | ||
249 | ExitOnFailure(hr, "Failed to create partition user, key: %S", attrs.pwzKey); | ||
250 | break; | ||
251 | case atRemove: | ||
252 | hr = RemovePartitionUser(&attrs); | ||
253 | ExitOnFailure(hr, "Failed to remove partition user, key: %S", attrs.pwzKey); | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | // write completion status to rollback file | ||
258 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
259 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
260 | |||
261 | // progress | ||
262 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
263 | ExitOnFailure(hr, "Failed to update progress"); | ||
264 | } | ||
265 | |||
266 | hr = S_OK; | ||
267 | |||
268 | LExit: | ||
269 | // clean up | ||
270 | FreePartitionUserAttributes(&attrs); | ||
271 | |||
272 | return hr; | ||
273 | } | ||
274 | |||
275 | HRESULT CpiRollbackConfigurePartitionUsers( | ||
276 | LPWSTR* ppwzData, | ||
277 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
278 | ) | ||
279 | { | ||
280 | HRESULT hr = S_OK; | ||
281 | |||
282 | int iRollbackStatus; | ||
283 | |||
284 | CPI_PARTITION_USER_ATTRIBUTES attrs; | ||
285 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
286 | |||
287 | // read action text | ||
288 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
289 | ExitOnFailure(hr, "Failed to send action start message"); | ||
290 | |||
291 | // get count | ||
292 | int iCnt = 0; | ||
293 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
294 | ExitOnFailure(hr, "Failed to read count"); | ||
295 | |||
296 | for (int i = 0; i < iCnt; i++) | ||
297 | { | ||
298 | // read partition attributes from CustomActionData | ||
299 | hr = ReadPartitionUserAttributes(ppwzData, &attrs); | ||
300 | ExitOnFailure(hr, "Failed to read attributes"); | ||
301 | |||
302 | // rollback status | ||
303 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
304 | |||
305 | if (S_FALSE == hr) | ||
306 | continue; // not found, nothing to rollback | ||
307 | |||
308 | // progress message | ||
309 | hr = CpiActionDataMessage(1, attrs.pwzAccount); | ||
310 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
311 | |||
312 | if (S_FALSE == hr) | ||
313 | ExitFunction(); | ||
314 | |||
315 | // action | ||
316 | switch (attrs.iActionType) | ||
317 | { | ||
318 | case atCreate: | ||
319 | hr = CreatePartitionUser(&attrs); | ||
320 | ExitOnFailure(hr, "Failed to create partition user, key: %S", attrs.pwzKey); | ||
321 | break; | ||
322 | case atRemove: | ||
323 | hr = RemovePartitionUser(&attrs); | ||
324 | ExitOnFailure(hr, "Failed to remove partition user, key: %S", attrs.pwzKey); | ||
325 | break; | ||
326 | } | ||
327 | |||
328 | // check rollback status | ||
329 | if (0 == iRollbackStatus) | ||
330 | continue; // operation did not complete, skip progress | ||
331 | |||
332 | // progress | ||
333 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
334 | ExitOnFailure(hr, "Failed to update progress"); | ||
335 | } | ||
336 | |||
337 | hr = S_OK; | ||
338 | |||
339 | LExit: | ||
340 | // clean up | ||
341 | FreePartitionUserAttributes(&attrs); | ||
342 | |||
343 | return hr; | ||
344 | } | ||
345 | |||
346 | |||
347 | // helper function definitions | ||
348 | |||
349 | static HRESULT ReadPartitionAttributes( | ||
350 | LPWSTR* ppwzData, | ||
351 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
352 | ) | ||
353 | { | ||
354 | HRESULT hr = S_OK; | ||
355 | |||
356 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
357 | ExitOnFailure(hr, "Failed to read action type"); | ||
358 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
359 | ExitOnFailure(hr, "Failed to read action cost"); | ||
360 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
361 | ExitOnFailure(hr, "Failed to read key"); | ||
362 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzID); | ||
363 | ExitOnFailure(hr, "Failed to read id"); | ||
364 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName); | ||
365 | ExitOnFailure(hr, "Failed to read name"); | ||
366 | hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList); | ||
367 | ExitOnFailure(hr, "Failed to read properties"); | ||
368 | |||
369 | hr = S_OK; | ||
370 | |||
371 | LExit: | ||
372 | return hr; | ||
373 | } | ||
374 | |||
375 | static void FreePartitionAttributes( | ||
376 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
377 | ) | ||
378 | { | ||
379 | ReleaseStr(pAttrs->pwzKey); | ||
380 | ReleaseStr(pAttrs->pwzID); | ||
381 | ReleaseStr(pAttrs->pwzName); | ||
382 | |||
383 | if (pAttrs->pPropList) | ||
384 | CpiFreePropertyList(pAttrs->pPropList); | ||
385 | } | ||
386 | |||
387 | static HRESULT CreatePartition( | ||
388 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
389 | ) | ||
390 | { | ||
391 | HRESULT hr = S_OK; | ||
392 | |||
393 | ICatalogCollection* piPartColl = NULL; | ||
394 | ICatalogObject* piPartObj = NULL; | ||
395 | |||
396 | long lChanges = 0; | ||
397 | |||
398 | // log | ||
399 | WcaLog(LOGMSG_VERBOSE, "Creating partition, key: %S", pAttrs->pwzKey); | ||
400 | |||
401 | // get partitions collection | ||
402 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
403 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
404 | |||
405 | // check if partition exists | ||
406 | hr = CpiFindCollectionObjectByStringKey(piPartColl, pAttrs->pwzID, &piPartObj); | ||
407 | ExitOnFailure(hr, "Failed to find partition"); | ||
408 | |||
409 | if (S_FALSE == hr) | ||
410 | { | ||
411 | // create partition | ||
412 | hr = CpiAddCollectionObject(piPartColl, &piPartObj); | ||
413 | ExitOnFailure(hr, "Failed to add partition to collection"); | ||
414 | |||
415 | hr = CpiPutCollectionObjectValue(piPartObj, L"ID", pAttrs->pwzID); | ||
416 | ExitOnFailure(hr, "Failed to set partition id property"); | ||
417 | |||
418 | hr = CpiPutCollectionObjectValue(piPartObj, L"Name", pAttrs->pwzName); | ||
419 | ExitOnFailure(hr, "Failed to set partition name property"); | ||
420 | } | ||
421 | |||
422 | // properties | ||
423 | hr = CpiPutCollectionObjectValues(piPartObj, pAttrs->pPropList); | ||
424 | ExitOnFailure(hr, "Failed to write properties"); | ||
425 | |||
426 | // save changes | ||
427 | hr = piPartColl->SaveChanges(&lChanges); | ||
428 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
429 | CpiLogCatalogErrorInfo(); | ||
430 | ExitOnFailure(hr, "Failed to save changes"); | ||
431 | |||
432 | // log | ||
433 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
434 | |||
435 | hr = S_OK; | ||
436 | |||
437 | LExit: | ||
438 | // clean up | ||
439 | ReleaseObject(piPartColl); | ||
440 | ReleaseObject(piPartObj); | ||
441 | |||
442 | return hr; | ||
443 | } | ||
444 | |||
445 | static HRESULT RemovePartition( | ||
446 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
447 | ) | ||
448 | { | ||
449 | HRESULT hr = S_OK; | ||
450 | |||
451 | ICatalogCollection* piPartColl = NULL; | ||
452 | |||
453 | long lChanges = 0; | ||
454 | |||
455 | // log | ||
456 | WcaLog(LOGMSG_VERBOSE, "Removing partition, key: %S", pAttrs->pwzKey); | ||
457 | |||
458 | // get partitions collection | ||
459 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
460 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
461 | |||
462 | // remove | ||
463 | hr = CpiRemoveCollectionObject(piPartColl, pAttrs->pwzID, NULL, TRUE); | ||
464 | ExitOnFailure(hr, "Failed to remove partition"); | ||
465 | |||
466 | if (S_FALSE == hr) | ||
467 | { | ||
468 | // partition not found | ||
469 | WcaLog(LOGMSG_VERBOSE, "Partition not found, nothing to delete, key: %S", pAttrs->pwzKey); | ||
470 | ExitFunction1(hr = S_OK); | ||
471 | } | ||
472 | |||
473 | // save changes | ||
474 | hr = piPartColl->SaveChanges(&lChanges); | ||
475 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
476 | CpiLogCatalogErrorInfo(); | ||
477 | ExitOnFailure(hr, "Failed to save changes"); | ||
478 | |||
479 | // log | ||
480 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
481 | |||
482 | hr = S_OK; | ||
483 | |||
484 | LExit: | ||
485 | // clean up | ||
486 | ReleaseObject(piPartColl); | ||
487 | |||
488 | return hr; | ||
489 | } | ||
490 | |||
491 | static HRESULT ReadPartitionUserAttributes( | ||
492 | LPWSTR* ppwzData, | ||
493 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
494 | ) | ||
495 | { | ||
496 | HRESULT hr = S_OK; | ||
497 | |||
498 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
499 | ExitOnFailure(hr, "Failed to read action type"); | ||
500 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
501 | ExitOnFailure(hr, "Failed to read action cost"); | ||
502 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
503 | ExitOnFailure(hr, "Failed to read key"); | ||
504 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount); | ||
505 | ExitOnFailure(hr, "Failed to read account name"); | ||
506 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
507 | ExitOnFailure(hr, "Failed to read partition id"); | ||
508 | |||
509 | hr = S_OK; | ||
510 | |||
511 | LExit: | ||
512 | return hr; | ||
513 | } | ||
514 | |||
515 | static void FreePartitionUserAttributes( | ||
516 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
517 | ) | ||
518 | { | ||
519 | ReleaseStr(pAttrs->pwzKey); | ||
520 | ReleaseStr(pAttrs->pwzAccount); | ||
521 | ReleaseStr(pAttrs->pwzPartID); | ||
522 | } | ||
523 | |||
524 | static HRESULT CreatePartitionUser( | ||
525 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
526 | ) | ||
527 | { | ||
528 | HRESULT hr = S_OK; | ||
529 | UINT er = ERROR_SUCCESS; | ||
530 | |||
531 | ICatalogCollection* piUserColl = NULL; | ||
532 | ICatalogObject* piUserObj = NULL; | ||
533 | |||
534 | PSID pSid = NULL; | ||
535 | long lChanges = 0; | ||
536 | |||
537 | // log | ||
538 | WcaLog(LOGMSG_VERBOSE, "Setting default partition for user, key: %S", pAttrs->pwzKey); | ||
539 | |||
540 | // get partition users collection | ||
541 | hr = CpiGetPartitionUsersCollection(&piUserColl); | ||
542 | ExitOnFailure(hr, "Failed to get partition users collection"); | ||
543 | |||
544 | // get SID for account | ||
545 | do { | ||
546 | er = ERROR_SUCCESS; | ||
547 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
548 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
549 | { | ||
550 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
551 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
552 | switch (er) | ||
553 | { | ||
554 | case IDABORT: | ||
555 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
556 | case IDRETRY: | ||
557 | break; | ||
558 | case IDIGNORE: | ||
559 | default: | ||
560 | ExitFunction1(hr = S_OK); | ||
561 | } | ||
562 | } | ||
563 | else | ||
564 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
565 | } while (IDRETRY == er); | ||
566 | |||
567 | // remove any existing entry | ||
568 | hr = CpiRemoveUserCollectionObject(piUserColl, pSid); | ||
569 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
570 | { | ||
571 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
572 | hr = S_FALSE; | ||
573 | } | ||
574 | else | ||
575 | ExitOnFailure(hr, "Failed to remove user"); | ||
576 | |||
577 | if (S_OK == hr) | ||
578 | WcaLog(LOGMSG_VERBOSE, "Existing default partition for user was removed, key: %S", pAttrs->pwzKey); | ||
579 | |||
580 | // add partition user | ||
581 | hr = CpiAddCollectionObject(piUserColl, &piUserObj); | ||
582 | ExitOnFailure(hr, "Failed to add partition to collection"); | ||
583 | |||
584 | hr = CpiPutCollectionObjectValue(piUserObj, L"AccountName", pAttrs->pwzAccount); | ||
585 | ExitOnFailure(hr, "Failed to set account name property"); | ||
586 | |||
587 | hr = CpiPutCollectionObjectValue(piUserObj, L"DefaultPartitionID", pAttrs->pwzPartID); | ||
588 | ExitOnFailure(hr, "Failed to set default partition id property"); | ||
589 | |||
590 | // save changes | ||
591 | hr = piUserColl->SaveChanges(&lChanges); | ||
592 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
593 | CpiLogCatalogErrorInfo(); | ||
594 | ExitOnFailure(hr, "Failed to save changes"); | ||
595 | |||
596 | // log | ||
597 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
598 | |||
599 | hr = S_OK; | ||
600 | |||
601 | LExit: | ||
602 | // clean up | ||
603 | ReleaseObject(piUserColl); | ||
604 | ReleaseObject(piUserObj); | ||
605 | |||
606 | if (pSid) | ||
607 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
608 | |||
609 | return hr; | ||
610 | } | ||
611 | |||
612 | static HRESULT RemovePartitionUser( | ||
613 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
614 | ) | ||
615 | { | ||
616 | HRESULT hr = S_OK; | ||
617 | UINT er = ERROR_SUCCESS; | ||
618 | |||
619 | ICatalogCollection* piUserColl = NULL; | ||
620 | |||
621 | PSID pSid = NULL; | ||
622 | long lChanges = 0; | ||
623 | |||
624 | // log | ||
625 | WcaLog(LOGMSG_VERBOSE, "Removing default partition for user, key: %S", pAttrs->pwzKey); | ||
626 | |||
627 | // get partition users collection | ||
628 | hr = CpiGetPartitionUsersCollection(&piUserColl); | ||
629 | ExitOnFailure(hr, "Failed to get partition users collection"); | ||
630 | |||
631 | // get SID for account | ||
632 | do { | ||
633 | er = ERROR_SUCCESS; | ||
634 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
635 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
636 | { | ||
637 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
638 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
639 | switch (er) | ||
640 | { | ||
641 | case IDABORT: | ||
642 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
643 | case IDRETRY: | ||
644 | break; | ||
645 | case IDIGNORE: | ||
646 | default: | ||
647 | ExitFunction1(hr = S_OK); | ||
648 | } | ||
649 | } | ||
650 | else | ||
651 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
652 | } while (IDRETRY == er); | ||
653 | |||
654 | // remove | ||
655 | hr = CpiRemoveUserCollectionObject(piUserColl, pSid); | ||
656 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
657 | { | ||
658 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
659 | hr = S_FALSE; | ||
660 | } | ||
661 | else | ||
662 | ExitOnFailure(hr, "Failed to remove user"); | ||
663 | |||
664 | if (S_FALSE == hr) | ||
665 | { | ||
666 | // user not found | ||
667 | WcaLog(LOGMSG_VERBOSE, "Default partition for user not found, nothing to delete, key: %S", pAttrs->pwzKey); | ||
668 | ExitFunction1(hr = S_OK); | ||
669 | } | ||
670 | |||
671 | // save changes | ||
672 | hr = piUserColl->SaveChanges(&lChanges); | ||
673 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
674 | CpiLogCatalogErrorInfo(); | ||
675 | ExitOnFailure(hr, "Failed to save changes"); | ||
676 | |||
677 | // log | ||
678 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
679 | |||
680 | hr = S_OK; | ||
681 | |||
682 | LExit: | ||
683 | // clean up | ||
684 | ReleaseObject(piUserColl); | ||
685 | |||
686 | if (pSid) | ||
687 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
688 | |||
689 | return hr; | ||
690 | } | ||
diff --git a/src/ca/cppartexec.h b/src/ca/cppartexec.h new file mode 100644 index 00000000..132a9f5a --- /dev/null +++ b/src/ca/cppartexec.h | |||
@@ -0,0 +1,20 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | HRESULT CpiConfigurePartitions( | ||
6 | LPWSTR* ppwzData, | ||
7 | HANDLE hRollbackFile | ||
8 | ); | ||
9 | HRESULT CpiRollbackConfigurePartitions( | ||
10 | LPWSTR* ppwzData, | ||
11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
12 | ); | ||
13 | HRESULT CpiConfigurePartitionUsers( | ||
14 | LPWSTR* ppwzData, | ||
15 | HANDLE hRollbackFile | ||
16 | ); | ||
17 | HRESULT CpiRollbackConfigurePartitionUsers( | ||
18 | LPWSTR* ppwzData, | ||
19 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
20 | ); | ||
diff --git a/src/ca/cppartroleexec.cpp b/src/ca/cppartroleexec.cpp new file mode 100644 index 00000000..4a503c79 --- /dev/null +++ b/src/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 | } | ||
diff --git a/src/ca/cppartroleexec.h b/src/ca/cppartroleexec.h new file mode 100644 index 00000000..0ec47dad --- /dev/null +++ b/src/ca/cppartroleexec.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | HRESULT CpiConfigureUsersInPartitionRoles( | ||
6 | LPWSTR* ppwzData, | ||
7 | HANDLE hRollbackFile | ||
8 | ); | ||
9 | HRESULT CpiRollbackConfigureUsersInPartitionRoles( | ||
10 | LPWSTR* ppwzData, | ||
11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
12 | ); | ||
diff --git a/src/ca/cppartrolesched.cpp b/src/ca/cppartrolesched.cpp new file mode 100644 index 00000000..a988f8e3 --- /dev/null +++ b/src/ca/cppartrolesched.cpp | |||
@@ -0,0 +1,421 @@ | |||
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 | // sql queries | ||
7 | |||
8 | LPCWSTR vcsPartitionRoleQuery = | ||
9 | L"SELECT `PartitionRole`, `Partition_`, `Component_`, `Name` FROM `ComPlusPartitionRole`"; | ||
10 | enum ePartitionRoleQuery { prqPartitionRole = 1, prqPartition, prqComponent, prqName }; | ||
11 | |||
12 | LPCWSTR vcsUserInPartitionRoleQuery = | ||
13 | L"SELECT `UserInPartitionRole`, `PartitionRole_`, `ComPlusUserInPartitionRole`.`Component_`, `Domain`, `Name` FROM `ComPlusUserInPartitionRole`, `User` WHERE `User_` = `User`"; | ||
14 | LPCWSTR vcsGroupInPartitionRoleQuery = | ||
15 | L"SELECT `GroupInPartitionRole`, `PartitionRole_`, `ComPlusGroupInPartitionRole`.`Component_`, `Domain`, `Name` FROM `ComPlusGroupInPartitionRole`, `Group` WHERE `Group_` = `Group`"; | ||
16 | enum eTrusteeInPartitionRoleQuery { tiprqUserInPartitionRole = 1, tiprqPartitionRole, tiprqComponent, tiprqDomain, tiprqName }; | ||
17 | |||
18 | |||
19 | // prototypes for private helper functions | ||
20 | |||
21 | static HRESULT TrusteesInPartitionRolesRead( | ||
22 | LPCWSTR pwzQuery, | ||
23 | CPI_PARTITION_ROLE_LIST* pPartRoleList, | ||
24 | CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList | ||
25 | ); | ||
26 | static void FreePartitionRole( | ||
27 | CPI_PARTITION_ROLE* pItm | ||
28 | ); | ||
29 | static void FreeUserInPartitionRole( | ||
30 | CPI_USER_IN_PARTITION_ROLE* pItm | ||
31 | ); | ||
32 | static HRESULT AddUserInPartitionRoleToActionData( | ||
33 | CPI_USER_IN_PARTITION_ROLE* pItm, | ||
34 | int iActionType, | ||
35 | int iActionCost, | ||
36 | LPWSTR* ppwzActionData | ||
37 | ); | ||
38 | |||
39 | |||
40 | // function definitions | ||
41 | |||
42 | void CpiPartitionRoleListFree( | ||
43 | CPI_PARTITION_ROLE_LIST* pList | ||
44 | ) | ||
45 | { | ||
46 | CPI_PARTITION_ROLE* pItm = pList->pFirst; | ||
47 | |||
48 | while (pItm) | ||
49 | { | ||
50 | CPI_PARTITION_ROLE* pDelete = pItm; | ||
51 | pItm = pItm->pNext; | ||
52 | FreePartitionRole(pDelete); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | HRESULT CpiPartitionRolesRead( | ||
57 | CPI_PARTITION_LIST* pPartList, | ||
58 | CPI_PARTITION_ROLE_LIST* pPartRoleList | ||
59 | ) | ||
60 | { | ||
61 | HRESULT hr = S_OK; | ||
62 | PMSIHANDLE hView, hRec; | ||
63 | CPI_PARTITION_ROLE* pItm = NULL; | ||
64 | LPWSTR pwzData = NULL; | ||
65 | |||
66 | // loop through all application roles | ||
67 | hr = WcaOpenExecuteView(vcsPartitionRoleQuery, &hView); | ||
68 | ExitOnFailure(hr, "Failed to execute view on ComPlusPartitionRole table"); | ||
69 | |||
70 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
71 | { | ||
72 | // create entry | ||
73 | pItm = (CPI_PARTITION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION_ROLE)); | ||
74 | if (!pItm) | ||
75 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
76 | |||
77 | // get key | ||
78 | hr = WcaGetRecordString(hRec, prqPartitionRole, &pwzData); | ||
79 | ExitOnFailure(hr, "Failed to get key"); | ||
80 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
81 | |||
82 | // get partition | ||
83 | hr = WcaGetRecordString(hRec, prqPartition, &pwzData); | ||
84 | ExitOnFailure(hr, "Failed to get application"); | ||
85 | |||
86 | hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition); | ||
87 | if (S_FALSE == hr) | ||
88 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
89 | ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData); | ||
90 | |||
91 | // get name | ||
92 | hr = WcaGetRecordFormattedString(hRec, prqName, &pwzData); | ||
93 | ExitOnFailure(hr, "Failed to get name"); | ||
94 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
95 | |||
96 | // add entry | ||
97 | if (pPartRoleList->pFirst) | ||
98 | pItm->pNext = pPartRoleList->pFirst; | ||
99 | pPartRoleList->pFirst = pItm; | ||
100 | pItm = NULL; | ||
101 | } | ||
102 | |||
103 | if (E_NOMOREITEMS == hr) | ||
104 | hr = S_OK; | ||
105 | |||
106 | LExit: | ||
107 | // clean up | ||
108 | if (pItm) | ||
109 | FreePartitionRole(pItm); | ||
110 | |||
111 | ReleaseStr(pwzData); | ||
112 | |||
113 | return hr; | ||
114 | } | ||
115 | |||
116 | HRESULT CpiPartitionRoleFindByKey( | ||
117 | CPI_PARTITION_ROLE_LIST* pList, | ||
118 | LPCWSTR pwzKey, | ||
119 | CPI_PARTITION_ROLE** ppPartRole | ||
120 | ) | ||
121 | { | ||
122 | for (CPI_PARTITION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
123 | { | ||
124 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
125 | { | ||
126 | *ppPartRole = pItm; | ||
127 | return S_OK; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return E_FAIL; | ||
132 | } | ||
133 | |||
134 | void CpiUserInPartitionRoleListFree( | ||
135 | CPI_USER_IN_PARTITION_ROLE_LIST* pList | ||
136 | ) | ||
137 | { | ||
138 | CPI_USER_IN_PARTITION_ROLE* pItm = pList->pFirst; | ||
139 | |||
140 | while (pItm) | ||
141 | { | ||
142 | CPI_USER_IN_PARTITION_ROLE* pDelete = pItm; | ||
143 | pItm = pItm->pNext; | ||
144 | FreeUserInPartitionRole(pDelete); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | HRESULT CpiUsersInPartitionRolesRead( | ||
149 | CPI_PARTITION_ROLE_LIST* pPartRoleList, | ||
150 | CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList | ||
151 | ) | ||
152 | { | ||
153 | HRESULT hr = S_OK; | ||
154 | |||
155 | // read users in partition roles | ||
156 | if (CpiTableExists(cptComPlusUserInPartitionRole)) | ||
157 | { | ||
158 | hr = TrusteesInPartitionRolesRead(vcsUserInPartitionRoleQuery, pPartRoleList, pUsrInPartRoleList); | ||
159 | ExitOnFailure(hr, "Failed to read users in partition roles"); | ||
160 | } | ||
161 | |||
162 | // read groups in partition roles | ||
163 | if (CpiTableExists(cptComPlusGroupInPartitionRole)) | ||
164 | { | ||
165 | hr = TrusteesInPartitionRolesRead(vcsGroupInPartitionRoleQuery, pPartRoleList, pUsrInPartRoleList); | ||
166 | ExitOnFailure(hr, "Failed to read groups in partition roles"); | ||
167 | } | ||
168 | |||
169 | hr = S_OK; | ||
170 | |||
171 | LExit: | ||
172 | return hr; | ||
173 | } | ||
174 | |||
175 | HRESULT CpiUsersInPartitionRolesInstall( | ||
176 | CPI_USER_IN_PARTITION_ROLE_LIST* pList, | ||
177 | int iRunMode, | ||
178 | LPWSTR* ppwzActionData, | ||
179 | int* piProgress | ||
180 | ) | ||
181 | { | ||
182 | HRESULT hr = S_OK; | ||
183 | |||
184 | int iActionType; | ||
185 | |||
186 | // add action text | ||
187 | hr = CpiAddActionTextToActionData(L"AddUsersToComPlusPartitionRoles", ppwzActionData); | ||
188 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
189 | |||
190 | // add count to action data | ||
191 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
192 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
193 | |||
194 | // add roles to custom action data | ||
195 | for (CPI_USER_IN_PARTITION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
196 | { | ||
197 | // roles that are being installed only | ||
198 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
199 | continue; | ||
200 | |||
201 | // action type | ||
202 | if (rmRollback == iRunMode) | ||
203 | { | ||
204 | if (CpiIsInstalled(pItm->isInstalled)) | ||
205 | iActionType = atNoOp; | ||
206 | else | ||
207 | iActionType = atRemove; | ||
208 | } | ||
209 | else | ||
210 | iActionType = atCreate; | ||
211 | |||
212 | // add to action data | ||
213 | hr = AddUserInPartitionRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_CREATE, ppwzActionData); | ||
214 | ExitOnFailure(hr, "Failed to add user in partition role to custom action data, key: %S", pItm->wzKey); | ||
215 | } | ||
216 | |||
217 | // add progress tics | ||
218 | if (piProgress) | ||
219 | *piProgress += COST_USER_IN_APPLICATION_ROLE_CREATE * pList->iInstallCount; | ||
220 | |||
221 | hr = S_OK; | ||
222 | |||
223 | LExit: | ||
224 | return hr; | ||
225 | } | ||
226 | |||
227 | HRESULT CpiUsersInPartitionRolesUninstall( | ||
228 | CPI_USER_IN_PARTITION_ROLE_LIST* pList, | ||
229 | int iRunMode, | ||
230 | LPWSTR* ppwzActionData, | ||
231 | int* piProgress | ||
232 | ) | ||
233 | { | ||
234 | HRESULT hr = S_OK; | ||
235 | |||
236 | int iActionType; | ||
237 | |||
238 | // add action text | ||
239 | hr = CpiAddActionTextToActionData(L"RemoveUsersFromComPlusPartRoles", ppwzActionData); | ||
240 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
241 | |||
242 | // add count to action data | ||
243 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
244 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
245 | |||
246 | // add roles to custom action data | ||
247 | for (CPI_USER_IN_PARTITION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
248 | { | ||
249 | // roles that are being uninstalled only | ||
250 | if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
251 | continue; | ||
252 | |||
253 | // action type | ||
254 | if (rmRollback == iRunMode) | ||
255 | iActionType = atCreate; | ||
256 | else | ||
257 | iActionType = atRemove; | ||
258 | |||
259 | // add to action data | ||
260 | hr = AddUserInPartitionRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_DELETE, ppwzActionData); | ||
261 | ExitOnFailure(hr, "Failed to add user in partition role to custom action data, key: %S", pItm->wzKey); | ||
262 | } | ||
263 | |||
264 | // add progress tics | ||
265 | if (piProgress) | ||
266 | *piProgress += COST_USER_IN_APPLICATION_ROLE_DELETE * pList->iUninstallCount; | ||
267 | |||
268 | hr = S_OK; | ||
269 | |||
270 | LExit: | ||
271 | return hr; | ||
272 | } | ||
273 | |||
274 | |||
275 | // helper function definitions | ||
276 | |||
277 | static HRESULT TrusteesInPartitionRolesRead( | ||
278 | LPCWSTR pwzQuery, | ||
279 | CPI_PARTITION_ROLE_LIST* pPartRoleList, | ||
280 | CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList | ||
281 | ) | ||
282 | { | ||
283 | HRESULT hr = S_OK; | ||
284 | UINT er = ERROR_SUCCESS; | ||
285 | |||
286 | PMSIHANDLE hView, hRec; | ||
287 | |||
288 | CPI_USER_IN_PARTITION_ROLE* pItm = NULL; | ||
289 | LPWSTR pwzData = NULL; | ||
290 | LPWSTR pwzDomain = NULL; | ||
291 | LPWSTR pwzName = NULL; | ||
292 | BOOL fMatchingArchitecture = FALSE; | ||
293 | |||
294 | // loop through all application roles | ||
295 | hr = WcaOpenExecuteView(pwzQuery, &hView); | ||
296 | ExitOnFailure(hr, "Failed to execute view on table"); | ||
297 | |||
298 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
299 | { | ||
300 | // get component | ||
301 | hr = WcaGetRecordString(hRec, tiprqComponent, &pwzData); | ||
302 | ExitOnFailure(hr, "Failed to get component"); | ||
303 | |||
304 | // check if the component is our processor architecture | ||
305 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
306 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
307 | |||
308 | if (!fMatchingArchitecture) | ||
309 | { | ||
310 | continue; // not the same architecture, ignore | ||
311 | } | ||
312 | |||
313 | // create entry | ||
314 | pItm = (CPI_USER_IN_PARTITION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_USER_IN_PARTITION_ROLE)); | ||
315 | if (!pItm) | ||
316 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
317 | |||
318 | // get component install state | ||
319 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
320 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
321 | |||
322 | // get key | ||
323 | hr = WcaGetRecordString(hRec, tiprqUserInPartitionRole, &pwzData); | ||
324 | ExitOnFailure(hr, "Failed to get key"); | ||
325 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
326 | |||
327 | // get partition role | ||
328 | hr = WcaGetRecordString(hRec, tiprqPartitionRole, &pwzData); | ||
329 | ExitOnFailure(hr, "Failed to get partition role"); | ||
330 | |||
331 | hr = CpiPartitionRoleFindByKey(pPartRoleList, pwzData, &pItm->pPartitionRole); | ||
332 | ExitOnFailure(hr, "Failed to find partition role, key: %S", pwzData); | ||
333 | |||
334 | // get user domain | ||
335 | hr = WcaGetRecordFormattedString(hRec, tiprqDomain, &pwzDomain); | ||
336 | ExitOnFailure(hr, "Failed to get domain"); | ||
337 | |||
338 | // get user name | ||
339 | hr = WcaGetRecordFormattedString(hRec, tiprqName, &pwzName); | ||
340 | ExitOnFailure(hr, "Failed to get name"); | ||
341 | |||
342 | // build account name | ||
343 | hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount); | ||
344 | ExitOnFailure(hr, "Failed to build account name"); | ||
345 | |||
346 | // increment counters | ||
347 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
348 | pUsrInPartRoleList->iInstallCount++; | ||
349 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
350 | pUsrInPartRoleList->iUninstallCount++; | ||
351 | |||
352 | // add entry | ||
353 | if (pUsrInPartRoleList->pFirst) | ||
354 | pItm->pNext = pUsrInPartRoleList->pFirst; | ||
355 | pUsrInPartRoleList->pFirst = pItm; | ||
356 | pItm = NULL; | ||
357 | } | ||
358 | |||
359 | if (E_NOMOREITEMS == hr) | ||
360 | hr = S_OK; | ||
361 | |||
362 | LExit: | ||
363 | // clean up | ||
364 | if (pItm) | ||
365 | FreeUserInPartitionRole(pItm); | ||
366 | |||
367 | ReleaseStr(pwzData); | ||
368 | ReleaseStr(pwzDomain); | ||
369 | ReleaseStr(pwzName); | ||
370 | |||
371 | return hr; | ||
372 | } | ||
373 | |||
374 | static void FreePartitionRole( | ||
375 | CPI_PARTITION_ROLE* pItm | ||
376 | ) | ||
377 | { | ||
378 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
379 | } | ||
380 | |||
381 | static void FreeUserInPartitionRole( | ||
382 | CPI_USER_IN_PARTITION_ROLE* pItm | ||
383 | ) | ||
384 | { | ||
385 | ReleaseStr(pItm->pwzAccount); | ||
386 | |||
387 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
388 | } | ||
389 | |||
390 | static HRESULT AddUserInPartitionRoleToActionData( | ||
391 | CPI_USER_IN_PARTITION_ROLE* pItm, | ||
392 | int iActionType, | ||
393 | int iActionCost, | ||
394 | LPWSTR* ppwzActionData | ||
395 | ) | ||
396 | { | ||
397 | HRESULT hr = S_OK; | ||
398 | |||
399 | // add action information to custom action data | ||
400 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
401 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
402 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
403 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
404 | |||
405 | // add application role information to custom action data | ||
406 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
407 | ExitOnFailure(hr, "Failed to add key to custom action data"); | ||
408 | hr = WcaWriteStringToCaData(pItm->pPartitionRole->wzName, ppwzActionData); | ||
409 | ExitOnFailure(hr, "Failed to add role name to custom action data"); | ||
410 | hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData); | ||
411 | ExitOnFailure(hr, "Failed to add user account to custom action data"); | ||
412 | |||
413 | // add partition information to custom action data | ||
414 | hr = WcaWriteStringToCaData(pItm->pPartitionRole->pPartition->wzID, ppwzActionData); | ||
415 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
416 | |||
417 | hr = S_OK; | ||
418 | |||
419 | LExit: | ||
420 | return hr; | ||
421 | } | ||
diff --git a/src/ca/cppartrolesched.h b/src/ca/cppartrolesched.h new file mode 100644 index 00000000..ff1275d9 --- /dev/null +++ b/src/ca/cppartrolesched.h | |||
@@ -0,0 +1,76 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | struct CPI_PARTITION_ROLE | ||
6 | { | ||
7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
8 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
9 | |||
10 | CPI_PARTITION* pPartition; | ||
11 | |||
12 | ICatalogCollection* piUsersColl; | ||
13 | |||
14 | CPI_PARTITION_ROLE* pNext; | ||
15 | }; | ||
16 | |||
17 | struct CPI_PARTITION_ROLE_LIST | ||
18 | { | ||
19 | CPI_PARTITION_ROLE* pFirst; | ||
20 | }; | ||
21 | |||
22 | struct CPI_USER_IN_PARTITION_ROLE | ||
23 | { | ||
24 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
25 | LPWSTR pwzAccount; | ||
26 | |||
27 | INSTALLSTATE isInstalled, isAction; | ||
28 | |||
29 | CPI_PARTITION_ROLE* pPartitionRole; | ||
30 | |||
31 | CPI_USER_IN_PARTITION_ROLE* pNext; | ||
32 | }; | ||
33 | |||
34 | struct CPI_USER_IN_PARTITION_ROLE_LIST | ||
35 | { | ||
36 | CPI_USER_IN_PARTITION_ROLE* pFirst; | ||
37 | |||
38 | int iInstallCount; | ||
39 | int iUninstallCount; | ||
40 | }; | ||
41 | |||
42 | |||
43 | // function prototypes | ||
44 | |||
45 | void CpiPartitionRoleListFree( | ||
46 | CPI_PARTITION_ROLE_LIST* pList | ||
47 | ); | ||
48 | HRESULT CpiPartitionRolesRead( | ||
49 | CPI_PARTITION_LIST* pPartList, | ||
50 | CPI_PARTITION_ROLE_LIST* pPartRoleList | ||
51 | ); | ||
52 | HRESULT CpiPartitionRoleFindByKey( | ||
53 | CPI_PARTITION_ROLE_LIST* pList, | ||
54 | LPCWSTR pwzKey, | ||
55 | CPI_PARTITION_ROLE** ppPartRole | ||
56 | ); | ||
57 | |||
58 | void CpiUserInPartitionRoleListFree( | ||
59 | CPI_USER_IN_PARTITION_ROLE_LIST* pList | ||
60 | ); | ||
61 | HRESULT CpiUsersInPartitionRolesRead( | ||
62 | CPI_PARTITION_ROLE_LIST* pPartRoleList, | ||
63 | CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList | ||
64 | ); | ||
65 | HRESULT CpiUsersInPartitionRolesInstall( | ||
66 | CPI_USER_IN_PARTITION_ROLE_LIST* pList, | ||
67 | int iRunMode, | ||
68 | LPWSTR* ppwzActionData, | ||
69 | int* piProgress | ||
70 | ); | ||
71 | HRESULT CpiUsersInPartitionRolesUninstall( | ||
72 | CPI_USER_IN_PARTITION_ROLE_LIST* pList, | ||
73 | int iRunMode, | ||
74 | LPWSTR* ppwzActionData, | ||
75 | int* piProgress | ||
76 | ); | ||
diff --git a/src/ca/cppartsched.cpp b/src/ca/cppartsched.cpp new file mode 100644 index 00000000..6643a50b --- /dev/null +++ b/src/ca/cppartsched.cpp | |||
@@ -0,0 +1,912 @@ | |||
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 | // sql queries | ||
7 | |||
8 | LPCWSTR vcsPartitionQuery = | ||
9 | L"SELECT `Partition`, `Component_`, `Id`, `Name` FROM `ComPlusPartition`"; | ||
10 | enum ePartitionQuery { pqPartition = 1, pqComponent, pqID, pqName }; | ||
11 | |||
12 | LPCWSTR vcsPartitionPropertyQuery = | ||
13 | L"SELECT `Name`, `Value` FROM `ComPlusPartitionProperty` WHERE `Partition_` = ?"; | ||
14 | |||
15 | LPCWSTR vcsPartitionUserQuery = | ||
16 | L"SELECT `PartitionUser`, `Partition_`, `ComPlusPartitionUser`.`Component_`, `Domain`, `Name` FROM `ComPlusPartitionUser`, `User` WHERE `User_` = `User`"; | ||
17 | enum ePartitionUserQuery { puqPartitionUser = 1, puqPartition, puqComponent, puqDomain, puqName }; | ||
18 | |||
19 | |||
20 | // property definitions | ||
21 | |||
22 | CPI_PROPERTY_DEFINITION pdlPartitionProperties[] = | ||
23 | { | ||
24 | {L"Changeable", cpptBoolean, 502}, | ||
25 | {L"Deleteable", cpptBoolean, 502}, | ||
26 | {L"Description", cpptString, 502}, | ||
27 | {NULL, cpptNone, 0} | ||
28 | }; | ||
29 | |||
30 | |||
31 | // prototypes for private helper functions | ||
32 | |||
33 | static void FreePartition( | ||
34 | CPI_PARTITION* pItm | ||
35 | ); | ||
36 | static void FreePartitionUser( | ||
37 | CPI_PARTITION_USER* pItm | ||
38 | ); | ||
39 | static HRESULT AddPartitionToActionData( | ||
40 | CPI_PARTITION* pItm, | ||
41 | int iActionType, | ||
42 | int iActionCost, | ||
43 | LPWSTR* ppwzActionData | ||
44 | ); | ||
45 | static HRESULT AddPartitionUserToActionData( | ||
46 | CPI_PARTITION_USER* pItm, | ||
47 | int iActionType, | ||
48 | int iActionCost, | ||
49 | LPWSTR* ppwzActionData | ||
50 | ); | ||
51 | |||
52 | |||
53 | // function definitions | ||
54 | |||
55 | void CpiPartitionListFree( | ||
56 | CPI_PARTITION_LIST* pList | ||
57 | ) | ||
58 | { | ||
59 | CPI_PARTITION* pItm = pList->pFirst; | ||
60 | |||
61 | while (pItm) | ||
62 | { | ||
63 | CPI_PARTITION* pDelete = pItm; | ||
64 | pItm = pItm->pNext; | ||
65 | FreePartition(pDelete); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | HRESULT CpiPartitionsRead( | ||
70 | CPI_PARTITION_LIST* pPartList | ||
71 | ) | ||
72 | { | ||
73 | HRESULT hr = S_OK; | ||
74 | UINT er = ERROR_SUCCESS; | ||
75 | |||
76 | PMSIHANDLE hView, hRec; | ||
77 | |||
78 | CPI_PARTITION* pItm = NULL; | ||
79 | LPWSTR pwzData = NULL; | ||
80 | BOOL fMatchingArchitecture = FALSE; | ||
81 | |||
82 | // loop through all partitions | ||
83 | hr = WcaOpenExecuteView(vcsPartitionQuery, &hView); | ||
84 | ExitOnFailure(hr, "Failed to execute view on ComPlusPartition table"); | ||
85 | |||
86 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
87 | { | ||
88 | // get component | ||
89 | hr = WcaGetRecordString(hRec, pqComponent, &pwzData); | ||
90 | ExitOnFailure(hr, "Failed to get component"); | ||
91 | |||
92 | // check if the component is our processor architecture | ||
93 | if (pwzData && *pwzData) | ||
94 | { | ||
95 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
96 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
97 | |||
98 | if (!fMatchingArchitecture) | ||
99 | { | ||
100 | continue; // not the same architecture, ignore | ||
101 | } | ||
102 | } | ||
103 | |||
104 | // create entry | ||
105 | pItm = (CPI_PARTITION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION)); | ||
106 | if (!pItm) | ||
107 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
108 | |||
109 | // get component install state | ||
110 | if (pwzData && *pwzData) | ||
111 | { | ||
112 | pItm->fHasComponent = TRUE; | ||
113 | |||
114 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
115 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
116 | } | ||
117 | |||
118 | // get key | ||
119 | hr = WcaGetRecordString(hRec, pqPartition, &pwzData); | ||
120 | ExitOnFailure(hr, "Failed to get key"); | ||
121 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
122 | |||
123 | // get id | ||
124 | hr = WcaGetRecordFormattedString(hRec, pqID, &pwzData); | ||
125 | ExitOnFailure(hr, "Failed to get id"); | ||
126 | |||
127 | if (pwzData && *pwzData) | ||
128 | { | ||
129 | hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID)); | ||
130 | ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData); | ||
131 | } | ||
132 | |||
133 | // get name | ||
134 | hr = WcaGetRecordFormattedString(hRec, pqName, &pwzData); | ||
135 | ExitOnFailure(hr, "Failed to get name"); | ||
136 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
137 | |||
138 | // if partition is a locater, either an id or a name must be provided | ||
139 | if (!pItm->fHasComponent && !*pItm->wzID && !*pItm->wzName) | ||
140 | ExitOnFailure(hr = E_FAIL, "A partition locater must have either an id or a name associated, key: %S", pItm->wzKey); | ||
141 | |||
142 | // if partition is not a locater, an name must be provided | ||
143 | if (pItm->fHasComponent && !*pItm->wzName) | ||
144 | ExitOnFailure(hr = E_FAIL, "A partition must have a name associated, key: %S", pItm->wzKey); | ||
145 | |||
146 | // get properties | ||
147 | if (CpiTableExists(cptComPlusPartitionProperty) && pItm->fHasComponent) | ||
148 | { | ||
149 | hr = CpiPropertiesRead(vcsPartitionPropertyQuery, pItm->wzKey, pdlPartitionProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
150 | ExitOnFailure(hr, "Failed to get properties"); | ||
151 | } | ||
152 | |||
153 | // increment counters | ||
154 | if (pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
155 | pPartList->iInstallCount++; | ||
156 | if (pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
157 | pPartList->iUninstallCount++; | ||
158 | |||
159 | // add entry | ||
160 | if (pPartList->pFirst) | ||
161 | pItm->pNext = pPartList->pFirst; | ||
162 | pPartList->pFirst = pItm; | ||
163 | pItm = NULL; | ||
164 | } | ||
165 | |||
166 | if (E_NOMOREITEMS == hr) | ||
167 | hr = S_OK; | ||
168 | |||
169 | LExit: | ||
170 | // clean up | ||
171 | if (pItm) | ||
172 | FreePartition(pItm); | ||
173 | |||
174 | ReleaseStr(pwzData); | ||
175 | |||
176 | return hr; | ||
177 | } | ||
178 | |||
179 | HRESULT CpiPartitionsVerifyInstall( | ||
180 | CPI_PARTITION_LIST* pList | ||
181 | ) | ||
182 | { | ||
183 | HRESULT hr = S_OK; | ||
184 | UINT er = ERROR_SUCCESS; | ||
185 | |||
186 | ICatalogCollection* piPartColl = NULL; | ||
187 | ICatalogObject* piPartObj = NULL; | ||
188 | |||
189 | for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
190 | { | ||
191 | // referenced locaters or partitions that are being installed | ||
192 | if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction))) | ||
193 | continue; | ||
194 | |||
195 | // if the partition is referensed and is not a locater, it must be installed | ||
196 | if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction)) | ||
197 | MessageExitOnFailure(hr = E_FAIL, msierrComPlusPartitionDependency, "A partition is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey); | ||
198 | |||
199 | // get partitions collection | ||
200 | if (!piPartColl) | ||
201 | { | ||
202 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
203 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
204 | } | ||
205 | |||
206 | // partition is supposed to exist | ||
207 | if (!pItm->fHasComponent || CpiIsInstalled(pItm->isInstalled)) | ||
208 | { | ||
209 | // get collection object for partition | ||
210 | hr = CpiFindCollectionObject(piPartColl, pItm->wzID, *pItm->wzID ? NULL : pItm->wzName, &piPartObj); | ||
211 | ExitOnFailure(hr, "Failed to find collection object for partition"); | ||
212 | |||
213 | // if the partition was found | ||
214 | if (S_OK == hr) | ||
215 | { | ||
216 | // if we don't have an id, copy id from object | ||
217 | if (!*pItm->wzID) | ||
218 | { | ||
219 | hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID)); | ||
220 | ExitOnFailure(hr, "Failed to get id"); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | // if the partition was not found | ||
225 | else | ||
226 | { | ||
227 | // if the application is a locater, this is an error | ||
228 | if (!pItm->fHasComponent) | ||
229 | MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusPartitionNotFound, "A partition required by this installation was not found, key: %S", pItm->wzKey); | ||
230 | |||
231 | // create a new id if one is missing | ||
232 | if (!*pItm->wzID) | ||
233 | { | ||
234 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
235 | ExitOnFailure(hr, "Failed to create id"); | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | |||
240 | // partition is supposed to be created | ||
241 | else | ||
242 | { | ||
243 | // check for conflicts | ||
244 | do { | ||
245 | if (*pItm->wzID) | ||
246 | { | ||
247 | // find partitions with conflicting id | ||
248 | hr = CpiFindCollectionObject(piPartColl, pItm->wzID, NULL, &piPartObj); | ||
249 | ExitOnFailure(hr, "Failed to find collection object for partition"); | ||
250 | |||
251 | if (S_FALSE == hr) | ||
252 | { | ||
253 | // find partitions with conflicting name | ||
254 | hr = CpiFindCollectionObject(piPartColl, NULL, pItm->wzName, &piPartObj); | ||
255 | ExitOnFailure(hr, "Failed to find collection object for partition"); | ||
256 | |||
257 | if (S_OK == hr) | ||
258 | // "A partition with a conflictiong name exists. retry cancel" | ||
259 | er = WcaErrorMessage(msierrComPlusPartitionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0); | ||
260 | else | ||
261 | break; // no conflicting entry found, break loop | ||
262 | } | ||
263 | else | ||
264 | // "A partition with a conflicting id exists. abort retry ignore" | ||
265 | er = WcaErrorMessage(msierrComPlusPartitionIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | // find partitions with conflicting name | ||
270 | hr = CpiFindCollectionObject(piPartColl, NULL, pItm->wzName, &piPartObj); | ||
271 | ExitOnFailure(hr, "Failed to find collection object for partition"); | ||
272 | |||
273 | if (S_OK == hr) | ||
274 | // "A partition with a conflictiong name exists. abort retry ignore" | ||
275 | er = WcaErrorMessage(msierrComPlusPartitionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
276 | else | ||
277 | break; // no conflicting entry found, break loop | ||
278 | } | ||
279 | |||
280 | switch (er) | ||
281 | { | ||
282 | case IDCANCEL: | ||
283 | case IDABORT: | ||
284 | ExitOnFailure(hr = E_FAIL, "A partition with a conflictiong name or id exists, key: %S", pItm->wzKey); | ||
285 | break; | ||
286 | case IDRETRY: | ||
287 | break; | ||
288 | case IDIGNORE: | ||
289 | default: | ||
290 | // if we don't have an id, copy id from object | ||
291 | if (!*pItm->wzID) | ||
292 | { | ||
293 | hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID)); | ||
294 | ExitOnFailure(hr, "Failed to get id"); | ||
295 | } | ||
296 | hr = S_FALSE; // indicate that this is not a conflict | ||
297 | } | ||
298 | } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts | ||
299 | |||
300 | // create a new id if one is missing | ||
301 | if (!*pItm->wzID) | ||
302 | { | ||
303 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
304 | ExitOnFailure(hr, "Failed to create id"); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | // clean up | ||
309 | ReleaseNullObject(piPartObj); | ||
310 | } | ||
311 | |||
312 | hr = S_OK; | ||
313 | |||
314 | LExit: | ||
315 | // clean up | ||
316 | ReleaseObject(piPartColl); | ||
317 | ReleaseObject(piPartObj); | ||
318 | |||
319 | return hr; | ||
320 | } | ||
321 | |||
322 | HRESULT CpiPartitionsVerifyUninstall( | ||
323 | CPI_PARTITION_LIST* pList | ||
324 | ) | ||
325 | { | ||
326 | HRESULT hr = S_OK; | ||
327 | ICatalogCollection* piPartColl = NULL; | ||
328 | ICatalogObject* piPartObj = NULL; | ||
329 | |||
330 | for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
331 | { | ||
332 | // referenced locaters or partitions that are being uninstalled | ||
333 | if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction))) | ||
334 | continue; | ||
335 | |||
336 | // get partitions collection | ||
337 | if (!piPartColl) | ||
338 | { | ||
339 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
340 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
341 | } | ||
342 | |||
343 | // get collection object for partition | ||
344 | hr = CpiFindCollectionObject(piPartColl, pItm->wzID, *pItm->wzID ? NULL : pItm->wzName, &piPartObj); | ||
345 | ExitOnFailure(hr, "Failed to find collection object for partition"); | ||
346 | |||
347 | // if the partition was found | ||
348 | if (S_OK == hr) | ||
349 | { | ||
350 | // if we don't have an id, copy id from object | ||
351 | if (!*pItm->wzID) | ||
352 | { | ||
353 | hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID)); | ||
354 | ExitOnFailure(hr, "Failed to get id"); | ||
355 | } | ||
356 | } | ||
357 | |||
358 | // if the partition was not found | ||
359 | else | ||
360 | { | ||
361 | pItm->fObjectNotFound = TRUE; | ||
362 | if (pItm->fHasComponent) | ||
363 | pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall | ||
364 | } | ||
365 | |||
366 | // clean up | ||
367 | ReleaseNullObject(piPartObj); | ||
368 | } | ||
369 | |||
370 | hr = S_OK; | ||
371 | |||
372 | LExit: | ||
373 | // clean up | ||
374 | ReleaseObject(piPartColl); | ||
375 | ReleaseObject(piPartObj); | ||
376 | |||
377 | return hr; | ||
378 | } | ||
379 | |||
380 | void CpiPartitionAddReferenceInstall( | ||
381 | CPI_PARTITION* pItm | ||
382 | ) | ||
383 | { | ||
384 | pItm->fReferencedForInstall = TRUE; | ||
385 | } | ||
386 | |||
387 | void CpiPartitionAddReferenceUninstall( | ||
388 | CPI_PARTITION* pItm | ||
389 | ) | ||
390 | { | ||
391 | pItm->fReferencedForUninstall = TRUE; | ||
392 | } | ||
393 | |||
394 | HRESULT CpiPartitionsInstall( | ||
395 | CPI_PARTITION_LIST* pList, | ||
396 | int iRunMode, | ||
397 | LPWSTR* ppwzActionData, | ||
398 | int* piProgress | ||
399 | ) | ||
400 | { | ||
401 | HRESULT hr = S_OK; | ||
402 | |||
403 | int iActionType; | ||
404 | |||
405 | // add action text | ||
406 | hr = CpiAddActionTextToActionData(L"CreateComPlusPartitions", ppwzActionData); | ||
407 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
408 | |||
409 | // add partition count to action data | ||
410 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
411 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
412 | |||
413 | // add applications to custom action data | ||
414 | for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
415 | { | ||
416 | // partitions that are being installed only | ||
417 | if (!pItm->fHasComponent || !WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
418 | continue; | ||
419 | |||
420 | // action type | ||
421 | if (rmRollback == iRunMode) | ||
422 | { | ||
423 | if (CpiIsInstalled(pItm->isInstalled)) | ||
424 | iActionType = atNoOp; | ||
425 | else | ||
426 | iActionType = atRemove; | ||
427 | } | ||
428 | else | ||
429 | iActionType = atCreate; | ||
430 | |||
431 | // add to action data | ||
432 | hr = AddPartitionToActionData(pItm, iActionType, COST_PARTITION_CREATE, ppwzActionData); | ||
433 | ExitOnFailure(hr, "Failed to add partition to custom action data, key: %S", pItm->wzKey); | ||
434 | } | ||
435 | |||
436 | // add progress tics | ||
437 | if (piProgress) | ||
438 | *piProgress += COST_PARTITION_CREATE * pList->iInstallCount; | ||
439 | |||
440 | hr = S_OK; | ||
441 | |||
442 | LExit: | ||
443 | return hr; | ||
444 | } | ||
445 | |||
446 | HRESULT CpiPartitionsUninstall( | ||
447 | CPI_PARTITION_LIST* pList, | ||
448 | int iRunMode, | ||
449 | LPWSTR* ppwzActionData, | ||
450 | int* piProgress | ||
451 | ) | ||
452 | { | ||
453 | HRESULT hr = S_OK; | ||
454 | |||
455 | int iActionType; | ||
456 | |||
457 | // add action text | ||
458 | hr = CpiAddActionTextToActionData(L"RemoveComPlusPartitions", ppwzActionData); | ||
459 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
460 | |||
461 | // add partition count to action data | ||
462 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
463 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
464 | |||
465 | // add partitions to custom action data | ||
466 | for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
467 | { | ||
468 | // partitions that are being uninstalled only | ||
469 | if (!pItm->fHasComponent || pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
470 | continue; | ||
471 | |||
472 | // action type | ||
473 | if (rmRollback == iRunMode) | ||
474 | iActionType = atCreate; | ||
475 | else | ||
476 | iActionType = atRemove; | ||
477 | |||
478 | // add to action data | ||
479 | hr = AddPartitionToActionData(pItm, iActionType, COST_PARTITION_DELETE, ppwzActionData); | ||
480 | ExitOnFailure(hr, "Failed to add partition to custom action data, key:", pItm->wzKey); | ||
481 | } | ||
482 | |||
483 | // add progress tics | ||
484 | if (piProgress) | ||
485 | *piProgress += COST_PARTITION_DELETE * pList->iUninstallCount; | ||
486 | |||
487 | hr = S_OK; | ||
488 | |||
489 | LExit: | ||
490 | return hr; | ||
491 | } | ||
492 | |||
493 | HRESULT CpiPartitionFindByKey( | ||
494 | CPI_PARTITION_LIST* pList, | ||
495 | LPCWSTR wzKey, | ||
496 | CPI_PARTITION** ppItm | ||
497 | ) | ||
498 | { | ||
499 | for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
500 | { | ||
501 | if (0 == lstrcmpW(pItm->wzKey, wzKey)) | ||
502 | { | ||
503 | *ppItm = pItm; | ||
504 | return S_OK; | ||
505 | } | ||
506 | } | ||
507 | |||
508 | return S_FALSE; | ||
509 | } | ||
510 | |||
511 | HRESULT CpiGetApplicationsCollForPartition( | ||
512 | CPI_PARTITION* pPart, | ||
513 | ICatalogCollection** ppiAppColl | ||
514 | ) | ||
515 | { | ||
516 | HRESULT hr = S_OK; | ||
517 | |||
518 | ICatalogCollection* piPartColl = NULL; | ||
519 | ICatalogObject* piPartObj = NULL; | ||
520 | |||
521 | // if a previous attempt to locate the collection object failed | ||
522 | if (pPart->fObjectNotFound) | ||
523 | ExitFunction1(hr = S_FALSE); | ||
524 | |||
525 | // get applications collection | ||
526 | if (!pPart->piApplicationsColl) | ||
527 | { | ||
528 | // get partitions collection from catalog | ||
529 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
530 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
531 | |||
532 | // find application object | ||
533 | hr = CpiFindCollectionObject(piPartColl, pPart->wzID, *pPart->wzID ? NULL : pPart->wzName, &piPartObj); | ||
534 | ExitOnFailure(hr, "Failed to find partition object"); | ||
535 | |||
536 | if (S_FALSE == hr) | ||
537 | { | ||
538 | pPart->fObjectNotFound = TRUE; | ||
539 | ExitFunction(); // exit with hr = S_FALSE | ||
540 | } | ||
541 | |||
542 | // get roles collection | ||
543 | hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"Applications", &pPart->piApplicationsColl); | ||
544 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
545 | } | ||
546 | |||
547 | // return value | ||
548 | *ppiAppColl = pPart->piApplicationsColl; | ||
549 | (*ppiAppColl)->AddRef(); | ||
550 | |||
551 | hr = S_OK; | ||
552 | |||
553 | LExit: | ||
554 | // clean up | ||
555 | ReleaseObject(piPartColl); | ||
556 | ReleaseObject(piPartObj); | ||
557 | |||
558 | return hr; | ||
559 | } | ||
560 | |||
561 | HRESULT CpiGetRolesCollForPartition( | ||
562 | CPI_PARTITION* pPart, | ||
563 | ICatalogCollection** ppiRolesColl | ||
564 | ) | ||
565 | { | ||
566 | HRESULT hr = S_OK; | ||
567 | |||
568 | ICatalogCollection* piPartColl = NULL; | ||
569 | ICatalogObject* piPartObj = NULL; | ||
570 | |||
571 | // if a previous attempt to locate the collection object failed | ||
572 | if (pPart->fObjectNotFound) | ||
573 | ExitFunction1(hr = S_FALSE); | ||
574 | |||
575 | // get applications collection | ||
576 | if (!pPart->piRolesColl) | ||
577 | { | ||
578 | // get partitions collection from catalog | ||
579 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
580 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
581 | |||
582 | // find partition object | ||
583 | hr = CpiFindCollectionObject(piPartColl, pPart->wzID, *pPart->wzID ? NULL : pPart->wzName, &piPartObj); | ||
584 | ExitOnFailure(hr, "Failed to find partition object"); | ||
585 | |||
586 | if (S_FALSE == hr) | ||
587 | ExitFunction(); // exit with hr = S_FALSE | ||
588 | |||
589 | // get roles collection | ||
590 | hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"RolesForPartition", &pPart->piRolesColl); | ||
591 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
592 | } | ||
593 | |||
594 | // return value | ||
595 | *ppiRolesColl = pPart->piRolesColl; | ||
596 | (*ppiRolesColl)->AddRef(); | ||
597 | |||
598 | hr = S_OK; | ||
599 | |||
600 | LExit: | ||
601 | // clean up | ||
602 | ReleaseObject(piPartColl); | ||
603 | ReleaseObject(piPartObj); | ||
604 | |||
605 | return hr; | ||
606 | } | ||
607 | |||
608 | void CpiPartitionUserListFree( | ||
609 | CPI_PARTITION_USER_LIST* pList | ||
610 | ) | ||
611 | { | ||
612 | CPI_PARTITION_USER* pItm = pList->pFirst; | ||
613 | |||
614 | while (pItm) | ||
615 | { | ||
616 | CPI_PARTITION_USER* pDelete = pItm; | ||
617 | pItm = pItm->pNext; | ||
618 | FreePartitionUser(pDelete); | ||
619 | } | ||
620 | } | ||
621 | |||
622 | HRESULT CpiPartitionUsersRead( | ||
623 | CPI_PARTITION_LIST* pPartList, | ||
624 | CPI_PARTITION_USER_LIST* pPartUsrList | ||
625 | ) | ||
626 | { | ||
627 | HRESULT hr = S_OK; | ||
628 | UINT er = ERROR_SUCCESS; | ||
629 | |||
630 | PMSIHANDLE hView, hRec; | ||
631 | |||
632 | CPI_PARTITION_USER* pItm = NULL; | ||
633 | LPWSTR pwzData = NULL; | ||
634 | LPWSTR pwzDomain = NULL; | ||
635 | LPWSTR pwzName = NULL; | ||
636 | BOOL fMatchingArchitecture = FALSE; | ||
637 | |||
638 | // loop through all partition users | ||
639 | hr = WcaOpenExecuteView(vcsPartitionUserQuery, &hView); | ||
640 | ExitOnFailure(hr, "Failed to execute view on ComPlusPartitionUser table"); | ||
641 | |||
642 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
643 | { | ||
644 | // get component | ||
645 | hr = WcaGetRecordString(hRec, puqComponent, &pwzData); | ||
646 | ExitOnFailure(hr, "Failed to get component"); | ||
647 | |||
648 | // check if the component is our processor architecture | ||
649 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
650 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
651 | |||
652 | if (!fMatchingArchitecture) | ||
653 | { | ||
654 | continue; // not the same architecture, ignore | ||
655 | } | ||
656 | |||
657 | // create entry | ||
658 | pItm = (CPI_PARTITION_USER*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION_USER)); | ||
659 | if (!pItm) | ||
660 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
661 | |||
662 | // get component install state | ||
663 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
664 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
665 | |||
666 | // get key | ||
667 | hr = WcaGetRecordString(hRec, puqPartitionUser, &pwzData); | ||
668 | ExitOnFailure(hr, "Failed to get key"); | ||
669 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
670 | |||
671 | // get partition | ||
672 | hr = WcaGetRecordString(hRec, puqPartition, &pwzData); | ||
673 | ExitOnFailure(hr, "Failed to get partition"); | ||
674 | |||
675 | hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition); | ||
676 | if (S_FALSE == hr) | ||
677 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
678 | ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData); | ||
679 | |||
680 | // get user domain | ||
681 | hr = WcaGetRecordFormattedString(hRec, puqDomain, &pwzDomain); | ||
682 | ExitOnFailure(hr, "Failed to get user domain"); | ||
683 | |||
684 | // get user name | ||
685 | hr = WcaGetRecordFormattedString(hRec, puqName, &pwzName); | ||
686 | ExitOnFailure(hr, "Failed to get user name"); | ||
687 | |||
688 | // build account name | ||
689 | hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount); | ||
690 | ExitOnFailure(hr, "Failed to build account name"); | ||
691 | |||
692 | // set references & increment counters | ||
693 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
694 | { | ||
695 | pItm->pPartition->fReferencedForInstall = TRUE; | ||
696 | pPartUsrList->iInstallCount++; | ||
697 | } | ||
698 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
699 | { | ||
700 | pItm->pPartition->fReferencedForUninstall = TRUE; | ||
701 | pPartUsrList->iUninstallCount++; | ||
702 | } | ||
703 | |||
704 | // add entry | ||
705 | if (pPartUsrList->pFirst) | ||
706 | pItm->pNext = pPartUsrList->pFirst; | ||
707 | pPartUsrList->pFirst = pItm; | ||
708 | pItm = NULL; | ||
709 | } | ||
710 | |||
711 | if (E_NOMOREITEMS == hr) | ||
712 | hr = S_OK; | ||
713 | |||
714 | LExit: | ||
715 | // clean up | ||
716 | if (pItm) | ||
717 | FreePartitionUser(pItm); | ||
718 | |||
719 | ReleaseStr(pwzData); | ||
720 | ReleaseStr(pwzDomain); | ||
721 | ReleaseStr(pwzName); | ||
722 | |||
723 | return hr; | ||
724 | } | ||
725 | |||
726 | HRESULT CpiPartitionUsersInstall( | ||
727 | CPI_PARTITION_USER_LIST* pList, | ||
728 | int iRunMode, | ||
729 | LPWSTR* ppwzActionData, | ||
730 | int* piProgress | ||
731 | ) | ||
732 | { | ||
733 | HRESULT hr = S_OK; | ||
734 | |||
735 | int iActionType; | ||
736 | |||
737 | // add action text | ||
738 | hr = CpiAddActionTextToActionData(L"AddComPlusPartitionUsers", ppwzActionData); | ||
739 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
740 | |||
741 | // add partition count to action data | ||
742 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
743 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
744 | |||
745 | // add applications to custom action data | ||
746 | for (CPI_PARTITION_USER* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
747 | { | ||
748 | // partitions that are being installed only | ||
749 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
750 | continue; | ||
751 | |||
752 | // action type | ||
753 | if (rmRollback == iRunMode) | ||
754 | { | ||
755 | if (CpiIsInstalled(pItm->isInstalled)) | ||
756 | iActionType = atNoOp; | ||
757 | else | ||
758 | iActionType = atRemove; | ||
759 | } | ||
760 | else | ||
761 | iActionType = atCreate; | ||
762 | |||
763 | // add to action data | ||
764 | hr = AddPartitionUserToActionData(pItm, iActionType, COST_PARTITION_USER_CREATE, ppwzActionData); | ||
765 | ExitOnFailure(hr, "Failed to add partition user to custom action data, key: %S", pItm->wzKey); | ||
766 | } | ||
767 | |||
768 | // add progress tics | ||
769 | if (piProgress) | ||
770 | *piProgress += COST_PARTITION_USER_CREATE * pList->iInstallCount; | ||
771 | |||
772 | hr = S_OK; | ||
773 | |||
774 | LExit: | ||
775 | return hr; | ||
776 | } | ||
777 | |||
778 | HRESULT CpiPartitionUsersUninstall( | ||
779 | CPI_PARTITION_USER_LIST* pList, | ||
780 | int iRunMode, | ||
781 | LPWSTR* ppwzActionData, | ||
782 | int* piProgress | ||
783 | ) | ||
784 | { | ||
785 | HRESULT hr = S_OK; | ||
786 | |||
787 | int iActionType; | ||
788 | |||
789 | // add action text | ||
790 | hr = CpiAddActionTextToActionData(L"RemoveComPlusPartitionUsers", ppwzActionData); | ||
791 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
792 | |||
793 | // add partition count to action data | ||
794 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
795 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
796 | |||
797 | // add partitions to custom action data | ||
798 | for (CPI_PARTITION_USER* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
799 | { | ||
800 | // partitions that are being uninstalled only | ||
801 | if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
802 | continue; | ||
803 | |||
804 | // action type | ||
805 | if (rmRollback == iRunMode) | ||
806 | iActionType = atCreate; | ||
807 | else | ||
808 | iActionType = atRemove; | ||
809 | |||
810 | // add to action data | ||
811 | hr = AddPartitionUserToActionData(pItm, iActionType, COST_PARTITION_USER_DELETE, ppwzActionData); | ||
812 | ExitOnFailure(hr, "Failed to add partition user to custom action data, key: %S", pItm->wzKey); | ||
813 | } | ||
814 | |||
815 | // add progress tics | ||
816 | if (piProgress) | ||
817 | *piProgress += COST_PARTITION_USER_DELETE * pList->iUninstallCount; | ||
818 | |||
819 | hr = S_OK; | ||
820 | |||
821 | LExit: | ||
822 | return hr; | ||
823 | } | ||
824 | |||
825 | |||
826 | // helper function definitions | ||
827 | |||
828 | static void FreePartition( | ||
829 | CPI_PARTITION* pItm | ||
830 | ) | ||
831 | { | ||
832 | if (pItm->pProperties) | ||
833 | CpiPropertiesFreeList(pItm->pProperties); | ||
834 | |||
835 | ReleaseObject(pItm->piApplicationsColl); | ||
836 | ReleaseObject(pItm->piRolesColl); | ||
837 | |||
838 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
839 | } | ||
840 | |||
841 | static void FreePartitionUser( | ||
842 | CPI_PARTITION_USER* pItm | ||
843 | ) | ||
844 | { | ||
845 | ReleaseStr(pItm->pwzAccount); | ||
846 | |||
847 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
848 | } | ||
849 | |||
850 | static HRESULT AddPartitionToActionData( | ||
851 | CPI_PARTITION* pItm, | ||
852 | int iActionType, | ||
853 | int iActionCost, | ||
854 | LPWSTR* ppwzActionData | ||
855 | ) | ||
856 | { | ||
857 | HRESULT hr = S_OK; | ||
858 | |||
859 | // add action information to custom action data | ||
860 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
861 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
862 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
863 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
864 | |||
865 | // add partition information to custom action data | ||
866 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
867 | ExitOnFailure(hr, "Failed to add partition key to custom action data"); | ||
868 | hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData); | ||
869 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
870 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
871 | ExitOnFailure(hr, "Failed to add partition name to custom action data"); | ||
872 | |||
873 | // add properties to custom action data | ||
874 | hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
875 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
876 | |||
877 | hr = S_OK; | ||
878 | |||
879 | LExit: | ||
880 | return hr; | ||
881 | } | ||
882 | |||
883 | static HRESULT AddPartitionUserToActionData( | ||
884 | CPI_PARTITION_USER* pItm, | ||
885 | int iActionType, | ||
886 | int iActionCost, | ||
887 | LPWSTR* ppwzActionData | ||
888 | ) | ||
889 | { | ||
890 | HRESULT hr = S_OK; | ||
891 | |||
892 | // add action information to custom action data | ||
893 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
894 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
895 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
896 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
897 | |||
898 | // add partition user information to custom action data | ||
899 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
900 | ExitOnFailure(hr, "Failed to add partition user key to custom action data"); | ||
901 | hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData); | ||
902 | ExitOnFailure(hr, "Failed to add user account to custom action data"); | ||
903 | |||
904 | // add partition information to custom action data | ||
905 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pPartition->wzID : L"", ppwzActionData); | ||
906 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
907 | |||
908 | hr = S_OK; | ||
909 | |||
910 | LExit: | ||
911 | return hr; | ||
912 | } | ||
diff --git a/src/ca/cppartsched.h b/src/ca/cppartsched.h new file mode 100644 index 00000000..55085912 --- /dev/null +++ b/src/ca/cppartsched.h | |||
@@ -0,0 +1,125 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | struct CPI_PARTITION | ||
6 | { | ||
7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
8 | WCHAR wzID[CPI_MAX_GUID + 1]; | ||
9 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
10 | |||
11 | int iPropertyCount; | ||
12 | CPI_PROPERTY* pProperties; | ||
13 | |||
14 | BOOL fHasComponent; | ||
15 | BOOL fReferencedForInstall; | ||
16 | BOOL fReferencedForUninstall; | ||
17 | BOOL fObjectNotFound; | ||
18 | |||
19 | INSTALLSTATE isInstalled, isAction; | ||
20 | |||
21 | ICatalogCollection* piApplicationsColl; | ||
22 | ICatalogCollection* piRolesColl; | ||
23 | |||
24 | CPI_PARTITION* pNext; | ||
25 | }; | ||
26 | |||
27 | struct CPI_PARTITION_LIST | ||
28 | { | ||
29 | CPI_PARTITION* pFirst; | ||
30 | |||
31 | int iInstallCount; | ||
32 | int iUninstallCount; | ||
33 | }; | ||
34 | |||
35 | struct CPI_PARTITION_USER | ||
36 | { | ||
37 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
38 | LPWSTR pwzAccount; | ||
39 | |||
40 | BOOL fNoFind; | ||
41 | |||
42 | INSTALLSTATE isInstalled, isAction; | ||
43 | |||
44 | CPI_PARTITION* pPartition; | ||
45 | |||
46 | CPI_PARTITION_USER* pNext; | ||
47 | }; | ||
48 | |||
49 | struct CPI_PARTITION_USER_LIST | ||
50 | { | ||
51 | CPI_PARTITION_USER* pFirst; | ||
52 | |||
53 | int iInstallCount; | ||
54 | int iUninstallCount; | ||
55 | }; | ||
56 | |||
57 | |||
58 | // function prototypes | ||
59 | |||
60 | void CpiPartitionListFree( | ||
61 | CPI_PARTITION_LIST* pList | ||
62 | ); | ||
63 | HRESULT CpiPartitionsRead( | ||
64 | CPI_PARTITION_LIST* pPartList | ||
65 | ); | ||
66 | HRESULT CpiPartitionsVerifyInstall( | ||
67 | CPI_PARTITION_LIST* pList | ||
68 | ); | ||
69 | HRESULT CpiPartitionsVerifyUninstall( | ||
70 | CPI_PARTITION_LIST* pList | ||
71 | ); | ||
72 | void CpiPartitionAddReferenceInstall( | ||
73 | CPI_PARTITION* pItm | ||
74 | ); | ||
75 | void CpiPartitionAddReferenceUninstall( | ||
76 | CPI_PARTITION* pItm | ||
77 | ); | ||
78 | HRESULT CpiPartitionsInstall( | ||
79 | CPI_PARTITION_LIST* pList, | ||
80 | int iRunMode, | ||
81 | LPWSTR* ppwzActionData, | ||
82 | int* piProgress | ||
83 | ); | ||
84 | HRESULT CpiPartitionsUninstall( | ||
85 | CPI_PARTITION_LIST* pList, | ||
86 | int iRunMode, | ||
87 | LPWSTR* ppwzActionData, | ||
88 | int* piProgress | ||
89 | ); | ||
90 | HRESULT CpiPartitionFindByKey( | ||
91 | CPI_PARTITION_LIST* pList, | ||
92 | LPCWSTR wzKey, | ||
93 | CPI_PARTITION** ppItm | ||
94 | ); | ||
95 | HRESULT CpiGetApplicationsCollForPartition( | ||
96 | CPI_PARTITION* pPart, | ||
97 | ICatalogCollection** ppiAppColl | ||
98 | ); | ||
99 | HRESULT CpiGetPartitionUsersCollection( | ||
100 | CPI_PARTITION* pPart, | ||
101 | ICatalogCollection** ppiPartUsrColl | ||
102 | ); | ||
103 | HRESULT CpiGetRolesCollForPartition( | ||
104 | CPI_PARTITION* pPart, | ||
105 | ICatalogCollection** ppiRolesColl | ||
106 | ); | ||
107 | void CpiPartitionUserListFree( | ||
108 | CPI_PARTITION_USER_LIST* pList | ||
109 | ); | ||
110 | HRESULT CpiPartitionUsersRead( | ||
111 | CPI_PARTITION_LIST* pPartList, | ||
112 | CPI_PARTITION_USER_LIST* pPartUsrList | ||
113 | ); | ||
114 | HRESULT CpiPartitionUsersInstall( | ||
115 | CPI_PARTITION_USER_LIST* pList, | ||
116 | int iRunMode, | ||
117 | LPWSTR* ppwzActionData, | ||
118 | int* piProgress | ||
119 | ); | ||
120 | HRESULT CpiPartitionUsersUninstall( | ||
121 | CPI_PARTITION_USER_LIST* pList, | ||
122 | int iRunMode, | ||
123 | LPWSTR* ppwzActionData, | ||
124 | int* piProgress | ||
125 | ); | ||
diff --git a/src/ca/cpsched.cpp b/src/ca/cpsched.cpp new file mode 100644 index 00000000..ac0dda59 --- /dev/null +++ b/src/ca/cpsched.cpp | |||
@@ -0,0 +1,590 @@ | |||
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 | #ifdef _WIN64 | ||
7 | #define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare_64" | ||
8 | #define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare_64" | ||
9 | #define CP_COMPLUSROLLBACKINSTALLEXECUTE L"ComPlusRollbackInstallExecute_64" | ||
10 | #define CP_COMPLUSINSTALLEXECUTE L"ComPlusInstallExecute_64" | ||
11 | #define CP_COMPLUSINSTALLEXECUTECOMMIT L"ComPlusInstallExecuteCommit_64" | ||
12 | #define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit_64" | ||
13 | #define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare_64" | ||
14 | #define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare_64" | ||
15 | #define CP_COMPLUSROLLBACKUNINSTALLEXECUTE L"ComPlusRollbackUninstallExecute_64" | ||
16 | #define CP_COMPLUSUNINSTALLEXECUTE L"ComPlusUninstallExecute_64" | ||
17 | #define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit_64" | ||
18 | #else | ||
19 | #define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare" | ||
20 | #define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare" | ||
21 | #define CP_COMPLUSROLLBACKINSTALLEXECUTE L"ComPlusRollbackInstallExecute" | ||
22 | #define CP_COMPLUSINSTALLEXECUTE L"ComPlusInstallExecute" | ||
23 | #define CP_COMPLUSINSTALLEXECUTECOMMIT L"ComPlusInstallExecuteCommit" | ||
24 | #define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit" | ||
25 | #define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare" | ||
26 | #define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare" | ||
27 | #define CP_COMPLUSROLLBACKUNINSTALLEXECUTE L"ComPlusRollbackUninstallExecute" | ||
28 | #define CP_COMPLUSUNINSTALLEXECUTE L"ComPlusUninstallExecute" | ||
29 | #define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit" | ||
30 | #endif | ||
31 | |||
32 | |||
33 | /******************************************************************** | ||
34 | DllMain - standard entry point for all WiX CustomActions | ||
35 | |||
36 | ********************************************************************/ | ||
37 | extern "C" BOOL WINAPI DllMain( | ||
38 | IN HINSTANCE hInst, | ||
39 | IN ULONG ulReason, | ||
40 | IN LPVOID) | ||
41 | { | ||
42 | switch(ulReason) | ||
43 | { | ||
44 | case DLL_PROCESS_ATTACH: | ||
45 | WcaGlobalInitialize(hInst); | ||
46 | break; | ||
47 | |||
48 | case DLL_PROCESS_DETACH: | ||
49 | WcaGlobalFinalize(); | ||
50 | break; | ||
51 | } | ||
52 | |||
53 | return TRUE; | ||
54 | } | ||
55 | |||
56 | /******************************************************************** | ||
57 | ConfigureComPlusInstall - CUSTOM ACTION ENTRY POINT for installing COM+ components | ||
58 | |||
59 | ********************************************************************/ | ||
60 | extern "C" UINT __stdcall ConfigureComPlusInstall(MSIHANDLE hInstall) | ||
61 | { | ||
62 | HRESULT hr = S_OK; | ||
63 | UINT er = ERROR_SUCCESS; | ||
64 | |||
65 | BOOL fInitializedCom = FALSE; | ||
66 | |||
67 | ICOMAdminCatalog* piCatalog = NULL; | ||
68 | |||
69 | CPI_PARTITION_LIST partList; | ||
70 | CPI_PARTITION_ROLE_LIST partRoleList; | ||
71 | CPI_USER_IN_PARTITION_ROLE_LIST usrInPartRoleList; | ||
72 | CPI_PARTITION_USER_LIST partUsrList; | ||
73 | CPI_APPLICATION_LIST appList; | ||
74 | CPI_APPLICATION_ROLE_LIST appRoleList; | ||
75 | CPI_USER_IN_APPLICATION_ROLE_LIST usrInAppRoleList; | ||
76 | CPI_ASSEMBLY_LIST asmList; | ||
77 | CPI_SUBSCRIPTION_LIST subList; | ||
78 | |||
79 | LPWSTR pwzRollbackFileName = NULL; | ||
80 | LPWSTR pwzActionData = NULL; | ||
81 | LPWSTR pwzRollbackActionData = NULL; | ||
82 | LPWSTR pwzCommitActionData = NULL; | ||
83 | |||
84 | int iVersionNT = 0; | ||
85 | int iProgress = 0; | ||
86 | int iCommitProgress = 0; | ||
87 | |||
88 | ::ZeroMemory(&partList, sizeof(CPI_PARTITION_LIST)); | ||
89 | ::ZeroMemory(&partRoleList, sizeof(CPI_PARTITION_ROLE_LIST)); | ||
90 | ::ZeroMemory(&usrInPartRoleList, sizeof(CPI_USER_IN_PARTITION_ROLE_LIST)); | ||
91 | ::ZeroMemory(&partUsrList, sizeof(CPI_PARTITION_USER_LIST)); | ||
92 | ::ZeroMemory(&appList, sizeof(CPI_APPLICATION_LIST)); | ||
93 | ::ZeroMemory(&appRoleList, sizeof(CPI_APPLICATION_ROLE_LIST)); | ||
94 | ::ZeroMemory(&usrInAppRoleList, sizeof(CPI_USER_IN_APPLICATION_ROLE_LIST)); | ||
95 | ::ZeroMemory(&asmList, sizeof(CPI_ASSEMBLY_LIST)); | ||
96 | ::ZeroMemory(&subList, sizeof(CPI_SUBSCRIPTION_LIST)); | ||
97 | |||
98 | // initialize | ||
99 | hr = WcaInitialize(hInstall, "ConfigureComPlusInstall"); | ||
100 | ExitOnFailure(hr, "Failed to initialize"); | ||
101 | |||
102 | hr = ::CoInitialize(NULL); | ||
103 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
104 | fInitializedCom = TRUE; | ||
105 | |||
106 | CpiInitialize(); | ||
107 | |||
108 | // check for the prerequsite tables | ||
109 | if (!CpiTableExists(cptComPlusPartition) && !CpiTableExists(cptComPlusApplication) && !CpiTableExists(cptComPlusAssembly)) | ||
110 | { | ||
111 | WcaLog(LOGMSG_VERBOSE, "skipping install COM+ CustomAction, no ComPlusPartition, ComPlusApplication or ComPlusAssembly table present"); | ||
112 | ExitFunction1(hr = S_FALSE); | ||
113 | } | ||
114 | |||
115 | // make sure we can access the COM+ admin catalog | ||
116 | do { | ||
117 | hr = CpiGetAdminCatalog(&piCatalog); | ||
118 | if (FAILED(hr)) | ||
119 | { | ||
120 | WcaLog(LOGMSG_STANDARD, "Failed to get COM+ admin catalog"); | ||
121 | er = WcaErrorMessage(msierrComPlusCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
122 | switch (er) | ||
123 | { | ||
124 | case IDABORT: | ||
125 | ExitFunction(); // exit with hr from CpiGetAdminCatalog() to kick off a rollback | ||
126 | case IDRETRY: | ||
127 | hr = S_FALSE; | ||
128 | break; | ||
129 | case IDIGNORE: | ||
130 | default: | ||
131 | ExitFunction1(hr = S_OK); // pretend everything is okay and bail | ||
132 | } | ||
133 | } | ||
134 | } while (S_FALSE == hr); | ||
135 | |||
136 | // get NT version | ||
137 | hr = WcaGetIntProperty(L"VersionNT", &iVersionNT); | ||
138 | ExitOnFailure(hr, "Failed to get VersionNT property"); | ||
139 | |||
140 | // read elements | ||
141 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartition)) | ||
142 | { | ||
143 | hr = CpiPartitionsRead(&partList); | ||
144 | MessageExitOnFailure(hr, msierrComPlusPartitionReadFailed, "Failed to read ComPlusPartitions table"); | ||
145 | } | ||
146 | |||
147 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionRole)) | ||
148 | { | ||
149 | hr = CpiPartitionRolesRead(&partList, &partRoleList); | ||
150 | MessageExitOnFailure(hr, msierrComPlusPartitionRoleReadFailed, "Failed to read ComPlusPartitionRole table"); | ||
151 | } | ||
152 | |||
153 | if (502 <= iVersionNT && (CpiTableExists(cptComPlusUserInPartitionRole) || CpiTableExists(cptComPlusGroupInPartitionRole))) | ||
154 | { | ||
155 | hr = CpiUsersInPartitionRolesRead(&partRoleList, &usrInPartRoleList); | ||
156 | MessageExitOnFailure(hr, msierrComPlusUserInPartitionRoleReadFailed, "Failed to read ComPlusUserInPartitionRole table"); | ||
157 | } | ||
158 | |||
159 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionUser)) | ||
160 | { | ||
161 | hr = CpiPartitionUsersRead(&partList, &partUsrList); | ||
162 | MessageExitOnFailure(hr, msierrComPlusPartitionUserReadFailed, "Failed to read ComPlusPartitionUser table"); | ||
163 | } | ||
164 | |||
165 | if (CpiTableExists(cptComPlusApplication)) | ||
166 | { | ||
167 | hr = CpiApplicationsRead(&partList, &appList); | ||
168 | MessageExitOnFailure(hr, msierrComPlusApplicationReadFailed, "Failed to read ComPlusApplication table"); | ||
169 | } | ||
170 | |||
171 | if (CpiTableExists(cptComPlusApplicationRole)) | ||
172 | { | ||
173 | hr = CpiApplicationRolesRead(&appList, &appRoleList); | ||
174 | MessageExitOnFailure(hr, msierrComPlusApplicationRoleReadFailed, "Failed to read ComPlusApplicationRole table"); | ||
175 | } | ||
176 | |||
177 | if (CpiTableExists(cptComPlusUserInApplicationRole) || CpiTableExists(cptComPlusGroupInApplicationRole)) | ||
178 | { | ||
179 | hr = CpiUsersInApplicationRolesRead(&appRoleList, &usrInAppRoleList); | ||
180 | MessageExitOnFailure(hr, msierrComPlusUserInApplicationRoleReadFailed, "Failed to read ComPlusUserInApplicationRole table"); | ||
181 | } | ||
182 | |||
183 | if (CpiTableExists(cptComPlusAssembly)) | ||
184 | { | ||
185 | hr = CpiAssembliesRead(&appList, &appRoleList, &asmList); | ||
186 | MessageExitOnFailure(hr, msierrComPlusAssembliesReadFailed, "Failed to read ComPlusAssembly table"); | ||
187 | } | ||
188 | |||
189 | if (CpiTableExists(cptComPlusSubscription)) | ||
190 | { | ||
191 | hr = CpiSubscriptionsRead(&asmList, &subList); | ||
192 | MessageExitOnFailure(hr, msierrComPlusSubscriptionReadFailed, "Failed to read ComPlusSubscription table"); | ||
193 | } | ||
194 | |||
195 | // verify elements | ||
196 | hr = CpiPartitionsVerifyInstall(&partList); | ||
197 | ExitOnFailure(hr, "Failed to verify partitions"); | ||
198 | |||
199 | hr = CpiApplicationsVerifyInstall(&appList); | ||
200 | ExitOnFailure(hr, "Failed to verify applications"); | ||
201 | |||
202 | hr = CpiApplicationRolesVerifyInstall(&appRoleList); | ||
203 | ExitOnFailure(hr, "Failed to verify application roles"); | ||
204 | |||
205 | hr = CpiAssembliesVerifyInstall(&asmList); | ||
206 | ExitOnFailure(hr, "Failed to verify assemblies"); | ||
207 | |||
208 | if (subList.iInstallCount) | ||
209 | { | ||
210 | hr = CpiSubscriptionsVerifyInstall(&subList); | ||
211 | ExitOnFailure(hr, "Failed to verify subscriptions"); | ||
212 | } | ||
213 | |||
214 | // schedule | ||
215 | if (partList.iInstallCount || appList.iInstallCount || usrInAppRoleList.iInstallCount || | ||
216 | appRoleList.iInstallCount || asmList.iInstallCount || asmList.iRoleInstallCount || subList.iInstallCount) | ||
217 | { | ||
218 | // create rollback file name | ||
219 | hr = CpiGetTempFileName(&pwzRollbackFileName); | ||
220 | ExitOnFailure(hr, "Failed to get rollback file name"); | ||
221 | |||
222 | // schedule rollback prepare custom action | ||
223 | hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKINSTALLPREPARE, pwzRollbackFileName, 0); | ||
224 | ExitOnFailure(hr, "Failed to schedule ComPlusRollbackInstallPrepare"); | ||
225 | |||
226 | // schedule prepare custom action | ||
227 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLPREPARE, pwzRollbackFileName, 0); | ||
228 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallPrepare"); | ||
229 | |||
230 | // schedule rollback custom action | ||
231 | hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzRollbackActionData); | ||
232 | ExitOnFailure(hr, "Failed to add rollback file name to rollback custom action data"); | ||
233 | |||
234 | hr = CpiSubscriptionsInstall(&subList, rmRollback, &pwzRollbackActionData, NULL); | ||
235 | ExitOnFailure(hr, "Failed to install subscriptions"); | ||
236 | hr = CpiRoleAssignmentsInstall(&asmList, rmRollback, &pwzRollbackActionData, NULL); | ||
237 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
238 | hr = CpiAssembliesInstall(&asmList, rmRollback, &pwzRollbackActionData, NULL); | ||
239 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
240 | hr = CpiUsersInApplicationRolesInstall(&usrInAppRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
241 | ExitOnFailure(hr, "Failed to install users in application roles"); | ||
242 | hr = CpiApplicationRolesInstall(&appRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
243 | ExitOnFailure(hr, "Failed to install application roles"); | ||
244 | hr = CpiApplicationsInstall(&appList, rmRollback, &pwzRollbackActionData, NULL); | ||
245 | ExitOnFailure(hr, "Failed to install applications"); | ||
246 | hr = CpiPartitionUsersInstall(&partUsrList, rmRollback, &pwzRollbackActionData, NULL); | ||
247 | ExitOnFailure(hr, "Failed to install partition users"); | ||
248 | hr = CpiUsersInPartitionRolesInstall(&usrInPartRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
249 | ExitOnFailure(hr, "Failed to install users in partition roles"); | ||
250 | hr = CpiPartitionsInstall(&partList, rmRollback, &pwzRollbackActionData, NULL); | ||
251 | ExitOnFailure(hr, "Failed to install partitions"); | ||
252 | |||
253 | hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKINSTALLEXECUTE, pwzRollbackActionData, 0); | ||
254 | ExitOnFailure(hr, "Failed to schedule ComPlusRollbackInstallExecute"); | ||
255 | |||
256 | // schedule install custom action | ||
257 | hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzActionData); | ||
258 | ExitOnFailure(hr, "Failed to add rollback file name to custom action data"); | ||
259 | |||
260 | hr = CpiPartitionsInstall(&partList, rmDeferred, &pwzActionData, &iProgress); | ||
261 | ExitOnFailure(hr, "Failed to install partitions"); | ||
262 | hr = CpiUsersInPartitionRolesInstall(&usrInPartRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
263 | ExitOnFailure(hr, "Failed to install users in partition roles"); | ||
264 | hr = CpiPartitionUsersInstall(&partUsrList, rmDeferred, &pwzActionData, &iProgress); | ||
265 | ExitOnFailure(hr, "Failed to install partition users"); | ||
266 | hr = CpiApplicationsInstall(&appList, rmDeferred, &pwzActionData, &iProgress); | ||
267 | ExitOnFailure(hr, "Failed to install applications"); | ||
268 | hr = CpiApplicationRolesInstall(&appRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
269 | ExitOnFailure(hr, "Failed to install application roles"); | ||
270 | hr = CpiUsersInApplicationRolesInstall(&usrInAppRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
271 | ExitOnFailure(hr, "Failed to install users in application roles"); | ||
272 | hr = CpiAssembliesInstall(&asmList, rmDeferred, &pwzActionData, &iProgress); | ||
273 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
274 | hr = CpiRoleAssignmentsInstall(&asmList, rmDeferred, &pwzActionData, &iProgress); | ||
275 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
276 | hr = CpiSubscriptionsInstall(&subList, rmDeferred, &pwzActionData, &iProgress); | ||
277 | ExitOnFailure(hr, "Failed to install subscriptions"); | ||
278 | |||
279 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLEXECUTE, pwzActionData, iProgress); | ||
280 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallExecute"); | ||
281 | |||
282 | // schedule install commit custom action | ||
283 | hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzCommitActionData); | ||
284 | ExitOnFailure(hr, "Failed to add rollback file name to commit custom action data"); | ||
285 | |||
286 | hr = CpiAssembliesInstall(&asmList, rmCommit, &pwzCommitActionData, &iCommitProgress); | ||
287 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
288 | hr = CpiRoleAssignmentsInstall(&asmList, rmCommit, &pwzCommitActionData, &iCommitProgress); | ||
289 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
290 | hr = CpiSubscriptionsInstall(&subList, rmCommit, &pwzCommitActionData, &iCommitProgress); | ||
291 | ExitOnFailure(hr, "Failed to install subscriptions"); | ||
292 | |||
293 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLEXECUTECOMMIT, pwzCommitActionData, iCommitProgress); | ||
294 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallExecuteCommit"); | ||
295 | |||
296 | // schedule commit custom action | ||
297 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLCOMMIT, pwzRollbackFileName, 0); | ||
298 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallCommit"); | ||
299 | } | ||
300 | |||
301 | hr = S_OK; | ||
302 | |||
303 | LExit: | ||
304 | // clean up | ||
305 | ReleaseObject(piCatalog); | ||
306 | |||
307 | ReleaseStr(pwzRollbackFileName); | ||
308 | ReleaseStr(pwzActionData); | ||
309 | ReleaseStr(pwzRollbackActionData); | ||
310 | ReleaseStr(pwzCommitActionData); | ||
311 | |||
312 | CpiPartitionListFree(&partList); | ||
313 | CpiPartitionRoleListFree(&partRoleList); | ||
314 | CpiUserInPartitionRoleListFree(&usrInPartRoleList); | ||
315 | CpiPartitionUserListFree(&partUsrList); | ||
316 | CpiApplicationListFree(&appList); | ||
317 | CpiApplicationRoleListFree(&appRoleList); | ||
318 | CpiUserInApplicationRoleListFree(&usrInAppRoleList); | ||
319 | CpiAssemblyListFree(&asmList); | ||
320 | CpiSubscriptionListFree(&subList); | ||
321 | |||
322 | // unitialize | ||
323 | CpiFinalize(); | ||
324 | |||
325 | if (fInitializedCom) | ||
326 | ::CoUninitialize(); | ||
327 | |||
328 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
329 | return WcaFinalize(er); | ||
330 | } | ||
331 | |||
332 | |||
333 | /******************************************************************** | ||
334 | ConfigureComPlusUninstall - CUSTOM ACTION ENTRY POINT for uninstalling COM+ components | ||
335 | |||
336 | ********************************************************************/ | ||
337 | extern "C" UINT __stdcall ConfigureComPlusUninstall(MSIHANDLE hInstall) | ||
338 | { | ||
339 | HRESULT hr = S_OK; | ||
340 | UINT er = ERROR_SUCCESS; | ||
341 | |||
342 | BOOL fInitializedCom = FALSE; | ||
343 | |||
344 | ICOMAdminCatalog* piCatalog = NULL; | ||
345 | |||
346 | CPI_PARTITION_LIST partList; | ||
347 | CPI_PARTITION_ROLE_LIST partRoleList; | ||
348 | CPI_USER_IN_PARTITION_ROLE_LIST usrInPartRoleList; | ||
349 | CPI_PARTITION_USER_LIST partUsrList; | ||
350 | CPI_APPLICATION_LIST appList; | ||
351 | CPI_APPLICATION_ROLE_LIST appRoleList; | ||
352 | CPI_USER_IN_APPLICATION_ROLE_LIST usrInAppRoleList; | ||
353 | CPI_ASSEMBLY_LIST asmList; | ||
354 | CPI_SUBSCRIPTION_LIST subList; | ||
355 | |||
356 | LPWSTR pwzRollbackFileName = NULL; | ||
357 | LPWSTR pwzActionData = NULL; | ||
358 | LPWSTR pwzRollbackActionData = NULL; | ||
359 | |||
360 | int iVersionNT = 0; | ||
361 | int iProgress = 0; | ||
362 | |||
363 | ::ZeroMemory(&partList, sizeof(CPI_PARTITION_LIST)); | ||
364 | ::ZeroMemory(&partRoleList, sizeof(CPI_PARTITION_ROLE_LIST)); | ||
365 | ::ZeroMemory(&usrInPartRoleList, sizeof(CPI_USER_IN_PARTITION_ROLE_LIST)); | ||
366 | ::ZeroMemory(&partUsrList, sizeof(CPI_PARTITION_USER_LIST)); | ||
367 | ::ZeroMemory(&appList, sizeof(CPI_APPLICATION_LIST)); | ||
368 | ::ZeroMemory(&appRoleList, sizeof(CPI_APPLICATION_ROLE_LIST)); | ||
369 | ::ZeroMemory(&usrInAppRoleList, sizeof(CPI_USER_IN_APPLICATION_ROLE_LIST)); | ||
370 | ::ZeroMemory(&asmList, sizeof(CPI_ASSEMBLY_LIST)); | ||
371 | ::ZeroMemory(&subList, sizeof(CPI_SUBSCRIPTION_LIST)); | ||
372 | |||
373 | // initialize | ||
374 | hr = WcaInitialize(hInstall, "ConfigureComPlusUninstall"); | ||
375 | ExitOnFailure(hr, "Failed to initialize"); | ||
376 | |||
377 | hr = ::CoInitialize(NULL); | ||
378 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
379 | fInitializedCom = TRUE; | ||
380 | |||
381 | CpiInitialize(); | ||
382 | |||
383 | // check for the prerequsite tables | ||
384 | if (!CpiTableExists(cptComPlusPartition) && !CpiTableExists(cptComPlusApplication) && !CpiTableExists(cptComPlusAssembly)) | ||
385 | { | ||
386 | WcaLog(LOGMSG_VERBOSE, "skipping uninstall COM+ CustomAction, no ComPlusPartition, ComPlusApplication or ComPlusAssembly table present"); | ||
387 | ExitFunction1(hr = S_FALSE); | ||
388 | } | ||
389 | |||
390 | // make sure we can access the COM+ admin catalog | ||
391 | do { | ||
392 | hr = CpiGetAdminCatalog(&piCatalog); | ||
393 | if (FAILED(hr)) | ||
394 | { | ||
395 | WcaLog(LOGMSG_STANDARD, "Failed to get COM+ admin catalog"); | ||
396 | er = WcaErrorMessage(msierrComPlusCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
397 | switch (er) | ||
398 | { | ||
399 | case IDABORT: | ||
400 | ExitFunction(); // exit with hr from CpiGetAdminCatalog() to kick off a rollback | ||
401 | case IDRETRY: | ||
402 | hr = S_FALSE; | ||
403 | break; | ||
404 | case IDIGNORE: | ||
405 | default: | ||
406 | ExitFunction1(hr = S_OK); // pretend everything is okay and bail | ||
407 | } | ||
408 | } | ||
409 | } while (S_FALSE == hr); | ||
410 | |||
411 | // get NT version | ||
412 | hr = WcaGetIntProperty(L"VersionNT", &iVersionNT); | ||
413 | ExitOnFailure(hr, "Failed to get VersionNT property"); | ||
414 | |||
415 | // read elements | ||
416 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartition)) | ||
417 | { | ||
418 | hr = CpiPartitionsRead(&partList); | ||
419 | MessageExitOnFailure(hr, msierrComPlusPartitionReadFailed, "Failed to read ComPlusPartitions table"); | ||
420 | } | ||
421 | |||
422 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionRole)) | ||
423 | { | ||
424 | hr = CpiPartitionRolesRead(&partList, &partRoleList); | ||
425 | MessageExitOnFailure(hr, msierrComPlusPartitionRoleReadFailed, "Failed to read ComPlusPartitionRole table"); | ||
426 | } | ||
427 | |||
428 | if (502 <= iVersionNT && (CpiTableExists(cptComPlusUserInPartitionRole) || CpiTableExists(cptComPlusGroupInPartitionRole))) | ||
429 | { | ||
430 | hr = CpiUsersInPartitionRolesRead(&partRoleList, &usrInPartRoleList); | ||
431 | MessageExitOnFailure(hr, msierrComPlusUserInPartitionRoleReadFailed, "Failed to read ComPlusUserInPartitionRole table"); | ||
432 | } | ||
433 | |||
434 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionUser)) | ||
435 | { | ||
436 | hr = CpiPartitionUsersRead(&partList, &partUsrList); | ||
437 | MessageExitOnFailure(hr, msierrComPlusPartitionUserReadFailed, "Failed to read ComPlusPartitionUser table"); | ||
438 | } | ||
439 | |||
440 | if (CpiTableExists(cptComPlusApplication)) | ||
441 | { | ||
442 | hr = CpiApplicationsRead(&partList, &appList); | ||
443 | MessageExitOnFailure(hr, msierrComPlusApplicationReadFailed, "Failed to read ComPlusApplication table"); | ||
444 | } | ||
445 | |||
446 | if (CpiTableExists(cptComPlusApplicationRole)) | ||
447 | { | ||
448 | hr = CpiApplicationRolesRead(&appList, &appRoleList); | ||
449 | MessageExitOnFailure(hr, msierrComPlusApplicationRoleReadFailed, "Failed to read ComPlusApplicationRole table"); | ||
450 | } | ||
451 | |||
452 | if (CpiTableExists(cptComPlusUserInApplicationRole) || CpiTableExists(cptComPlusGroupInApplicationRole)) | ||
453 | { | ||
454 | hr = CpiUsersInApplicationRolesRead(&appRoleList, &usrInAppRoleList); | ||
455 | MessageExitOnFailure(hr, msierrComPlusUserInApplicationRoleReadFailed, "Failed to read ComPlusUserInApplicationRole table"); | ||
456 | } | ||
457 | |||
458 | if (CpiTableExists(cptComPlusAssembly)) | ||
459 | { | ||
460 | hr = CpiAssembliesRead(&appList, &appRoleList, &asmList); | ||
461 | MessageExitOnFailure(hr, msierrComPlusAssembliesReadFailed, "Failed to read ComPlusAssembly table"); | ||
462 | } | ||
463 | |||
464 | if (CpiTableExists(cptComPlusSubscription)) | ||
465 | { | ||
466 | hr = CpiSubscriptionsRead(&asmList, &subList); | ||
467 | MessageExitOnFailure(hr, msierrComPlusSubscriptionReadFailed, "Failed to read ComPlusSubscription table"); | ||
468 | } | ||
469 | |||
470 | // verify elements | ||
471 | hr = CpiPartitionsVerifyUninstall(&partList); | ||
472 | ExitOnFailure(hr, "Failed to verify partitions"); | ||
473 | |||
474 | hr = CpiApplicationsVerifyUninstall(&appList); | ||
475 | ExitOnFailure(hr, "Failed to verify applications"); | ||
476 | |||
477 | hr = CpiApplicationRolesVerifyUninstall(&appRoleList); | ||
478 | ExitOnFailure(hr, "Failed to verify application roles"); | ||
479 | |||
480 | hr = CpiAssembliesVerifyUninstall(&asmList); | ||
481 | ExitOnFailure(hr, "Failed to verify assemblies"); | ||
482 | |||
483 | if (subList.iUninstallCount) | ||
484 | { | ||
485 | hr = CpiSubscriptionsVerifyUninstall(&subList); | ||
486 | ExitOnFailure(hr, "Failed to verify subscriptions"); | ||
487 | } | ||
488 | |||
489 | // schedule | ||
490 | if (partList.iUninstallCount || appList.iUninstallCount || appRoleList.iUninstallCount || | ||
491 | usrInAppRoleList.iUninstallCount || asmList.iUninstallCount || asmList.iRoleUninstallCount || subList.iUninstallCount) | ||
492 | { | ||
493 | // create rollback file name | ||
494 | hr = CpiGetTempFileName(&pwzRollbackFileName); | ||
495 | ExitOnFailure(hr, "Failed to get rollback file name"); | ||
496 | |||
497 | // schedule rollback prepare custom action | ||
498 | hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKINSTALLPREPARE, pwzRollbackFileName, 0); | ||
499 | ExitOnFailure(hr, "Failed to schedule ComPlusRollbackInstallPrepare"); | ||
500 | |||
501 | // schedule prepare custom action | ||
502 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLPREPARE, pwzRollbackFileName, 0); | ||
503 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallPrepare"); | ||
504 | |||
505 | // schedule rollback custom action | ||
506 | hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzRollbackActionData); | ||
507 | ExitOnFailure(hr, "Failed to add rollback file name to rollback custom action data"); | ||
508 | |||
509 | hr = CpiPartitionsUninstall(&partList, rmRollback, &pwzRollbackActionData, NULL); | ||
510 | ExitOnFailure(hr, "Failed to uninstall partitions"); | ||
511 | hr = CpiUsersInPartitionRolesUninstall(&usrInPartRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
512 | ExitOnFailure(hr, "Failed to uninstall users in partition roles"); | ||
513 | hr = CpiPartitionUsersUninstall(&partUsrList, rmRollback, &pwzRollbackActionData, NULL); | ||
514 | ExitOnFailure(hr, "Failed to uninstall partition users"); | ||
515 | hr = CpiApplicationsUninstall(&appList, rmRollback, &pwzRollbackActionData, NULL); | ||
516 | ExitOnFailure(hr, "Failed to uninstall applications"); | ||
517 | hr = CpiApplicationRolesUninstall(&appRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
518 | ExitOnFailure(hr, "Failed to uninstall application roles"); | ||
519 | hr = CpiUsersInApplicationRolesUninstall(&usrInAppRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
520 | ExitOnFailure(hr, "Failed to uninstall users in application roles"); | ||
521 | hr = CpiAssembliesUninstall(&asmList, rmRollback, &pwzRollbackActionData, NULL); | ||
522 | ExitOnFailure(hr, "Failed to uninstall assemblies"); | ||
523 | hr = CpiRoleAssignmentsUninstall(&asmList, rmRollback, &pwzRollbackActionData, NULL); | ||
524 | ExitOnFailure(hr, "Failed to uninstall assemblies"); | ||
525 | hr = CpiSubscriptionsUninstall(&subList, rmRollback, &pwzRollbackActionData, NULL); | ||
526 | ExitOnFailure(hr, "Failed to uninstall subscriptions"); | ||
527 | |||
528 | hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKUNINSTALLEXECUTE, pwzRollbackActionData, 0); | ||
529 | ExitOnFailure(hr, "Failed to schedule ComPlusRollbackUninstallExecute"); | ||
530 | |||
531 | // schedule install custom action | ||
532 | hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzActionData); | ||
533 | ExitOnFailure(hr, "Failed to add rollback file name to custom action data"); | ||
534 | |||
535 | hr = CpiSubscriptionsUninstall(&subList, rmDeferred, &pwzActionData, &iProgress); | ||
536 | ExitOnFailure(hr, "Failed to uninstall subscriptions"); | ||
537 | hr = CpiRoleAssignmentsUninstall(&asmList, rmDeferred, &pwzActionData, &iProgress); | ||
538 | ExitOnFailure(hr, "Failed to uninstall assemblies"); | ||
539 | hr = CpiAssembliesUninstall(&asmList, rmDeferred, &pwzActionData, &iProgress); | ||
540 | ExitOnFailure(hr, "Failed to uninstall assemblies"); | ||
541 | hr = CpiUsersInApplicationRolesUninstall(&usrInAppRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
542 | ExitOnFailure(hr, "Failed to uninstall users in application roles"); | ||
543 | hr = CpiApplicationRolesUninstall(&appRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
544 | ExitOnFailure(hr, "Failed to uninstall application roles"); | ||
545 | hr = CpiApplicationsUninstall(&appList, rmDeferred, &pwzActionData, &iProgress); | ||
546 | ExitOnFailure(hr, "Failed to uninstall applications"); | ||
547 | hr = CpiPartitionUsersUninstall(&partUsrList, rmDeferred, &pwzActionData, &iProgress); | ||
548 | ExitOnFailure(hr, "Failed to uninstall partition users"); | ||
549 | hr = CpiUsersInPartitionRolesUninstall(&usrInPartRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
550 | ExitOnFailure(hr, "Failed to uninstall users in partition roles"); | ||
551 | hr = CpiPartitionsUninstall(&partList, rmDeferred, &pwzActionData, &iProgress); | ||
552 | ExitOnFailure(hr, "Failed to uninstall partitions"); | ||
553 | |||
554 | hr = WcaDoDeferredAction(CP_COMPLUSUNINSTALLEXECUTE, pwzActionData, iProgress); | ||
555 | ExitOnFailure(hr, "Failed to schedule ComPlusUninstallExecute"); | ||
556 | |||
557 | // schedule commit custom action | ||
558 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLCOMMIT, pwzRollbackFileName, 0); | ||
559 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallCommit"); | ||
560 | } | ||
561 | |||
562 | hr = S_OK; | ||
563 | |||
564 | LExit: | ||
565 | // clean up | ||
566 | ReleaseObject(piCatalog); | ||
567 | |||
568 | ReleaseStr(pwzRollbackFileName); | ||
569 | ReleaseStr(pwzActionData); | ||
570 | ReleaseStr(pwzRollbackActionData); | ||
571 | |||
572 | CpiPartitionListFree(&partList); | ||
573 | CpiPartitionRoleListFree(&partRoleList); | ||
574 | CpiUserInPartitionRoleListFree(&usrInPartRoleList); | ||
575 | CpiPartitionUserListFree(&partUsrList); | ||
576 | CpiApplicationListFree(&appList); | ||
577 | CpiApplicationRoleListFree(&appRoleList); | ||
578 | CpiUserInApplicationRoleListFree(&usrInAppRoleList); | ||
579 | CpiAssemblyListFree(&asmList); | ||
580 | CpiSubscriptionListFree(&subList); | ||
581 | |||
582 | // unitialize | ||
583 | CpiFinalize(); | ||
584 | |||
585 | if (fInitializedCom) | ||
586 | ::CoUninitialize(); | ||
587 | |||
588 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
589 | return WcaFinalize(er); | ||
590 | } | ||
diff --git a/src/ca/cpsubsexec.cpp b/src/ca/cpsubsexec.cpp new file mode 100644 index 00000000..bbcf9853 --- /dev/null +++ b/src/ca/cpsubsexec.cpp | |||
@@ -0,0 +1,411 @@ | |||
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_SUBSCRIPTION_ATTRIBUTES | ||
9 | { | ||
10 | int iActionType; | ||
11 | int iActionCost; | ||
12 | LPWSTR pwzKey; | ||
13 | LPWSTR pwzID; | ||
14 | LPWSTR pwzName; | ||
15 | LPWSTR pwzEventCLSID; | ||
16 | LPWSTR pwzPublisherID; | ||
17 | LPWSTR pwzCompCLSID; | ||
18 | LPWSTR pwzAppID; | ||
19 | LPWSTR pwzPartID; | ||
20 | CPI_PROPERTY* pPropList; | ||
21 | }; | ||
22 | |||
23 | |||
24 | // prototypes for private helper functions | ||
25 | |||
26 | static HRESULT ReadSubscriptionAttributes( | ||
27 | LPWSTR* ppwzData, | ||
28 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
29 | ); | ||
30 | static void FreeSubscriptionAttributes( | ||
31 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
32 | ); | ||
33 | static HRESULT CreateSubscription( | ||
34 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
35 | ); | ||
36 | static HRESULT RemoveSubscription( | ||
37 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
38 | ); | ||
39 | |||
40 | |||
41 | // function definitions | ||
42 | |||
43 | HRESULT CpiConfigureSubscriptions( | ||
44 | LPWSTR* ppwzData, | ||
45 | HANDLE hRollbackFile | ||
46 | ) | ||
47 | { | ||
48 | HRESULT hr = S_OK; | ||
49 | |||
50 | CPI_SUBSCRIPTION_ATTRIBUTES attrs; | ||
51 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
52 | |||
53 | // read action text | ||
54 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
55 | ExitOnFailure(hr, "Failed to send action start message"); | ||
56 | |||
57 | // ger count | ||
58 | int iCnt = 0; | ||
59 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
60 | ExitOnFailure(hr, "Failed to read count"); | ||
61 | |||
62 | // write count to rollback file | ||
63 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
64 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
65 | |||
66 | for (int i = 0; i < iCnt; i++) | ||
67 | { | ||
68 | // read attributes from CustomActionData | ||
69 | hr = ReadSubscriptionAttributes(ppwzData, &attrs); | ||
70 | ExitOnFailure(hr, "Failed to read attributes"); | ||
71 | |||
72 | // progress message | ||
73 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
74 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
75 | |||
76 | if (S_FALSE == hr) | ||
77 | ExitFunction(); | ||
78 | |||
79 | // write key to rollback file | ||
80 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
81 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
82 | |||
83 | // action | ||
84 | switch (attrs.iActionType) | ||
85 | { | ||
86 | case atCreate: | ||
87 | hr = CreateSubscription(&attrs); | ||
88 | ExitOnFailure(hr, "Failed to create subscription, key: %S", attrs.pwzKey); | ||
89 | break; | ||
90 | case atRemove: | ||
91 | hr = RemoveSubscription(&attrs); | ||
92 | ExitOnFailure(hr, "Failed to remove subscription, key: %S", attrs.pwzKey); | ||
93 | break; | ||
94 | } | ||
95 | |||
96 | // write completion status to rollback file | ||
97 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
98 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
99 | |||
100 | // progress | ||
101 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
102 | ExitOnFailure(hr, "Failed to update progress"); | ||
103 | } | ||
104 | |||
105 | hr = S_OK; | ||
106 | |||
107 | LExit: | ||
108 | // clean up | ||
109 | FreeSubscriptionAttributes(&attrs); | ||
110 | |||
111 | return hr; | ||
112 | } | ||
113 | |||
114 | HRESULT CpiRollbackConfigureSubscriptions( | ||
115 | LPWSTR* ppwzData, | ||
116 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
117 | ) | ||
118 | { | ||
119 | HRESULT hr = S_OK; | ||
120 | |||
121 | int iRollbackStatus; | ||
122 | |||
123 | CPI_SUBSCRIPTION_ATTRIBUTES attrs; | ||
124 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
125 | |||
126 | // read action text | ||
127 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
128 | ExitOnFailure(hr, "Failed to send action start message"); | ||
129 | |||
130 | // ger count | ||
131 | int iCnt = 0; | ||
132 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
133 | ExitOnFailure(hr, "Failed to read count"); | ||
134 | |||
135 | for (int i = 0; i < iCnt; i++) | ||
136 | { | ||
137 | // read attributes from CustomActionData | ||
138 | hr = ReadSubscriptionAttributes(ppwzData, &attrs); | ||
139 | ExitOnFailure(hr, "Failed to read attributes"); | ||
140 | |||
141 | // rollback status | ||
142 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
143 | |||
144 | if (S_FALSE == hr) | ||
145 | continue; // not found, nothing to rollback | ||
146 | |||
147 | // progress message | ||
148 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
149 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
150 | |||
151 | if (S_FALSE == hr) | ||
152 | ExitFunction(); | ||
153 | |||
154 | // action | ||
155 | switch (attrs.iActionType) | ||
156 | { | ||
157 | case atCreate: | ||
158 | hr = CreateSubscription(&attrs); | ||
159 | if (FAILED(hr)) | ||
160 | WcaLog(LOGMSG_STANDARD, "Failed to create subscription, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
161 | break; | ||
162 | case atRemove: | ||
163 | hr = RemoveSubscription(&attrs); | ||
164 | if (FAILED(hr)) | ||
165 | WcaLog(LOGMSG_STANDARD, "Failed to remove subscription, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | // check rollback status | ||
170 | if (0 == iRollbackStatus) | ||
171 | continue; // operation did not complete, skip progress | ||
172 | |||
173 | // progress | ||
174 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
175 | ExitOnFailure(hr, "Failed to update progress"); | ||
176 | } | ||
177 | |||
178 | hr = S_OK; | ||
179 | |||
180 | LExit: | ||
181 | // clean up | ||
182 | FreeSubscriptionAttributes(&attrs); | ||
183 | |||
184 | return hr; | ||
185 | } | ||
186 | |||
187 | |||
188 | // helper function definitions | ||
189 | |||
190 | static HRESULT ReadSubscriptionAttributes( | ||
191 | LPWSTR* ppwzData, | ||
192 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
193 | ) | ||
194 | { | ||
195 | HRESULT hr = S_OK; | ||
196 | |||
197 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
198 | ExitOnFailure(hr, "Failed to read action type"); | ||
199 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
200 | ExitOnFailure(hr, "Failed to read action cost"); | ||
201 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
202 | ExitOnFailure(hr, "Failed to read key"); | ||
203 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzID); | ||
204 | ExitOnFailure(hr, "Failed to read id"); | ||
205 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName); | ||
206 | ExitOnFailure(hr, "Failed to read name"); | ||
207 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzEventCLSID); | ||
208 | ExitOnFailure(hr, "Failed to read event clsid"); | ||
209 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPublisherID); | ||
210 | ExitOnFailure(hr, "Failed to read publisher id"); | ||
211 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzCompCLSID); | ||
212 | ExitOnFailure(hr, "Failed to read component clsid"); | ||
213 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
214 | ExitOnFailure(hr, "Failed to read application id"); | ||
215 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
216 | ExitOnFailure(hr, "Failed to read partition id"); | ||
217 | |||
218 | hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList); | ||
219 | ExitOnFailure(hr, "Failed to read properties"); | ||
220 | |||
221 | hr = S_OK; | ||
222 | |||
223 | LExit: | ||
224 | return hr; | ||
225 | } | ||
226 | |||
227 | static void FreeSubscriptionAttributes( | ||
228 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
229 | ) | ||
230 | { | ||
231 | ReleaseStr(pAttrs->pwzKey); | ||
232 | ReleaseStr(pAttrs->pwzID); | ||
233 | ReleaseStr(pAttrs->pwzName); | ||
234 | ReleaseStr(pAttrs->pwzEventCLSID); | ||
235 | ReleaseStr(pAttrs->pwzPublisherID); | ||
236 | ReleaseStr(pAttrs->pwzCompCLSID); | ||
237 | ReleaseStr(pAttrs->pwzAppID); | ||
238 | ReleaseStr(pAttrs->pwzPartID); | ||
239 | |||
240 | if (pAttrs->pPropList) | ||
241 | CpiFreePropertyList(pAttrs->pPropList); | ||
242 | } | ||
243 | |||
244 | static HRESULT CreateSubscription( | ||
245 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
246 | ) | ||
247 | { | ||
248 | HRESULT hr = S_OK; | ||
249 | UINT er = ERROR_SUCCESS; | ||
250 | |||
251 | ICatalogCollection* piSubsColl = NULL; | ||
252 | ICatalogObject* piSubsObj = NULL; | ||
253 | |||
254 | PSID pSid = NULL; | ||
255 | long lChanges = 0; | ||
256 | |||
257 | // log | ||
258 | WcaLog(LOGMSG_VERBOSE, "Creating subscription, key: %S", pAttrs->pwzKey); | ||
259 | |||
260 | // get subscriptions collection | ||
261 | hr = CpiGetSubscriptionsCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzCompCLSID, &piSubsColl); | ||
262 | if (S_FALSE == hr) | ||
263 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
264 | ExitOnFailure(hr, "Failed to get subscriptions collection"); | ||
265 | |||
266 | // check if subscription exists | ||
267 | hr = CpiFindCollectionObjectByStringKey(piSubsColl, pAttrs->pwzID, &piSubsObj); | ||
268 | ExitOnFailure(hr, "Failed to find subscription"); | ||
269 | |||
270 | if (S_FALSE == hr) | ||
271 | { | ||
272 | // create subscription | ||
273 | hr = CpiAddCollectionObject(piSubsColl, &piSubsObj); | ||
274 | ExitOnFailure(hr, "Failed to add subscription to collection"); | ||
275 | |||
276 | hr = CpiPutCollectionObjectValue(piSubsObj, L"ID", pAttrs->pwzID); | ||
277 | ExitOnFailure(hr, "Failed to set subscription id property"); | ||
278 | |||
279 | hr = CpiPutCollectionObjectValue(piSubsObj, L"Name", pAttrs->pwzName); | ||
280 | ExitOnFailure(hr, "Failed to set subscription name property"); | ||
281 | |||
282 | if (pAttrs->pwzEventCLSID && *pAttrs->pwzEventCLSID) | ||
283 | { | ||
284 | hr = CpiPutCollectionObjectValue(piSubsObj, L"EventCLSID", pAttrs->pwzEventCLSID); | ||
285 | ExitOnFailure(hr, "Failed to set role event clsid property"); | ||
286 | } | ||
287 | |||
288 | if (pAttrs->pwzPublisherID && *pAttrs->pwzPublisherID) | ||
289 | { | ||
290 | hr = CpiPutCollectionObjectValue(piSubsObj, L"PublisherID", pAttrs->pwzPublisherID); | ||
291 | ExitOnFailure(hr, "Failed to set role publisher id property"); | ||
292 | } | ||
293 | } | ||
294 | |||
295 | // properties | ||
296 | for (CPI_PROPERTY* pItm = pAttrs->pPropList; pItm; pItm = pItm->pNext) | ||
297 | { | ||
298 | // UserName property | ||
299 | if (0 == lstrcmpW(pItm->wzName, L"UserName")) | ||
300 | { | ||
301 | // get SID for account | ||
302 | do { | ||
303 | er = ERROR_SUCCESS; | ||
304 | hr = CpiAccountNameToSid(pItm->pwzValue, &pSid); | ||
305 | if (!::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
306 | { | ||
307 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr) | ||
308 | { | ||
309 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pItm->pwzValue); | ||
310 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
311 | switch (er) | ||
312 | { | ||
313 | case IDABORT: | ||
314 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
315 | case IDRETRY: | ||
316 | break; | ||
317 | case IDIGNORE: | ||
318 | default: | ||
319 | hr = S_FALSE; | ||
320 | } | ||
321 | } | ||
322 | else | ||
323 | ExitOnFailure(hr, "Failed to get SID for account, account: '%S'", pItm->pwzValue); | ||
324 | } | ||
325 | else if (FAILED(hr)) | ||
326 | { | ||
327 | WcaLog(LOGMSG_STANDARD, "Failed to get SID for account, hr: 0x%x, account: '%S'", hr, pItm->pwzValue); | ||
328 | hr = S_FALSE; | ||
329 | } | ||
330 | } while (IDRETRY == er); | ||
331 | |||
332 | if (S_FALSE == hr) | ||
333 | continue; | ||
334 | |||
335 | // convert SID back to account name | ||
336 | hr = CpiSidToAccountName(pSid, &pItm->pwzValue); | ||
337 | ExitOnFailure(hr, "Failed to convert SID to account name"); | ||
338 | } | ||
339 | |||
340 | // set property | ||
341 | hr = CpiPutCollectionObjectValue(piSubsObj, pItm->wzName, pItm->pwzValue); | ||
342 | ExitOnFailure(hr, "Failed to set object property value, name: %S", pItm->wzName); | ||
343 | } | ||
344 | |||
345 | // save changes | ||
346 | hr = piSubsColl->SaveChanges(&lChanges); | ||
347 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
348 | CpiLogCatalogErrorInfo(); | ||
349 | ExitOnFailure(hr, "Failed to save changes"); | ||
350 | |||
351 | // log | ||
352 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
353 | |||
354 | hr = S_OK; | ||
355 | |||
356 | LExit: | ||
357 | // clean up | ||
358 | ReleaseObject(piSubsColl); | ||
359 | ReleaseObject(piSubsObj); | ||
360 | |||
361 | if (pSid) | ||
362 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
363 | |||
364 | return hr; | ||
365 | } | ||
366 | |||
367 | static HRESULT RemoveSubscription( | ||
368 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
369 | ) | ||
370 | { | ||
371 | HRESULT hr = S_OK; | ||
372 | |||
373 | ICatalogCollection* piSubsColl = NULL; | ||
374 | |||
375 | long lChanges = 0; | ||
376 | |||
377 | // log | ||
378 | WcaLog(LOGMSG_VERBOSE, "Removing subscription, key: %S", pAttrs->pwzKey); | ||
379 | |||
380 | // get subscriptions collection | ||
381 | hr = CpiGetSubscriptionsCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzCompCLSID, &piSubsColl); | ||
382 | ExitOnFailure(hr, "Failed to get subscriptions collection"); | ||
383 | |||
384 | if (S_FALSE == hr) | ||
385 | { | ||
386 | // subscription not found | ||
387 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve subscriptions collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
388 | ExitFunction1(hr = S_OK); | ||
389 | } | ||
390 | |||
391 | // remove | ||
392 | hr = CpiRemoveCollectionObject(piSubsColl, pAttrs->pwzID, NULL, FALSE); | ||
393 | ExitOnFailure(hr, "Failed to remove subscriptions"); | ||
394 | |||
395 | // save changes | ||
396 | hr = piSubsColl->SaveChanges(&lChanges); | ||
397 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
398 | CpiLogCatalogErrorInfo(); | ||
399 | ExitOnFailure(hr, "Failed to save changes"); | ||
400 | |||
401 | // log | ||
402 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
403 | |||
404 | hr = S_OK; | ||
405 | |||
406 | LExit: | ||
407 | // clean up | ||
408 | ReleaseObject(piSubsColl); | ||
409 | |||
410 | return hr; | ||
411 | } | ||
diff --git a/src/ca/cpsubsexec.h b/src/ca/cpsubsexec.h new file mode 100644 index 00000000..2f4d3c75 --- /dev/null +++ b/src/ca/cpsubsexec.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | HRESULT CpiConfigureSubscriptions( | ||
6 | LPWSTR* ppwzData, | ||
7 | HANDLE hRollbackFile | ||
8 | ); | ||
9 | HRESULT CpiRollbackConfigureSubscriptions( | ||
10 | LPWSTR* ppwzData, | ||
11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
12 | ); | ||
diff --git a/src/ca/cpsubssched.cpp b/src/ca/cpsubssched.cpp new file mode 100644 index 00000000..73fd4f6d --- /dev/null +++ b/src/ca/cpsubssched.cpp | |||
@@ -0,0 +1,606 @@ | |||
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 | // sql queries | ||
7 | |||
8 | LPCWSTR vcsSubscriptionQuery = | ||
9 | L"SELECT `Subscription`, `ComPlusComponent_`, `Component_`, `Id`, `Name`, `EventCLSID`, `PublisherID` FROM `ComPlusSubscription`"; | ||
10 | enum eSubscriptionQuery { sqSubscription = 1, sqComPlusComponent, sqComponent, sqID, sqName, sqEventCLSID, sqPublisherID }; | ||
11 | |||
12 | LPCWSTR vcsSubscriptionPropertyQuery = | ||
13 | L"SELECT `Name`, `Value` FROM `ComPlusSubscriptionProperty` WHERE `Subscription_` = ?"; | ||
14 | |||
15 | |||
16 | // property definitions | ||
17 | |||
18 | CPI_PROPERTY_DEFINITION pdlSubscriptionProperties[] = | ||
19 | { | ||
20 | {L"Description", cpptString, 500}, | ||
21 | {L"Enabled", cpptBoolean, 500}, | ||
22 | {L"EventClassPartitionID", cpptString, 502}, | ||
23 | {L"FilterCriteria", cpptString, 500}, | ||
24 | {L"InterfaceID", cpptString, 500}, | ||
25 | {L"MachineName", cpptString, 500}, | ||
26 | {L"MethodName", cpptString, 500}, | ||
27 | {L"PerUser", cpptBoolean, 500}, | ||
28 | {L"Queued", cpptBoolean, 500}, | ||
29 | {L"SubscriberMoniker", cpptString, 500}, | ||
30 | {L"UserName", cpptUser, 500}, | ||
31 | {NULL, cpptNone, 0} | ||
32 | }; | ||
33 | |||
34 | |||
35 | // prototypes for private helper functions | ||
36 | |||
37 | static void FreeSubscription( | ||
38 | CPI_SUBSCRIPTION* pItm | ||
39 | ); | ||
40 | static HRESULT FindObjectForSubscription( | ||
41 | CPI_SUBSCRIPTION* pItm, | ||
42 | BOOL fFindId, | ||
43 | BOOL fFindName, | ||
44 | ICatalogObject** ppiSubsObj | ||
45 | ); | ||
46 | static HRESULT AddSubscriptionToActionData( | ||
47 | CPI_SUBSCRIPTION* pItm, | ||
48 | int iActionType, | ||
49 | int iActionCost, | ||
50 | LPWSTR* ppwzActionData | ||
51 | ); | ||
52 | static HRESULT ComponentFindByKey( | ||
53 | CPI_ASSEMBLY_LIST* pAsmList, | ||
54 | LPCWSTR pwzKey, | ||
55 | CPI_ASSEMBLY** ppAsmItm, | ||
56 | CPI_COMPONENT** ppCompItm | ||
57 | ); | ||
58 | |||
59 | |||
60 | // function definitions | ||
61 | |||
62 | void CpiSubscriptionListFree( | ||
63 | CPI_SUBSCRIPTION_LIST* pList | ||
64 | ) | ||
65 | { | ||
66 | CPI_SUBSCRIPTION* pItm = pList->pFirst; | ||
67 | |||
68 | while (pItm) | ||
69 | { | ||
70 | CPI_SUBSCRIPTION* pDelete = pItm; | ||
71 | pItm = pItm->pNext; | ||
72 | FreeSubscription(pDelete); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | HRESULT CpiSubscriptionsRead( | ||
77 | CPI_ASSEMBLY_LIST* pAsmList, | ||
78 | CPI_SUBSCRIPTION_LIST* pSubList | ||
79 | ) | ||
80 | { | ||
81 | HRESULT hr = S_OK; | ||
82 | UINT er = ERROR_SUCCESS; | ||
83 | |||
84 | PMSIHANDLE hView, hRec; | ||
85 | |||
86 | CPI_SUBSCRIPTION* pItm = NULL; | ||
87 | LPWSTR pwzData = NULL; | ||
88 | BOOL fMatchingArchitecture = FALSE; | ||
89 | |||
90 | // loop through all applications | ||
91 | hr = WcaOpenExecuteView(vcsSubscriptionQuery, &hView); | ||
92 | ExitOnFailure(hr, "Failed to execute view on ComPlusSubscription table"); | ||
93 | |||
94 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
95 | { | ||
96 | // get component | ||
97 | hr = WcaGetRecordString(hRec, sqComponent, &pwzData); | ||
98 | ExitOnFailure(hr, "Failed to get component"); | ||
99 | |||
100 | // check if the component is our processor architecture | ||
101 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
102 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
103 | |||
104 | if (!fMatchingArchitecture) | ||
105 | { | ||
106 | continue; // not the same architecture, ignore | ||
107 | } | ||
108 | |||
109 | // create entry | ||
110 | pItm = (CPI_SUBSCRIPTION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_SUBSCRIPTION)); | ||
111 | if (!pItm) | ||
112 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
113 | |||
114 | // get component install state | ||
115 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
116 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
117 | |||
118 | // get key | ||
119 | hr = WcaGetRecordString(hRec, sqSubscription, &pwzData); | ||
120 | ExitOnFailure(hr, "Failed to get key"); | ||
121 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
122 | |||
123 | // get com+ component | ||
124 | hr = WcaGetRecordString(hRec, sqComPlusComponent, &pwzData); | ||
125 | ExitOnFailure(hr, "Failed to get COM+ component"); | ||
126 | |||
127 | hr = ComponentFindByKey(pAsmList, pwzData, &pItm->pAssembly, &pItm->pComponent); | ||
128 | |||
129 | if (S_FALSE == hr) | ||
130 | { | ||
131 | // component not found | ||
132 | ExitOnFailure(hr = E_FAIL, "Failed to find component, key: %S", pwzData); | ||
133 | } | ||
134 | |||
135 | // get id | ||
136 | hr = WcaGetRecordFormattedString(hRec, sqID, &pwzData); | ||
137 | ExitOnFailure(hr, "Failed to get id"); | ||
138 | |||
139 | if (pwzData && *pwzData) | ||
140 | { | ||
141 | hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID)); | ||
142 | ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData); | ||
143 | } | ||
144 | |||
145 | // get name | ||
146 | hr = WcaGetRecordFormattedString(hRec, sqName, &pwzData); | ||
147 | ExitOnFailure(hr, "Failed to get name"); | ||
148 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
149 | |||
150 | // get event clsid | ||
151 | hr = WcaGetRecordFormattedString(hRec, sqEventCLSID, &pwzData); | ||
152 | ExitOnFailure(hr, "Failed to get event clsid"); | ||
153 | StringCchCopyW(pItm->wzEventCLSID, countof(pItm->wzEventCLSID), pwzData); | ||
154 | |||
155 | // get publisher id | ||
156 | hr = WcaGetRecordFormattedString(hRec, sqPublisherID, &pwzData); | ||
157 | ExitOnFailure(hr, "Failed to get publisher id"); | ||
158 | StringCchCopyW(pItm->wzPublisherID, countof(pItm->wzPublisherID), pwzData); | ||
159 | |||
160 | // get properties | ||
161 | if (CpiTableExists(cptComPlusSubscriptionProperty)) | ||
162 | { | ||
163 | hr = CpiPropertiesRead(vcsSubscriptionPropertyQuery, pItm->wzKey, pdlSubscriptionProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
164 | ExitOnFailure(hr, "Failed to get subscription properties"); | ||
165 | } | ||
166 | |||
167 | // set references & increment counters | ||
168 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
169 | { | ||
170 | CpiApplicationAddReferenceInstall(pItm->pAssembly->pApplication); | ||
171 | pItm->pAssembly->fReferencedForInstall = TRUE; | ||
172 | pSubList->iInstallCount++; | ||
173 | if (pItm->pAssembly->iAttributes & aaRunInCommit) | ||
174 | pSubList->iCommitCount++; | ||
175 | } | ||
176 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
177 | { | ||
178 | CpiApplicationAddReferenceUninstall(pItm->pAssembly->pApplication); | ||
179 | pItm->pAssembly->fReferencedForUninstall = TRUE; | ||
180 | pSubList->iUninstallCount++; | ||
181 | } | ||
182 | |||
183 | // add entry | ||
184 | if (pSubList->pFirst) | ||
185 | pItm->pNext = pSubList->pFirst; | ||
186 | pSubList->pFirst = pItm; | ||
187 | pItm = NULL; | ||
188 | } | ||
189 | |||
190 | if (E_NOMOREITEMS == hr) | ||
191 | hr = S_OK; | ||
192 | |||
193 | LExit: | ||
194 | // clean up | ||
195 | if (pItm) | ||
196 | FreeSubscription(pItm); | ||
197 | |||
198 | ReleaseStr(pwzData); | ||
199 | |||
200 | return hr; | ||
201 | } | ||
202 | |||
203 | HRESULT CpiSubscriptionsVerifyInstall( | ||
204 | CPI_SUBSCRIPTION_LIST* pList | ||
205 | ) | ||
206 | { | ||
207 | HRESULT hr = S_OK; | ||
208 | UINT er = ERROR_SUCCESS; | ||
209 | |||
210 | ICatalogObject* piSubsObj = NULL; | ||
211 | |||
212 | for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
213 | { | ||
214 | // subscriptions that are being installed | ||
215 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
216 | continue; | ||
217 | |||
218 | // subscription is supposed to exist | ||
219 | if (CpiIsInstalled(pItm->isInstalled)) | ||
220 | { | ||
221 | // if we don't have an id | ||
222 | if (!*pItm->wzID) | ||
223 | { | ||
224 | // find subscriptions with conflicting name | ||
225 | hr = FindObjectForSubscription(pItm, FALSE, TRUE, &piSubsObj); | ||
226 | ExitOnFailure(hr, "Failed to find collection object for subscription"); | ||
227 | |||
228 | // if the subscription was found | ||
229 | if (S_OK == hr) | ||
230 | { | ||
231 | // get id from subscription object | ||
232 | hr = CpiGetKeyForObject(piSubsObj, pItm->wzID, countof(pItm->wzID)); | ||
233 | ExitOnFailure(hr, "Failed to get id"); | ||
234 | } | ||
235 | |||
236 | // if the subscription was not found | ||
237 | else | ||
238 | { | ||
239 | // create a new id | ||
240 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
241 | ExitOnFailure(hr, "Failed to create id"); | ||
242 | } | ||
243 | } | ||
244 | } | ||
245 | |||
246 | // subscription is supposed to be created | ||
247 | else | ||
248 | { | ||
249 | // check for conflicts | ||
250 | do { | ||
251 | if (*pItm->wzID) | ||
252 | { | ||
253 | // find subscriptions with conflicting id | ||
254 | hr = FindObjectForSubscription(pItm, TRUE, FALSE, &piSubsObj); | ||
255 | ExitOnFailure(hr, "Failed to find collection object for subscription"); | ||
256 | |||
257 | if (S_FALSE == hr) | ||
258 | { | ||
259 | // find subscriptions with conflicting name | ||
260 | hr = FindObjectForSubscription(pItm, FALSE, TRUE, &piSubsObj); | ||
261 | ExitOnFailure(hr, "Failed to find collection object for subscription"); | ||
262 | |||
263 | if (S_OK == hr) | ||
264 | // "A subscription with a conflictiong name exists. retry cancel" | ||
265 | er = WcaErrorMessage(msierrComPlusSubscriptionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0); | ||
266 | else | ||
267 | break; // no conflicting entry found, break loop | ||
268 | } | ||
269 | else | ||
270 | // "A subscription with a conflicting id exists. abort retry ignore" | ||
271 | er = WcaErrorMessage(msierrComPlusSubscriptionIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
272 | } | ||
273 | else | ||
274 | { | ||
275 | // find subscriptions with conflicting name | ||
276 | hr = FindObjectForSubscription(pItm, FALSE, TRUE, &piSubsObj); | ||
277 | ExitOnFailure(hr, "Failed to find collection object for subscription"); | ||
278 | |||
279 | if (S_OK == hr) | ||
280 | // "A subscription with a conflictiong name exists. abort retry ignore" | ||
281 | er = WcaErrorMessage(msierrComPlusSubscriptionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
282 | else | ||
283 | break; // no conflicting entry found, break loop | ||
284 | } | ||
285 | |||
286 | switch (er) | ||
287 | { | ||
288 | case IDCANCEL: | ||
289 | case IDABORT: | ||
290 | ExitOnFailure(hr = E_FAIL, "A subscription with a conflictiong name or id exists, key: %S", pItm->wzKey); | ||
291 | break; | ||
292 | case IDRETRY: | ||
293 | break; | ||
294 | case IDIGNORE: | ||
295 | default: | ||
296 | // if we don't have an id, copy id from object | ||
297 | if (!*pItm->wzID) | ||
298 | { | ||
299 | hr = CpiGetKeyForObject(piSubsObj, pItm->wzID, countof(pItm->wzID)); | ||
300 | ExitOnFailure(hr, "Failed to get id"); | ||
301 | } | ||
302 | hr = S_FALSE; // indicate that this is not a conflict | ||
303 | } | ||
304 | } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts | ||
305 | |||
306 | // create a new id if one is missing | ||
307 | if (!*pItm->wzID) | ||
308 | { | ||
309 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
310 | ExitOnFailure(hr, "Failed to create id"); | ||
311 | } | ||
312 | } | ||
313 | |||
314 | // clean up | ||
315 | ReleaseNullObject(piSubsObj); | ||
316 | } | ||
317 | |||
318 | hr = S_OK; | ||
319 | |||
320 | LExit: | ||
321 | // clean up | ||
322 | ReleaseObject(piSubsObj); | ||
323 | |||
324 | return hr; | ||
325 | } | ||
326 | |||
327 | HRESULT CpiSubscriptionsVerifyUninstall( | ||
328 | CPI_SUBSCRIPTION_LIST* pList | ||
329 | ) | ||
330 | { | ||
331 | HRESULT hr = S_OK; | ||
332 | ICatalogObject* piSubsObj = NULL; | ||
333 | |||
334 | for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
335 | { | ||
336 | // subscriptions that are being installed | ||
337 | if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
338 | continue; | ||
339 | |||
340 | // find subscriptions with conflicting name | ||
341 | hr = FindObjectForSubscription(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piSubsObj); | ||
342 | ExitOnFailure(hr, "Failed to find collection object for subscription"); | ||
343 | |||
344 | // if the subscription was found | ||
345 | if (S_OK == hr) | ||
346 | { | ||
347 | // if we don't have an id, copy id from object | ||
348 | if (!*pItm->wzID) | ||
349 | { | ||
350 | hr = CpiGetKeyForObject(piSubsObj, pItm->wzID, countof(pItm->wzID)); | ||
351 | ExitOnFailure(hr, "Failed to get id"); | ||
352 | } | ||
353 | } | ||
354 | |||
355 | // if the subscription was not found | ||
356 | else | ||
357 | { | ||
358 | pItm->fObjectNotFound = TRUE; | ||
359 | pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall | ||
360 | } | ||
361 | |||
362 | // clean up | ||
363 | ReleaseNullObject(piSubsObj); | ||
364 | } | ||
365 | |||
366 | hr = S_OK; | ||
367 | |||
368 | LExit: | ||
369 | // clean up | ||
370 | ReleaseObject(piSubsObj); | ||
371 | |||
372 | return hr; | ||
373 | } | ||
374 | |||
375 | HRESULT CpiSubscriptionsInstall( | ||
376 | CPI_SUBSCRIPTION_LIST* pList, | ||
377 | int iRunMode, | ||
378 | LPWSTR* ppwzActionData, | ||
379 | int* piProgress | ||
380 | ) | ||
381 | { | ||
382 | HRESULT hr = S_OK; | ||
383 | |||
384 | int iActionType; | ||
385 | int iCount = 0; | ||
386 | |||
387 | // add action text | ||
388 | hr = CpiAddActionTextToActionData(L"CreateSubscrComPlusComponents", ppwzActionData); | ||
389 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
390 | |||
391 | // subscription count | ||
392 | switch (iRunMode) | ||
393 | { | ||
394 | case rmDeferred: | ||
395 | iCount = pList->iInstallCount - pList->iCommitCount; | ||
396 | break; | ||
397 | case rmCommit: | ||
398 | iCount = pList->iCommitCount; | ||
399 | break; | ||
400 | case rmRollback: | ||
401 | iCount = pList->iInstallCount; | ||
402 | break; | ||
403 | } | ||
404 | |||
405 | // add subscription count to action data | ||
406 | hr = WcaWriteIntegerToCaData(iCount, ppwzActionData); | ||
407 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
408 | |||
409 | // add assemblies to custom action data in forward order | ||
410 | for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
411 | { | ||
412 | // roles that are being installed only | ||
413 | if ((rmCommit == iRunMode && !(pItm->pAssembly->iAttributes & aaRunInCommit)) || | ||
414 | (rmDeferred == iRunMode && (pItm->pAssembly->iAttributes & aaRunInCommit)) || | ||
415 | !WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
416 | continue; | ||
417 | |||
418 | // action type | ||
419 | if (rmRollback == iRunMode) | ||
420 | { | ||
421 | if (CpiIsInstalled(pItm->isInstalled)) | ||
422 | iActionType = atNoOp; | ||
423 | else | ||
424 | iActionType = atRemove; | ||
425 | } | ||
426 | else | ||
427 | iActionType = atCreate; | ||
428 | |||
429 | // add to action data | ||
430 | hr = AddSubscriptionToActionData(pItm, iActionType, COST_SUBSCRIPTION_CREATE, ppwzActionData); | ||
431 | ExitOnFailure(hr, "Failed to add subscription to custom action data, key: %S", pItm->wzKey); | ||
432 | } | ||
433 | |||
434 | // add progress tics | ||
435 | if (piProgress) | ||
436 | *piProgress += COST_SUBSCRIPTION_CREATE * pList->iInstallCount; | ||
437 | |||
438 | hr = S_OK; | ||
439 | |||
440 | LExit: | ||
441 | return hr; | ||
442 | } | ||
443 | |||
444 | HRESULT CpiSubscriptionsUninstall( | ||
445 | CPI_SUBSCRIPTION_LIST* pList, | ||
446 | int iRunMode, | ||
447 | LPWSTR* ppwzActionData, | ||
448 | int* piProgress | ||
449 | ) | ||
450 | { | ||
451 | HRESULT hr = S_OK; | ||
452 | |||
453 | int iActionType; | ||
454 | |||
455 | // add action text | ||
456 | hr = CpiAddActionTextToActionData(L"RemoveSubscrComPlusComponents", ppwzActionData); | ||
457 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
458 | |||
459 | // add subscription count to action data | ||
460 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
461 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
462 | |||
463 | // add assemblies to custom action data in reverse order | ||
464 | for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
465 | { | ||
466 | // roles that are being uninstalled only | ||
467 | if (pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
468 | continue; | ||
469 | |||
470 | // action type | ||
471 | if (rmRollback == iRunMode) | ||
472 | iActionType = atCreate; | ||
473 | else | ||
474 | iActionType = atRemove; | ||
475 | |||
476 | // add to action data | ||
477 | hr = AddSubscriptionToActionData(pItm, iActionType, COST_SUBSCRIPTION_DELETE, ppwzActionData); | ||
478 | ExitOnFailure(hr, "Failed to add subscription to custom action data, key: %S", pItm->wzKey); | ||
479 | } | ||
480 | |||
481 | // add progress tics | ||
482 | if (piProgress) | ||
483 | *piProgress += COST_SUBSCRIPTION_DELETE * pList->iUninstallCount; | ||
484 | |||
485 | hr = S_OK; | ||
486 | |||
487 | LExit: | ||
488 | return hr; | ||
489 | } | ||
490 | |||
491 | |||
492 | // helper function definitions | ||
493 | |||
494 | static void FreeSubscription( | ||
495 | CPI_SUBSCRIPTION* pItm | ||
496 | ) | ||
497 | { | ||
498 | if (pItm->pProperties) | ||
499 | CpiPropertiesFreeList(pItm->pProperties); | ||
500 | |||
501 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
502 | } | ||
503 | |||
504 | static HRESULT FindObjectForSubscription( | ||
505 | CPI_SUBSCRIPTION* pItm, | ||
506 | BOOL fFindId, | ||
507 | BOOL fFindName, | ||
508 | ICatalogObject** ppiSubsObj | ||
509 | ) | ||
510 | { | ||
511 | HRESULT hr = S_OK; | ||
512 | |||
513 | ICatalogCollection* piSubsColl = NULL; | ||
514 | |||
515 | // get applications collection | ||
516 | hr = CpiGetSubscriptionsCollForComponent(pItm->pAssembly, pItm->pComponent, &piSubsColl); | ||
517 | ExitOnFailure(hr, "Failed to get collection"); | ||
518 | |||
519 | if (S_FALSE == hr) | ||
520 | ExitFunction(); // exit with hr = S_FALSE | ||
521 | |||
522 | // find application object | ||
523 | hr = CpiFindCollectionObject(piSubsColl, fFindId ? pItm->wzID : NULL, fFindName ? pItm->wzName : NULL, ppiSubsObj); | ||
524 | ExitOnFailure(hr, "Failed to find object"); | ||
525 | |||
526 | // exit with hr from CpiFindCollectionObject() | ||
527 | |||
528 | LExit: | ||
529 | // clean up | ||
530 | ReleaseObject(piSubsColl); | ||
531 | |||
532 | return hr; | ||
533 | } | ||
534 | |||
535 | static HRESULT AddSubscriptionToActionData( | ||
536 | CPI_SUBSCRIPTION* pItm, | ||
537 | int iActionType, | ||
538 | int iActionCost, | ||
539 | LPWSTR* ppwzActionData | ||
540 | ) | ||
541 | { | ||
542 | HRESULT hr = S_OK; | ||
543 | |||
544 | // add action information to custom action data | ||
545 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
546 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
547 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
548 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
549 | |||
550 | // add application role information to custom action data | ||
551 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
552 | ExitOnFailure(hr, "Failed to add subscription key to custom action data"); | ||
553 | hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData); | ||
554 | ExitOnFailure(hr, "Failed to add subscription id to custom action data"); | ||
555 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
556 | ExitOnFailure(hr, "Failed to add subscription name to custom action data"); | ||
557 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->wzEventCLSID : L"", ppwzActionData); | ||
558 | ExitOnFailure(hr, "Failed to add assembly tlb path to custom action data"); | ||
559 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->wzPublisherID : L"", ppwzActionData); | ||
560 | ExitOnFailure(hr, "Failed to add assembly proxy-stub dll path to custom action data"); | ||
561 | |||
562 | // add component information to custom action data | ||
563 | hr = WcaWriteStringToCaData(pItm->pComponent->wzCLSID, ppwzActionData); | ||
564 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
565 | |||
566 | // add application information to custom action data | ||
567 | hr = WcaWriteStringToCaData(pItm->pAssembly->pApplication->wzID, ppwzActionData); | ||
568 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
569 | |||
570 | // add partition information to custom action data | ||
571 | LPCWSTR pwzPartID = pItm->pAssembly->pApplication->pPartition ? pItm->pAssembly->pApplication->pPartition->wzID : L""; | ||
572 | hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData); | ||
573 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
574 | |||
575 | // add properties to custom action data | ||
576 | hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
577 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
578 | |||
579 | hr = S_OK; | ||
580 | |||
581 | LExit: | ||
582 | return hr; | ||
583 | } | ||
584 | |||
585 | static HRESULT ComponentFindByKey( | ||
586 | CPI_ASSEMBLY_LIST* pAsmList, | ||
587 | LPCWSTR pwzKey, | ||
588 | CPI_ASSEMBLY** ppAsmItm, | ||
589 | CPI_COMPONENT** ppCompItm | ||
590 | ) | ||
591 | { | ||
592 | for (CPI_ASSEMBLY* pAsmItm = pAsmList->pFirst; pAsmItm; pAsmItm = pAsmItm->pNext) | ||
593 | { | ||
594 | for (CPI_COMPONENT* pCompItm = pAsmItm->pComponents; pCompItm; pCompItm = pCompItm->pNext) | ||
595 | { | ||
596 | if (0 == lstrcmpW(pCompItm->wzKey, pwzKey)) | ||
597 | { | ||
598 | *ppAsmItm = pAsmItm; | ||
599 | *ppCompItm = pCompItm; | ||
600 | return S_OK; | ||
601 | } | ||
602 | } | ||
603 | } | ||
604 | |||
605 | return S_FALSE; | ||
606 | } | ||
diff --git a/src/ca/cpsubssched.h b/src/ca/cpsubssched.h new file mode 100644 index 00000000..3fc18478 --- /dev/null +++ b/src/ca/cpsubssched.h | |||
@@ -0,0 +1,62 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | struct CPI_SUBSCRIPTION | ||
6 | { | ||
7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
8 | WCHAR wzID[CPI_MAX_GUID + 1]; | ||
9 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
10 | WCHAR wzEventCLSID[CPI_MAX_GUID + 1]; | ||
11 | WCHAR wzPublisherID[CPI_MAX_GUID + 1]; | ||
12 | |||
13 | BOOL fObjectNotFound; | ||
14 | |||
15 | int iPropertyCount; | ||
16 | CPI_PROPERTY* pProperties; | ||
17 | |||
18 | INSTALLSTATE isInstalled, isAction; | ||
19 | |||
20 | CPI_ASSEMBLY* pAssembly; | ||
21 | CPI_COMPONENT* pComponent; | ||
22 | |||
23 | CPI_SUBSCRIPTION* pNext; | ||
24 | }; | ||
25 | |||
26 | struct CPI_SUBSCRIPTION_LIST | ||
27 | { | ||
28 | CPI_SUBSCRIPTION* pFirst; | ||
29 | |||
30 | int iInstallCount; | ||
31 | int iCommitCount; | ||
32 | int iUninstallCount; | ||
33 | }; | ||
34 | |||
35 | |||
36 | // function prototypes | ||
37 | |||
38 | void CpiSubscriptionListFree( | ||
39 | CPI_SUBSCRIPTION_LIST* pList | ||
40 | ); | ||
41 | HRESULT CpiSubscriptionsRead( | ||
42 | CPI_ASSEMBLY_LIST* pAsmList, | ||
43 | CPI_SUBSCRIPTION_LIST* pSubList | ||
44 | ); | ||
45 | HRESULT CpiSubscriptionsVerifyInstall( | ||
46 | CPI_SUBSCRIPTION_LIST* pList | ||
47 | ); | ||
48 | HRESULT CpiSubscriptionsVerifyUninstall( | ||
49 | CPI_SUBSCRIPTION_LIST* pList | ||
50 | ); | ||
51 | HRESULT CpiSubscriptionsInstall( | ||
52 | CPI_SUBSCRIPTION_LIST* pList, | ||
53 | int iRunMode, | ||
54 | LPWSTR* ppwzActionData, | ||
55 | int* piProgress | ||
56 | ); | ||
57 | HRESULT CpiSubscriptionsUninstall( | ||
58 | CPI_SUBSCRIPTION_LIST* pList, | ||
59 | int iRunMode, | ||
60 | LPWSTR* ppwzActionData, | ||
61 | int* piProgress | ||
62 | ); | ||
diff --git a/src/ca/cputilexec.cpp b/src/ca/cputilexec.cpp new file mode 100644 index 00000000..e081678b --- /dev/null +++ b/src/ca/cputilexec.cpp | |||
@@ -0,0 +1,1881 @@ | |||
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_WELLKNOWN_SID | ||
9 | { | ||
10 | LPCWSTR pwzName; | ||
11 | SID_IDENTIFIER_AUTHORITY iaIdentifierAuthority; | ||
12 | BYTE nSubAuthorityCount; | ||
13 | DWORD dwSubAuthority[8]; | ||
14 | }; | ||
15 | |||
16 | |||
17 | // well known SIDs | ||
18 | |||
19 | CPI_WELLKNOWN_SID wsWellKnownSids[] = { | ||
20 | {L"\\Everyone", SECURITY_WORLD_SID_AUTHORITY, 1, {SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
21 | {L"\\Administrators", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0}}, | ||
22 | {L"\\LocalSystem", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
23 | {L"\\LocalService", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
24 | {L"\\NetworkService", SECURITY_NT_AUTHORITY, 1, {SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
25 | {L"\\AuthenticatedUser", SECURITY_NT_AUTHORITY, 1, {SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
26 | {L"\\Guests", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS, 0, 0, 0, 0, 0, 0}}, | ||
27 | {L"\\Users", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0}}, | ||
28 | {L"\\CREATOR OWNER", SECURITY_NT_AUTHORITY, 1, {SECURITY_CREATOR_OWNER_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
29 | {NULL, SECURITY_NULL_SID_AUTHORITY, 0, {0, 0, 0, 0, 0, 0, 0, 0}} | ||
30 | }; | ||
31 | |||
32 | |||
33 | // prototypes for private helper functions | ||
34 | |||
35 | static HRESULT FindUserCollectionObjectIndex( | ||
36 | ICatalogCollection* piColl, | ||
37 | PSID pSid, | ||
38 | int* pi | ||
39 | ); | ||
40 | static HRESULT CreateSidFromDomainRidPair( | ||
41 | PSID pDomainSid, | ||
42 | DWORD dwRid, | ||
43 | PSID* ppSid | ||
44 | ); | ||
45 | static HRESULT InitLsaUnicodeString( | ||
46 | PLSA_UNICODE_STRING plusStr, | ||
47 | LPCWSTR pwzStr, | ||
48 | DWORD dwLen | ||
49 | ); | ||
50 | static void FreeLsaUnicodeString( | ||
51 | PLSA_UNICODE_STRING plusStr | ||
52 | ); | ||
53 | static HRESULT WriteFileAll( | ||
54 | HANDLE hFile, | ||
55 | PBYTE pbBuffer, | ||
56 | DWORD dwBufferLength | ||
57 | ); | ||
58 | static HRESULT ReadFileAll( | ||
59 | HANDLE hFile, | ||
60 | PBYTE pbBuffer, | ||
61 | DWORD dwBufferLength | ||
62 | ); | ||
63 | |||
64 | |||
65 | // variables | ||
66 | |||
67 | static ICOMAdminCatalog* gpiCatalog; | ||
68 | |||
69 | |||
70 | // function definitions | ||
71 | |||
72 | void CpiInitialize() | ||
73 | { | ||
74 | // collections | ||
75 | gpiCatalog = NULL; | ||
76 | } | ||
77 | |||
78 | void CpiFinalize() | ||
79 | { | ||
80 | // collections | ||
81 | ReleaseObject(gpiCatalog); | ||
82 | } | ||
83 | |||
84 | HRESULT CpiActionStartMessage( | ||
85 | LPWSTR* ppwzActionData, | ||
86 | BOOL fSuppress | ||
87 | ) | ||
88 | { | ||
89 | HRESULT hr = S_OK; | ||
90 | UINT er = ERROR_SUCCESS; | ||
91 | |||
92 | PMSIHANDLE hRec; | ||
93 | |||
94 | LPWSTR pwzData = NULL; | ||
95 | |||
96 | // create record | ||
97 | hRec = ::MsiCreateRecord(3); | ||
98 | ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
99 | |||
100 | // action name | ||
101 | hr = WcaReadStringFromCaData(ppwzActionData, &pwzData); | ||
102 | ExitOnFailure(hr, "Failed to action name"); | ||
103 | |||
104 | er = ::MsiRecordSetStringW(hRec, 1, pwzData); | ||
105 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set action name"); | ||
106 | |||
107 | // description | ||
108 | hr = WcaReadStringFromCaData(ppwzActionData, &pwzData); | ||
109 | ExitOnFailure(hr, "Failed to description"); | ||
110 | |||
111 | er = ::MsiRecordSetStringW(hRec, 2, pwzData); | ||
112 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set description"); | ||
113 | |||
114 | // template | ||
115 | hr = WcaReadStringFromCaData(ppwzActionData, &pwzData); | ||
116 | ExitOnFailure(hr, "Failed to template"); | ||
117 | |||
118 | er = ::MsiRecordSetStringW(hRec, 3, pwzData); | ||
119 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set template"); | ||
120 | |||
121 | // message | ||
122 | if (!fSuppress) | ||
123 | { | ||
124 | er = WcaProcessMessage(INSTALLMESSAGE_ACTIONSTART, hRec); | ||
125 | if (0 == er || IDOK == er || IDYES == er) | ||
126 | { | ||
127 | hr = S_OK; | ||
128 | } | ||
129 | else if (IDABORT == er || IDCANCEL == er) | ||
130 | { | ||
131 | WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit | ||
132 | hr = S_FALSE; | ||
133 | } | ||
134 | else | ||
135 | hr = E_UNEXPECTED; | ||
136 | } | ||
137 | |||
138 | LExit: | ||
139 | // clean up | ||
140 | ReleaseStr(pwzData); | ||
141 | |||
142 | return hr; | ||
143 | } | ||
144 | |||
145 | HRESULT CpiActionDataMessage( | ||
146 | DWORD cArgs, | ||
147 | ... | ||
148 | ) | ||
149 | { | ||
150 | HRESULT hr = S_OK; | ||
151 | UINT er = ERROR_SUCCESS; | ||
152 | |||
153 | PMSIHANDLE hRec; | ||
154 | va_list args; | ||
155 | |||
156 | // record | ||
157 | hRec = ::MsiCreateRecord(cArgs); | ||
158 | ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
159 | |||
160 | va_start(args, cArgs); | ||
161 | for (DWORD i = 1; i <= cArgs; i++) | ||
162 | { | ||
163 | LPCWSTR pwzArg = va_arg(args, WCHAR*); | ||
164 | if (pwzArg && *pwzArg) | ||
165 | { | ||
166 | er = ::MsiRecordSetStringW(hRec, i, pwzArg); | ||
167 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set record field string"); | ||
168 | } | ||
169 | } | ||
170 | va_end(args); | ||
171 | |||
172 | // message | ||
173 | er = WcaProcessMessage(INSTALLMESSAGE_ACTIONDATA, hRec); | ||
174 | if (0 == er || IDOK == er || IDYES == er) | ||
175 | { | ||
176 | hr = S_OK; | ||
177 | } | ||
178 | else if (IDABORT == er || IDCANCEL == er) | ||
179 | { | ||
180 | WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit | ||
181 | hr = S_FALSE; | ||
182 | } | ||
183 | else | ||
184 | hr = E_UNEXPECTED; | ||
185 | |||
186 | LExit: | ||
187 | return hr; | ||
188 | } | ||
189 | |||
190 | HRESULT CpiGetAdminCatalog( | ||
191 | ICOMAdminCatalog** ppiCatalog | ||
192 | ) | ||
193 | { | ||
194 | HRESULT hr = S_OK; | ||
195 | |||
196 | if (!gpiCatalog) | ||
197 | { | ||
198 | // get collection | ||
199 | hr = ::CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_ALL, IID_ICOMAdminCatalog, (void**)&gpiCatalog); | ||
200 | ExitOnFailure(hr, "Failed to create COM+ admin catalog object"); | ||
201 | } | ||
202 | |||
203 | // return value | ||
204 | gpiCatalog->AddRef(); | ||
205 | *ppiCatalog = gpiCatalog; | ||
206 | |||
207 | hr = S_OK; | ||
208 | |||
209 | LExit: | ||
210 | return hr; | ||
211 | } | ||
212 | |||
213 | HRESULT CpiLogCatalogErrorInfo() | ||
214 | { | ||
215 | HRESULT hr = S_OK; | ||
216 | |||
217 | ICOMAdminCatalog* piCatalog = NULL; | ||
218 | ICatalogCollection* piErrColl = NULL; | ||
219 | IDispatch* piDisp = NULL; | ||
220 | ICatalogObject* piObj = NULL; | ||
221 | |||
222 | LPWSTR pwzName = NULL; | ||
223 | LPWSTR pwzErrorCode = NULL; | ||
224 | LPWSTR pwzMajorRef = NULL; | ||
225 | LPWSTR pwzMinorRef = NULL; | ||
226 | |||
227 | // get catalog | ||
228 | hr = CpiGetAdminCatalog(&piCatalog); | ||
229 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
230 | |||
231 | // get error info collection | ||
232 | hr = CpiGetCatalogCollection(L"ErrorInfo", &piErrColl); | ||
233 | ExitOnFailure(hr, "Failed to get error info collection"); | ||
234 | |||
235 | // loop objects | ||
236 | long lCnt; | ||
237 | hr = piErrColl->get_Count(&lCnt); | ||
238 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
239 | |||
240 | for (long i = 0; i < lCnt; i++) | ||
241 | { | ||
242 | // get ICatalogObject interface | ||
243 | hr = piErrColl->get_Item(i, &piDisp); | ||
244 | ExitOnFailure(hr, "Failed to get item from partitions collection"); | ||
245 | |||
246 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
247 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
248 | |||
249 | // get properties | ||
250 | hr = CpiGetCollectionObjectValue(piObj, L"Name", &pwzName); | ||
251 | ExitOnFailure(hr, "Failed to get name"); | ||
252 | hr = CpiGetCollectionObjectValue(piObj, L"ErrorCode", &pwzErrorCode); | ||
253 | ExitOnFailure(hr, "Failed to get error code"); | ||
254 | hr = CpiGetCollectionObjectValue(piObj, L"MajorRef", &pwzMajorRef); | ||
255 | ExitOnFailure(hr, "Failed to get major ref"); | ||
256 | hr = CpiGetCollectionObjectValue(piObj, L"MinorRef", &pwzMinorRef); | ||
257 | ExitOnFailure(hr, "Failed to get minor ref"); | ||
258 | |||
259 | // write to log | ||
260 | WcaLog(LOGMSG_STANDARD, "ErrorInfo: Name='%S', ErrorCode='%S', MajorRef='%S', MinorRef='%S'", | ||
261 | pwzName, pwzErrorCode, pwzMajorRef, pwzMinorRef); | ||
262 | |||
263 | // clean up | ||
264 | ReleaseNullObject(piDisp); | ||
265 | ReleaseNullObject(piObj); | ||
266 | } | ||
267 | |||
268 | hr = S_OK; | ||
269 | |||
270 | LExit: | ||
271 | // clean up | ||
272 | ReleaseObject(piCatalog); | ||
273 | ReleaseObject(piErrColl); | ||
274 | ReleaseObject(piDisp); | ||
275 | ReleaseObject(piObj); | ||
276 | |||
277 | ReleaseStr(pwzName); | ||
278 | ReleaseStr(pwzErrorCode); | ||
279 | ReleaseStr(pwzMajorRef); | ||
280 | ReleaseStr(pwzMinorRef); | ||
281 | |||
282 | return hr; | ||
283 | } | ||
284 | |||
285 | HRESULT CpiGetCatalogCollection( | ||
286 | LPCWSTR pwzName, | ||
287 | ICatalogCollection** ppiColl | ||
288 | ) | ||
289 | { | ||
290 | HRESULT hr = S_OK; | ||
291 | |||
292 | ICOMAdminCatalog* piCatalog = NULL; | ||
293 | IDispatch* piDisp = NULL; | ||
294 | |||
295 | BSTR bstrName = NULL; | ||
296 | |||
297 | // copy name string | ||
298 | bstrName = ::SysAllocString(pwzName); | ||
299 | ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name"); | ||
300 | |||
301 | // get catalog | ||
302 | hr = CpiGetAdminCatalog(&piCatalog); | ||
303 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
304 | |||
305 | // get collecton from catalog | ||
306 | hr = piCatalog->GetCollection(bstrName, &piDisp); | ||
307 | ExitOnFailure(hr, "Failed to get collection"); | ||
308 | |||
309 | hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl); | ||
310 | ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface"); | ||
311 | |||
312 | // populate collection | ||
313 | hr = (*ppiColl)->Populate(); | ||
314 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
315 | CpiLogCatalogErrorInfo(); | ||
316 | ExitOnFailure(hr, "Failed to populate collection"); | ||
317 | |||
318 | hr = S_OK; | ||
319 | |||
320 | LExit: | ||
321 | // clean up | ||
322 | ReleaseObject(piCatalog); | ||
323 | ReleaseObject(piDisp); | ||
324 | ReleaseBSTR(bstrName); | ||
325 | |||
326 | return hr; | ||
327 | } | ||
328 | |||
329 | HRESULT CpiGetCatalogCollection( | ||
330 | ICatalogCollection* piColl, | ||
331 | ICatalogObject* piObj, | ||
332 | LPCWSTR pwzName, | ||
333 | ICatalogCollection** ppiColl | ||
334 | ) | ||
335 | { | ||
336 | HRESULT hr = S_OK; | ||
337 | |||
338 | ICOMAdminCatalog* piCatalog = NULL; | ||
339 | IDispatch* piDisp = NULL; | ||
340 | |||
341 | BSTR bstrName = NULL; | ||
342 | |||
343 | VARIANT vtKey; | ||
344 | ::VariantInit(&vtKey); | ||
345 | |||
346 | // copy name string | ||
347 | bstrName = ::SysAllocString(pwzName); | ||
348 | ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name"); | ||
349 | |||
350 | // get catalog | ||
351 | hr = CpiGetAdminCatalog(&piCatalog); | ||
352 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
353 | |||
354 | // get key | ||
355 | hr = piObj->get_Key(&vtKey); | ||
356 | ExitOnFailure(hr, "Failed to get object key"); | ||
357 | |||
358 | // get collecton from catalog | ||
359 | hr = piColl->GetCollection(bstrName, vtKey, &piDisp); | ||
360 | ExitOnFailure(hr, "Failed to get collection"); | ||
361 | |||
362 | hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl); | ||
363 | ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface"); | ||
364 | |||
365 | // populate collection | ||
366 | hr = (*ppiColl)->Populate(); | ||
367 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
368 | CpiLogCatalogErrorInfo(); | ||
369 | ExitOnFailure(hr, "Failed to populate collection"); | ||
370 | |||
371 | hr = S_OK; | ||
372 | |||
373 | LExit: | ||
374 | // clean up | ||
375 | ReleaseObject(piCatalog); | ||
376 | ReleaseObject(piDisp); | ||
377 | ReleaseBSTR(bstrName); | ||
378 | ::VariantClear(&vtKey); | ||
379 | |||
380 | return hr; | ||
381 | } | ||
382 | |||
383 | HRESULT CpiAddCollectionObject( | ||
384 | ICatalogCollection* piColl, | ||
385 | ICatalogObject** ppiObj | ||
386 | ) | ||
387 | { | ||
388 | HRESULT hr = S_OK; | ||
389 | |||
390 | IDispatch* piDisp = NULL; | ||
391 | |||
392 | hr = piColl->Add(&piDisp); | ||
393 | ExitOnFailure(hr, "Failed to add object to collection"); | ||
394 | |||
395 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)ppiObj); | ||
396 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
397 | |||
398 | hr = S_OK; | ||
399 | |||
400 | LExit: | ||
401 | // clean up | ||
402 | ReleaseObject(piDisp); | ||
403 | |||
404 | return hr; | ||
405 | } | ||
406 | |||
407 | HRESULT CpiPutCollectionObjectValue( | ||
408 | ICatalogObject* piObj, | ||
409 | LPCWSTR pwzPropName, | ||
410 | LPCWSTR pwzValue | ||
411 | ) | ||
412 | { | ||
413 | HRESULT hr = S_OK; | ||
414 | |||
415 | BSTR bstrPropName = NULL; | ||
416 | |||
417 | VARIANT vtVal; | ||
418 | ::VariantInit(&vtVal); | ||
419 | |||
420 | // allocate property name string | ||
421 | bstrPropName = ::SysAllocString(pwzPropName); | ||
422 | ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate property name string"); | ||
423 | |||
424 | // prepare value variant | ||
425 | vtVal.vt = VT_BSTR; | ||
426 | vtVal.bstrVal = ::SysAllocString(pwzValue); | ||
427 | ExitOnNull(vtVal.bstrVal, hr, E_OUTOFMEMORY, "Failed to allocate property value string"); | ||
428 | |||
429 | // put value | ||
430 | hr = piObj->put_Value(bstrPropName, vtVal); | ||
431 | ExitOnFailure(hr, "Failed to put property value"); | ||
432 | |||
433 | hr = S_OK; | ||
434 | |||
435 | LExit: | ||
436 | // clean up | ||
437 | ReleaseBSTR(bstrPropName); | ||
438 | ::VariantClear(&vtVal); | ||
439 | |||
440 | return hr; | ||
441 | } | ||
442 | |||
443 | HRESULT CpiPutCollectionObjectValues( | ||
444 | ICatalogObject* piObj, | ||
445 | CPI_PROPERTY* pPropList | ||
446 | ) | ||
447 | { | ||
448 | HRESULT hr = S_OK; | ||
449 | |||
450 | for (CPI_PROPERTY* pItm = pPropList; pItm; pItm = pItm->pNext) | ||
451 | { | ||
452 | // set property | ||
453 | hr = CpiPutCollectionObjectValue(piObj, pItm->wzName, pItm->pwzValue); | ||
454 | ExitOnFailure(hr, "Failed to set object property value, name: %S", pItm->wzName); | ||
455 | } | ||
456 | |||
457 | hr = S_OK; | ||
458 | |||
459 | LExit: | ||
460 | return hr; | ||
461 | } | ||
462 | |||
463 | HRESULT CpiGetCollectionObjectValue( | ||
464 | ICatalogObject* piObj, | ||
465 | LPCWSTR szPropName, | ||
466 | LPWSTR* ppwzValue | ||
467 | ) | ||
468 | { | ||
469 | HRESULT hr = S_OK; | ||
470 | |||
471 | BSTR bstrPropName = NULL; | ||
472 | |||
473 | VARIANT vtVal; | ||
474 | ::VariantInit(&vtVal); | ||
475 | |||
476 | // allocate property name string | ||
477 | bstrPropName = ::SysAllocString(szPropName); | ||
478 | ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate property name string"); | ||
479 | |||
480 | // get value | ||
481 | hr = piObj->get_Value(bstrPropName, &vtVal); | ||
482 | ExitOnFailure(hr, "Failed to get property value"); | ||
483 | |||
484 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
485 | ExitOnFailure(hr, "Failed to change variant type"); | ||
486 | |||
487 | hr = StrAllocString(ppwzValue, vtVal.bstrVal, ::SysStringLen(vtVal.bstrVal)); | ||
488 | ExitOnFailure(hr, "Failed to allocate memory for value string"); | ||
489 | |||
490 | hr = S_OK; | ||
491 | |||
492 | LExit: | ||
493 | // clean up | ||
494 | ReleaseBSTR(bstrPropName); | ||
495 | ::VariantClear(&vtVal); | ||
496 | |||
497 | return hr; | ||
498 | } | ||
499 | |||
500 | HRESULT CpiResetObjectProperty( | ||
501 | ICatalogCollection* piColl, | ||
502 | ICatalogObject* piObj, | ||
503 | LPCWSTR pwzPropName | ||
504 | ) | ||
505 | { | ||
506 | HRESULT hr = S_OK; | ||
507 | |||
508 | BSTR bstrPropName = NULL; | ||
509 | |||
510 | long lChanges = 0; | ||
511 | |||
512 | VARIANT vtVal; | ||
513 | ::VariantInit(&vtVal); | ||
514 | |||
515 | // allocate property name string | ||
516 | bstrPropName = ::SysAllocString(pwzPropName); | ||
517 | ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate deleteable property name string"); | ||
518 | |||
519 | // get value | ||
520 | hr = piObj->get_Value(bstrPropName, &vtVal); | ||
521 | ExitOnFailure(hr, "Failed to get deleteable property value"); | ||
522 | |||
523 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BOOL); | ||
524 | ExitOnFailure(hr, "Failed to change variant type"); | ||
525 | |||
526 | // if the deleteable property is set | ||
527 | if (VARIANT_FALSE == vtVal.boolVal) | ||
528 | { | ||
529 | // clear property | ||
530 | vtVal.boolVal = VARIANT_TRUE; | ||
531 | |||
532 | hr = piObj->put_Value(bstrPropName, vtVal); | ||
533 | ExitOnFailure(hr, "Failed to get property value"); | ||
534 | |||
535 | // save changes | ||
536 | hr = piColl->SaveChanges(&lChanges); | ||
537 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
538 | CpiLogCatalogErrorInfo(); | ||
539 | ExitOnFailure(hr, "Failed to save changes"); | ||
540 | } | ||
541 | |||
542 | hr = S_OK; | ||
543 | |||
544 | LExit: | ||
545 | // clean up | ||
546 | ReleaseBSTR(bstrPropName); | ||
547 | ::VariantClear(&vtVal); | ||
548 | |||
549 | return hr; | ||
550 | } | ||
551 | |||
552 | HRESULT CpiRemoveCollectionObject( | ||
553 | ICatalogCollection* piColl, | ||
554 | LPCWSTR pwzID, | ||
555 | LPCWSTR pwzName, | ||
556 | BOOL fResetDeleteable | ||
557 | ) | ||
558 | { | ||
559 | HRESULT hr = S_OK; | ||
560 | |||
561 | IDispatch* piDisp = NULL; | ||
562 | ICatalogObject* piObj = NULL; | ||
563 | |||
564 | BOOL fMatch = FALSE; | ||
565 | |||
566 | VARIANT vtVal; | ||
567 | ::VariantInit(&vtVal); | ||
568 | |||
569 | long lCnt; | ||
570 | hr = piColl->get_Count(&lCnt); | ||
571 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
572 | |||
573 | for (long i = 0; i < lCnt; i++) | ||
574 | { | ||
575 | // get ICatalogObject interface | ||
576 | hr = piColl->get_Item(i, &piDisp); | ||
577 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
578 | |||
579 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
580 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
581 | |||
582 | // compare id | ||
583 | if (pwzID && *pwzID) | ||
584 | { | ||
585 | hr = piObj->get_Key(&vtVal); | ||
586 | ExitOnFailure(hr, "Failed to get key"); | ||
587 | |||
588 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
589 | ExitOnFailure(hr, "Failed to change variant type"); | ||
590 | |||
591 | if (0 == lstrcmpiW(vtVal.bstrVal, pwzID)) | ||
592 | fMatch = TRUE; | ||
593 | |||
594 | ::VariantClear(&vtVal); | ||
595 | } | ||
596 | |||
597 | // compare name | ||
598 | if (pwzName && *pwzName) | ||
599 | { | ||
600 | hr = piObj->get_Name(&vtVal); | ||
601 | ExitOnFailure(hr, "Failed to get name"); | ||
602 | |||
603 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
604 | ExitOnFailure(hr, "Failed to change variant type"); | ||
605 | |||
606 | if (0 == lstrcmpW(vtVal.bstrVal, pwzName)) | ||
607 | fMatch = TRUE; | ||
608 | |||
609 | ::VariantClear(&vtVal); | ||
610 | } | ||
611 | |||
612 | // if it's a match, remove it | ||
613 | if (fMatch) | ||
614 | { | ||
615 | if (fResetDeleteable) | ||
616 | { | ||
617 | // reset deleteable property, if set | ||
618 | hr = CpiResetObjectProperty(piColl, piObj, L"Deleteable"); | ||
619 | ExitOnFailure(hr, "Failed to reset deleteable property"); | ||
620 | } | ||
621 | |||
622 | hr = piColl->Remove(i); | ||
623 | ExitOnFailure(hr, "Failed to remove item from collection"); | ||
624 | break; | ||
625 | } | ||
626 | |||
627 | // release interface pointers | ||
628 | ReleaseNullObject(piDisp); | ||
629 | ReleaseNullObject(piObj); | ||
630 | } | ||
631 | |||
632 | hr = S_OK; | ||
633 | |||
634 | LExit: | ||
635 | // clean up | ||
636 | ReleaseObject(piDisp); | ||
637 | ReleaseObject(piObj); | ||
638 | |||
639 | ::VariantClear(&vtVal); | ||
640 | |||
641 | return hr; | ||
642 | } | ||
643 | |||
644 | HRESULT CpiRemoveUserCollectionObject( | ||
645 | ICatalogCollection* piColl, | ||
646 | PSID pSid | ||
647 | ) | ||
648 | { | ||
649 | HRESULT hr = S_OK; | ||
650 | |||
651 | int i = 0; | ||
652 | |||
653 | // find index | ||
654 | hr = FindUserCollectionObjectIndex(piColl, pSid, &i); | ||
655 | ExitOnFailure(hr, "Failed to find user collection index"); | ||
656 | |||
657 | if (S_FALSE == hr) | ||
658 | ExitFunction(); // not found, exit with hr = S_FALSE | ||
659 | |||
660 | // remove object | ||
661 | hr = piColl->Remove(i); | ||
662 | ExitOnFailure(hr, "Failed to remove object from collection"); | ||
663 | |||
664 | hr = S_OK; | ||
665 | |||
666 | LExit: | ||
667 | return hr; | ||
668 | } | ||
669 | |||
670 | HRESULT CpiFindCollectionObjectByStringKey( | ||
671 | ICatalogCollection* piColl, | ||
672 | LPCWSTR pwzKey, | ||
673 | ICatalogObject** ppiObj | ||
674 | ) | ||
675 | { | ||
676 | HRESULT hr = S_OK; | ||
677 | |||
678 | IDispatch* piDisp = NULL; | ||
679 | ICatalogObject* piObj = NULL; | ||
680 | |||
681 | VARIANT vtVal; | ||
682 | ::VariantInit(&vtVal); | ||
683 | |||
684 | long lCnt; | ||
685 | hr = piColl->get_Count(&lCnt); | ||
686 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
687 | |||
688 | for (long i = 0; i < lCnt; i++) | ||
689 | { | ||
690 | // get ICatalogObject interface | ||
691 | hr = piColl->get_Item(i, &piDisp); | ||
692 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
693 | |||
694 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
695 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
696 | |||
697 | // compare key | ||
698 | hr = piObj->get_Key(&vtVal); | ||
699 | ExitOnFailure(hr, "Failed to get key"); | ||
700 | |||
701 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
702 | ExitOnFailure(hr, "Failed to change variant type"); | ||
703 | |||
704 | if (0 == lstrcmpiW(vtVal.bstrVal, pwzKey)) | ||
705 | { | ||
706 | if (ppiObj) | ||
707 | { | ||
708 | *ppiObj = piObj; | ||
709 | piObj = NULL; | ||
710 | } | ||
711 | ExitFunction1(hr = S_OK); | ||
712 | } | ||
713 | |||
714 | // clean up | ||
715 | ReleaseNullObject(piDisp); | ||
716 | ReleaseNullObject(piObj); | ||
717 | |||
718 | ::VariantClear(&vtVal); | ||
719 | } | ||
720 | |||
721 | hr = S_FALSE; | ||
722 | |||
723 | LExit: | ||
724 | // clean up | ||
725 | ReleaseObject(piDisp); | ||
726 | ReleaseObject(piObj); | ||
727 | |||
728 | ::VariantClear(&vtVal); | ||
729 | |||
730 | return hr; | ||
731 | } | ||
732 | |||
733 | HRESULT CpiFindCollectionObjectByIntegerKey( | ||
734 | ICatalogCollection* piColl, | ||
735 | long lKey, | ||
736 | ICatalogObject** ppiObj | ||
737 | ) | ||
738 | { | ||
739 | HRESULT hr = S_OK; | ||
740 | |||
741 | IDispatch* piDisp = NULL; | ||
742 | ICatalogObject* piObj = NULL; | ||
743 | |||
744 | VARIANT vtVal; | ||
745 | ::VariantInit(&vtVal); | ||
746 | |||
747 | long lCnt; | ||
748 | hr = piColl->get_Count(&lCnt); | ||
749 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
750 | |||
751 | for (long i = 0; i < lCnt; i++) | ||
752 | { | ||
753 | // get ICatalogObject interface | ||
754 | hr = piColl->get_Item(i, &piDisp); | ||
755 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
756 | |||
757 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
758 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
759 | |||
760 | // compare key | ||
761 | hr = piObj->get_Key(&vtVal); | ||
762 | ExitOnFailure(hr, "Failed to get key"); | ||
763 | |||
764 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_I4); | ||
765 | ExitOnFailure(hr, "Failed to change variant type"); | ||
766 | |||
767 | if (vtVal.lVal == lKey) | ||
768 | { | ||
769 | if (ppiObj) | ||
770 | { | ||
771 | *ppiObj = piObj; | ||
772 | piObj = NULL; | ||
773 | } | ||
774 | ExitFunction1(hr = S_OK); | ||
775 | } | ||
776 | |||
777 | // clean up | ||
778 | ReleaseNullObject(piDisp); | ||
779 | ReleaseNullObject(piObj); | ||
780 | |||
781 | ::VariantClear(&vtVal); | ||
782 | } | ||
783 | |||
784 | hr = S_FALSE; | ||
785 | |||
786 | LExit: | ||
787 | // clean up | ||
788 | ReleaseObject(piDisp); | ||
789 | ReleaseObject(piObj); | ||
790 | |||
791 | ::VariantClear(&vtVal); | ||
792 | |||
793 | return hr; | ||
794 | } | ||
795 | |||
796 | HRESULT CpiFindCollectionObjectByName( | ||
797 | ICatalogCollection* piColl, | ||
798 | LPCWSTR pwzName, | ||
799 | ICatalogObject** ppiObj | ||
800 | ) | ||
801 | { | ||
802 | HRESULT hr = S_OK; | ||
803 | |||
804 | IDispatch* piDisp = NULL; | ||
805 | ICatalogObject* piObj = NULL; | ||
806 | |||
807 | VARIANT vtVal; | ||
808 | ::VariantInit(&vtVal); | ||
809 | |||
810 | long lCnt; | ||
811 | hr = piColl->get_Count(&lCnt); | ||
812 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
813 | |||
814 | for (long i = 0; i < lCnt; i++) | ||
815 | { | ||
816 | // get ICatalogObject interface | ||
817 | hr = piColl->get_Item(i, &piDisp); | ||
818 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
819 | |||
820 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
821 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
822 | |||
823 | // compare key | ||
824 | hr = piObj->get_Name(&vtVal); | ||
825 | ExitOnFailure(hr, "Failed to get key"); | ||
826 | |||
827 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
828 | ExitOnFailure(hr, "Failed to change variant type"); | ||
829 | |||
830 | if (0 == lstrcmpW(vtVal.bstrVal, pwzName)) | ||
831 | { | ||
832 | if (ppiObj) | ||
833 | { | ||
834 | *ppiObj = piObj; | ||
835 | piObj = NULL; | ||
836 | } | ||
837 | ExitFunction1(hr = S_OK); | ||
838 | } | ||
839 | |||
840 | // clean up | ||
841 | ReleaseNullObject(piDisp); | ||
842 | ReleaseNullObject(piObj); | ||
843 | |||
844 | ::VariantClear(&vtVal); | ||
845 | } | ||
846 | |||
847 | hr = S_FALSE; | ||
848 | |||
849 | LExit: | ||
850 | // clean up | ||
851 | ReleaseObject(piDisp); | ||
852 | ReleaseObject(piObj); | ||
853 | |||
854 | ::VariantClear(&vtVal); | ||
855 | |||
856 | return hr; | ||
857 | } | ||
858 | |||
859 | HRESULT CpiFindUserCollectionObject( | ||
860 | ICatalogCollection* piColl, | ||
861 | PSID pSid, | ||
862 | ICatalogObject** ppiObj | ||
863 | ) | ||
864 | { | ||
865 | HRESULT hr = S_OK; | ||
866 | |||
867 | int i = 0; | ||
868 | |||
869 | IDispatch* piDisp = NULL; | ||
870 | |||
871 | // find index | ||
872 | hr = FindUserCollectionObjectIndex(piColl, pSid, &i); | ||
873 | ExitOnFailure(hr, "Failed to find user collection index"); | ||
874 | |||
875 | if (S_FALSE == hr) | ||
876 | ExitFunction(); // not found, exit with hr = S_FALSE | ||
877 | |||
878 | // get object | ||
879 | if (ppiObj) | ||
880 | { | ||
881 | hr = piColl->get_Item(i, &piDisp); | ||
882 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
883 | |||
884 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)ppiObj); | ||
885 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
886 | } | ||
887 | |||
888 | hr = S_OK; | ||
889 | |||
890 | LExit: | ||
891 | // clean up | ||
892 | ReleaseObject(piDisp); | ||
893 | |||
894 | return hr; | ||
895 | } | ||
896 | |||
897 | HRESULT CpiGetPartitionsCollection( | ||
898 | ICatalogCollection** ppiPartColl | ||
899 | ) | ||
900 | { | ||
901 | HRESULT hr = S_OK; | ||
902 | |||
903 | // get collection | ||
904 | hr = CpiGetCatalogCollection(L"Partitions", ppiPartColl); | ||
905 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
906 | |||
907 | hr = S_OK; | ||
908 | |||
909 | LExit: | ||
910 | return hr; | ||
911 | } | ||
912 | |||
913 | HRESULT CpiGetPartitionRolesCollection( | ||
914 | LPCWSTR pwzPartID, | ||
915 | ICatalogCollection** ppiRolesColl | ||
916 | ) | ||
917 | { | ||
918 | HRESULT hr = S_OK; | ||
919 | |||
920 | ICatalogCollection* piPartColl = NULL; | ||
921 | ICatalogObject* piPartObj = NULL; | ||
922 | |||
923 | // get partitions collection | ||
924 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
925 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
926 | |||
927 | if (S_FALSE == hr) | ||
928 | ExitFunction(); // partitions collection not found, exit with hr = S_FALSE | ||
929 | |||
930 | // find object | ||
931 | hr = CpiFindCollectionObjectByStringKey(piPartColl, pwzPartID, &piPartObj); | ||
932 | ExitOnFailure(hr, "Failed to find collection object"); | ||
933 | |||
934 | if (S_FALSE == hr) | ||
935 | ExitFunction(); // partition not found, exit with hr = S_FALSE | ||
936 | |||
937 | // get roles collection | ||
938 | hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"RolesForPartition", ppiRolesColl); | ||
939 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
940 | |||
941 | hr = S_OK; | ||
942 | |||
943 | LExit: | ||
944 | // clean up | ||
945 | ReleaseObject(piPartColl); | ||
946 | ReleaseObject(piPartObj); | ||
947 | |||
948 | return hr; | ||
949 | } | ||
950 | |||
951 | HRESULT CpiGetUsersInPartitionRoleCollection( | ||
952 | LPCWSTR pwzPartID, | ||
953 | LPCWSTR pwzRoleName, | ||
954 | ICatalogCollection** ppiUsrInRoleColl | ||
955 | ) | ||
956 | { | ||
957 | HRESULT hr = S_OK; | ||
958 | |||
959 | ICatalogCollection* piRoleColl = NULL; | ||
960 | ICatalogObject* piRoleObj = NULL; | ||
961 | |||
962 | // get roles collection | ||
963 | hr = CpiGetPartitionRolesCollection(pwzPartID, &piRoleColl); | ||
964 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
965 | |||
966 | if (S_FALSE == hr) | ||
967 | ExitFunction(); // partition roles collection not found, exit with hr = S_FALSE | ||
968 | |||
969 | // find object | ||
970 | hr = CpiFindCollectionObjectByName(piRoleColl, pwzRoleName, &piRoleObj); | ||
971 | ExitOnFailure(hr, "Failed to find collection object"); | ||
972 | |||
973 | if (S_FALSE == hr) | ||
974 | ExitFunction(); // user not found, exit with hr = S_FALSE | ||
975 | |||
976 | // get roles collection | ||
977 | hr = CpiGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInPartitionRole", ppiUsrInRoleColl); | ||
978 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
979 | |||
980 | hr = S_OK; | ||
981 | |||
982 | LExit: | ||
983 | // clean up | ||
984 | ReleaseObject(piRoleColl); | ||
985 | ReleaseObject(piRoleObj); | ||
986 | |||
987 | return hr; | ||
988 | } | ||
989 | |||
990 | HRESULT CpiGetPartitionUsersCollection( | ||
991 | ICatalogCollection** ppiUserColl | ||
992 | ) | ||
993 | { | ||
994 | HRESULT hr = S_OK; | ||
995 | |||
996 | // get roles collection | ||
997 | hr = CpiGetCatalogCollection(L"PartitionUsers", ppiUserColl); | ||
998 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
999 | |||
1000 | hr = S_OK; | ||
1001 | |||
1002 | LExit: | ||
1003 | return hr; | ||
1004 | } | ||
1005 | |||
1006 | HRESULT CpiGetApplicationsCollection( | ||
1007 | LPCWSTR pwzPartID, | ||
1008 | ICatalogCollection** ppiAppColl | ||
1009 | ) | ||
1010 | { | ||
1011 | HRESULT hr = S_OK; | ||
1012 | |||
1013 | ICOMAdminCatalog* piCatalog = NULL; | ||
1014 | ICOMAdminCatalog2* piCatalog2 = NULL; | ||
1015 | BSTR bstrGlobPartID = NULL; | ||
1016 | |||
1017 | ICatalogCollection* piPartColl = NULL; | ||
1018 | ICatalogObject* piPartObj = NULL; | ||
1019 | |||
1020 | // get catalog | ||
1021 | hr = CpiGetAdminCatalog(&piCatalog); | ||
1022 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
1023 | |||
1024 | // get ICOMAdminCatalog2 interface | ||
1025 | hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2); | ||
1026 | |||
1027 | // COM+ 1.5 or later | ||
1028 | if (E_NOINTERFACE != hr) | ||
1029 | { | ||
1030 | ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface"); | ||
1031 | |||
1032 | // partition id | ||
1033 | if (!pwzPartID || !*pwzPartID) | ||
1034 | { | ||
1035 | // get global partition id | ||
1036 | hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID); | ||
1037 | ExitOnFailure(hr, "Failed to get global partition id"); | ||
1038 | } | ||
1039 | |||
1040 | // get partitions collection | ||
1041 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
1042 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
1043 | |||
1044 | // find object | ||
1045 | hr = CpiFindCollectionObjectByStringKey(piPartColl, bstrGlobPartID ? bstrGlobPartID : pwzPartID, &piPartObj); | ||
1046 | ExitOnFailure(hr, "Failed to find collection object"); | ||
1047 | |||
1048 | if (S_FALSE == hr) | ||
1049 | ExitFunction(); // partition not found, exit with hr = S_FALSE | ||
1050 | |||
1051 | // get applications collection | ||
1052 | hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"Applications", ppiAppColl); | ||
1053 | ExitOnFailure(hr, "Failed to get catalog collection for partition"); | ||
1054 | } | ||
1055 | |||
1056 | // COM+ pre 1.5 | ||
1057 | else | ||
1058 | { | ||
1059 | // this version of COM+ does not support partitions, make sure a partition was not specified | ||
1060 | if (pwzPartID && *pwzPartID) | ||
1061 | ExitOnFailure(hr = E_FAIL, "Partitions are not supported by this version of COM+"); | ||
1062 | |||
1063 | // get applications collection | ||
1064 | hr = CpiGetCatalogCollection(L"Applications", ppiAppColl); | ||
1065 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
1066 | } | ||
1067 | |||
1068 | hr = S_OK; | ||
1069 | |||
1070 | LExit: | ||
1071 | // clean up | ||
1072 | ReleaseObject(piCatalog); | ||
1073 | ReleaseObject(piCatalog2); | ||
1074 | ReleaseBSTR(bstrGlobPartID); | ||
1075 | |||
1076 | ReleaseObject(piPartColl); | ||
1077 | ReleaseObject(piPartObj); | ||
1078 | |||
1079 | return hr; | ||
1080 | } | ||
1081 | |||
1082 | HRESULT CpiGetRolesCollection( | ||
1083 | LPCWSTR pwzPartID, | ||
1084 | LPCWSTR pwzAppID, | ||
1085 | ICatalogCollection** ppiRolesColl | ||
1086 | ) | ||
1087 | { | ||
1088 | HRESULT hr = S_OK; | ||
1089 | |||
1090 | ICatalogCollection* piAppColl = NULL; | ||
1091 | ICatalogObject* piAppObj = NULL; | ||
1092 | |||
1093 | // get applications collection | ||
1094 | hr = CpiGetApplicationsCollection(pwzPartID, &piAppColl); | ||
1095 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
1096 | |||
1097 | if (S_FALSE == hr) | ||
1098 | ExitFunction(); // applications collection not found, exit with hr = S_FALSE | ||
1099 | |||
1100 | // find object | ||
1101 | hr = CpiFindCollectionObjectByStringKey(piAppColl, pwzAppID, &piAppObj); | ||
1102 | ExitOnFailure(hr, "Failed to find collection object"); | ||
1103 | |||
1104 | if (S_FALSE == hr) | ||
1105 | ExitFunction(); // application not found, exit with hr = S_FALSE | ||
1106 | |||
1107 | // get roles collection | ||
1108 | hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Roles", ppiRolesColl); | ||
1109 | ExitOnFailure(hr, "Failed to catalog collection"); | ||
1110 | |||
1111 | hr = S_OK; | ||
1112 | |||
1113 | LExit: | ||
1114 | // clean up | ||
1115 | ReleaseObject(piAppColl); | ||
1116 | ReleaseObject(piAppObj); | ||
1117 | |||
1118 | return hr; | ||
1119 | } | ||
1120 | |||
1121 | HRESULT CpiGetUsersInRoleCollection( | ||
1122 | LPCWSTR pwzPartID, | ||
1123 | LPCWSTR pwzAppID, | ||
1124 | LPCWSTR pwzRoleName, | ||
1125 | ICatalogCollection** ppiUsrInRoleColl | ||
1126 | ) | ||
1127 | { | ||
1128 | HRESULT hr = S_OK; | ||
1129 | |||
1130 | ICatalogCollection* piRoleColl = NULL; | ||
1131 | ICatalogObject* piRoleObj = NULL; | ||
1132 | |||
1133 | // get roles collection | ||
1134 | hr = CpiGetRolesCollection(pwzPartID, pwzAppID, &piRoleColl); | ||
1135 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
1136 | |||
1137 | if (S_FALSE == hr) | ||
1138 | ExitFunction(); // roles collection not found, exit with hr = S_FALSE | ||
1139 | |||
1140 | // find object | ||
1141 | hr = CpiFindCollectionObjectByName(piRoleColl, pwzRoleName, &piRoleObj); | ||
1142 | ExitOnFailure(hr, "Failed to find collection object"); | ||
1143 | |||
1144 | if (S_FALSE == hr) | ||
1145 | ExitFunction(); // role not found, exit with hr = S_FALSE | ||
1146 | |||
1147 | // get roles collection | ||
1148 | hr = CpiGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInRole", ppiUsrInRoleColl); | ||
1149 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
1150 | |||
1151 | hr = S_OK; | ||
1152 | |||
1153 | LExit: | ||
1154 | // clean up | ||
1155 | ReleaseObject(piRoleColl); | ||
1156 | ReleaseObject(piRoleObj); | ||
1157 | |||
1158 | return hr; | ||
1159 | } | ||
1160 | |||
1161 | HRESULT CpiGetComponentsCollection( | ||
1162 | LPCWSTR pwzPartID, | ||
1163 | LPCWSTR pwzAppID, | ||
1164 | ICatalogCollection** ppiCompsColl | ||
1165 | ) | ||
1166 | { | ||
1167 | HRESULT hr = S_OK; | ||
1168 | |||
1169 | ICatalogCollection* piAppColl = NULL; | ||
1170 | ICatalogObject* piAppObj = NULL; | ||
1171 | |||
1172 | // get applications collection | ||
1173 | hr = CpiGetApplicationsCollection(pwzPartID, &piAppColl); | ||
1174 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
1175 | |||
1176 | if (S_FALSE == hr) | ||
1177 | ExitFunction(); // applications collection not found, exit with hr = S_FALSE | ||
1178 | |||
1179 | // find object | ||
1180 | hr = CpiFindCollectionObjectByStringKey(piAppColl, pwzAppID, &piAppObj); | ||
1181 | ExitOnFailure(hr, "Failed to find collection object"); | ||
1182 | |||
1183 | if (S_FALSE == hr) | ||
1184 | ExitFunction(); // application not found, exit with hr = S_FALSE | ||
1185 | |||
1186 | // get components collection | ||
1187 | hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Components", ppiCompsColl); | ||
1188 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
1189 | |||
1190 | hr = S_OK; | ||
1191 | |||
1192 | LExit: | ||
1193 | // clean up | ||
1194 | ReleaseObject(piAppColl); | ||
1195 | ReleaseObject(piAppObj); | ||
1196 | |||
1197 | return hr; | ||
1198 | } | ||
1199 | |||
1200 | HRESULT CpiGetInterfacesCollection( | ||
1201 | ICatalogCollection* piCompColl, | ||
1202 | ICatalogObject* piCompObj, | ||
1203 | ICatalogCollection** ppiIntfColl | ||
1204 | ) | ||
1205 | { | ||
1206 | HRESULT hr = S_OK; | ||
1207 | |||
1208 | // get interfaces collection | ||
1209 | hr = CpiGetCatalogCollection(piCompColl, piCompObj, L"InterfacesForComponent", ppiIntfColl); | ||
1210 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
1211 | |||
1212 | hr = S_OK; | ||
1213 | |||
1214 | LExit: | ||
1215 | return hr; | ||
1216 | } | ||
1217 | |||
1218 | HRESULT CpiGetMethodsCollection( | ||
1219 | ICatalogCollection* piIntfColl, | ||
1220 | ICatalogObject* piIntfObj, | ||
1221 | ICatalogCollection** ppiMethColl | ||
1222 | ) | ||
1223 | { | ||
1224 | HRESULT hr = S_OK; | ||
1225 | |||
1226 | // get interfaces collection | ||
1227 | hr = CpiGetCatalogCollection(piIntfColl, piIntfObj, L"MethodsForInterface", ppiMethColl); | ||
1228 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
1229 | |||
1230 | hr = S_OK; | ||
1231 | |||
1232 | LExit: | ||
1233 | return hr; | ||
1234 | } | ||
1235 | |||
1236 | HRESULT CpiGetSubscriptionsCollection( | ||
1237 | LPCWSTR pwzPartID, | ||
1238 | LPCWSTR pwzAppID, | ||
1239 | LPCWSTR pwzCompCLSID, | ||
1240 | ICatalogCollection** ppiSubsColl | ||
1241 | ) | ||
1242 | { | ||
1243 | HRESULT hr = S_OK; | ||
1244 | |||
1245 | ICatalogCollection* piCompColl = NULL; | ||
1246 | ICatalogObject* piCompObj = NULL; | ||
1247 | |||
1248 | // get components collection | ||
1249 | hr = CpiGetComponentsCollection(pwzPartID, pwzAppID, &piCompColl); | ||
1250 | ExitOnFailure(hr, "Failed to get components collection"); | ||
1251 | |||
1252 | if (S_FALSE == hr) | ||
1253 | ExitFunction(); // components collection not found, exit with hr = S_FALSE | ||
1254 | |||
1255 | // find object | ||
1256 | hr = CpiFindCollectionObjectByStringKey(piCompColl, pwzCompCLSID, &piCompObj); | ||
1257 | ExitOnFailure(hr, "Failed to find collection object"); | ||
1258 | |||
1259 | if (S_FALSE == hr) | ||
1260 | ExitFunction(); // component not found, exit with hr = S_FALSE | ||
1261 | |||
1262 | // get subscriptions collection | ||
1263 | hr = CpiGetCatalogCollection(piCompColl, piCompObj, L"SubscriptionsForComponent", ppiSubsColl); | ||
1264 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
1265 | |||
1266 | hr = S_OK; | ||
1267 | |||
1268 | LExit: | ||
1269 | // clean up | ||
1270 | ReleaseObject(piCompColl); | ||
1271 | ReleaseObject(piCompObj); | ||
1272 | |||
1273 | return hr; | ||
1274 | } | ||
1275 | |||
1276 | HRESULT CpiReadPropertyList( | ||
1277 | LPWSTR* ppwzData, | ||
1278 | CPI_PROPERTY** ppPropList | ||
1279 | ) | ||
1280 | { | ||
1281 | HRESULT hr = S_OK; | ||
1282 | |||
1283 | CPI_PROPERTY* pItm = NULL; | ||
1284 | LPWSTR pwzName = NULL; | ||
1285 | |||
1286 | // clear list if it already contains items | ||
1287 | if (*ppPropList) | ||
1288 | CpiFreePropertyList(*ppPropList); | ||
1289 | *ppPropList = NULL; | ||
1290 | |||
1291 | // read property count | ||
1292 | int iPropCnt = 0; | ||
1293 | hr = WcaReadIntegerFromCaData(ppwzData, &iPropCnt); | ||
1294 | ExitOnFailure(hr, "Failed to read property count"); | ||
1295 | |||
1296 | for (int i = 0; i < iPropCnt; i++) | ||
1297 | { | ||
1298 | // allocate new element | ||
1299 | pItm = (CPI_PROPERTY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PROPERTY)); | ||
1300 | if (!pItm) | ||
1301 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1302 | |||
1303 | // Name | ||
1304 | hr = WcaReadStringFromCaData(ppwzData, &pwzName); | ||
1305 | ExitOnFailure(hr, "Failed to read name"); | ||
1306 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzName); | ||
1307 | |||
1308 | // Value | ||
1309 | hr = WcaReadStringFromCaData(ppwzData, &pItm->pwzValue); | ||
1310 | ExitOnFailure(hr, "Failed to read property value"); | ||
1311 | |||
1312 | // add to list | ||
1313 | if (*ppPropList) | ||
1314 | pItm->pNext = *ppPropList; | ||
1315 | *ppPropList = pItm; | ||
1316 | pItm = NULL; | ||
1317 | } | ||
1318 | |||
1319 | hr = S_OK; | ||
1320 | |||
1321 | LExit: | ||
1322 | // clean up | ||
1323 | ReleaseStr(pwzName); | ||
1324 | |||
1325 | if (pItm) | ||
1326 | CpiFreePropertyList(pItm); | ||
1327 | |||
1328 | return hr; | ||
1329 | } | ||
1330 | |||
1331 | void CpiFreePropertyList( | ||
1332 | CPI_PROPERTY* pList | ||
1333 | ) | ||
1334 | { | ||
1335 | while (pList) | ||
1336 | { | ||
1337 | ReleaseStr(pList->pwzValue); | ||
1338 | |||
1339 | CPI_PROPERTY* pDelete = pList; | ||
1340 | pList = pList->pNext; | ||
1341 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
1342 | } | ||
1343 | } | ||
1344 | |||
1345 | HRESULT CpiWriteKeyToRollbackFile( | ||
1346 | HANDLE hFile, | ||
1347 | LPCWSTR pwzKey | ||
1348 | ) | ||
1349 | { | ||
1350 | HRESULT hr = S_OK; | ||
1351 | |||
1352 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
1353 | ::ZeroMemory(wzKey, sizeof(wzKey)); | ||
1354 | hr = StringCchCopyW(wzKey, countof(wzKey), pwzKey); | ||
1355 | ExitOnFailure(hr, "Failed to copy key"); | ||
1356 | |||
1357 | hr = WriteFileAll(hFile, (PBYTE)wzKey, MAX_DARWIN_KEY * sizeof(WCHAR)); | ||
1358 | ExitOnFailure(hr, "Failed to write buffer"); | ||
1359 | |||
1360 | FlushFileBuffers(hFile); | ||
1361 | |||
1362 | hr = S_OK; | ||
1363 | |||
1364 | LExit: | ||
1365 | return hr; | ||
1366 | } | ||
1367 | |||
1368 | HRESULT CpiWriteIntegerToRollbackFile( | ||
1369 | HANDLE hFile, | ||
1370 | int i | ||
1371 | ) | ||
1372 | { | ||
1373 | HRESULT hr = S_OK; | ||
1374 | |||
1375 | hr = WriteFileAll(hFile, (PBYTE)&i, sizeof(int)); | ||
1376 | ExitOnFailure(hr, "Failed to write buffer"); | ||
1377 | |||
1378 | FlushFileBuffers(hFile); | ||
1379 | |||
1380 | hr = S_OK; | ||
1381 | |||
1382 | LExit: | ||
1383 | return hr; | ||
1384 | } | ||
1385 | |||
1386 | HRESULT CpiReadRollbackDataList( | ||
1387 | HANDLE hFile, | ||
1388 | CPI_ROLLBACK_DATA** pprdList | ||
1389 | ) | ||
1390 | { | ||
1391 | HRESULT hr = S_OK; | ||
1392 | |||
1393 | int iCount; | ||
1394 | |||
1395 | CPI_ROLLBACK_DATA* pItm = NULL; | ||
1396 | |||
1397 | // read count | ||
1398 | hr = ReadFileAll(hFile, (PBYTE)&iCount, sizeof(int)); | ||
1399 | if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr) | ||
1400 | ExitFunction1(hr = S_OK); // EOF reached, nothing left to read | ||
1401 | ExitOnFailure(hr, "Failed to read count"); | ||
1402 | |||
1403 | for (int i = 0; i < iCount; i++) | ||
1404 | { | ||
1405 | // allocate new element | ||
1406 | pItm = (CPI_ROLLBACK_DATA*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLLBACK_DATA)); | ||
1407 | if (!pItm) | ||
1408 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
1409 | |||
1410 | // read from file | ||
1411 | hr = ReadFileAll(hFile, (PBYTE)pItm->wzKey, MAX_DARWIN_KEY * sizeof(WCHAR)); | ||
1412 | if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr) | ||
1413 | break; // EOF reached, nothing left to read | ||
1414 | ExitOnFailure(hr, "Failed to read key"); | ||
1415 | |||
1416 | hr = ReadFileAll(hFile, (PBYTE)&pItm->iStatus, sizeof(int)); | ||
1417 | if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr) | ||
1418 | pItm->iStatus = 0; // EOF reached, the operation was interupted; set status to zero | ||
1419 | else | ||
1420 | ExitOnFailure(hr, "Failed to read status"); | ||
1421 | |||
1422 | // add to list | ||
1423 | if (*pprdList) | ||
1424 | pItm->pNext = *pprdList; | ||
1425 | *pprdList = pItm; | ||
1426 | pItm = NULL; | ||
1427 | } | ||
1428 | |||
1429 | hr = S_OK; | ||
1430 | |||
1431 | LExit: | ||
1432 | // clean up | ||
1433 | if (pItm) | ||
1434 | CpiFreeRollbackDataList(pItm); | ||
1435 | |||
1436 | return hr; | ||
1437 | } | ||
1438 | |||
1439 | void CpiFreeRollbackDataList( | ||
1440 | CPI_ROLLBACK_DATA* pList | ||
1441 | ) | ||
1442 | { | ||
1443 | while (pList) | ||
1444 | { | ||
1445 | CPI_ROLLBACK_DATA* pDelete = pList; | ||
1446 | pList = pList->pNext; | ||
1447 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
1448 | } | ||
1449 | } | ||
1450 | |||
1451 | HRESULT CpiFindRollbackStatus( | ||
1452 | CPI_ROLLBACK_DATA* pList, | ||
1453 | LPCWSTR pwzKey, | ||
1454 | int* piStatus | ||
1455 | ) | ||
1456 | { | ||
1457 | HRESULT hr = S_OK; | ||
1458 | |||
1459 | for (; pList; pList = pList->pNext) | ||
1460 | { | ||
1461 | if (0 == lstrcmpW(pList->wzKey, pwzKey)) | ||
1462 | { | ||
1463 | *piStatus = pList->iStatus; | ||
1464 | ExitFunction1(hr = S_OK); | ||
1465 | } | ||
1466 | } | ||
1467 | |||
1468 | hr = S_FALSE; | ||
1469 | |||
1470 | LExit: | ||
1471 | return hr; | ||
1472 | } | ||
1473 | |||
1474 | HRESULT CpiAccountNameToSid( | ||
1475 | LPCWSTR pwzAccountName, | ||
1476 | PSID* ppSid | ||
1477 | ) | ||
1478 | { | ||
1479 | HRESULT hr = S_OK; | ||
1480 | UINT er = ERROR_SUCCESS; | ||
1481 | NTSTATUS st = 0; | ||
1482 | |||
1483 | PSID pSid = NULL; | ||
1484 | LSA_OBJECT_ATTRIBUTES loaAttributes; | ||
1485 | LSA_HANDLE lsahPolicy = NULL; | ||
1486 | LSA_UNICODE_STRING lusName; | ||
1487 | PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL; | ||
1488 | PLSA_TRANSLATED_SID pltsSid = NULL; | ||
1489 | |||
1490 | ::ZeroMemory(&loaAttributes, sizeof(loaAttributes)); | ||
1491 | ::ZeroMemory(&lusName, sizeof(lusName)); | ||
1492 | |||
1493 | // identify well known SIDs | ||
1494 | for (CPI_WELLKNOWN_SID* pWS = wsWellKnownSids; pWS->pwzName; pWS++) | ||
1495 | { | ||
1496 | if (0 == lstrcmpiW(pwzAccountName, pWS->pwzName)) | ||
1497 | { | ||
1498 | // allocate SID buffer | ||
1499 | pSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, ::GetSidLengthRequired(pWS->nSubAuthorityCount)); | ||
1500 | ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID"); | ||
1501 | |||
1502 | // initialize SID | ||
1503 | ::InitializeSid(pSid, &pWS->iaIdentifierAuthority, pWS->nSubAuthorityCount); | ||
1504 | |||
1505 | // copy sub autorities | ||
1506 | for (DWORD i = 0; i < pWS->nSubAuthorityCount; i++) | ||
1507 | *::GetSidSubAuthority(pSid, i) = pWS->dwSubAuthority[i]; | ||
1508 | |||
1509 | break; | ||
1510 | } | ||
1511 | } | ||
1512 | |||
1513 | // lookup name | ||
1514 | if (!pSid) | ||
1515 | { | ||
1516 | // open policy handle | ||
1517 | st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy); | ||
1518 | er = ::LsaNtStatusToWinError(st); | ||
1519 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle"); | ||
1520 | |||
1521 | // create account name lsa unicode string | ||
1522 | hr = InitLsaUnicodeString(&lusName, pwzAccountName, (DWORD)wcslen(pwzAccountName)); | ||
1523 | ExitOnFailure(hr, "Failed to initialize account name string"); | ||
1524 | |||
1525 | // lookup name | ||
1526 | st = ::LsaLookupNames(lsahPolicy, 1, &lusName, &plrdsDomains, &pltsSid); | ||
1527 | er = ::LsaNtStatusToWinError(st); | ||
1528 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names"); | ||
1529 | |||
1530 | if (SidTypeDomain == pltsSid->Use) | ||
1531 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported"); | ||
1532 | |||
1533 | // convert sid | ||
1534 | hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pSid); | ||
1535 | ExitOnFailure(hr, "Failed to convert SID"); | ||
1536 | } | ||
1537 | |||
1538 | *ppSid = pSid; | ||
1539 | pSid = NULL; | ||
1540 | |||
1541 | hr = S_OK; | ||
1542 | |||
1543 | LExit: | ||
1544 | // clean up | ||
1545 | if (pSid) | ||
1546 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
1547 | if (lsahPolicy) | ||
1548 | ::LsaClose(lsahPolicy); | ||
1549 | if (plrdsDomains) | ||
1550 | ::LsaFreeMemory(plrdsDomains); | ||
1551 | if (pltsSid) | ||
1552 | ::LsaFreeMemory(pltsSid); | ||
1553 | FreeLsaUnicodeString(&lusName); | ||
1554 | |||
1555 | return hr; | ||
1556 | } | ||
1557 | |||
1558 | HRESULT CpiSidToAccountName( | ||
1559 | PSID pSid, | ||
1560 | LPWSTR* ppwzAccountName | ||
1561 | ) | ||
1562 | { | ||
1563 | HRESULT hr = S_OK; | ||
1564 | UINT er = ERROR_SUCCESS; | ||
1565 | NTSTATUS st = 0; | ||
1566 | |||
1567 | LSA_OBJECT_ATTRIBUTES loaAttributes; | ||
1568 | LSA_HANDLE lsahPolicy = NULL; | ||
1569 | PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL; | ||
1570 | PLSA_TRANSLATED_NAME pltnName = NULL; | ||
1571 | |||
1572 | LPWSTR pwzDomain = NULL; | ||
1573 | LPWSTR pwzName = NULL; | ||
1574 | |||
1575 | ::ZeroMemory(&loaAttributes, sizeof(loaAttributes)); | ||
1576 | |||
1577 | // open policy handle | ||
1578 | st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy); | ||
1579 | er = ::LsaNtStatusToWinError(st); | ||
1580 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle"); | ||
1581 | |||
1582 | // lookup SID | ||
1583 | st = ::LsaLookupSids(lsahPolicy, 1, &pSid, &plrdsDomains, &pltnName); | ||
1584 | er = ::LsaNtStatusToWinError(st); | ||
1585 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed lookup SID"); | ||
1586 | |||
1587 | if (SidTypeDomain == pltnName->Use) | ||
1588 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported"); | ||
1589 | |||
1590 | // format account name string | ||
1591 | if (SidTypeWellKnownGroup != pltnName->Use) | ||
1592 | { | ||
1593 | PLSA_UNICODE_STRING plusDomain = &plrdsDomains->Domains[pltnName->DomainIndex].Name; | ||
1594 | hr = StrAllocString(&pwzDomain, plusDomain->Buffer, plusDomain->Length / sizeof(WCHAR)); | ||
1595 | ExitOnFailure(hr, "Failed to allocate name string"); | ||
1596 | } | ||
1597 | |||
1598 | hr = StrAllocString(&pwzName, pltnName->Name.Buffer, pltnName->Name.Length / sizeof(WCHAR)); | ||
1599 | ExitOnFailure(hr, "Failed to allocate domain string"); | ||
1600 | |||
1601 | hr = StrAllocFormatted(ppwzAccountName, L"%s\\%s", pwzDomain ? pwzDomain : L"", pwzName); | ||
1602 | ExitOnFailure(hr, "Failed to format account name string"); | ||
1603 | |||
1604 | hr = S_OK; | ||
1605 | |||
1606 | LExit: | ||
1607 | // clean up | ||
1608 | if (lsahPolicy) | ||
1609 | ::LsaClose(lsahPolicy); | ||
1610 | if (plrdsDomains) | ||
1611 | ::LsaFreeMemory(plrdsDomains); | ||
1612 | if (pltnName) | ||
1613 | ::LsaFreeMemory(pltnName); | ||
1614 | |||
1615 | ReleaseStr(pwzDomain); | ||
1616 | ReleaseStr(pwzName); | ||
1617 | |||
1618 | return hr; | ||
1619 | } | ||
1620 | |||
1621 | // helper function definitions | ||
1622 | |||
1623 | static HRESULT FindUserCollectionObjectIndex( | ||
1624 | ICatalogCollection* piColl, | ||
1625 | PSID pSid, | ||
1626 | int* pi | ||
1627 | ) | ||
1628 | { | ||
1629 | HRESULT hr = S_OK; | ||
1630 | UINT er = ERROR_SUCCESS; | ||
1631 | NTSTATUS st = 0; | ||
1632 | |||
1633 | long i = 0; | ||
1634 | long lCollCnt = 0; | ||
1635 | |||
1636 | LSA_OBJECT_ATTRIBUTES loaAttributes; | ||
1637 | LSA_HANDLE lsahPolicy = NULL; | ||
1638 | PLSA_UNICODE_STRING plusNames = NULL; | ||
1639 | PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL; | ||
1640 | PLSA_TRANSLATED_SID pltsSids = NULL; | ||
1641 | |||
1642 | IDispatch* piDisp = NULL; | ||
1643 | ICatalogObject* piObj = NULL; | ||
1644 | VARIANT vtVal; | ||
1645 | |||
1646 | PSID pTmpSid = NULL; | ||
1647 | |||
1648 | PLSA_TRANSLATED_SID pltsSid; | ||
1649 | |||
1650 | ::VariantInit(&vtVal); | ||
1651 | ::ZeroMemory(&loaAttributes, sizeof(loaAttributes)); | ||
1652 | |||
1653 | // open policy handle | ||
1654 | st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy); | ||
1655 | er = ::LsaNtStatusToWinError(st); | ||
1656 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle"); | ||
1657 | |||
1658 | // get number of elements in collection | ||
1659 | hr = piColl->get_Count(&lCollCnt); | ||
1660 | ExitOnFailure(hr, "Failed to get to number of objects in collection"); | ||
1661 | |||
1662 | if (0 == lCollCnt) | ||
1663 | ExitFunction1(hr = S_FALSE); // not found | ||
1664 | |||
1665 | // allocate name buffer | ||
1666 | plusNames = (PLSA_UNICODE_STRING)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LSA_UNICODE_STRING) * lCollCnt); | ||
1667 | ExitOnNull(plusNames, hr, E_OUTOFMEMORY, "Failed to allocate names buffer"); | ||
1668 | |||
1669 | // get accounts in collection | ||
1670 | for (i = 0; i < lCollCnt; i++) | ||
1671 | { | ||
1672 | // get ICatalogObject interface | ||
1673 | hr = piColl->get_Item(i, &piDisp); | ||
1674 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
1675 | |||
1676 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
1677 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
1678 | |||
1679 | // get value | ||
1680 | hr = piObj->get_Key(&vtVal); | ||
1681 | ExitOnFailure(hr, "Failed to get key"); | ||
1682 | |||
1683 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
1684 | ExitOnFailure(hr, "Failed to change variant type"); | ||
1685 | |||
1686 | // copy account name string | ||
1687 | hr = InitLsaUnicodeString(&plusNames[i], vtVal.bstrVal, ::SysStringLen(vtVal.bstrVal)); | ||
1688 | ExitOnFailure(hr, "Failed to initialize account name string"); | ||
1689 | |||
1690 | // clean up | ||
1691 | ReleaseNullObject(piDisp); | ||
1692 | ReleaseNullObject(piObj); | ||
1693 | ::VariantClear(&vtVal); | ||
1694 | } | ||
1695 | |||
1696 | // lookup names | ||
1697 | st = ::LsaLookupNames(lsahPolicy, lCollCnt, plusNames, &plrdsDomains, &pltsSids); | ||
1698 | er = ::LsaNtStatusToWinError(st); | ||
1699 | if (ERROR_NONE_MAPPED != er && ERROR_SOME_NOT_MAPPED != er) | ||
1700 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names"); | ||
1701 | |||
1702 | // compare SIDs | ||
1703 | for (i = 0; i < lCollCnt; i++) | ||
1704 | { | ||
1705 | // get SID | ||
1706 | pltsSid = &pltsSids[i]; | ||
1707 | if (SidTypeDomain == pltsSid->Use || SidTypeInvalid == pltsSid->Use || SidTypeUnknown == pltsSid->Use) | ||
1708 | continue; // ignore... | ||
1709 | |||
1710 | hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pTmpSid); | ||
1711 | ExitOnFailure(hr, "Failed to convert SID"); | ||
1712 | |||
1713 | // compare SIDs | ||
1714 | if (::EqualSid(pSid, pTmpSid)) | ||
1715 | { | ||
1716 | *pi = i; | ||
1717 | ExitFunction1(hr = S_OK); | ||
1718 | } | ||
1719 | } | ||
1720 | |||
1721 | if (ERROR_NONE_MAPPED == er || ERROR_SOME_NOT_MAPPED == er) | ||
1722 | hr = HRESULT_FROM_WIN32(er); | ||
1723 | else | ||
1724 | hr = S_FALSE; // not found | ||
1725 | |||
1726 | LExit: | ||
1727 | // clean up | ||
1728 | ReleaseObject(piDisp); | ||
1729 | ReleaseObject(piObj); | ||
1730 | ::VariantClear(&vtVal); | ||
1731 | |||
1732 | if (plusNames) | ||
1733 | { | ||
1734 | for (i = 0; i < lCollCnt; i++) | ||
1735 | FreeLsaUnicodeString(&plusNames[i]); | ||
1736 | ::HeapFree(::GetProcessHeap(), 0, plusNames); | ||
1737 | } | ||
1738 | |||
1739 | if (lsahPolicy) | ||
1740 | ::LsaClose(lsahPolicy); | ||
1741 | if (plrdsDomains) | ||
1742 | ::LsaFreeMemory(plrdsDomains); | ||
1743 | if (pltsSids) | ||
1744 | ::LsaFreeMemory(pltsSids); | ||
1745 | |||
1746 | if (pTmpSid) | ||
1747 | ::HeapFree(::GetProcessHeap(), 0, pTmpSid); | ||
1748 | |||
1749 | return hr; | ||
1750 | } | ||
1751 | |||
1752 | static HRESULT CreateSidFromDomainRidPair( | ||
1753 | PSID pDomainSid, | ||
1754 | DWORD dwRid, | ||
1755 | PSID* ppSid | ||
1756 | ) | ||
1757 | { | ||
1758 | HRESULT hr = S_OK; | ||
1759 | PSID pSid = NULL; | ||
1760 | |||
1761 | // get domain SID sub authority count | ||
1762 | UCHAR ucSubAuthorityCount = *::GetSidSubAuthorityCount(pDomainSid); | ||
1763 | |||
1764 | // allocate SID buffer | ||
1765 | DWORD dwLengthRequired = ::GetSidLengthRequired(ucSubAuthorityCount + (UCHAR)1); | ||
1766 | if (*ppSid) | ||
1767 | { | ||
1768 | SIZE_T ccb = ::HeapSize(::GetProcessHeap(), 0, *ppSid); | ||
1769 | if (-1 == ccb) | ||
1770 | ExitOnFailure(hr = E_FAIL, "Failed to get size of SID buffer"); | ||
1771 | |||
1772 | if (ccb < dwLengthRequired) | ||
1773 | { | ||
1774 | pSid = (PSID)::HeapReAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, *ppSid, dwLengthRequired); | ||
1775 | ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to reallocate buffer for SID, len: %d", dwLengthRequired); | ||
1776 | *ppSid = pSid; | ||
1777 | } | ||
1778 | } | ||
1779 | else | ||
1780 | { | ||
1781 | *ppSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwLengthRequired); | ||
1782 | ExitOnNull(*ppSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID, len: %d", dwLengthRequired); | ||
1783 | } | ||
1784 | |||
1785 | ::InitializeSid(*ppSid, ::GetSidIdentifierAuthority(pDomainSid), ucSubAuthorityCount + (UCHAR)1); | ||
1786 | |||
1787 | // copy sub autorities | ||
1788 | DWORD i = 0; | ||
1789 | for (; i < ucSubAuthorityCount; i++) | ||
1790 | *::GetSidSubAuthority(*ppSid, i) = *::GetSidSubAuthority(pDomainSid, i); | ||
1791 | *::GetSidSubAuthority(*ppSid, i) = dwRid; | ||
1792 | |||
1793 | hr = S_OK; | ||
1794 | |||
1795 | LExit: | ||
1796 | return hr; | ||
1797 | } | ||
1798 | |||
1799 | static HRESULT InitLsaUnicodeString( | ||
1800 | PLSA_UNICODE_STRING plusStr, | ||
1801 | LPCWSTR pwzStr, | ||
1802 | DWORD dwLen | ||
1803 | ) | ||
1804 | { | ||
1805 | HRESULT hr = S_OK; | ||
1806 | |||
1807 | plusStr->Length = (USHORT)dwLen * sizeof(WCHAR); | ||
1808 | plusStr->MaximumLength = (USHORT)(dwLen + 1) * sizeof(WCHAR); | ||
1809 | |||
1810 | plusStr->Buffer = (WCHAR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) * (dwLen + 1)); | ||
1811 | ExitOnNull(plusStr->Buffer, hr, E_OUTOFMEMORY, "Failed to allocate account name string"); | ||
1812 | |||
1813 | hr = StringCchCopyW(plusStr->Buffer, dwLen + 1, pwzStr); | ||
1814 | ExitOnFailure(hr, "Failed to copy buffer"); | ||
1815 | |||
1816 | hr = S_OK; | ||
1817 | |||
1818 | LExit: | ||
1819 | return hr; | ||
1820 | } | ||
1821 | |||
1822 | static void FreeLsaUnicodeString( | ||
1823 | PLSA_UNICODE_STRING plusStr | ||
1824 | ) | ||
1825 | { | ||
1826 | if (plusStr->Buffer) | ||
1827 | ::HeapFree(::GetProcessHeap(), 0, plusStr->Buffer); | ||
1828 | } | ||
1829 | |||
1830 | static HRESULT WriteFileAll( | ||
1831 | HANDLE hFile, | ||
1832 | PBYTE pbBuffer, | ||
1833 | DWORD dwBufferLength | ||
1834 | ) | ||
1835 | { | ||
1836 | HRESULT hr = S_OK; | ||
1837 | |||
1838 | DWORD dwBytesWritten; | ||
1839 | |||
1840 | while (dwBufferLength) | ||
1841 | { | ||
1842 | if (!::WriteFile(hFile, pbBuffer, dwBufferLength, &dwBytesWritten, NULL)) | ||
1843 | ExitFunction1(hr = HRESULT_FROM_WIN32(::GetLastError())); | ||
1844 | |||
1845 | dwBufferLength -= dwBytesWritten; | ||
1846 | pbBuffer += dwBytesWritten; | ||
1847 | } | ||
1848 | |||
1849 | hr = S_OK; | ||
1850 | |||
1851 | LExit: | ||
1852 | return hr; | ||
1853 | } | ||
1854 | |||
1855 | static HRESULT ReadFileAll( | ||
1856 | HANDLE hFile, | ||
1857 | PBYTE pbBuffer, | ||
1858 | DWORD dwBufferLength | ||
1859 | ) | ||
1860 | { | ||
1861 | HRESULT hr = S_OK; | ||
1862 | |||
1863 | DWORD dwBytesRead; | ||
1864 | |||
1865 | while (dwBufferLength) | ||
1866 | { | ||
1867 | if (!::ReadFile(hFile, pbBuffer, dwBufferLength, &dwBytesRead, NULL)) | ||
1868 | ExitFunction1(hr = HRESULT_FROM_WIN32(::GetLastError())); | ||
1869 | |||
1870 | if (0 == dwBytesRead) | ||
1871 | ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF)); | ||
1872 | |||
1873 | dwBufferLength -= dwBytesRead; | ||
1874 | pbBuffer += dwBytesRead; | ||
1875 | } | ||
1876 | |||
1877 | hr = S_OK; | ||
1878 | |||
1879 | LExit: | ||
1880 | return hr; | ||
1881 | } | ||
diff --git a/src/ca/cputilexec.h b/src/ca/cputilexec.h new file mode 100644 index 00000000..51b47583 --- /dev/null +++ b/src/ca/cputilexec.h | |||
@@ -0,0 +1,193 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | #define CPI_MAX_GUID 38 | ||
6 | |||
7 | enum eActionType { atNoOp = 0, atCreate, atRemove }; | ||
8 | |||
9 | |||
10 | // structs | ||
11 | |||
12 | struct CPI_PROPERTY | ||
13 | { | ||
14 | WCHAR wzName[MAX_DARWIN_KEY + 1]; | ||
15 | LPWSTR pwzValue; | ||
16 | |||
17 | CPI_PROPERTY* pNext; | ||
18 | }; | ||
19 | |||
20 | struct CPI_ROLLBACK_DATA | ||
21 | { | ||
22 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
23 | int iStatus; | ||
24 | |||
25 | CPI_ROLLBACK_DATA* pNext; | ||
26 | }; | ||
27 | |||
28 | |||
29 | // function prototypes | ||
30 | |||
31 | void CpiInitialize(); | ||
32 | void CpiFinalize(); | ||
33 | HRESULT CpiActionStartMessage( | ||
34 | LPWSTR* ppwzActionData, | ||
35 | BOOL fSuppress | ||
36 | ); | ||
37 | HRESULT CpiActionDataMessage( | ||
38 | DWORD cArgs, | ||
39 | ... | ||
40 | ); | ||
41 | HRESULT CpiGetAdminCatalog( | ||
42 | ICOMAdminCatalog** ppiCatalog | ||
43 | ); | ||
44 | HRESULT CpiLogCatalogErrorInfo(); | ||
45 | HRESULT CpiGetCatalogCollection( | ||
46 | LPCWSTR pwzName, | ||
47 | ICatalogCollection** ppiColl | ||
48 | ); | ||
49 | HRESULT CpiGetCatalogCollection( | ||
50 | ICatalogCollection* piColl, | ||
51 | ICatalogObject* piObj, | ||
52 | LPCWSTR pwzName, | ||
53 | ICatalogCollection** ppiColl | ||
54 | ); | ||
55 | HRESULT CpiAddCollectionObject( | ||
56 | ICatalogCollection* piColl, | ||
57 | ICatalogObject** ppiObj | ||
58 | ); | ||
59 | HRESULT CpiPutCollectionObjectValue( | ||
60 | ICatalogObject* piObj, | ||
61 | LPCWSTR pwzPropName, | ||
62 | LPCWSTR pwzValue | ||
63 | ); | ||
64 | HRESULT CpiPutCollectionObjectValues( | ||
65 | ICatalogObject* piObj, | ||
66 | CPI_PROPERTY* pPropList | ||
67 | ); | ||
68 | HRESULT CpiGetCollectionObjectValue( | ||
69 | ICatalogObject* piObj, | ||
70 | LPCWSTR szPropName, | ||
71 | LPWSTR* ppwzValue | ||
72 | ); | ||
73 | HRESULT CpiResetObjectProperty( | ||
74 | ICatalogCollection* piColl, | ||
75 | ICatalogObject* piObj, | ||
76 | LPCWSTR pwzPropName | ||
77 | ); | ||
78 | HRESULT CpiRemoveCollectionObject( | ||
79 | ICatalogCollection* piColl, | ||
80 | LPCWSTR pwzID, | ||
81 | LPCWSTR pwzName, | ||
82 | BOOL fResetDeleteable | ||
83 | ); | ||
84 | HRESULT CpiRemoveUserCollectionObject( | ||
85 | ICatalogCollection* piColl, | ||
86 | PSID pSid | ||
87 | ); | ||
88 | HRESULT CpiFindCollectionObjectByStringKey( | ||
89 | ICatalogCollection* piColl, | ||
90 | LPCWSTR pwzKey, | ||
91 | ICatalogObject** ppiObj | ||
92 | ); | ||
93 | HRESULT CpiFindCollectionObjectByIntegerKey( | ||
94 | ICatalogCollection* piColl, | ||
95 | long lKey, | ||
96 | ICatalogObject** ppiObj | ||
97 | ); | ||
98 | HRESULT CpiFindCollectionObjectByName( | ||
99 | ICatalogCollection* piColl, | ||
100 | LPCWSTR pwzName, | ||
101 | ICatalogObject** ppiObj | ||
102 | ); | ||
103 | HRESULT CpiFindUserCollectionObject( | ||
104 | ICatalogCollection* piColl, | ||
105 | PSID pSid, | ||
106 | ICatalogObject** ppiObj | ||
107 | ); | ||
108 | HRESULT CpiGetPartitionsCollection( | ||
109 | ICatalogCollection** ppiPartColl | ||
110 | ); | ||
111 | HRESULT CpiGetPartitionRolesCollection( | ||
112 | LPCWSTR pwzPartID, | ||
113 | ICatalogCollection** ppiRolesColl | ||
114 | ); | ||
115 | HRESULT CpiGetUsersInPartitionRoleCollection( | ||
116 | LPCWSTR pwzPartID, | ||
117 | LPCWSTR pwzRoleName, | ||
118 | ICatalogCollection** ppiUsrInRoleColl | ||
119 | ); | ||
120 | HRESULT CpiGetPartitionUsersCollection( | ||
121 | ICatalogCollection** ppiUserColl | ||
122 | ); | ||
123 | HRESULT CpiGetApplicationsCollection( | ||
124 | LPCWSTR pwzPartID, | ||
125 | ICatalogCollection** ppiAppColl | ||
126 | ); | ||
127 | HRESULT CpiGetRolesCollection( | ||
128 | LPCWSTR pwzPartID, | ||
129 | LPCWSTR pwzAppID, | ||
130 | ICatalogCollection** ppiRolesColl | ||
131 | ); | ||
132 | HRESULT CpiGetUsersInRoleCollection( | ||
133 | LPCWSTR pwzPartID, | ||
134 | LPCWSTR pwzAppID, | ||
135 | LPCWSTR pwzRoleName, | ||
136 | ICatalogCollection** ppiUsrInRoleColl | ||
137 | ); | ||
138 | HRESULT CpiGetComponentsCollection( | ||
139 | LPCWSTR pwzPartID, | ||
140 | LPCWSTR pwzAppID, | ||
141 | ICatalogCollection** ppiCompsColl | ||
142 | ); | ||
143 | HRESULT CpiGetInterfacesCollection( | ||
144 | ICatalogCollection* piCompColl, | ||
145 | ICatalogObject* piCompObj, | ||
146 | ICatalogCollection** ppiIntfColl | ||
147 | ); | ||
148 | HRESULT CpiGetMethodsCollection( | ||
149 | ICatalogCollection* piIntfColl, | ||
150 | ICatalogObject* piIntfObj, | ||
151 | ICatalogCollection** ppiMethColl | ||
152 | ); | ||
153 | HRESULT CpiGetSubscriptionsCollection( | ||
154 | LPCWSTR pwzPartID, | ||
155 | LPCWSTR pwzAppID, | ||
156 | LPCWSTR pwzCompCLSID, | ||
157 | ICatalogCollection** ppiCompsColl | ||
158 | ); | ||
159 | HRESULT CpiReadPropertyList( | ||
160 | LPWSTR* ppwzData, | ||
161 | CPI_PROPERTY** ppPropList | ||
162 | ); | ||
163 | void CpiFreePropertyList( | ||
164 | CPI_PROPERTY* pList | ||
165 | ); | ||
166 | HRESULT CpiWriteKeyToRollbackFile( | ||
167 | HANDLE hFile, | ||
168 | LPCWSTR pwzKey | ||
169 | ); | ||
170 | HRESULT CpiWriteIntegerToRollbackFile( | ||
171 | HANDLE hFile, | ||
172 | int i | ||
173 | ); | ||
174 | HRESULT CpiReadRollbackDataList( | ||
175 | HANDLE hFile, | ||
176 | CPI_ROLLBACK_DATA** pprdList | ||
177 | ); | ||
178 | void CpiFreeRollbackDataList( | ||
179 | CPI_ROLLBACK_DATA* pList | ||
180 | ); | ||
181 | HRESULT CpiFindRollbackStatus( | ||
182 | CPI_ROLLBACK_DATA* pList, | ||
183 | LPCWSTR pwzKey, | ||
184 | int* piStatus | ||
185 | ); | ||
186 | HRESULT CpiAccountNameToSid( | ||
187 | LPCWSTR pwzAccountName, | ||
188 | PSID* ppSid | ||
189 | ); | ||
190 | HRESULT CpiSidToAccountName( | ||
191 | PSID pSid, | ||
192 | LPWSTR* ppwzAccountName | ||
193 | ); | ||
diff --git a/src/ca/cputilsched.cpp b/src/ca/cputilsched.cpp new file mode 100644 index 00000000..9dbe21ec --- /dev/null +++ b/src/ca/cputilsched.cpp | |||
@@ -0,0 +1,885 @@ | |||
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 | // sql queries | ||
7 | |||
8 | LPCWSTR vcsActionTextQuery = | ||
9 | L"SELECT `Description`, `Template` FROM `ActionText` WHERE `Action` = ?"; | ||
10 | enum eActionTextQuery { atqDescription = 1, atqTemplate }; | ||
11 | |||
12 | LPCWSTR vcsComponentAttributesQuery = | ||
13 | L"SELECT `Attributes` FROM `Component` WHERE `Component` = ?"; | ||
14 | enum eComponentAttributesQuery { caqAttributes = 1 }; | ||
15 | |||
16 | LPCWSTR vcsUserQuery = L"SELECT `Domain`, `Name` FROM `User` WHERE `User` = ?"; | ||
17 | enum eUserQuery { uqDomain = 1, uqName }; | ||
18 | |||
19 | enum ePropertyQuery { pqName = 1, pqValue }; | ||
20 | |||
21 | |||
22 | // prototypes for private helper functions | ||
23 | |||
24 | static HRESULT FindPropertyDefinition( | ||
25 | CPI_PROPERTY_DEFINITION* pPropDefList, | ||
26 | LPCWSTR pwzName, | ||
27 | CPI_PROPERTY_DEFINITION** ppPropDef | ||
28 | ); | ||
29 | static HRESULT GetUserAccountName( | ||
30 | LPCWSTR pwzKey, | ||
31 | LPWSTR* ppwzAccount | ||
32 | ); | ||
33 | |||
34 | |||
35 | // variables | ||
36 | |||
37 | static ICOMAdminCatalog* gpiCatalog; | ||
38 | static ICatalogCollection* gpiPartColl; | ||
39 | static ICatalogCollection* gpiAppColl; | ||
40 | |||
41 | static int giTables; | ||
42 | |||
43 | |||
44 | // function definitions | ||
45 | |||
46 | void CpiInitialize() | ||
47 | { | ||
48 | // collections | ||
49 | gpiCatalog = NULL; | ||
50 | gpiPartColl = NULL; | ||
51 | gpiAppColl = NULL; | ||
52 | |||
53 | // tables | ||
54 | giTables = 0; | ||
55 | |||
56 | if (S_OK == WcaTableExists(L"ComPlusPartition")) giTables |= cptComPlusPartition; | ||
57 | if (S_OK == WcaTableExists(L"ComPlusPartitionProperty")) giTables |= cptComPlusPartitionProperty; | ||
58 | if (S_OK == WcaTableExists(L"ComPlusPartitionRole")) giTables |= cptComPlusPartitionRole; | ||
59 | if (S_OK == WcaTableExists(L"ComPlusUserInPartitionRole")) giTables |= cptComPlusUserInPartitionRole; | ||
60 | if (S_OK == WcaTableExists(L"ComPlusGroupInPartitionRole")) giTables |= cptComPlusGroupInPartitionRole; | ||
61 | if (S_OK == WcaTableExists(L"ComPlusPartitionUser")) giTables |= cptComPlusPartitionUser; | ||
62 | if (S_OK == WcaTableExists(L"ComPlusApplication")) giTables |= cptComPlusApplication; | ||
63 | if (S_OK == WcaTableExists(L"ComPlusApplicationProperty")) giTables |= cptComPlusApplicationProperty; | ||
64 | if (S_OK == WcaTableExists(L"ComPlusApplicationRole")) giTables |= cptComPlusApplicationRole; | ||
65 | if (S_OK == WcaTableExists(L"ComPlusApplicationRoleProperty")) giTables |= cptComPlusApplicationRoleProperty; | ||
66 | if (S_OK == WcaTableExists(L"ComPlusUserInApplicationRole")) giTables |= cptComPlusUserInApplicationRole; | ||
67 | if (S_OK == WcaTableExists(L"ComPlusGroupInApplicationRole")) giTables |= cptComPlusGroupInApplicationRole; | ||
68 | if (S_OK == WcaTableExists(L"ComPlusAssembly")) giTables |= cptComPlusAssembly; | ||
69 | if (S_OK == WcaTableExists(L"ComPlusAssemblyDependency")) giTables |= cptComPlusAssemblyDependency; | ||
70 | if (S_OK == WcaTableExists(L"ComPlusComponent")) giTables |= cptComPlusComponent; | ||
71 | if (S_OK == WcaTableExists(L"ComPlusComponentProperty")) giTables |= cptComPlusComponentProperty; | ||
72 | if (S_OK == WcaTableExists(L"ComPlusRoleForComponent")) giTables |= cptComPlusRoleForComponent; | ||
73 | if (S_OK == WcaTableExists(L"ComPlusInterface")) giTables |= cptComPlusInterface; | ||
74 | if (S_OK == WcaTableExists(L"ComPlusInterfaceProperty")) giTables |= cptComPlusInterfaceProperty; | ||
75 | if (S_OK == WcaTableExists(L"ComPlusRoleForInterface")) giTables |= cptComPlusRoleForInterface; | ||
76 | if (S_OK == WcaTableExists(L"ComPlusMethod")) giTables |= cptComPlusMethod; | ||
77 | if (S_OK == WcaTableExists(L"ComPlusMethodProperty")) giTables |= cptComPlusMethodProperty; | ||
78 | if (S_OK == WcaTableExists(L"ComPlusRoleForMethod")) giTables |= cptComPlusRoleForMethod; | ||
79 | if (S_OK == WcaTableExists(L"ComPlusSubscription")) giTables |= cptComPlusSubscription; | ||
80 | if (S_OK == WcaTableExists(L"ComPlusSubscriptionProperty")) giTables |= cptComPlusSubscriptionProperty; | ||
81 | } | ||
82 | |||
83 | void CpiFinalize() | ||
84 | { | ||
85 | // collections | ||
86 | ReleaseObject(gpiCatalog); | ||
87 | ReleaseObject(gpiPartColl); | ||
88 | ReleaseObject(gpiAppColl); | ||
89 | } | ||
90 | |||
91 | BOOL CpiTableExists( | ||
92 | int iTable | ||
93 | ) | ||
94 | { | ||
95 | return (giTables & iTable) == iTable; | ||
96 | } | ||
97 | |||
98 | HRESULT CpiGetAdminCatalog( | ||
99 | ICOMAdminCatalog** ppiCatalog | ||
100 | ) | ||
101 | { | ||
102 | HRESULT hr = S_OK; | ||
103 | |||
104 | if (!gpiCatalog) | ||
105 | { | ||
106 | // get collection | ||
107 | hr = ::CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_ALL, IID_ICOMAdminCatalog, (void**)&gpiCatalog); | ||
108 | ExitOnFailure(hr, "Failed to create COM+ admin catalog object"); | ||
109 | } | ||
110 | |||
111 | // return value | ||
112 | gpiCatalog->AddRef(); | ||
113 | *ppiCatalog = gpiCatalog; | ||
114 | |||
115 | hr = S_OK; | ||
116 | |||
117 | LExit: | ||
118 | return hr; | ||
119 | } | ||
120 | |||
121 | HRESULT CpiGetCatalogCollection( | ||
122 | LPCWSTR pwzName, | ||
123 | ICatalogCollection** ppiColl | ||
124 | ) | ||
125 | { | ||
126 | HRESULT hr = S_OK; | ||
127 | |||
128 | ICOMAdminCatalog* piCatalog = NULL; | ||
129 | IDispatch* piDisp = NULL; | ||
130 | BSTR bstrName = NULL; | ||
131 | |||
132 | // copy name string | ||
133 | bstrName = ::SysAllocString(pwzName); | ||
134 | ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name"); | ||
135 | |||
136 | // get catalog | ||
137 | hr = CpiGetAdminCatalog(&piCatalog); | ||
138 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
139 | |||
140 | // get collecton from catalog | ||
141 | hr = piCatalog->GetCollection(bstrName, &piDisp); | ||
142 | ExitOnFailure(hr, "Failed to get collection"); | ||
143 | |||
144 | hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl); | ||
145 | ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface"); | ||
146 | |||
147 | // populate collection | ||
148 | hr = (*ppiColl)->Populate(); | ||
149 | ExitOnFailure(hr, "Failed to populate collection"); | ||
150 | |||
151 | hr = S_OK; | ||
152 | |||
153 | LExit: | ||
154 | // clean up | ||
155 | ReleaseObject(piCatalog); | ||
156 | ReleaseObject(piDisp); | ||
157 | ReleaseBSTR(bstrName); | ||
158 | |||
159 | return hr; | ||
160 | } | ||
161 | |||
162 | HRESULT CpiGetCatalogCollection( | ||
163 | ICatalogCollection* piColl, | ||
164 | ICatalogObject* piObj, | ||
165 | LPCWSTR pwzName, | ||
166 | ICatalogCollection** ppiColl | ||
167 | ) | ||
168 | { | ||
169 | HRESULT hr = S_OK; | ||
170 | |||
171 | ICOMAdminCatalog* piCatalog = NULL; | ||
172 | IDispatch* piDisp = NULL; | ||
173 | BSTR bstrName = NULL; | ||
174 | |||
175 | VARIANT vtKey; | ||
176 | ::VariantInit(&vtKey); | ||
177 | |||
178 | // copy name string | ||
179 | bstrName = ::SysAllocString(pwzName); | ||
180 | ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name"); | ||
181 | |||
182 | // get catalog | ||
183 | hr = CpiGetAdminCatalog(&piCatalog); | ||
184 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
185 | |||
186 | // get key | ||
187 | hr = piObj->get_Key(&vtKey); | ||
188 | ExitOnFailure(hr, "Failed to get object key"); | ||
189 | |||
190 | // get collecton from catalog | ||
191 | hr = piColl->GetCollection(bstrName, vtKey, &piDisp); | ||
192 | ExitOnFailure(hr, "Failed to get collection"); | ||
193 | |||
194 | hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl); | ||
195 | ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface"); | ||
196 | |||
197 | // populate collection | ||
198 | hr = (*ppiColl)->Populate(); | ||
199 | ExitOnFailure(hr, "Failed to populate collection"); | ||
200 | |||
201 | hr = S_OK; | ||
202 | |||
203 | LExit: | ||
204 | // clean up | ||
205 | ReleaseObject(piCatalog); | ||
206 | ReleaseObject(piDisp); | ||
207 | ReleaseBSTR(bstrName); | ||
208 | ::VariantClear(&vtKey); | ||
209 | |||
210 | return hr; | ||
211 | } | ||
212 | |||
213 | HRESULT CpiGetKeyForObject( | ||
214 | ICatalogObject* piObj, | ||
215 | LPWSTR pwzKey, | ||
216 | SIZE_T cchKey | ||
217 | ) | ||
218 | { | ||
219 | HRESULT hr = S_OK; | ||
220 | |||
221 | VARIANT vtKey; | ||
222 | ::VariantInit(&vtKey); | ||
223 | |||
224 | // get key | ||
225 | hr = piObj->get_Key(&vtKey); | ||
226 | ExitOnFailure(hr, "Failed to get key"); | ||
227 | |||
228 | // change variant type | ||
229 | hr = ::VariantChangeType(&vtKey, &vtKey, 0, VT_BSTR); | ||
230 | ExitOnFailure(hr, "Failed to change variant type"); | ||
231 | |||
232 | // copy key | ||
233 | hr = StringCchCopyW(pwzKey, cchKey, vtKey.bstrVal); | ||
234 | ExitOnFailure(hr, "Failed to copy key"); | ||
235 | |||
236 | hr = S_OK; | ||
237 | |||
238 | LExit: | ||
239 | // clean up | ||
240 | ::VariantClear(&vtKey); | ||
241 | |||
242 | return hr; | ||
243 | } | ||
244 | |||
245 | HRESULT CpiFindCollectionObject( | ||
246 | ICatalogCollection* piColl, | ||
247 | LPCWSTR pwzID, | ||
248 | LPCWSTR pwzName, | ||
249 | ICatalogObject** ppiObj | ||
250 | ) | ||
251 | { | ||
252 | HRESULT hr = S_OK; | ||
253 | |||
254 | IDispatch* piDisp = NULL; | ||
255 | ICatalogObject* piObj = NULL; | ||
256 | |||
257 | VARIANT vtVal; | ||
258 | ::VariantInit(&vtVal); | ||
259 | |||
260 | long lCnt; | ||
261 | hr = piColl->get_Count(&lCnt); | ||
262 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
263 | |||
264 | for (long i = 0; i < lCnt; i++) | ||
265 | { | ||
266 | // get ICatalogObject interface | ||
267 | hr = piColl->get_Item(i, &piDisp); | ||
268 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
269 | |||
270 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
271 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
272 | |||
273 | // compare id | ||
274 | if (pwzID && *pwzID) | ||
275 | { | ||
276 | hr = piObj->get_Key(&vtVal); | ||
277 | ExitOnFailure(hr, "Failed to get key"); | ||
278 | |||
279 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
280 | ExitOnFailure(hr, "Failed to change variant type"); | ||
281 | |||
282 | if (0 == lstrcmpiW(vtVal.bstrVal, pwzID)) | ||
283 | { | ||
284 | if (ppiObj) | ||
285 | { | ||
286 | *ppiObj = piObj; | ||
287 | piObj = NULL; | ||
288 | } | ||
289 | ExitFunction1(hr = S_OK); | ||
290 | } | ||
291 | |||
292 | ::VariantClear(&vtVal); | ||
293 | } | ||
294 | |||
295 | // compare name | ||
296 | if (pwzName && *pwzName) | ||
297 | { | ||
298 | hr = piObj->get_Name(&vtVal); | ||
299 | ExitOnFailure(hr, "Failed to get name"); | ||
300 | |||
301 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
302 | ExitOnFailure(hr, "Failed to change variant type"); | ||
303 | |||
304 | if (0 == lstrcmpW(vtVal.bstrVal, pwzName)) | ||
305 | { | ||
306 | if (ppiObj) | ||
307 | { | ||
308 | *ppiObj = piObj; | ||
309 | piObj = NULL; | ||
310 | } | ||
311 | ExitFunction1(hr = S_OK); | ||
312 | } | ||
313 | |||
314 | ::VariantClear(&vtVal); | ||
315 | } | ||
316 | |||
317 | // release interface pointers | ||
318 | ReleaseNullObject(piDisp); | ||
319 | ReleaseNullObject(piObj); | ||
320 | } | ||
321 | |||
322 | hr = S_FALSE; | ||
323 | |||
324 | LExit: | ||
325 | // clean up | ||
326 | ReleaseObject(piDisp); | ||
327 | ReleaseObject(piObj); | ||
328 | |||
329 | ::VariantClear(&vtVal); | ||
330 | |||
331 | return hr; | ||
332 | } | ||
333 | |||
334 | HRESULT CpiGetPartitionsCollection( | ||
335 | ICatalogCollection** ppiPartColl | ||
336 | ) | ||
337 | { | ||
338 | HRESULT hr = S_OK; | ||
339 | |||
340 | if (!gpiPartColl) | ||
341 | { | ||
342 | // get collection | ||
343 | hr = CpiGetCatalogCollection(L"Partitions", &gpiPartColl); | ||
344 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
345 | } | ||
346 | |||
347 | // return value | ||
348 | gpiPartColl->AddRef(); | ||
349 | *ppiPartColl = gpiPartColl; | ||
350 | |||
351 | hr = S_OK; | ||
352 | |||
353 | LExit: | ||
354 | return hr; | ||
355 | } | ||
356 | |||
357 | HRESULT CpiGetApplicationsCollection( | ||
358 | ICatalogCollection** ppiAppColl | ||
359 | ) | ||
360 | { | ||
361 | HRESULT hr = S_OK; | ||
362 | |||
363 | ICOMAdminCatalog* piCatalog = NULL; | ||
364 | ICOMAdminCatalog2* piCatalog2 = NULL; | ||
365 | ICatalogCollection* piPartColl = NULL; | ||
366 | ICatalogObject* piPartObj = NULL; | ||
367 | BSTR bstrGlobPartID = NULL; | ||
368 | |||
369 | if (!gpiAppColl) | ||
370 | { | ||
371 | // get catalog | ||
372 | hr = CpiGetAdminCatalog(&piCatalog); | ||
373 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
374 | |||
375 | // get ICOMAdminCatalog2 interface | ||
376 | hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2); | ||
377 | |||
378 | // COM+ 1.5 or later | ||
379 | if (E_NOINTERFACE != hr) | ||
380 | { | ||
381 | ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface"); | ||
382 | |||
383 | // get global partition id | ||
384 | hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID); | ||
385 | ExitOnFailure(hr, "Failed to get global partition id"); | ||
386 | |||
387 | // get partitions collection | ||
388 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
389 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
390 | |||
391 | // find object | ||
392 | hr = CpiFindCollectionObject(piPartColl, bstrGlobPartID, NULL, &piPartObj); | ||
393 | ExitOnFailure(hr, "Failed to find collection object"); | ||
394 | |||
395 | if (S_FALSE == hr) | ||
396 | ExitFunction(); // partition not found, exit with hr = S_FALSE | ||
397 | |||
398 | // get applications collection | ||
399 | hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"Applications", &gpiAppColl); | ||
400 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
401 | } | ||
402 | |||
403 | // COM+ pre 1.5 | ||
404 | else | ||
405 | { | ||
406 | // get applications collection | ||
407 | hr = CpiGetCatalogCollection(L"Applications", &gpiAppColl); | ||
408 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
409 | } | ||
410 | } | ||
411 | |||
412 | // return value | ||
413 | gpiAppColl->AddRef(); | ||
414 | *ppiAppColl = gpiAppColl; | ||
415 | |||
416 | hr = S_OK; | ||
417 | |||
418 | LExit: | ||
419 | // clean up | ||
420 | ReleaseObject(piCatalog); | ||
421 | ReleaseObject(piCatalog2); | ||
422 | ReleaseObject(piPartColl); | ||
423 | ReleaseObject(piPartObj); | ||
424 | ReleaseBSTR(bstrGlobPartID); | ||
425 | |||
426 | return hr; | ||
427 | } | ||
428 | |||
429 | HRESULT CpiAddActionTextToActionData( | ||
430 | LPCWSTR pwzAction, | ||
431 | LPWSTR* ppwzActionData | ||
432 | ) | ||
433 | { | ||
434 | HRESULT hr = S_OK; | ||
435 | |||
436 | PMSIHANDLE hView, hRecKey, hRec; | ||
437 | |||
438 | LPWSTR pwzDescription = NULL; | ||
439 | LPWSTR pwzTemplate = NULL; | ||
440 | |||
441 | if (S_OK == WcaTableExists(L"ActionText")) | ||
442 | { | ||
443 | // create parameter record | ||
444 | hRecKey = ::MsiCreateRecord(1); | ||
445 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
446 | hr = WcaSetRecordString(hRecKey, 1, pwzAction); | ||
447 | ExitOnFailure(hr, "Failed to set record string"); | ||
448 | |||
449 | // open view | ||
450 | hr = WcaOpenView(vcsActionTextQuery, &hView); | ||
451 | ExitOnFailure(hr, "Failed to open view on ActionText table"); | ||
452 | hr = WcaExecuteView(hView, hRecKey); | ||
453 | ExitOnFailure(hr, "Failed to execute view on ActionText table"); | ||
454 | |||
455 | // fetch record | ||
456 | hr = WcaFetchSingleRecord(hView, &hRec); | ||
457 | if (S_FALSE != hr) | ||
458 | { | ||
459 | ExitOnFailure(hr, "Failed to fetch action text record"); | ||
460 | |||
461 | // get description | ||
462 | hr = WcaGetRecordString(hRec, atqDescription, &pwzDescription); | ||
463 | ExitOnFailure(hr, "Failed to get description"); | ||
464 | |||
465 | // get template | ||
466 | hr = WcaGetRecordString(hRec, atqTemplate, &pwzTemplate); | ||
467 | ExitOnFailure(hr, "Failed to get template"); | ||
468 | } | ||
469 | } | ||
470 | |||
471 | // add action name to action data | ||
472 | hr = WcaWriteStringToCaData(pwzAction, ppwzActionData); | ||
473 | ExitOnFailure(hr, "Failed to add action name to custom action data"); | ||
474 | |||
475 | // add description to action data | ||
476 | hr = WcaWriteStringToCaData(pwzDescription ? pwzDescription : L"", ppwzActionData); | ||
477 | ExitOnFailure(hr, "Failed to add description to custom action data"); | ||
478 | |||
479 | // add template to action data | ||
480 | hr = WcaWriteStringToCaData(pwzTemplate ? pwzTemplate : L"", ppwzActionData); | ||
481 | ExitOnFailure(hr, "Failed to add template to custom action data"); | ||
482 | |||
483 | hr = S_OK; | ||
484 | |||
485 | LExit: | ||
486 | // clean up | ||
487 | ReleaseStr(pwzDescription); | ||
488 | ReleaseStr(pwzTemplate); | ||
489 | |||
490 | return hr; | ||
491 | } | ||
492 | |||
493 | HRESULT CpiVerifyComponentArchitecure( | ||
494 | LPCWSTR pwzComponent, | ||
495 | BOOL* pfMatchingArchitecture | ||
496 | ) | ||
497 | { | ||
498 | HRESULT hr = S_OK; | ||
499 | |||
500 | PMSIHANDLE hView, hRecKey, hRec; | ||
501 | |||
502 | int iAttributes = 0; | ||
503 | |||
504 | if (S_OK == WcaTableExists(L"Component")) | ||
505 | { | ||
506 | // create parameter record | ||
507 | hRecKey = ::MsiCreateRecord(1); | ||
508 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
509 | hr = WcaSetRecordString(hRecKey, 1, pwzComponent); | ||
510 | ExitOnFailure(hr, "Failed to set record string"); | ||
511 | |||
512 | // open view | ||
513 | hr = WcaOpenView(vcsComponentAttributesQuery, &hView); | ||
514 | ExitOnFailure(hr, "Failed to open view on ActionText table"); | ||
515 | hr = WcaExecuteView(hView, hRecKey); | ||
516 | ExitOnFailure(hr, "Failed to execute view on ActionText table"); | ||
517 | |||
518 | // fetch record | ||
519 | hr = WcaFetchSingleRecord(hView, &hRec); | ||
520 | if (S_FALSE != hr) | ||
521 | { | ||
522 | ExitOnFailure(hr, "Failed to fetch component record"); | ||
523 | |||
524 | hr = WcaGetRecordInteger(hRec, caqAttributes, &iAttributes); | ||
525 | ExitOnFailure(hr, "Failed to get component attributes"); | ||
526 | } | ||
527 | } | ||
528 | |||
529 | // return values | ||
530 | #ifdef _WIN64 | ||
531 | *pfMatchingArchitecture = 256 == (iAttributes & 256); | ||
532 | #else | ||
533 | *pfMatchingArchitecture = 256 != (iAttributes & 256); | ||
534 | #endif | ||
535 | |||
536 | hr = S_OK; | ||
537 | |||
538 | LExit: | ||
539 | return hr; | ||
540 | } | ||
541 | |||
542 | HRESULT CpiPropertiesRead( | ||
543 | LPCWSTR pwzQuery, | ||
544 | LPCWSTR pwzKey, | ||
545 | CPI_PROPERTY_DEFINITION* pPropDefList, | ||
546 | CPI_PROPERTY** ppPropList, | ||
547 | int* piCount | ||
548 | ) | ||
549 | { | ||
550 | HRESULT hr = S_OK; | ||
551 | |||
552 | PMSIHANDLE hView, hRecKey, hRec; | ||
553 | |||
554 | CPI_PROPERTY* pItm = NULL; | ||
555 | LPWSTR pwzData = NULL; | ||
556 | |||
557 | int iVersionNT = 0; | ||
558 | |||
559 | CPI_PROPERTY_DEFINITION* pPropDef; | ||
560 | |||
561 | *piCount = 0; | ||
562 | |||
563 | // get NT version | ||
564 | hr = WcaGetIntProperty(L"VersionNT", &iVersionNT); | ||
565 | ExitOnFailure(hr, "Failed to set record string"); | ||
566 | |||
567 | // create parameter record | ||
568 | hRecKey = ::MsiCreateRecord(1); | ||
569 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
570 | hr = WcaSetRecordString(hRecKey, 1, pwzKey); | ||
571 | ExitOnFailure(hr, "Failed to set record string"); | ||
572 | |||
573 | // open view | ||
574 | hr = WcaOpenView(pwzQuery, &hView); | ||
575 | ExitOnFailure(hr, "Failed to open view on property table"); | ||
576 | hr = WcaExecuteView(hView, hRecKey); | ||
577 | ExitOnFailure(hr, "Failed to execute view on property table"); | ||
578 | |||
579 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
580 | { | ||
581 | // create entry | ||
582 | pItm = (CPI_PROPERTY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PROPERTY)); | ||
583 | if (!pItm) | ||
584 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
585 | |||
586 | // get name | ||
587 | hr = WcaGetRecordString(hRec, pqName, &pwzData); | ||
588 | ExitOnFailure(hr, "Failed to get name"); | ||
589 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
590 | |||
591 | // get value | ||
592 | hr = WcaGetRecordFormattedString(hRec, pqValue, &pItm->pwzValue); | ||
593 | ExitOnFailure(hr, "Failed to get value"); | ||
594 | |||
595 | // find property definition | ||
596 | hr = FindPropertyDefinition(pPropDefList, pItm->wzName, &pPropDef); | ||
597 | ExitOnFailure(hr, "Failed to find property definition"); | ||
598 | |||
599 | if (S_FALSE == hr) | ||
600 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Unknown property, key: %S, property: %S", pwzKey, pItm->wzName); | ||
601 | |||
602 | // check version, ignore if catalog version is too low | ||
603 | if (iVersionNT < pPropDef->iMinVersionNT) | ||
604 | { | ||
605 | WcaLog(LOGMSG_VERBOSE, "Skipping property since NT version is too low, key: %S, property: %S", pwzKey, pItm->wzName); | ||
606 | CpiPropertiesFreeList(pItm); | ||
607 | pItm = NULL; | ||
608 | continue; | ||
609 | } | ||
610 | |||
611 | // if the property is a user, replace the User table key with a user account name | ||
612 | if (cpptUser == pPropDef->iType) | ||
613 | { | ||
614 | hr = GetUserAccountName(pItm->pwzValue, &pItm->pwzValue); | ||
615 | ExitOnFailure(hr, "Failed to get user account name"); | ||
616 | } | ||
617 | |||
618 | // add entry | ||
619 | ++*piCount; | ||
620 | if (*ppPropList) | ||
621 | pItm->pNext = *ppPropList; | ||
622 | *ppPropList = pItm; | ||
623 | pItm = NULL; | ||
624 | } | ||
625 | |||
626 | if (E_NOMOREITEMS == hr) | ||
627 | hr = S_OK; | ||
628 | |||
629 | LExit: | ||
630 | // clean up | ||
631 | if (pItm) | ||
632 | CpiPropertiesFreeList(pItm); | ||
633 | |||
634 | ReleaseStr(pwzData); | ||
635 | |||
636 | return hr; | ||
637 | } | ||
638 | |||
639 | void CpiPropertiesFreeList( | ||
640 | CPI_PROPERTY* pList | ||
641 | ) | ||
642 | { | ||
643 | while (pList) | ||
644 | { | ||
645 | ReleaseStr(pList->pwzValue); | ||
646 | |||
647 | CPI_PROPERTY* pDelete = pList; | ||
648 | pList = pList->pNext; | ||
649 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
650 | } | ||
651 | } | ||
652 | |||
653 | HRESULT CpiAddPropertiesToActionData( | ||
654 | int iPropCount, | ||
655 | CPI_PROPERTY* pPropList, | ||
656 | LPWSTR* ppwzActionData | ||
657 | ) | ||
658 | { | ||
659 | HRESULT hr = S_OK; | ||
660 | |||
661 | hr = WcaWriteIntegerToCaData(iPropCount, ppwzActionData); | ||
662 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
663 | |||
664 | if (iPropCount) // count might be 0 event thought there are elements in the list | ||
665 | { | ||
666 | for (CPI_PROPERTY* pProp = pPropList; pProp; pProp = pProp->pNext) | ||
667 | { | ||
668 | hr = WcaWriteStringToCaData(pProp->wzName, ppwzActionData); | ||
669 | ExitOnFailure(hr, "Failed to add property name to custom action data, name: %S", pProp->wzName); | ||
670 | |||
671 | hr = WcaWriteStringToCaData(pProp->pwzValue, ppwzActionData); | ||
672 | ExitOnFailure(hr, "Failed to add property value to custom action data, name: %S", pProp->wzName); | ||
673 | } | ||
674 | } | ||
675 | |||
676 | hr = S_OK; | ||
677 | |||
678 | LExit: | ||
679 | return hr; | ||
680 | } | ||
681 | |||
682 | HRESULT CpiBuildAccountName( | ||
683 | LPCWSTR pwzDomain, | ||
684 | LPCWSTR pwzName, | ||
685 | LPWSTR* ppwzAccount | ||
686 | ) | ||
687 | { | ||
688 | HRESULT hr = S_OK; | ||
689 | |||
690 | WCHAR wzComputerName[MAX_COMPUTERNAME_LENGTH + 1]; | ||
691 | ::ZeroMemory(wzComputerName, sizeof(wzComputerName)); | ||
692 | |||
693 | // if domain is '.', get computer name | ||
694 | if (0 == lstrcmpW(pwzDomain, L".")) | ||
695 | { | ||
696 | DWORD dwSize = countof(wzComputerName); | ||
697 | if (!::GetComputerNameW(wzComputerName, &dwSize)) | ||
698 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to get computer name"); | ||
699 | } | ||
700 | |||
701 | // build account name | ||
702 | hr = StrAllocFormatted(ppwzAccount, L"%s\\%s", *wzComputerName ? wzComputerName : pwzDomain, pwzName); | ||
703 | ExitOnFailure(hr, "Failed to build domain user name"); | ||
704 | |||
705 | hr = S_OK; | ||
706 | |||
707 | LExit: | ||
708 | return hr; | ||
709 | } | ||
710 | |||
711 | HRESULT CpiGetTempFileName( | ||
712 | LPWSTR* ppwzTempFile | ||
713 | ) | ||
714 | { | ||
715 | HRESULT hr = S_OK; | ||
716 | |||
717 | // get temp path | ||
718 | WCHAR wzTempPath[MAX_PATH]; | ||
719 | DWORD dw = ::GetTempPathW(countof(wzTempPath), wzTempPath); | ||
720 | if (countof(wzTempPath) <= dw) | ||
721 | ExitOnFailure(hr = E_FAIL, "TEMP directory path too long"); | ||
722 | |||
723 | // get unique number | ||
724 | LARGE_INTEGER liCount; | ||
725 | if (!::QueryPerformanceCounter(&liCount)) | ||
726 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to query performance counter"); | ||
727 | |||
728 | // create temp file name | ||
729 | hr = StrAllocFormatted(ppwzTempFile, L"%sCPI%I64X.tmp", wzTempPath, liCount.QuadPart); | ||
730 | ExitOnFailure(hr, "Failed to create temp file name string"); | ||
731 | |||
732 | hr = S_OK; | ||
733 | |||
734 | LExit: | ||
735 | return hr; | ||
736 | } | ||
737 | |||
738 | HRESULT CpiCreateId( | ||
739 | LPWSTR pwzDest, | ||
740 | SIZE_T cchDest | ||
741 | ) | ||
742 | { | ||
743 | HRESULT hr = S_OK; | ||
744 | |||
745 | GUID guid; | ||
746 | |||
747 | // create new guid | ||
748 | hr = ::CoCreateGuid(&guid); | ||
749 | ExitOnFailure(hr, "Failed to create new guid"); | ||
750 | |||
751 | // convert guid to string | ||
752 | if (0 == ::StringFromGUID2(guid, pwzDest, (int)cchDest)) | ||
753 | ExitOnFailure(hr = E_FAIL, "Failed to convert guid to string"); | ||
754 | |||
755 | hr = S_OK; | ||
756 | |||
757 | LExit: | ||
758 | return hr; | ||
759 | } | ||
760 | |||
761 | BOOL CpiIsInstalled( | ||
762 | INSTALLSTATE isInstalled | ||
763 | ) | ||
764 | { | ||
765 | return INSTALLSTATE_LOCAL == isInstalled || INSTALLSTATE_SOURCE == isInstalled; | ||
766 | } | ||
767 | |||
768 | BOOL CpiWillBeInstalled( | ||
769 | INSTALLSTATE isInstalled, | ||
770 | INSTALLSTATE isAction | ||
771 | ) | ||
772 | { | ||
773 | return WcaIsInstalling(isInstalled, isAction) || | ||
774 | (CpiIsInstalled(isInstalled) && !WcaIsUninstalling(isInstalled, isAction)); | ||
775 | } | ||
776 | |||
777 | HRESULT PcaGuidToRegFormat( | ||
778 | LPWSTR pwzGuid, | ||
779 | LPWSTR pwzDest, | ||
780 | SIZE_T cchDest | ||
781 | ) | ||
782 | { | ||
783 | HRESULT hr = S_OK; | ||
784 | |||
785 | GUID guid = GUID_NULL; | ||
786 | int cch = 0; | ||
787 | |||
788 | WCHAR wz[39]; | ||
789 | ::ZeroMemory(wz, sizeof(wz)); | ||
790 | |||
791 | cch = lstrlenW(pwzGuid); | ||
792 | |||
793 | if (38 == cch && L'{' == pwzGuid[0] && L'}' == pwzGuid[37]) | ||
794 | StringCchCopyW(wz, countof(wz), pwzGuid); | ||
795 | else if (36 == cch) | ||
796 | StringCchPrintfW(wz, countof(wz), L"{%s}", pwzGuid); | ||
797 | else | ||
798 | ExitFunction1(hr = E_INVALIDARG); | ||
799 | |||
800 | // convert string to guid | ||
801 | hr = ::CLSIDFromString(wz, &guid); | ||
802 | ExitOnFailure(hr, "Failed to parse guid string"); | ||
803 | |||
804 | // convert guid to string | ||
805 | if (0 == ::StringFromGUID2(guid, pwzDest, (int)cchDest)) | ||
806 | ExitOnFailure(hr = E_FAIL, "Failed to convert guid to string"); | ||
807 | |||
808 | hr = S_OK; | ||
809 | |||
810 | LExit: | ||
811 | return hr; | ||
812 | } | ||
813 | |||
814 | |||
815 | // helper function definitions | ||
816 | |||
817 | static HRESULT FindPropertyDefinition( | ||
818 | CPI_PROPERTY_DEFINITION* pPropDefList, | ||
819 | LPCWSTR pwzName, | ||
820 | CPI_PROPERTY_DEFINITION** ppPropDef | ||
821 | ) | ||
822 | { | ||
823 | for (CPI_PROPERTY_DEFINITION* pItm = pPropDefList; pItm->pwzName; pItm++) | ||
824 | { | ||
825 | if (0 == lstrcmpW(pItm->pwzName, pwzName)) | ||
826 | { | ||
827 | *ppPropDef = pItm; | ||
828 | return S_OK; | ||
829 | } | ||
830 | } | ||
831 | |||
832 | return S_FALSE; | ||
833 | } | ||
834 | |||
835 | static HRESULT GetUserAccountName( | ||
836 | LPCWSTR pwzKey, | ||
837 | LPWSTR* ppwzAccount | ||
838 | ) | ||
839 | { | ||
840 | HRESULT hr = S_OK; | ||
841 | |||
842 | PMSIHANDLE hView, hRecKey, hRec; | ||
843 | |||
844 | LPWSTR pwzDomain = NULL; | ||
845 | LPWSTR pwzName = NULL; | ||
846 | |||
847 | // create parameter record | ||
848 | hRecKey = ::MsiCreateRecord(1); | ||
849 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
850 | hr = WcaSetRecordString(hRecKey, 1, pwzKey); | ||
851 | ExitOnFailure(hr, "Failed to set record string"); | ||
852 | |||
853 | // open view | ||
854 | hr = WcaOpenView(vcsUserQuery, &hView); | ||
855 | ExitOnFailure(hr, "Failed to open view on User table"); | ||
856 | hr = WcaExecuteView(hView, hRecKey); | ||
857 | ExitOnFailure(hr, "Failed to execute view on User table"); | ||
858 | |||
859 | // fetch record | ||
860 | hr = WcaFetchSingleRecord(hView, &hRec); | ||
861 | if (S_FALSE == hr) | ||
862 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "User not found, key: %S", pwzKey); | ||
863 | ExitOnFailure(hr, "Failed to fetch user record"); | ||
864 | |||
865 | // get user domain | ||
866 | hr = WcaGetRecordFormattedString(hRec, uqDomain, &pwzDomain); | ||
867 | ExitOnFailure(hr, "Failed to get domain"); | ||
868 | |||
869 | // get user name | ||
870 | hr = WcaGetRecordFormattedString(hRec, uqName, &pwzName); | ||
871 | ExitOnFailure(hr, "Failed to get name"); | ||
872 | |||
873 | // build account name | ||
874 | hr = CpiBuildAccountName(pwzDomain, pwzName, ppwzAccount); | ||
875 | ExitOnFailure(hr, "Failed to build account name"); | ||
876 | |||
877 | hr = S_OK; | ||
878 | |||
879 | LExit: | ||
880 | // clean up | ||
881 | ReleaseStr(pwzDomain); | ||
882 | ReleaseStr(pwzName); | ||
883 | |||
884 | return hr; | ||
885 | } | ||
diff --git a/src/ca/cputilsched.h b/src/ca/cputilsched.h new file mode 100644 index 00000000..61aaab84 --- /dev/null +++ b/src/ca/cputilsched.h | |||
@@ -0,0 +1,144 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | #define CPI_MAX_GUID 38 | ||
6 | |||
7 | enum eRunMode { rmDeferred = 1, rmCommit, rmRollback }; | ||
8 | |||
9 | enum eActionType { atNoOp = 0, atCreate, atRemove }; | ||
10 | |||
11 | enum eComPlusPropertyType { cpptNone = 0, cpptBoolean, cpptInteger, cpptString, cpptUser }; | ||
12 | |||
13 | enum eComPlusTables | ||
14 | { | ||
15 | cptComPlusPartition = (1 << 0), | ||
16 | cptComPlusPartitionProperty = (1 << 1), | ||
17 | cptComPlusPartitionRole = (1 << 2), | ||
18 | cptComPlusUserInPartitionRole = (1 << 3), | ||
19 | cptComPlusGroupInPartitionRole = (1 << 4), | ||
20 | cptComPlusPartitionUser = (1 << 5), | ||
21 | cptComPlusApplication = (1 << 6), | ||
22 | cptComPlusApplicationProperty = (1 << 7), | ||
23 | cptComPlusApplicationRole = (1 << 8), | ||
24 | cptComPlusApplicationRoleProperty = (1 << 9), | ||
25 | cptComPlusUserInApplicationRole = (1 << 10), | ||
26 | cptComPlusGroupInApplicationRole = (1 << 11), | ||
27 | cptComPlusAssembly = (1 << 12), | ||
28 | cptComPlusAssemblyDependency = (1 << 13), | ||
29 | cptComPlusComponent = (1 << 14), | ||
30 | cptComPlusComponentProperty = (1 << 15), | ||
31 | cptComPlusRoleForComponent = (1 << 16), | ||
32 | cptComPlusInterface = (1 << 17), | ||
33 | cptComPlusInterfaceProperty = (1 << 18), | ||
34 | cptComPlusRoleForInterface = (1 << 19), | ||
35 | cptComPlusMethod = (1 << 20), | ||
36 | cptComPlusMethodProperty = (1 << 21), | ||
37 | cptComPlusRoleForMethod = (1 << 22), | ||
38 | cptComPlusSubscription = (1 << 23), | ||
39 | cptComPlusSubscriptionProperty = (1 << 24) | ||
40 | }; | ||
41 | |||
42 | |||
43 | // structs | ||
44 | |||
45 | struct CPI_PROPERTY | ||
46 | { | ||
47 | WCHAR wzName[MAX_DARWIN_KEY + 1]; | ||
48 | LPWSTR pwzValue; | ||
49 | |||
50 | CPI_PROPERTY* pNext; | ||
51 | }; | ||
52 | |||
53 | struct CPI_PROPERTY_DEFINITION | ||
54 | { | ||
55 | LPCWSTR pwzName; | ||
56 | int iType; | ||
57 | int iMinVersionNT; | ||
58 | }; | ||
59 | |||
60 | |||
61 | // function prototypes | ||
62 | |||
63 | void CpiInitialize(); | ||
64 | void CpiFinalize(); | ||
65 | BOOL CpiTableExists( | ||
66 | int iTable | ||
67 | ); | ||
68 | HRESULT CpiGetAdminCatalog( | ||
69 | ICOMAdminCatalog** ppiCatalog | ||
70 | ); | ||
71 | HRESULT CpiGetCatalogCollection( | ||
72 | LPCWSTR pwzName, | ||
73 | ICatalogCollection** ppiColl | ||
74 | ); | ||
75 | HRESULT CpiGetCatalogCollection( | ||
76 | ICatalogCollection* piColl, | ||
77 | ICatalogObject* piObj, | ||
78 | LPCWSTR pwzName, | ||
79 | ICatalogCollection** ppiColl | ||
80 | ); | ||
81 | HRESULT CpiGetKeyForObject( | ||
82 | ICatalogObject* piObj, | ||
83 | LPWSTR pwzKey, | ||
84 | SIZE_T cchKey | ||
85 | ); | ||
86 | HRESULT CpiFindCollectionObject( | ||
87 | ICatalogCollection* piColl, | ||
88 | LPCWSTR pwzID, | ||
89 | LPCWSTR pwzName, | ||
90 | ICatalogObject** ppiObj | ||
91 | ); | ||
92 | HRESULT CpiGetPartitionsCollection( | ||
93 | ICatalogCollection** ppiPartColl | ||
94 | ); | ||
95 | HRESULT CpiGetApplicationsCollection( | ||
96 | ICatalogCollection** ppiAppColl | ||
97 | ); | ||
98 | HRESULT CpiAddActionTextToActionData( | ||
99 | LPCWSTR pwzAction, | ||
100 | LPWSTR* ppwzActionData | ||
101 | ); | ||
102 | HRESULT CpiVerifyComponentArchitecure( | ||
103 | LPCWSTR pwzComponent, | ||
104 | BOOL* pfMatchingArchitecture | ||
105 | ); | ||
106 | HRESULT CpiPropertiesRead( | ||
107 | LPCWSTR pwzQuery, | ||
108 | LPCWSTR pwzKey, | ||
109 | CPI_PROPERTY_DEFINITION* pPropDefList, | ||
110 | CPI_PROPERTY** ppPropList, | ||
111 | int* piCount | ||
112 | ); | ||
113 | void CpiPropertiesFreeList( | ||
114 | CPI_PROPERTY* pList | ||
115 | ); | ||
116 | HRESULT CpiAddPropertiesToActionData( | ||
117 | int iPropCount, | ||
118 | CPI_PROPERTY* pPropList, | ||
119 | LPWSTR* ppwzActionData | ||
120 | ); | ||
121 | HRESULT CpiBuildAccountName( | ||
122 | LPCWSTR pwzDomain, | ||
123 | LPCWSTR pwzName, | ||
124 | LPWSTR* ppwzAccount | ||
125 | ); | ||
126 | HRESULT CpiGetTempFileName( | ||
127 | LPWSTR* ppwzTempFile | ||
128 | ); | ||
129 | HRESULT CpiCreateId( | ||
130 | LPWSTR pwzDest, | ||
131 | SIZE_T cchDest | ||
132 | ); | ||
133 | BOOL CpiIsInstalled( | ||
134 | INSTALLSTATE isInstalled | ||
135 | ); | ||
136 | BOOL CpiWillBeInstalled( | ||
137 | INSTALLSTATE isInstalled, | ||
138 | INSTALLSTATE isAction | ||
139 | ); | ||
140 | HRESULT PcaGuidToRegFormat( | ||
141 | LPWSTR pwzGuid, | ||
142 | LPWSTR pwzDest, | ||
143 | SIZE_T cchDest | ||
144 | ); | ||
diff --git a/src/wixext/ComPlusCompiler.cs b/src/wixext/ComPlusCompiler.cs new file mode 100644 index 00000000..7f22c56b --- /dev/null +++ b/src/wixext/ComPlusCompiler.cs | |||
@@ -0,0 +1,2188 @@ | |||
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 | namespace WixToolset.Extensions | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections; | ||
7 | using System.Collections.Generic; | ||
8 | using System.Globalization; | ||
9 | using System.Reflection; | ||
10 | using System.Xml; | ||
11 | using System.Xml.Linq; | ||
12 | using System.Xml.Schema; | ||
13 | using WixToolset.Data; | ||
14 | using WixToolset.Extensibility; | ||
15 | |||
16 | /// <summary> | ||
17 | /// The compiler for the WiX Toolset Internet Information Services Extension. | ||
18 | /// </summary> | ||
19 | public sealed class ComPlusCompiler : CompilerExtension | ||
20 | { | ||
21 | /// <summary> | ||
22 | /// Instantiate a new ComPlusCompiler. | ||
23 | /// </summary> | ||
24 | public ComPlusCompiler() | ||
25 | { | ||
26 | this.Namespace = "http://wixtoolset.org/schemas/v4/wxs/complus"; | ||
27 | } | ||
28 | |||
29 | /// <summary> | ||
30 | /// </summary> | ||
31 | /// <remarks></remarks> | ||
32 | public enum CpiAssemblyAttributes | ||
33 | { | ||
34 | EventClass = (1 << 0), | ||
35 | DotNetAssembly = (1 << 1), | ||
36 | DllPathFromGAC = (1 << 2), | ||
37 | RegisterInCommit = (1 << 3) | ||
38 | } | ||
39 | |||
40 | /// <summary> | ||
41 | /// Processes an element for the Compiler. | ||
42 | /// </summary> | ||
43 | /// <param name="sourceLineNumbers">Source line number for the parent element.</param> | ||
44 | /// <param name="parentElement">Parent element of element to process.</param> | ||
45 | /// <param name="element">Element to process.</param> | ||
46 | /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param> | ||
47 | public override void ParseElement(XElement parentElement, XElement element, IDictionary<string, string> context) | ||
48 | { | ||
49 | switch (parentElement.Name.LocalName) | ||
50 | { | ||
51 | case "Component": | ||
52 | string componentId = context["ComponentId"]; | ||
53 | string directoryId = context["DirectoryId"]; | ||
54 | bool win64 = Boolean.Parse(context["Win64"]); | ||
55 | |||
56 | switch (element.Name.LocalName) | ||
57 | { | ||
58 | case "ComPlusPartition": | ||
59 | this.ParseComPlusPartitionElement(element, componentId, win64); | ||
60 | break; | ||
61 | case "ComPlusPartitionRole": | ||
62 | this.ParseComPlusPartitionRoleElement(element, componentId, null); | ||
63 | break; | ||
64 | case "ComPlusUserInPartitionRole": | ||
65 | this.ParseComPlusUserInPartitionRoleElement(element, componentId, null); | ||
66 | break; | ||
67 | case "ComPlusGroupInPartitionRole": | ||
68 | this.ParseComPlusGroupInPartitionRoleElement(element, componentId, null); | ||
69 | break; | ||
70 | case "ComPlusPartitionUser": | ||
71 | this.ParseComPlusPartitionUserElement(element, componentId, null); | ||
72 | break; | ||
73 | case "ComPlusApplication": | ||
74 | this.ParseComPlusApplicationElement(element, componentId, win64, null); | ||
75 | break; | ||
76 | case "ComPlusApplicationRole": | ||
77 | this.ParseComPlusApplicationRoleElement(element, componentId, null); | ||
78 | break; | ||
79 | case "ComPlusUserInApplicationRole": | ||
80 | this.ParseComPlusUserInApplicationRoleElement(element, componentId, null); | ||
81 | break; | ||
82 | case "ComPlusGroupInApplicationRole": | ||
83 | this.ParseComPlusGroupInApplicationRoleElement(element, componentId, null); | ||
84 | break; | ||
85 | case "ComPlusAssembly": | ||
86 | this.ParseComPlusAssemblyElement(element, componentId, win64, null); | ||
87 | break; | ||
88 | case "ComPlusRoleForComponent": | ||
89 | this.ParseComPlusRoleForComponentElement(element, componentId, null); | ||
90 | break; | ||
91 | case "ComPlusRoleForInterface": | ||
92 | this.ParseComPlusRoleForInterfaceElement(element, componentId, null); | ||
93 | break; | ||
94 | case "ComPlusRoleForMethod": | ||
95 | this.ParseComPlusRoleForMethodElement(element, componentId, null); | ||
96 | break; | ||
97 | case "ComPlusSubscription": | ||
98 | this.ParseComPlusSubscriptionElement(element, componentId, null); | ||
99 | break; | ||
100 | default: | ||
101 | this.Core.UnexpectedElement(parentElement, element); | ||
102 | break; | ||
103 | } | ||
104 | break; | ||
105 | case "Fragment": | ||
106 | case "Module": | ||
107 | case "Product": | ||
108 | switch (element.Name.LocalName) | ||
109 | { | ||
110 | case "ComPlusPartition": | ||
111 | this.ParseComPlusPartitionElement(element, null, false); | ||
112 | break; | ||
113 | case "ComPlusPartitionRole": | ||
114 | this.ParseComPlusPartitionRoleElement(element, null, null); | ||
115 | break; | ||
116 | case "ComPlusApplication": | ||
117 | this.ParseComPlusApplicationElement(element, null, false, null); | ||
118 | break; | ||
119 | case "ComPlusApplicationRole": | ||
120 | this.ParseComPlusApplicationRoleElement(element, null, null); | ||
121 | break; | ||
122 | default: | ||
123 | this.Core.UnexpectedElement(parentElement, element); | ||
124 | break; | ||
125 | } | ||
126 | break; | ||
127 | default: | ||
128 | this.Core.UnexpectedElement(parentElement, element); | ||
129 | break; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | /// <summary> | ||
134 | /// Parses a COM+ partition element. | ||
135 | /// </summary> | ||
136 | /// <param name="node">Element to parse.</param> | ||
137 | /// <param name="componentKey">Identifier of parent component.</param> | ||
138 | private void ParseComPlusPartitionElement(XElement node, string componentKey, bool win64) | ||
139 | { | ||
140 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
141 | |||
142 | string key = null; | ||
143 | string id = null; | ||
144 | string name = null; | ||
145 | |||
146 | Hashtable properties = new Hashtable(); | ||
147 | |||
148 | foreach (XAttribute attrib in node.Attributes()) | ||
149 | { | ||
150 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
151 | { | ||
152 | switch (attrib.Name.LocalName) | ||
153 | { | ||
154 | case "Id": | ||
155 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
156 | break; | ||
157 | case "PartitionId": | ||
158 | id = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
159 | break; | ||
160 | case "Name": | ||
161 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
162 | break; | ||
163 | case "Changeable": | ||
164 | this.Core.OnMessage(WixWarnings.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
165 | break; | ||
166 | case "Deleteable": | ||
167 | if (null == componentKey) | ||
168 | { | ||
169 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
170 | } | ||
171 | properties["Deleteable"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
172 | break; | ||
173 | case "Description": | ||
174 | if (null == componentKey) | ||
175 | { | ||
176 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
177 | } | ||
178 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
179 | break; | ||
180 | default: | ||
181 | this.Core.UnexpectedAttribute(node, attrib); | ||
182 | break; | ||
183 | } | ||
184 | } | ||
185 | else | ||
186 | { | ||
187 | this.Core.ParseExtensionAttribute(node, attrib); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | if (null != componentKey && null == name) | ||
192 | { | ||
193 | this.Core.OnMessage(ComPlusErrors.RequiredAttributeUnderComponent(sourceLineNumbers, node.Name.LocalName, "Name")); | ||
194 | } | ||
195 | if (null == componentKey && null == id && null == name) | ||
196 | { | ||
197 | this.Core.OnMessage(ComPlusErrors.RequiredAttributeNotUnderComponent(sourceLineNumbers, node.Name.LocalName, "Id", "Name")); | ||
198 | } | ||
199 | |||
200 | foreach (XElement child in node.Elements()) | ||
201 | { | ||
202 | if (this.Namespace == child.Name.Namespace) | ||
203 | { | ||
204 | switch (child.Name.LocalName) | ||
205 | { | ||
206 | case "ComPlusPartitionRole": | ||
207 | this.ParseComPlusPartitionRoleElement(child, componentKey, key); | ||
208 | break; | ||
209 | case "ComPlusPartitionUser": | ||
210 | this.ParseComPlusPartitionUserElement(child, componentKey, key); | ||
211 | break; | ||
212 | case "ComPlusApplication": | ||
213 | this.ParseComPlusApplicationElement(child, componentKey, win64, key); | ||
214 | break; | ||
215 | default: | ||
216 | this.Core.UnexpectedElement(node, child); | ||
217 | break; | ||
218 | } | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | this.Core.ParseExtensionElement(node, child); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartition"); | ||
227 | row[0] = key; | ||
228 | row[1] = componentKey; | ||
229 | row[2] = id; | ||
230 | row[3] = name; | ||
231 | |||
232 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
233 | while (propertiesEnumerator.MoveNext()) | ||
234 | { | ||
235 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartitionProperty"); | ||
236 | propertyRow[0] = key; | ||
237 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
238 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
239 | } | ||
240 | |||
241 | if (componentKey != null) | ||
242 | { | ||
243 | if (win64) | ||
244 | { | ||
245 | if (this.Core.CurrentPlatform == Platform.IA64) | ||
246 | { | ||
247 | this.Core.OnMessage(WixErrors.UnsupportedPlatformForElement(sourceLineNumbers, "ia64", node.Name.LocalName)); | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall_x64"); | ||
252 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall_x64"); | ||
253 | } | ||
254 | } | ||
255 | else | ||
256 | { | ||
257 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall"); | ||
258 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall"); | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | |||
263 | /// <summary> | ||
264 | /// Parses a COM+ partition role element. | ||
265 | /// </summary> | ||
266 | /// <param name="node">Element to parse.</param> | ||
267 | /// <param name="componentKey">Identifier of parent component.</param> | ||
268 | /// <param name="applicationKey">Optional identifier of parent application.</param> | ||
269 | private void ParseComPlusPartitionRoleElement(XElement node, string componentKey, string partitionKey) | ||
270 | { | ||
271 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
272 | |||
273 | string key = null; | ||
274 | string name = null; | ||
275 | |||
276 | foreach (XAttribute attrib in node.Attributes()) | ||
277 | { | ||
278 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
279 | { | ||
280 | switch (attrib.Name.LocalName) | ||
281 | { | ||
282 | case "Id": | ||
283 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
284 | break; | ||
285 | case "Partition": | ||
286 | if (null != partitionKey) | ||
287 | { | ||
288 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
289 | } | ||
290 | partitionKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
291 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartition", partitionKey); | ||
292 | break; | ||
293 | case "Name": | ||
294 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
295 | break; | ||
296 | default: | ||
297 | this.Core.UnexpectedAttribute(node, attrib); | ||
298 | break; | ||
299 | } | ||
300 | } | ||
301 | else | ||
302 | { | ||
303 | this.Core.ParseExtensionAttribute(node, attrib); | ||
304 | } | ||
305 | } | ||
306 | |||
307 | if (null == partitionKey) | ||
308 | { | ||
309 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Partition")); | ||
310 | } | ||
311 | |||
312 | foreach (XElement child in node.Elements()) | ||
313 | { | ||
314 | if (this.Namespace == child.Name.Namespace) | ||
315 | { | ||
316 | switch (child.Name.LocalName) | ||
317 | { | ||
318 | case "ComPlusUserInPartitionRole": | ||
319 | this.ParseComPlusUserInPartitionRoleElement(child, componentKey, key); | ||
320 | break; | ||
321 | case "ComPlusGroupInPartitionRole": | ||
322 | this.ParseComPlusGroupInPartitionRoleElement(child, componentKey, key); | ||
323 | break; | ||
324 | default: | ||
325 | this.Core.UnexpectedElement(node, child); | ||
326 | break; | ||
327 | } | ||
328 | } | ||
329 | else | ||
330 | { | ||
331 | this.Core.ParseExtensionElement(node, child); | ||
332 | } | ||
333 | } | ||
334 | |||
335 | // add table row | ||
336 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartitionRole"); | ||
337 | row[0] = key; | ||
338 | row[1] = partitionKey; | ||
339 | row[3] = name; | ||
340 | } | ||
341 | |||
342 | /// <summary> | ||
343 | /// Parses a COM+ partition role user element. | ||
344 | /// </summary> | ||
345 | /// <param name="node">Element to parse.</param> | ||
346 | /// <param name="componentKey">Identifier of parent component.</param> | ||
347 | /// <param name="applicationKey">Optional identifier of parent application role.</param> | ||
348 | private void ParseComPlusUserInPartitionRoleElement(XElement node, string componentKey, string partitionRoleKey) | ||
349 | { | ||
350 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
351 | |||
352 | string key = null; | ||
353 | string user = null; | ||
354 | |||
355 | foreach (XAttribute attrib in node.Attributes()) | ||
356 | { | ||
357 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
358 | { | ||
359 | switch (attrib.Name.LocalName) | ||
360 | { | ||
361 | case "Id": | ||
362 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
363 | break; | ||
364 | case "PartitionRole": | ||
365 | if (null != partitionRoleKey) | ||
366 | { | ||
367 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
368 | } | ||
369 | partitionRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
370 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartitionRole", partitionRoleKey); | ||
371 | break; | ||
372 | case "User": | ||
373 | user = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
374 | this.Core.CreateSimpleReference(sourceLineNumbers, "User", user); | ||
375 | break; | ||
376 | default: | ||
377 | this.Core.UnexpectedAttribute(node, attrib); | ||
378 | break; | ||
379 | } | ||
380 | } | ||
381 | else | ||
382 | { | ||
383 | this.Core.ParseExtensionAttribute(node, attrib); | ||
384 | } | ||
385 | } | ||
386 | |||
387 | if (null == partitionRoleKey) | ||
388 | { | ||
389 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "PartitionRole")); | ||
390 | } | ||
391 | |||
392 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusUserInPartitionRole"); | ||
393 | row[0] = key; | ||
394 | row[1] = partitionRoleKey; | ||
395 | row[2] = componentKey; | ||
396 | row[3] = user; | ||
397 | } | ||
398 | |||
399 | /// <summary> | ||
400 | /// Parses a COM+ partition role user element. | ||
401 | /// </summary> | ||
402 | /// <param name="node">Element to parse.</param> | ||
403 | /// <param name="componentKey">Identifier of parent component.</param> | ||
404 | /// <param name="applicationKey">Optional identifier of parent application role.</param> | ||
405 | private void ParseComPlusGroupInPartitionRoleElement(XElement node, string componentKey, string partitionRoleKey) | ||
406 | { | ||
407 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
408 | |||
409 | string key = null; | ||
410 | string group = null; | ||
411 | |||
412 | foreach (XAttribute attrib in node.Attributes()) | ||
413 | { | ||
414 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
415 | { | ||
416 | switch (attrib.Name.LocalName) | ||
417 | { | ||
418 | case "Id": | ||
419 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
420 | break; | ||
421 | case "PartitionRole": | ||
422 | if (null != partitionRoleKey) | ||
423 | { | ||
424 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
425 | } | ||
426 | partitionRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
427 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartitionRole", partitionRoleKey); | ||
428 | break; | ||
429 | case "Group": | ||
430 | group = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
431 | this.Core.CreateSimpleReference(sourceLineNumbers, "Group", group); | ||
432 | break; | ||
433 | default: | ||
434 | this.Core.UnexpectedAttribute(node, attrib); | ||
435 | break; | ||
436 | } | ||
437 | } | ||
438 | else | ||
439 | { | ||
440 | this.Core.ParseExtensionAttribute(node, attrib); | ||
441 | } | ||
442 | } | ||
443 | |||
444 | if (null == partitionRoleKey) | ||
445 | { | ||
446 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "PartitionRole")); | ||
447 | } | ||
448 | |||
449 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusGroupInPartitionRole"); | ||
450 | row[0] = key; | ||
451 | row[1] = partitionRoleKey; | ||
452 | row[2] = componentKey; | ||
453 | row[3] = group; | ||
454 | } | ||
455 | |||
456 | /// <summary> | ||
457 | /// Parses a COM+ partition element. | ||
458 | /// </summary> | ||
459 | /// <param name="node">Element to parse.</param> | ||
460 | /// <param name="componentKey">Identifier of parent component.</param> | ||
461 | private void ParseComPlusPartitionUserElement(XElement node, string componentKey, string partitionKey) | ||
462 | { | ||
463 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
464 | |||
465 | string key = null; | ||
466 | string user = null; | ||
467 | |||
468 | foreach (XAttribute attrib in node.Attributes()) | ||
469 | { | ||
470 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
471 | { | ||
472 | switch (attrib.Name.LocalName) | ||
473 | { | ||
474 | case "Id": | ||
475 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
476 | break; | ||
477 | case "Partition": | ||
478 | if (null != partitionKey) | ||
479 | { | ||
480 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
481 | } | ||
482 | partitionKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
483 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartition", partitionKey); | ||
484 | break; | ||
485 | case "User": | ||
486 | user = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
487 | this.Core.CreateSimpleReference(sourceLineNumbers, "User", user); | ||
488 | break; | ||
489 | default: | ||
490 | this.Core.UnexpectedAttribute(node, attrib); | ||
491 | break; | ||
492 | } | ||
493 | } | ||
494 | else | ||
495 | { | ||
496 | this.Core.ParseExtensionAttribute(node, attrib); | ||
497 | } | ||
498 | } | ||
499 | |||
500 | if (null == partitionKey) | ||
501 | { | ||
502 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Partition")); | ||
503 | } | ||
504 | |||
505 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartitionUser"); | ||
506 | row[0] = key; | ||
507 | row[1] = partitionKey; | ||
508 | row[2] = componentKey; | ||
509 | row[3] = user; | ||
510 | } | ||
511 | |||
512 | /// <summary> | ||
513 | /// Parses a COM+ application element. | ||
514 | /// </summary> | ||
515 | /// <param name="node">Element to parse.</param> | ||
516 | /// <param name="componentKey">Identifier of parent component.</param> | ||
517 | /// <param name="partitionKey">Optional identifier of parent partition.</param> | ||
518 | private void ParseComPlusApplicationElement(XElement node, string componentKey, bool win64, string partitionKey) | ||
519 | { | ||
520 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
521 | |||
522 | string key = null; | ||
523 | string id = null; | ||
524 | string name = null; | ||
525 | |||
526 | Hashtable properties = new Hashtable(); | ||
527 | |||
528 | foreach (XAttribute attrib in node.Attributes()) | ||
529 | { | ||
530 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
531 | { | ||
532 | switch (attrib.Name.LocalName) | ||
533 | { | ||
534 | case "Id": | ||
535 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
536 | break; | ||
537 | case "Partition": | ||
538 | if (null != partitionKey) | ||
539 | { | ||
540 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
541 | } | ||
542 | partitionKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
543 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartition", partitionKey); | ||
544 | break; | ||
545 | case "ApplicationId": | ||
546 | id = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
547 | break; | ||
548 | case "Name": | ||
549 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
550 | break; | ||
551 | case "ThreeGigSupportEnabled": | ||
552 | if (null == componentKey) | ||
553 | { | ||
554 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
555 | } | ||
556 | properties["3GigSupportEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
557 | break; | ||
558 | case "AccessChecksLevel": | ||
559 | if (null == componentKey) | ||
560 | { | ||
561 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
562 | } | ||
563 | string accessChecksLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
564 | switch (accessChecksLevelValue) | ||
565 | { | ||
566 | case "applicationLevel": | ||
567 | properties["AccessChecksLevel"] = "0"; | ||
568 | break; | ||
569 | case "applicationComponentLevel": | ||
570 | properties["AccessChecksLevel"] = "1"; | ||
571 | break; | ||
572 | default: | ||
573 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "AccessChecksLevel", accessChecksLevelValue, "applicationLevel", "applicationComponentLevel")); | ||
574 | break; | ||
575 | } | ||
576 | break; | ||
577 | case "Activation": | ||
578 | if (null == componentKey) | ||
579 | { | ||
580 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
581 | } | ||
582 | string activationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
583 | switch (activationValue) | ||
584 | { | ||
585 | case "inproc": | ||
586 | properties["Activation"] = "Inproc"; | ||
587 | break; | ||
588 | case "local": | ||
589 | properties["Activation"] = "Local"; | ||
590 | break; | ||
591 | default: | ||
592 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "Activation", activationValue, "inproc", "local")); | ||
593 | break; | ||
594 | } | ||
595 | break; | ||
596 | case "ApplicationAccessChecksEnabled": | ||
597 | if (null == componentKey) | ||
598 | { | ||
599 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
600 | } | ||
601 | properties["ApplicationAccessChecksEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
602 | break; | ||
603 | case "ApplicationDirectory": | ||
604 | if (null == componentKey) | ||
605 | { | ||
606 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
607 | } | ||
608 | properties["ApplicationDirectory"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
609 | break; | ||
610 | case "Authentication": | ||
611 | if (null == componentKey) | ||
612 | { | ||
613 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
614 | } | ||
615 | string authenticationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
616 | switch (authenticationValue) | ||
617 | { | ||
618 | case "default": | ||
619 | properties["Authentication"] = "0"; | ||
620 | break; | ||
621 | case "none": | ||
622 | properties["Authentication"] = "1"; | ||
623 | break; | ||
624 | case "connect": | ||
625 | properties["Authentication"] = "2"; | ||
626 | break; | ||
627 | case "call": | ||
628 | properties["Authentication"] = "3"; | ||
629 | break; | ||
630 | case "packet": | ||
631 | properties["Authentication"] = "4"; | ||
632 | break; | ||
633 | case "integrity": | ||
634 | properties["Authentication"] = "5"; | ||
635 | break; | ||
636 | case "privacy": | ||
637 | properties["Authentication"] = "6"; | ||
638 | break; | ||
639 | default: | ||
640 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "Authentication", authenticationValue, "default", "none", "connect", "call", "packet", "integrity", "privacy")); | ||
641 | break; | ||
642 | } | ||
643 | break; | ||
644 | case "AuthenticationCapability": | ||
645 | if (null == componentKey) | ||
646 | { | ||
647 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
648 | } | ||
649 | string authenticationCapabilityValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
650 | switch (authenticationCapabilityValue) | ||
651 | { | ||
652 | case "none": | ||
653 | properties["AuthenticationCapability"] = "0"; | ||
654 | break; | ||
655 | case "secureReference": | ||
656 | properties["AuthenticationCapability"] = "2"; | ||
657 | break; | ||
658 | case "staticCloaking": | ||
659 | properties["AuthenticationCapability"] = "32"; | ||
660 | break; | ||
661 | case "dynamicCloaking": | ||
662 | properties["AuthenticationCapability"] = "64"; | ||
663 | break; | ||
664 | default: | ||
665 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "AuthenticationCapability", authenticationCapabilityValue, "none", "secureReference", "staticCloaking", "dynamicCloaking")); | ||
666 | break; | ||
667 | } | ||
668 | break; | ||
669 | case "Changeable": | ||
670 | this.Core.OnMessage(WixWarnings.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
671 | break; | ||
672 | case "CommandLine": | ||
673 | if (null == componentKey) | ||
674 | { | ||
675 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
676 | } | ||
677 | properties["CommandLine"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
678 | break; | ||
679 | case "ConcurrentApps": | ||
680 | if (null == componentKey) | ||
681 | { | ||
682 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
683 | } | ||
684 | properties["ConcurrentApps"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
685 | break; | ||
686 | case "CreatedBy": | ||
687 | if (null == componentKey) | ||
688 | { | ||
689 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
690 | } | ||
691 | properties["CreatedBy"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
692 | break; | ||
693 | case "CRMEnabled": | ||
694 | if (null == componentKey) | ||
695 | { | ||
696 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
697 | } | ||
698 | properties["CRMEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
699 | break; | ||
700 | case "CRMLogFile": | ||
701 | if (null == componentKey) | ||
702 | { | ||
703 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
704 | } | ||
705 | properties["CRMLogFile"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
706 | break; | ||
707 | case "Deleteable": | ||
708 | if (null == componentKey) | ||
709 | { | ||
710 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
711 | } | ||
712 | properties["Deleteable"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
713 | break; | ||
714 | case "Description": | ||
715 | if (null == componentKey) | ||
716 | { | ||
717 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
718 | } | ||
719 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
720 | break; | ||
721 | case "DumpEnabled": | ||
722 | if (null == componentKey) | ||
723 | { | ||
724 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
725 | } | ||
726 | properties["DumpEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
727 | break; | ||
728 | case "DumpOnException": | ||
729 | if (null == componentKey) | ||
730 | { | ||
731 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
732 | } | ||
733 | properties["DumpOnException"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
734 | break; | ||
735 | case "DumpOnFailfast": | ||
736 | if (null == componentKey) | ||
737 | { | ||
738 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
739 | } | ||
740 | properties["DumpOnFailfast"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
741 | break; | ||
742 | case "DumpPath": | ||
743 | if (null == componentKey) | ||
744 | { | ||
745 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
746 | } | ||
747 | properties["DumpPath"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
748 | break; | ||
749 | case "EventsEnabled": | ||
750 | if (null == componentKey) | ||
751 | { | ||
752 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
753 | } | ||
754 | properties["EventsEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
755 | break; | ||
756 | case "Identity": | ||
757 | if (null == componentKey) | ||
758 | { | ||
759 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
760 | } | ||
761 | properties["Identity"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
762 | break; | ||
763 | case "ImpersonationLevel": | ||
764 | if (null == componentKey) | ||
765 | { | ||
766 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
767 | } | ||
768 | string impersonationLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
769 | switch (impersonationLevelValue) | ||
770 | { | ||
771 | case "anonymous": | ||
772 | properties["ImpersonationLevel"] = "1"; | ||
773 | break; | ||
774 | case "identify": | ||
775 | properties["ImpersonationLevel"] = "2"; | ||
776 | break; | ||
777 | case "impersonate": | ||
778 | properties["ImpersonationLevel"] = "3"; | ||
779 | break; | ||
780 | case "delegate": | ||
781 | properties["ImpersonationLevel"] = "4"; | ||
782 | break; | ||
783 | default: | ||
784 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "ImpersonationLevel", impersonationLevelValue, "anonymous", "identify", "impersonate", "delegate")); | ||
785 | break; | ||
786 | } | ||
787 | break; | ||
788 | case "IsEnabled": | ||
789 | if (null == componentKey) | ||
790 | { | ||
791 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
792 | } | ||
793 | properties["IsEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
794 | break; | ||
795 | case "MaxDumpCount": | ||
796 | if (null == componentKey) | ||
797 | { | ||
798 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
799 | } | ||
800 | properties["MaxDumpCount"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
801 | break; | ||
802 | case "Password": | ||
803 | if (null == componentKey) | ||
804 | { | ||
805 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
806 | } | ||
807 | properties["Password"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
808 | break; | ||
809 | case "QCAuthenticateMsgs": | ||
810 | if (null == componentKey) | ||
811 | { | ||
812 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
813 | } | ||
814 | string qcAuthenticateMsgsValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
815 | switch (qcAuthenticateMsgsValue) | ||
816 | { | ||
817 | case "secureApps": | ||
818 | properties["QCAuthenticateMsgs"] = "0"; | ||
819 | break; | ||
820 | case "off": | ||
821 | properties["QCAuthenticateMsgs"] = "1"; | ||
822 | break; | ||
823 | case "on": | ||
824 | properties["QCAuthenticateMsgs"] = "2"; | ||
825 | break; | ||
826 | default: | ||
827 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "QCAuthenticateMsgs", qcAuthenticateMsgsValue, "secureApps", "off", "on")); | ||
828 | break; | ||
829 | } | ||
830 | break; | ||
831 | case "QCListenerMaxThreads": | ||
832 | if (null == componentKey) | ||
833 | { | ||
834 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
835 | } | ||
836 | properties["QCListenerMaxThreads"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
837 | break; | ||
838 | case "QueueListenerEnabled": | ||
839 | if (null == componentKey) | ||
840 | { | ||
841 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
842 | } | ||
843 | properties["QueueListenerEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
844 | break; | ||
845 | case "QueuingEnabled": | ||
846 | if (null == componentKey) | ||
847 | { | ||
848 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
849 | } | ||
850 | properties["QueuingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
851 | break; | ||
852 | case "RecycleActivationLimit": | ||
853 | if (null == componentKey) | ||
854 | { | ||
855 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
856 | } | ||
857 | properties["RecycleActivationLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
858 | break; | ||
859 | case "RecycleCallLimit": | ||
860 | if (null == componentKey) | ||
861 | { | ||
862 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
863 | } | ||
864 | properties["RecycleCallLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
865 | break; | ||
866 | case "RecycleExpirationTimeout": | ||
867 | if (null == componentKey) | ||
868 | { | ||
869 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
870 | } | ||
871 | properties["RecycleExpirationTimeout"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
872 | break; | ||
873 | case "RecycleLifetimeLimit": | ||
874 | if (null == componentKey) | ||
875 | { | ||
876 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
877 | } | ||
878 | properties["RecycleLifetimeLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
879 | break; | ||
880 | case "RecycleMemoryLimit": | ||
881 | if (null == componentKey) | ||
882 | { | ||
883 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
884 | } | ||
885 | properties["RecycleMemoryLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
886 | break; | ||
887 | case "Replicable": | ||
888 | if (null == componentKey) | ||
889 | { | ||
890 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
891 | } | ||
892 | properties["Replicable"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
893 | break; | ||
894 | case "RunForever": | ||
895 | if (null == componentKey) | ||
896 | { | ||
897 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
898 | } | ||
899 | properties["RunForever"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
900 | break; | ||
901 | case "ShutdownAfter": | ||
902 | if (null == componentKey) | ||
903 | { | ||
904 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
905 | } | ||
906 | properties["ShutdownAfter"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
907 | break; | ||
908 | case "SoapActivated": | ||
909 | if (null == componentKey) | ||
910 | { | ||
911 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
912 | } | ||
913 | properties["SoapActivated"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
914 | break; | ||
915 | case "SoapBaseUrl": | ||
916 | if (null == componentKey) | ||
917 | { | ||
918 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
919 | } | ||
920 | properties["SoapBaseUrl"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
921 | break; | ||
922 | case "SoapMailTo": | ||
923 | if (null == componentKey) | ||
924 | { | ||
925 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
926 | } | ||
927 | properties["SoapMailTo"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
928 | break; | ||
929 | case "SoapVRoot": | ||
930 | if (null == componentKey) | ||
931 | { | ||
932 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
933 | } | ||
934 | properties["SoapVRoot"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
935 | break; | ||
936 | case "SRPEnabled": | ||
937 | if (null == componentKey) | ||
938 | { | ||
939 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
940 | } | ||
941 | properties["SRPEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
942 | break; | ||
943 | case "SRPTrustLevel": | ||
944 | if (null == componentKey) | ||
945 | { | ||
946 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
947 | } | ||
948 | string srpTrustLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
949 | switch (srpTrustLevelValue) | ||
950 | { | ||
951 | case "disallowed": | ||
952 | properties["SRPTrustLevel"] = "0"; | ||
953 | break; | ||
954 | case "fullyTrusted": | ||
955 | properties["SRPTrustLevel"] = "262144"; | ||
956 | break; | ||
957 | default: | ||
958 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "SRPTrustLevel", srpTrustLevelValue, "disallowed", "fullyTrusted")); | ||
959 | break; | ||
960 | } | ||
961 | break; | ||
962 | default: | ||
963 | this.Core.UnexpectedAttribute(node, attrib); | ||
964 | break; | ||
965 | } | ||
966 | } | ||
967 | else | ||
968 | { | ||
969 | this.Core.ParseExtensionAttribute(node, attrib); | ||
970 | } | ||
971 | } | ||
972 | |||
973 | if (null != componentKey && null == name) | ||
974 | { | ||
975 | this.Core.OnMessage(ComPlusErrors.RequiredAttributeUnderComponent(sourceLineNumbers, node.Name.LocalName, "Name")); | ||
976 | } | ||
977 | if (null == componentKey && null == id && null == name) | ||
978 | { | ||
979 | this.Core.OnMessage(ComPlusErrors.RequiredAttributeNotUnderComponent(sourceLineNumbers, node.Name.LocalName, "Id", "Name")); | ||
980 | } | ||
981 | |||
982 | foreach (XElement child in node.Elements()) | ||
983 | { | ||
984 | if (this.Namespace == child.Name.Namespace) | ||
985 | { | ||
986 | switch (child.Name.LocalName) | ||
987 | { | ||
988 | case "ComPlusApplicationRole": | ||
989 | this.ParseComPlusApplicationRoleElement(child, componentKey, key); | ||
990 | break; | ||
991 | case "ComPlusAssembly": | ||
992 | this.ParseComPlusAssemblyElement(child, componentKey, win64, key); | ||
993 | break; | ||
994 | default: | ||
995 | this.Core.UnexpectedElement(node, child); | ||
996 | break; | ||
997 | } | ||
998 | } | ||
999 | else | ||
1000 | { | ||
1001 | this.Core.ParseExtensionElement(node, child); | ||
1002 | } | ||
1003 | } | ||
1004 | |||
1005 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplication"); | ||
1006 | row[0] = key; | ||
1007 | row[1] = partitionKey; | ||
1008 | row[2] = componentKey; | ||
1009 | row[3] = id; | ||
1010 | row[4] = name; | ||
1011 | |||
1012 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
1013 | while (propertiesEnumerator.MoveNext()) | ||
1014 | { | ||
1015 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplicationProperty"); | ||
1016 | propertyRow[0] = key; | ||
1017 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
1018 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
1019 | } | ||
1020 | |||
1021 | if (componentKey != null) | ||
1022 | { | ||
1023 | if (win64) | ||
1024 | { | ||
1025 | if (this.Core.CurrentPlatform == Platform.IA64) | ||
1026 | { | ||
1027 | this.Core.OnMessage(WixErrors.UnsupportedPlatformForElement(sourceLineNumbers, "ia64", node.Name.LocalName)); | ||
1028 | } | ||
1029 | else | ||
1030 | { | ||
1031 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall_x64"); | ||
1032 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall_x64"); | ||
1033 | } | ||
1034 | } | ||
1035 | else | ||
1036 | { | ||
1037 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall"); | ||
1038 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall"); | ||
1039 | } | ||
1040 | } | ||
1041 | } | ||
1042 | |||
1043 | /// <summary> | ||
1044 | /// Parses a COM+ application role element. | ||
1045 | /// </summary> | ||
1046 | /// <param name="node">Element to parse.</param> | ||
1047 | /// <param name="componentKey">Identifier of parent component.</param> | ||
1048 | /// <param name="applicationKey">Optional identifier of parent application.</param> | ||
1049 | private void ParseComPlusApplicationRoleElement(XElement node, string componentKey, string applicationKey) | ||
1050 | { | ||
1051 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1052 | |||
1053 | string key = null; | ||
1054 | string name = null; | ||
1055 | |||
1056 | Hashtable properties = new Hashtable(); | ||
1057 | |||
1058 | foreach (XAttribute attrib in node.Attributes()) | ||
1059 | { | ||
1060 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
1061 | { | ||
1062 | switch (attrib.Name.LocalName) | ||
1063 | { | ||
1064 | case "Id": | ||
1065 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1066 | break; | ||
1067 | case "Application": | ||
1068 | if (null != applicationKey) | ||
1069 | { | ||
1070 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
1071 | } | ||
1072 | applicationKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1073 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplication", applicationKey); | ||
1074 | break; | ||
1075 | case "Name": | ||
1076 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1077 | break; | ||
1078 | case "Description": | ||
1079 | if (null == componentKey) | ||
1080 | { | ||
1081 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
1082 | } | ||
1083 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1084 | break; | ||
1085 | default: | ||
1086 | this.Core.UnexpectedAttribute(node, attrib); | ||
1087 | break; | ||
1088 | } | ||
1089 | } | ||
1090 | else | ||
1091 | { | ||
1092 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1093 | } | ||
1094 | } | ||
1095 | |||
1096 | if (null == applicationKey) | ||
1097 | { | ||
1098 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Application")); | ||
1099 | } | ||
1100 | |||
1101 | foreach (XElement child in node.Elements()) | ||
1102 | { | ||
1103 | if (this.Namespace == child.Name.Namespace) | ||
1104 | { | ||
1105 | switch (child.Name.LocalName) | ||
1106 | { | ||
1107 | case "ComPlusUserInApplicationRole": | ||
1108 | this.ParseComPlusUserInApplicationRoleElement(child, componentKey, key); | ||
1109 | break; | ||
1110 | case "ComPlusGroupInApplicationRole": | ||
1111 | this.ParseComPlusGroupInApplicationRoleElement(child, componentKey, key); | ||
1112 | break; | ||
1113 | default: | ||
1114 | this.Core.UnexpectedElement(node, child); | ||
1115 | break; | ||
1116 | } | ||
1117 | } | ||
1118 | else | ||
1119 | { | ||
1120 | this.Core.ParseExtensionElement(node, child); | ||
1121 | } | ||
1122 | } | ||
1123 | |||
1124 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplicationRole"); | ||
1125 | row[0] = key; | ||
1126 | row[1] = applicationKey; | ||
1127 | row[2] = componentKey; | ||
1128 | row[3] = name; | ||
1129 | |||
1130 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
1131 | while (propertiesEnumerator.MoveNext()) | ||
1132 | { | ||
1133 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplicationRoleProperty"); | ||
1134 | propertyRow[0] = key; | ||
1135 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
1136 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
1137 | } | ||
1138 | } | ||
1139 | |||
1140 | /// <summary> | ||
1141 | /// Parses a COM+ application role user element. | ||
1142 | /// </summary> | ||
1143 | /// <param name="node">Element to parse.</param> | ||
1144 | /// <param name="componentKey">Identifier of parent component.</param> | ||
1145 | /// <param name="applicationKey">Optional identifier of parent application role.</param> | ||
1146 | private void ParseComPlusUserInApplicationRoleElement(XElement node, string componentKey, string applicationRoleKey) | ||
1147 | { | ||
1148 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1149 | |||
1150 | string key = null; | ||
1151 | string user = null; | ||
1152 | |||
1153 | foreach (XAttribute attrib in node.Attributes()) | ||
1154 | { | ||
1155 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
1156 | { | ||
1157 | switch (attrib.Name.LocalName) | ||
1158 | { | ||
1159 | case "Id": | ||
1160 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1161 | break; | ||
1162 | case "ApplicationRole": | ||
1163 | if (null != applicationRoleKey) | ||
1164 | { | ||
1165 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
1166 | } | ||
1167 | applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1168 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplicationRole", applicationRoleKey); | ||
1169 | break; | ||
1170 | case "User": | ||
1171 | user = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1172 | this.Core.CreateSimpleReference(sourceLineNumbers, "User", user); | ||
1173 | break; | ||
1174 | default: | ||
1175 | this.Core.UnexpectedAttribute(node, attrib); | ||
1176 | break; | ||
1177 | } | ||
1178 | } | ||
1179 | else | ||
1180 | { | ||
1181 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1182 | } | ||
1183 | } | ||
1184 | |||
1185 | if (null == applicationRoleKey) | ||
1186 | { | ||
1187 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ApplicationRole")); | ||
1188 | } | ||
1189 | |||
1190 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusUserInApplicationRole"); | ||
1191 | row[0] = key; | ||
1192 | row[1] = applicationRoleKey; | ||
1193 | row[2] = componentKey; | ||
1194 | row[3] = user; | ||
1195 | } | ||
1196 | |||
1197 | /// <summary> | ||
1198 | /// Parses a COM+ application role group element. | ||
1199 | /// </summary> | ||
1200 | /// <param name="node">Element to parse.</param> | ||
1201 | /// <param name="componentKey">Identifier of parent component.</param> | ||
1202 | /// <param name="applicationKey">Optional identifier of parent application role.</param> | ||
1203 | private void ParseComPlusGroupInApplicationRoleElement(XElement node, string componentKey, string applicationRoleKey) | ||
1204 | { | ||
1205 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1206 | |||
1207 | string key = null; | ||
1208 | string group = null; | ||
1209 | |||
1210 | foreach (XAttribute attrib in node.Attributes()) | ||
1211 | { | ||
1212 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
1213 | { | ||
1214 | switch (attrib.Name.LocalName) | ||
1215 | { | ||
1216 | case "Id": | ||
1217 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1218 | break; | ||
1219 | case "ApplicationRole": | ||
1220 | if (null != applicationRoleKey) | ||
1221 | { | ||
1222 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
1223 | } | ||
1224 | applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1225 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplicationRole", applicationRoleKey); | ||
1226 | break; | ||
1227 | case "Group": | ||
1228 | group = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1229 | this.Core.CreateSimpleReference(sourceLineNumbers, "Group", group); | ||
1230 | break; | ||
1231 | default: | ||
1232 | this.Core.UnexpectedAttribute(node, attrib); | ||
1233 | break; | ||
1234 | } | ||
1235 | } | ||
1236 | else | ||
1237 | { | ||
1238 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1239 | } | ||
1240 | } | ||
1241 | |||
1242 | if (null == applicationRoleKey) | ||
1243 | { | ||
1244 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ApplicationRole")); | ||
1245 | } | ||
1246 | |||
1247 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusGroupInApplicationRole"); | ||
1248 | row[0] = key; | ||
1249 | row[1] = applicationRoleKey; | ||
1250 | row[2] = componentKey; | ||
1251 | row[3] = group; | ||
1252 | } | ||
1253 | |||
1254 | /// <summary> | ||
1255 | /// Parses a COM+ assembly element. | ||
1256 | /// </summary> | ||
1257 | /// <param name="node">Element to parse.</param> | ||
1258 | /// <param name="componentKey">Identifier of parent component.</param> | ||
1259 | /// <param name="applicationKey">Optional identifier of parent application.</param> | ||
1260 | private void ParseComPlusAssemblyElement(XElement node, string componentKey, bool win64, string applicationKey) | ||
1261 | { | ||
1262 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1263 | |||
1264 | string key = null; | ||
1265 | string assemblyName = null; | ||
1266 | string dllPath = null; | ||
1267 | string tlbPath = null; | ||
1268 | string psDllPath = null; | ||
1269 | int attributes = 0; | ||
1270 | |||
1271 | bool hasComponents = false; | ||
1272 | |||
1273 | foreach (XAttribute attrib in node.Attributes()) | ||
1274 | { | ||
1275 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
1276 | { | ||
1277 | switch (attrib.Name.LocalName) | ||
1278 | { | ||
1279 | case "Id": | ||
1280 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1281 | break; | ||
1282 | case "Application": | ||
1283 | if (null != applicationKey) | ||
1284 | { | ||
1285 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
1286 | } | ||
1287 | applicationKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1288 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplication", applicationKey); | ||
1289 | break; | ||
1290 | case "AssemblyName": | ||
1291 | assemblyName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1292 | break; | ||
1293 | case "DllPath": | ||
1294 | dllPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1295 | break; | ||
1296 | case "TlbPath": | ||
1297 | tlbPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1298 | break; | ||
1299 | case "PSDllPath": | ||
1300 | psDllPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1301 | break; | ||
1302 | case "Type": | ||
1303 | string typeValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1304 | switch (typeValue) | ||
1305 | { | ||
1306 | case ".net": | ||
1307 | attributes |= (int)CpiAssemblyAttributes.DotNetAssembly; | ||
1308 | break; | ||
1309 | case "native": | ||
1310 | attributes &= ~(int)CpiAssemblyAttributes.DotNetAssembly; | ||
1311 | break; | ||
1312 | default: | ||
1313 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusAssembly", "Type", typeValue, ".net", "native")); | ||
1314 | break; | ||
1315 | } | ||
1316 | break; | ||
1317 | case "EventClass": | ||
1318 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
1319 | { | ||
1320 | attributes |= (int)CpiAssemblyAttributes.EventClass; | ||
1321 | } | ||
1322 | else | ||
1323 | { | ||
1324 | attributes &= ~(int)CpiAssemblyAttributes.EventClass; | ||
1325 | } | ||
1326 | break; | ||
1327 | case "DllPathFromGAC": | ||
1328 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
1329 | { | ||
1330 | attributes |= (int)CpiAssemblyAttributes.DllPathFromGAC; | ||
1331 | } | ||
1332 | else | ||
1333 | { | ||
1334 | attributes &= ~(int)CpiAssemblyAttributes.DllPathFromGAC; | ||
1335 | } | ||
1336 | break; | ||
1337 | case "RegisterInCommit": | ||
1338 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
1339 | { | ||
1340 | attributes |= (int)CpiAssemblyAttributes.RegisterInCommit; | ||
1341 | } | ||
1342 | else | ||
1343 | { | ||
1344 | attributes &= ~(int)CpiAssemblyAttributes.RegisterInCommit; | ||
1345 | } | ||
1346 | break; | ||
1347 | default: | ||
1348 | this.Core.UnexpectedAttribute(node, attrib); | ||
1349 | break; | ||
1350 | } | ||
1351 | } | ||
1352 | else | ||
1353 | { | ||
1354 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1355 | } | ||
1356 | } | ||
1357 | |||
1358 | if (null == applicationKey && 0 == (attributes & (int)CpiAssemblyAttributes.DotNetAssembly)) | ||
1359 | { | ||
1360 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Application", "Type", "native")); | ||
1361 | } | ||
1362 | if (null != assemblyName && 0 == (attributes & (int)CpiAssemblyAttributes.DllPathFromGAC)) | ||
1363 | { | ||
1364 | this.Core.OnMessage(ComPlusErrors.UnexpectedAttributeWithoutOtherValue(sourceLineNumbers, node.Name.LocalName, "AssemblyName", "DllPathFromGAC", "no")); | ||
1365 | } | ||
1366 | if (null == tlbPath && 0 != (attributes & (int)CpiAssemblyAttributes.DotNetAssembly)) | ||
1367 | { | ||
1368 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "TlbPath", "Type", ".net")); | ||
1369 | } | ||
1370 | if (null != psDllPath && 0 != (attributes & (int)CpiAssemblyAttributes.DotNetAssembly)) | ||
1371 | { | ||
1372 | this.Core.OnMessage(ComPlusErrors.UnexpectedAttributeWithOtherValue(sourceLineNumbers, node.Name.LocalName, "PSDllPath", "Type", ".net")); | ||
1373 | } | ||
1374 | if (0 != (attributes & (int)CpiAssemblyAttributes.EventClass) && 0 != (attributes & (int)CpiAssemblyAttributes.DotNetAssembly)) | ||
1375 | { | ||
1376 | this.Core.OnMessage(ComPlusErrors.UnexpectedAttributeWithOtherValue(sourceLineNumbers, node.Name.LocalName, "EventClass", "yes", "Type", ".net")); | ||
1377 | } | ||
1378 | |||
1379 | foreach (XElement child in node.Elements()) | ||
1380 | { | ||
1381 | if (this.Namespace == child.Name.Namespace) | ||
1382 | { | ||
1383 | switch (child.Name.LocalName) | ||
1384 | { | ||
1385 | case "ComPlusAssemblyDependency": | ||
1386 | this.ParseComPlusAssemblyDependencyElement(child, key); | ||
1387 | break; | ||
1388 | case "ComPlusComponent": | ||
1389 | this.ParseComPlusComponentElement(child, componentKey, key); | ||
1390 | hasComponents = true; | ||
1391 | break; | ||
1392 | default: | ||
1393 | this.Core.UnexpectedElement(node, child); | ||
1394 | break; | ||
1395 | } | ||
1396 | } | ||
1397 | else | ||
1398 | { | ||
1399 | this.Core.ParseExtensionElement(node, child); | ||
1400 | } | ||
1401 | } | ||
1402 | |||
1403 | if (0 == (attributes & (int)CpiAssemblyAttributes.DotNetAssembly) && !hasComponents) | ||
1404 | { | ||
1405 | this.Core.OnMessage(ComPlusWarnings.MissingComponents(sourceLineNumbers)); | ||
1406 | } | ||
1407 | |||
1408 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusAssembly"); | ||
1409 | row[0] = key; | ||
1410 | row[1] = applicationKey; | ||
1411 | row[2] = componentKey; | ||
1412 | row[3] = assemblyName; | ||
1413 | row[4] = dllPath; | ||
1414 | row[5] = tlbPath; | ||
1415 | row[6] = psDllPath; | ||
1416 | row[7] = attributes; | ||
1417 | |||
1418 | if (win64) | ||
1419 | { | ||
1420 | if (this.Core.CurrentPlatform == Platform.IA64) | ||
1421 | { | ||
1422 | this.Core.OnMessage(WixErrors.UnsupportedPlatformForElement(sourceLineNumbers, "ia64", node.Name.LocalName)); | ||
1423 | } | ||
1424 | else | ||
1425 | { | ||
1426 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall_x64"); | ||
1427 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall_x64"); | ||
1428 | } | ||
1429 | } | ||
1430 | else | ||
1431 | { | ||
1432 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall"); | ||
1433 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall"); | ||
1434 | } | ||
1435 | } | ||
1436 | |||
1437 | /// <summary> | ||
1438 | /// Parses a COM+ assembly dependency element. | ||
1439 | /// </summary> | ||
1440 | /// <param name="node">Element to parse.</param> | ||
1441 | /// <param name="assemblyKey">Identifier of parent assembly.</param> | ||
1442 | private void ParseComPlusAssemblyDependencyElement(XElement node, string assemblyKey) | ||
1443 | { | ||
1444 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1445 | |||
1446 | string requiredAssemblyKey = null; | ||
1447 | |||
1448 | foreach (XAttribute attrib in node.Attributes()) | ||
1449 | { | ||
1450 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
1451 | { | ||
1452 | switch (attrib.Name.LocalName) | ||
1453 | { | ||
1454 | case "RequiredAssembly": | ||
1455 | requiredAssemblyKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1456 | break; | ||
1457 | default: | ||
1458 | this.Core.UnexpectedAttribute(node, attrib); | ||
1459 | break; | ||
1460 | } | ||
1461 | } | ||
1462 | else | ||
1463 | { | ||
1464 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1465 | } | ||
1466 | } | ||
1467 | |||
1468 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusAssemblyDependency"); | ||
1469 | row[0] = assemblyKey; | ||
1470 | row[1] = requiredAssemblyKey; | ||
1471 | } | ||
1472 | |||
1473 | /// <summary> | ||
1474 | /// Parses a COM+ component element. | ||
1475 | /// </summary> | ||
1476 | /// <param name="node">Element to parse.</param> | ||
1477 | /// <param name="componentKey">Identifier of parent component.</param> | ||
1478 | /// <param name="assemblyKey">Identifier of parent assembly.</param> | ||
1479 | private void ParseComPlusComponentElement(XElement node, string componentKey, string assemblyKey) | ||
1480 | { | ||
1481 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1482 | |||
1483 | string key = null; | ||
1484 | string clsid = null; | ||
1485 | |||
1486 | Hashtable properties = new Hashtable(); | ||
1487 | |||
1488 | foreach (XAttribute attrib in node.Attributes()) | ||
1489 | { | ||
1490 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
1491 | { | ||
1492 | switch (attrib.Name.LocalName) | ||
1493 | { | ||
1494 | case "Id": | ||
1495 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1496 | break; | ||
1497 | case "CLSID": | ||
1498 | clsid = "{" + this.Core.GetAttributeValue(sourceLineNumbers, attrib) + "}"; | ||
1499 | break; | ||
1500 | case "AllowInprocSubscribers": | ||
1501 | properties["AllowInprocSubscribers"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1502 | break; | ||
1503 | case "ComponentAccessChecksEnabled": | ||
1504 | properties["ComponentAccessChecksEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1505 | break; | ||
1506 | case "ComponentTransactionTimeout": | ||
1507 | properties["ComponentTransactionTimeout"] = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 3600).ToString(); | ||
1508 | break; | ||
1509 | case "ComponentTransactionTimeoutEnabled": | ||
1510 | properties["ComponentTransactionTimeoutEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1511 | break; | ||
1512 | case "COMTIIntrinsics": | ||
1513 | properties["COMTIIntrinsics"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1514 | break; | ||
1515 | case "ConstructionEnabled": | ||
1516 | properties["ConstructionEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1517 | break; | ||
1518 | case "ConstructorString": | ||
1519 | properties["ConstructorString"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1520 | break; | ||
1521 | case "CreationTimeout": | ||
1522 | properties["CreationTimeout"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1523 | break; | ||
1524 | case "Description": | ||
1525 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1526 | break; | ||
1527 | case "EventTrackingEnabled": | ||
1528 | properties["EventTrackingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1529 | break; | ||
1530 | case "ExceptionClass": | ||
1531 | properties["ExceptionClass"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1532 | break; | ||
1533 | case "FireInParallel": | ||
1534 | properties["FireInParallel"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1535 | break; | ||
1536 | case "IISIntrinsics": | ||
1537 | properties["IISIntrinsics"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1538 | break; | ||
1539 | case "InitializesServerApplication": | ||
1540 | properties["InitializesServerApplication"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1541 | break; | ||
1542 | case "IsEnabled": | ||
1543 | properties["IsEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1544 | break; | ||
1545 | case "IsPrivateComponent": | ||
1546 | properties["IsPrivateComponent"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1547 | break; | ||
1548 | case "JustInTimeActivation": | ||
1549 | properties["JustInTimeActivation"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1550 | break; | ||
1551 | case "LoadBalancingSupported": | ||
1552 | properties["LoadBalancingSupported"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1553 | break; | ||
1554 | case "MaxPoolSize": | ||
1555 | properties["MaxPoolSize"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1556 | break; | ||
1557 | case "MinPoolSize": | ||
1558 | properties["MinPoolSize"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1559 | break; | ||
1560 | case "MultiInterfacePublisherFilterCLSID": | ||
1561 | properties["MultiInterfacePublisherFilterCLSID"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1562 | break; | ||
1563 | case "MustRunInClientContext": | ||
1564 | properties["MustRunInClientContext"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1565 | break; | ||
1566 | case "MustRunInDefaultContext": | ||
1567 | properties["MustRunInDefaultContext"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1568 | break; | ||
1569 | case "ObjectPoolingEnabled": | ||
1570 | properties["ObjectPoolingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1571 | break; | ||
1572 | case "PublisherID": | ||
1573 | properties["PublisherID"] = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
1574 | break; | ||
1575 | case "SoapAssemblyName": | ||
1576 | properties["SoapAssemblyName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1577 | break; | ||
1578 | case "SoapTypeName": | ||
1579 | properties["SoapTypeName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1580 | break; | ||
1581 | case "Synchronization": | ||
1582 | string synchronizationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1583 | switch (synchronizationValue) | ||
1584 | { | ||
1585 | case "ignored": | ||
1586 | properties["Synchronization"] = "0"; | ||
1587 | break; | ||
1588 | case "none": | ||
1589 | properties["Synchronization"] = "1"; | ||
1590 | break; | ||
1591 | case "supported": | ||
1592 | properties["Synchronization"] = "2"; | ||
1593 | break; | ||
1594 | case "required": | ||
1595 | properties["Synchronization"] = "3"; | ||
1596 | break; | ||
1597 | case "requiresNew": | ||
1598 | properties["Synchronization"] = "4"; | ||
1599 | break; | ||
1600 | default: | ||
1601 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusComponent", "Synchronization", synchronizationValue, "ignored", "none", "supported", "required", "requiresNew")); | ||
1602 | break; | ||
1603 | } | ||
1604 | break; | ||
1605 | case "Transaction": | ||
1606 | string transactionValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1607 | switch (transactionValue) | ||
1608 | { | ||
1609 | case "ignored": | ||
1610 | properties["Transaction"] = "0"; | ||
1611 | break; | ||
1612 | case "none": | ||
1613 | properties["Transaction"] = "1"; | ||
1614 | break; | ||
1615 | case "supported": | ||
1616 | properties["Transaction"] = "2"; | ||
1617 | break; | ||
1618 | case "required": | ||
1619 | properties["Transaction"] = "3"; | ||
1620 | break; | ||
1621 | case "requiresNew": | ||
1622 | properties["Transaction"] = "4"; | ||
1623 | break; | ||
1624 | default: | ||
1625 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusComponent", "Transaction", transactionValue, "ignored", "none", "supported", "required", "requiresNew")); | ||
1626 | break; | ||
1627 | } | ||
1628 | break; | ||
1629 | case "TxIsolationLevel": | ||
1630 | string txIsolationLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1631 | switch (txIsolationLevelValue) | ||
1632 | { | ||
1633 | case "any": | ||
1634 | properties["TxIsolationLevel"] = "0"; | ||
1635 | break; | ||
1636 | case "readUnCommitted": | ||
1637 | properties["TxIsolationLevel"] = "1"; | ||
1638 | break; | ||
1639 | case "readCommitted": | ||
1640 | properties["TxIsolationLevel"] = "2"; | ||
1641 | break; | ||
1642 | case "repeatableRead": | ||
1643 | properties["TxIsolationLevel"] = "3"; | ||
1644 | break; | ||
1645 | case "serializable": | ||
1646 | properties["TxIsolationLevel"] = "4"; | ||
1647 | break; | ||
1648 | default: | ||
1649 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusComponent", "TxIsolationLevel", txIsolationLevelValue, "any", "readUnCommitted", "readCommitted", "repeatableRead", "serializable")); | ||
1650 | break; | ||
1651 | } | ||
1652 | break; | ||
1653 | default: | ||
1654 | this.Core.UnexpectedAttribute(node, attrib); | ||
1655 | break; | ||
1656 | } | ||
1657 | } | ||
1658 | else | ||
1659 | { | ||
1660 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1661 | } | ||
1662 | } | ||
1663 | |||
1664 | foreach (XElement child in node.Elements()) | ||
1665 | { | ||
1666 | if (this.Namespace == child.Name.Namespace) | ||
1667 | { | ||
1668 | switch (child.Name.LocalName) | ||
1669 | { | ||
1670 | case "ComPlusRoleForComponent": | ||
1671 | this.ParseComPlusRoleForComponentElement(child, componentKey, key); | ||
1672 | break; | ||
1673 | case "ComPlusInterface": | ||
1674 | this.ParseComPlusInterfaceElement(child, componentKey, key); | ||
1675 | break; | ||
1676 | case "ComPlusSubscription": | ||
1677 | this.ParseComPlusSubscriptionElement(child, componentKey, key); | ||
1678 | break; | ||
1679 | default: | ||
1680 | this.Core.UnexpectedElement(node, child); | ||
1681 | break; | ||
1682 | } | ||
1683 | } | ||
1684 | else | ||
1685 | { | ||
1686 | this.Core.ParseExtensionElement(node, child); | ||
1687 | } | ||
1688 | } | ||
1689 | |||
1690 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusComponent"); | ||
1691 | row[0] = key; | ||
1692 | row[1] = assemblyKey; | ||
1693 | row[2] = clsid; | ||
1694 | |||
1695 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
1696 | while (propertiesEnumerator.MoveNext()) | ||
1697 | { | ||
1698 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusComponentProperty"); | ||
1699 | propertyRow[0] = key; | ||
1700 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
1701 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
1702 | } | ||
1703 | } | ||
1704 | |||
1705 | /// <summary> | ||
1706 | /// Parses a COM+ application role for component element. | ||
1707 | /// </summary> | ||
1708 | /// <param name="node">Element to parse.</param> | ||
1709 | /// <param name="componentKey">Identifier of parent component.</param> | ||
1710 | /// <param name="cpcomponentKey">Identifier of parent COM+ component.</param> | ||
1711 | private void ParseComPlusRoleForComponentElement(XElement node, string componentKey, string cpcomponentKey) | ||
1712 | { | ||
1713 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1714 | |||
1715 | string key = null; | ||
1716 | string applicationRoleKey = null; | ||
1717 | |||
1718 | foreach (XAttribute attrib in node.Attributes()) | ||
1719 | { | ||
1720 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
1721 | { | ||
1722 | switch (attrib.Name.LocalName) | ||
1723 | { | ||
1724 | case "Id": | ||
1725 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1726 | break; | ||
1727 | case "Component": | ||
1728 | if (null != cpcomponentKey) | ||
1729 | { | ||
1730 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
1731 | } | ||
1732 | cpcomponentKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1733 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusComponent", cpcomponentKey); | ||
1734 | break; | ||
1735 | case "ApplicationRole": | ||
1736 | applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1737 | break; | ||
1738 | default: | ||
1739 | this.Core.UnexpectedAttribute(node, attrib); | ||
1740 | break; | ||
1741 | } | ||
1742 | } | ||
1743 | else | ||
1744 | { | ||
1745 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1746 | } | ||
1747 | } | ||
1748 | |||
1749 | if (null == cpcomponentKey) | ||
1750 | { | ||
1751 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Component")); | ||
1752 | } | ||
1753 | |||
1754 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusRoleForComponent"); | ||
1755 | row[0] = key; | ||
1756 | row[1] = cpcomponentKey; | ||
1757 | row[2] = applicationRoleKey; | ||
1758 | row[3] = componentKey; | ||
1759 | } | ||
1760 | |||
1761 | /// <summary> | ||
1762 | /// Parses a COM+ interface element. | ||
1763 | /// </summary> | ||
1764 | /// <param name="node">Element to parse.</param> | ||
1765 | /// <param name="componentKey">Identifier of parent component.</param> | ||
1766 | /// <param name="cpcomponentKey">Identifier of parent COM+ component.</param> | ||
1767 | private void ParseComPlusInterfaceElement(XElement node, string componentKey, string cpcomponentKey) | ||
1768 | { | ||
1769 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1770 | |||
1771 | // parse attributes | ||
1772 | string key = null; | ||
1773 | string iid = null; | ||
1774 | |||
1775 | Hashtable properties = new Hashtable(); | ||
1776 | |||
1777 | foreach (XAttribute attrib in node.Attributes()) | ||
1778 | { | ||
1779 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
1780 | { | ||
1781 | switch (attrib.Name.LocalName) | ||
1782 | { | ||
1783 | case "Id": | ||
1784 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1785 | break; | ||
1786 | case "IID": | ||
1787 | iid = "{" + this.Core.GetAttributeValue(sourceLineNumbers, attrib) + "}"; | ||
1788 | break; | ||
1789 | case "Description": | ||
1790 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1791 | break; | ||
1792 | case "QueuingEnabled": | ||
1793 | properties["QueuingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1794 | break; | ||
1795 | default: | ||
1796 | this.Core.UnexpectedAttribute(node, attrib); | ||
1797 | break; | ||
1798 | } | ||
1799 | } | ||
1800 | else | ||
1801 | { | ||
1802 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1803 | } | ||
1804 | } | ||
1805 | |||
1806 | foreach (XElement child in node.Elements()) | ||
1807 | { | ||
1808 | if (this.Namespace == child.Name.Namespace) | ||
1809 | { | ||
1810 | switch (child.Name.LocalName) | ||
1811 | { | ||
1812 | case "ComPlusRoleForInterface": | ||
1813 | this.ParseComPlusRoleForInterfaceElement(child, componentKey, key); | ||
1814 | break; | ||
1815 | case "ComPlusMethod": | ||
1816 | this.ParseComPlusMethodElement(child, componentKey, key); | ||
1817 | break; | ||
1818 | default: | ||
1819 | this.Core.UnexpectedElement(node, child); | ||
1820 | break; | ||
1821 | } | ||
1822 | } | ||
1823 | else | ||
1824 | { | ||
1825 | this.Core.ParseExtensionElement(node, child); | ||
1826 | } | ||
1827 | } | ||
1828 | |||
1829 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusInterface"); | ||
1830 | row[0] = key; | ||
1831 | row[1] = cpcomponentKey; | ||
1832 | row[2] = iid; | ||
1833 | |||
1834 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
1835 | while (propertiesEnumerator.MoveNext()) | ||
1836 | { | ||
1837 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusInterfaceProperty"); | ||
1838 | propertyRow[0] = key; | ||
1839 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
1840 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
1841 | } | ||
1842 | } | ||
1843 | |||
1844 | /// <summary> | ||
1845 | /// Parses a COM+ application role for interface element. | ||
1846 | /// </summary> | ||
1847 | /// <param name="node">Element to parse.</param> | ||
1848 | /// <param name="componentKey">Identifier of parent component.</param> | ||
1849 | /// <param name="interfaceKey">Identifier of parent interface.</param> | ||
1850 | private void ParseComPlusRoleForInterfaceElement(XElement node, string componentKey, string interfaceKey) | ||
1851 | { | ||
1852 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1853 | |||
1854 | string key = null; | ||
1855 | string applicationRoleKey = null; | ||
1856 | |||
1857 | foreach (XAttribute attrib in node.Attributes()) | ||
1858 | { | ||
1859 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
1860 | { | ||
1861 | switch (attrib.Name.LocalName) | ||
1862 | { | ||
1863 | case "Id": | ||
1864 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1865 | break; | ||
1866 | case "Interface": | ||
1867 | if (null != interfaceKey) | ||
1868 | { | ||
1869 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
1870 | } | ||
1871 | interfaceKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1872 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusInterface", interfaceKey); | ||
1873 | break; | ||
1874 | case "ApplicationRole": | ||
1875 | applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1876 | break; | ||
1877 | default: | ||
1878 | this.Core.UnexpectedAttribute(node, attrib); | ||
1879 | break; | ||
1880 | } | ||
1881 | } | ||
1882 | else | ||
1883 | { | ||
1884 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1885 | } | ||
1886 | } | ||
1887 | |||
1888 | if (null == interfaceKey) | ||
1889 | { | ||
1890 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Interface")); | ||
1891 | } | ||
1892 | |||
1893 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusRoleForInterface"); | ||
1894 | row[0] = key; | ||
1895 | row[1] = interfaceKey; | ||
1896 | row[2] = applicationRoleKey; | ||
1897 | row[3] = componentKey; | ||
1898 | } | ||
1899 | |||
1900 | /// <summary> | ||
1901 | /// Parses a COM+ method element. | ||
1902 | /// </summary> | ||
1903 | /// <param name="node">Element to parse.</param> | ||
1904 | /// <param name="componentKey">Identifier of parent component.</param> | ||
1905 | /// <param name="interfaceKey">Identifier of parent interface.</param> | ||
1906 | private void ParseComPlusMethodElement(XElement node, string componentKey, string interfaceKey) | ||
1907 | { | ||
1908 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
1909 | |||
1910 | string key = null; | ||
1911 | int index = CompilerConstants.IntegerNotSet; | ||
1912 | string name = null; | ||
1913 | |||
1914 | Hashtable properties = new Hashtable(); | ||
1915 | |||
1916 | foreach (XAttribute attrib in node.Attributes()) | ||
1917 | { | ||
1918 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
1919 | { | ||
1920 | switch (attrib.Name.LocalName) | ||
1921 | { | ||
1922 | case "Id": | ||
1923 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
1924 | break; | ||
1925 | case "Index": | ||
1926 | index = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue); | ||
1927 | break; | ||
1928 | case "Name": | ||
1929 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1930 | break; | ||
1931 | case "AutoComplete": | ||
1932 | properties["AutoComplete"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
1933 | break; | ||
1934 | case "Description": | ||
1935 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
1936 | break; | ||
1937 | default: | ||
1938 | this.Core.UnexpectedAttribute(node, attrib); | ||
1939 | break; | ||
1940 | } | ||
1941 | } | ||
1942 | else | ||
1943 | { | ||
1944 | this.Core.ParseExtensionAttribute(node, attrib); | ||
1945 | } | ||
1946 | } | ||
1947 | |||
1948 | foreach (XElement child in node.Elements()) | ||
1949 | { | ||
1950 | if (this.Namespace == child.Name.Namespace) | ||
1951 | { | ||
1952 | switch (child.Name.LocalName) | ||
1953 | { | ||
1954 | case "ComPlusRoleForMethod": | ||
1955 | this.ParseComPlusRoleForMethodElement(child, componentKey, key); | ||
1956 | break; | ||
1957 | default: | ||
1958 | this.Core.UnexpectedElement(node, child); | ||
1959 | break; | ||
1960 | } | ||
1961 | } | ||
1962 | else | ||
1963 | { | ||
1964 | this.Core.ParseExtensionElement(node, child); | ||
1965 | } | ||
1966 | } | ||
1967 | |||
1968 | if (CompilerConstants.IntegerNotSet == index && null == name) | ||
1969 | { | ||
1970 | this.Core.OnMessage(ComPlusErrors.RequiredAttribute(sourceLineNumbers, node.Name.LocalName, "Index", "Name")); | ||
1971 | } | ||
1972 | |||
1973 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusMethod"); | ||
1974 | row[0] = key; | ||
1975 | row[1] = interfaceKey; | ||
1976 | if (CompilerConstants.IntegerNotSet != index) | ||
1977 | { | ||
1978 | row[2] = index; | ||
1979 | } | ||
1980 | row[3] = name; | ||
1981 | |||
1982 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
1983 | while (propertiesEnumerator.MoveNext()) | ||
1984 | { | ||
1985 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusMethodProperty"); | ||
1986 | propertyRow[0] = key; | ||
1987 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
1988 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
1989 | } | ||
1990 | } | ||
1991 | |||
1992 | /// <summary> | ||
1993 | /// Parses a COM+ application role for method element. | ||
1994 | /// </summary> | ||
1995 | /// <param name="node">Element to parse.</param> | ||
1996 | /// <param name="componentKey">Identifier of parent component.</param> | ||
1997 | /// <param name="methodKey">Identifier of parent method.</param> | ||
1998 | private void ParseComPlusRoleForMethodElement(XElement node, string componentKey, string methodKey) | ||
1999 | { | ||
2000 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
2001 | |||
2002 | string key = null; | ||
2003 | string applicationRoleKey = null; | ||
2004 | |||
2005 | foreach (XAttribute attrib in node.Attributes()) | ||
2006 | { | ||
2007 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
2008 | { | ||
2009 | switch (attrib.Name.LocalName) | ||
2010 | { | ||
2011 | case "Id": | ||
2012 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
2013 | break; | ||
2014 | case "Method": | ||
2015 | if (null != methodKey) | ||
2016 | { | ||
2017 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
2018 | } | ||
2019 | methodKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2020 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusMethod", methodKey); | ||
2021 | break; | ||
2022 | case "ApplicationRole": | ||
2023 | applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2024 | break; | ||
2025 | default: | ||
2026 | this.Core.UnexpectedAttribute(node, attrib); | ||
2027 | break; | ||
2028 | } | ||
2029 | } | ||
2030 | else | ||
2031 | { | ||
2032 | this.Core.ParseExtensionAttribute(node, attrib); | ||
2033 | } | ||
2034 | } | ||
2035 | |||
2036 | if (null == methodKey) | ||
2037 | { | ||
2038 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Method")); | ||
2039 | } | ||
2040 | |||
2041 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusRoleForMethod"); | ||
2042 | row[0] = key; | ||
2043 | row[1] = methodKey; | ||
2044 | row[2] = applicationRoleKey; | ||
2045 | row[3] = componentKey; | ||
2046 | } | ||
2047 | |||
2048 | /// <summary> | ||
2049 | /// Parses a COM+ event subscription element. | ||
2050 | /// </summary> | ||
2051 | /// <param name="node">Element to parse.</param> | ||
2052 | /// <param name="componentKey">Identifier of parent component.</param> | ||
2053 | /// <param name="cpcomponentKey">Identifier of parent COM+ component.</param> | ||
2054 | private void ParseComPlusSubscriptionElement(XElement node, string componentKey, string cpcomponentKey) | ||
2055 | { | ||
2056 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
2057 | |||
2058 | string key = null; | ||
2059 | string id = null; | ||
2060 | string name = null; | ||
2061 | string eventCLSID = null; | ||
2062 | string publisherID = null; | ||
2063 | |||
2064 | Hashtable properties = new Hashtable(); | ||
2065 | |||
2066 | foreach (XAttribute attrib in node.Attributes()) | ||
2067 | { | ||
2068 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
2069 | { | ||
2070 | switch (attrib.Name.LocalName) | ||
2071 | { | ||
2072 | case "Id": | ||
2073 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
2074 | break; | ||
2075 | case "Component": | ||
2076 | if (null != cpcomponentKey) | ||
2077 | { | ||
2078 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
2079 | } | ||
2080 | cpcomponentKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2081 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusComponent", cpcomponentKey); | ||
2082 | break; | ||
2083 | case "SubscriptionId": | ||
2084 | id = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
2085 | break; | ||
2086 | case "Name": | ||
2087 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2088 | break; | ||
2089 | case "EventCLSID": | ||
2090 | eventCLSID = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2091 | break; | ||
2092 | case "PublisherID": | ||
2093 | publisherID = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
2094 | break; | ||
2095 | case "Description": | ||
2096 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2097 | break; | ||
2098 | case "Enabled": | ||
2099 | properties["Enabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
2100 | break; | ||
2101 | case "EventClassPartitionID": | ||
2102 | properties["EventClassPartitionID"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2103 | break; | ||
2104 | case "FilterCriteria": | ||
2105 | properties["FilterCriteria"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2106 | break; | ||
2107 | case "InterfaceID": | ||
2108 | properties["InterfaceID"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2109 | break; | ||
2110 | case "MachineName": | ||
2111 | properties["MachineName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2112 | break; | ||
2113 | case "MethodName": | ||
2114 | properties["MethodName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2115 | break; | ||
2116 | case "PerUser": | ||
2117 | properties["PerUser"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
2118 | break; | ||
2119 | case "Queued": | ||
2120 | properties["Queued"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
2121 | break; | ||
2122 | case "SubscriberMoniker": | ||
2123 | properties["SubscriberMoniker"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2124 | break; | ||
2125 | case "UserName": | ||
2126 | properties["UserName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
2127 | break; | ||
2128 | default: | ||
2129 | this.Core.UnexpectedAttribute(node, attrib); | ||
2130 | break; | ||
2131 | } | ||
2132 | } | ||
2133 | else | ||
2134 | { | ||
2135 | this.Core.ParseExtensionAttribute(node, attrib); | ||
2136 | } | ||
2137 | } | ||
2138 | |||
2139 | if (null == cpcomponentKey) | ||
2140 | { | ||
2141 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Component")); | ||
2142 | } | ||
2143 | |||
2144 | this.Core.ParseForExtensionElements(node); | ||
2145 | |||
2146 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusSubscription"); | ||
2147 | row[0] = key; | ||
2148 | row[1] = cpcomponentKey; | ||
2149 | row[2] = componentKey; | ||
2150 | row[3] = id; | ||
2151 | row[4] = name; | ||
2152 | row[5] = eventCLSID; | ||
2153 | row[6] = publisherID; | ||
2154 | |||
2155 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
2156 | while (propertiesEnumerator.MoveNext()) | ||
2157 | { | ||
2158 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusSubscriptionProperty"); | ||
2159 | propertyRow[0] = key; | ||
2160 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
2161 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
2162 | } | ||
2163 | } | ||
2164 | |||
2165 | /// <summary> | ||
2166 | /// Attempts to parse the input value as a GUID, and in case the value is a valid | ||
2167 | /// GUID returnes it in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}". | ||
2168 | /// </summary> | ||
2169 | /// <param name="val"></param> | ||
2170 | /// <returns></returns> | ||
2171 | string TryFormatGuidValue(string val) | ||
2172 | { | ||
2173 | try | ||
2174 | { | ||
2175 | Guid guid = new Guid(val); | ||
2176 | return guid.ToString("B").ToUpper(); | ||
2177 | } | ||
2178 | catch (FormatException) | ||
2179 | { | ||
2180 | return val; | ||
2181 | } | ||
2182 | catch (OverflowException) | ||
2183 | { | ||
2184 | return val; | ||
2185 | } | ||
2186 | } | ||
2187 | } | ||
2188 | } | ||
diff --git a/src/wixext/ComPlusDecompiler.cs b/src/wixext/ComPlusDecompiler.cs new file mode 100644 index 00000000..27f1653e --- /dev/null +++ b/src/wixext/ComPlusDecompiler.cs | |||
@@ -0,0 +1,1843 @@ | |||
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 | namespace WixToolset.Extensions | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections; | ||
7 | using System.Globalization; | ||
8 | using WixToolset.Data; | ||
9 | using WixToolset.Extensibility; | ||
10 | using ComPlus = WixToolset.Extensions.Serialize.ComPlus; | ||
11 | using Wix = WixToolset.Data.Serialize; | ||
12 | |||
13 | /// <summary> | ||
14 | /// The decompiler for the WiX Toolset COM+ Extension. | ||
15 | /// </summary> | ||
16 | public sealed class ComPlusDecompiler : DecompilerExtension | ||
17 | { | ||
18 | /// <summary> | ||
19 | /// Creates a decompiler for ComPlus Extension. | ||
20 | /// </summary> | ||
21 | public ComPlusDecompiler() | ||
22 | { | ||
23 | this.TableDefinitions = ComPlusExtensionData.GetExtensionTableDefinitions(); | ||
24 | } | ||
25 | |||
26 | /// <summary> | ||
27 | /// Get the extensions library to be removed. | ||
28 | /// </summary> | ||
29 | /// <param name="tableDefinitions">Table definitions for library.</param> | ||
30 | /// <returns>Library to remove from decompiled output.</returns> | ||
31 | public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions) | ||
32 | { | ||
33 | return ComPlusExtensionData.GetExtensionLibrary(tableDefinitions); | ||
34 | } | ||
35 | |||
36 | /// <summary> | ||
37 | /// Decompiles an extension table. | ||
38 | /// </summary> | ||
39 | /// <param name="table">The table to decompile.</param> | ||
40 | public override void DecompileTable(Table table) | ||
41 | { | ||
42 | switch (table.Name) | ||
43 | { | ||
44 | case "ComPlusPartition": | ||
45 | this.DecompileComPlusPartitionTable(table); | ||
46 | break; | ||
47 | case "ComPlusPartitionProperty": | ||
48 | this.DecompileComPlusPartitionPropertyTable(table); | ||
49 | break; | ||
50 | case "ComPlusPartitionRole": | ||
51 | this.DecompileComPlusPartitionRoleTable(table); | ||
52 | break; | ||
53 | case "ComPlusUserInPartitionRole": | ||
54 | this.DecompileComPlusUserInPartitionRoleTable(table); | ||
55 | break; | ||
56 | case "ComPlusGroupInPartitionRole": | ||
57 | this.DecompileComPlusGroupInPartitionRoleTable(table); | ||
58 | break; | ||
59 | case "ComPlusPartitionUser": | ||
60 | this.DecompileComPlusPartitionUserTable(table); | ||
61 | break; | ||
62 | case "ComPlusApplication": | ||
63 | this.DecompileComPlusApplicationTable(table); | ||
64 | break; | ||
65 | case "ComPlusApplicationProperty": | ||
66 | this.DecompileComPlusApplicationPropertyTable(table); | ||
67 | break; | ||
68 | case "ComPlusApplicationRole": | ||
69 | this.DecompileComPlusApplicationRoleTable(table); | ||
70 | break; | ||
71 | case "ComPlusApplicationRoleProperty": | ||
72 | this.DecompileComPlusApplicationRolePropertyTable(table); | ||
73 | break; | ||
74 | case "ComPlusUserInApplicationRole": | ||
75 | this.DecompileComPlusUserInApplicationRoleTable(table); | ||
76 | break; | ||
77 | case "ComPlusGroupInApplicationRole": | ||
78 | this.DecompileComPlusGroupInApplicationRoleTable(table); | ||
79 | break; | ||
80 | case "ComPlusAssembly": | ||
81 | this.DecompileComPlusAssemblyTable(table); | ||
82 | break; | ||
83 | case "ComPlusComponent": | ||
84 | this.DecompileComPlusComponentTable(table); | ||
85 | break; | ||
86 | case "ComPlusComponentProperty": | ||
87 | this.DecompileComPlusComponentPropertyTable(table); | ||
88 | break; | ||
89 | case "ComPlusRoleForComponent": | ||
90 | this.DecompileComPlusRoleForComponentTable(table); | ||
91 | break; | ||
92 | case "ComPlusInterface": | ||
93 | this.DecompileComPlusInterfaceTable(table); | ||
94 | break; | ||
95 | case "ComPlusInterfaceProperty": | ||
96 | this.DecompileComPlusInterfacePropertyTable(table); | ||
97 | break; | ||
98 | case "ComPlusRoleForInterface": | ||
99 | this.DecompileComPlusRoleForInterfaceTable(table); | ||
100 | break; | ||
101 | case "ComPlusMethod": | ||
102 | this.DecompileComPlusMethodTable(table); | ||
103 | break; | ||
104 | case "ComPlusMethodProperty": | ||
105 | this.DecompileComPlusMethodPropertyTable(table); | ||
106 | break; | ||
107 | case "ComPlusRoleForMethod": | ||
108 | this.DecompileComPlusRoleForMethodTable(table); | ||
109 | break; | ||
110 | case "ComPlusSubscription": | ||
111 | this.DecompileComPlusSubscriptionTable(table); | ||
112 | break; | ||
113 | case "ComPlusSubscriptionProperty": | ||
114 | this.DecompileComPlusSubscriptionPropertyTable(table); | ||
115 | break; | ||
116 | default: | ||
117 | base.DecompileTable(table); | ||
118 | break; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | /// <summary> | ||
123 | /// Decompile the ComPlusPartition table. | ||
124 | /// </summary> | ||
125 | /// <param name="table">The table to decompile.</param> | ||
126 | private void DecompileComPlusPartitionTable(Table table) | ||
127 | { | ||
128 | foreach (Row row in table.Rows) | ||
129 | { | ||
130 | ComPlus.ComPlusPartition partition = new ComPlus.ComPlusPartition(); | ||
131 | |||
132 | partition.Id = (string)row[0]; | ||
133 | |||
134 | if (null != row[2]) | ||
135 | { | ||
136 | partition.PartitionId = (string)row[2]; | ||
137 | } | ||
138 | |||
139 | if (null != row[3]) | ||
140 | { | ||
141 | partition.Name = (string)row[3]; | ||
142 | } | ||
143 | |||
144 | if (null != row[1]) | ||
145 | { | ||
146 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); | ||
147 | if (null != component) | ||
148 | { | ||
149 | component.AddChild(partition); | ||
150 | } | ||
151 | else | ||
152 | { | ||
153 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); | ||
154 | } | ||
155 | } | ||
156 | else | ||
157 | { | ||
158 | this.Core.RootElement.AddChild(partition); | ||
159 | } | ||
160 | this.Core.IndexElement(row, partition); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | /// <summary> | ||
165 | /// Decompile the ComPlusPartitionProperty table. | ||
166 | /// </summary> | ||
167 | /// <param name="table">The table to decompile.</param> | ||
168 | private void DecompileComPlusPartitionPropertyTable(Table table) | ||
169 | { | ||
170 | foreach (Row row in table.Rows) | ||
171 | { | ||
172 | ComPlus.ComPlusPartition partition = (ComPlus.ComPlusPartition)this.Core.GetIndexedElement("ComPlusPartition", (string)row[0]); | ||
173 | if (null == partition) | ||
174 | { | ||
175 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Partition_", (string)row[0], "ComPlusPartition")); | ||
176 | } | ||
177 | |||
178 | switch ((string)row[1]) | ||
179 | { | ||
180 | case "Changeable": | ||
181 | switch ((string)row[2]) | ||
182 | { | ||
183 | case "1": | ||
184 | partition.Changeable = ComPlus.YesNoType.yes; | ||
185 | break; | ||
186 | case "0": | ||
187 | partition.Changeable = ComPlus.YesNoType.no; | ||
188 | break; | ||
189 | default: | ||
190 | // TODO: Warning | ||
191 | break; | ||
192 | } | ||
193 | break; | ||
194 | case "Deleteable": | ||
195 | switch ((string)row[2]) | ||
196 | { | ||
197 | case "1": | ||
198 | partition.Deleteable = ComPlus.YesNoType.yes; | ||
199 | break; | ||
200 | case "0": | ||
201 | partition.Deleteable = ComPlus.YesNoType.no; | ||
202 | break; | ||
203 | default: | ||
204 | // TODO: Warning | ||
205 | break; | ||
206 | } | ||
207 | break; | ||
208 | case "Description": | ||
209 | partition.Description = (string)row[2]; | ||
210 | break; | ||
211 | default: | ||
212 | // TODO: Warning | ||
213 | break; | ||
214 | } | ||
215 | } | ||
216 | } | ||
217 | |||
218 | /// <summary> | ||
219 | /// Decompile the ComPlusPartitionRole table. | ||
220 | /// </summary> | ||
221 | /// <param name="table">The table to decompile.</param> | ||
222 | private void DecompileComPlusPartitionRoleTable(Table table) | ||
223 | { | ||
224 | foreach (Row row in table.Rows) | ||
225 | { | ||
226 | ComPlus.ComPlusPartitionRole partitionRole = new ComPlus.ComPlusPartitionRole(); | ||
227 | |||
228 | partitionRole.Id = (string)row[0]; | ||
229 | partitionRole.Partition = (string)row[1]; | ||
230 | partitionRole.Name = (string)row[3]; | ||
231 | |||
232 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
233 | if (null != component) | ||
234 | { | ||
235 | component.AddChild(partitionRole); | ||
236 | } | ||
237 | else | ||
238 | { | ||
239 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | |||
244 | /// <summary> | ||
245 | /// Decompile the ComPlusUserInPartitionRole table. | ||
246 | /// </summary> | ||
247 | /// <param name="table">The table to decompile.</param> | ||
248 | private void DecompileComPlusUserInPartitionRoleTable(Table table) | ||
249 | { | ||
250 | foreach (Row row in table.Rows) | ||
251 | { | ||
252 | ComPlus.ComPlusUserInPartitionRole userInPartitionRole = new ComPlus.ComPlusUserInPartitionRole(); | ||
253 | |||
254 | userInPartitionRole.Id = (string)row[0]; | ||
255 | userInPartitionRole.PartitionRole = (string)row[1]; | ||
256 | userInPartitionRole.User = (string)row[3]; | ||
257 | |||
258 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
259 | if (null != component) | ||
260 | { | ||
261 | component.AddChild(userInPartitionRole); | ||
262 | } | ||
263 | else | ||
264 | { | ||
265 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | |||
270 | /// <summary> | ||
271 | /// Decompile the ComPlusGroupInPartitionRole table. | ||
272 | /// </summary> | ||
273 | /// <param name="table">The table to decompile.</param> | ||
274 | private void DecompileComPlusGroupInPartitionRoleTable(Table table) | ||
275 | { | ||
276 | foreach (Row row in table.Rows) | ||
277 | { | ||
278 | ComPlus.ComPlusGroupInPartitionRole groupInPartitionRole = new ComPlus.ComPlusGroupInPartitionRole(); | ||
279 | |||
280 | groupInPartitionRole.Id = (string)row[0]; | ||
281 | groupInPartitionRole.PartitionRole = (string)row[1]; | ||
282 | groupInPartitionRole.Group = (string)row[3]; | ||
283 | |||
284 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
285 | if (null != component) | ||
286 | { | ||
287 | component.AddChild(groupInPartitionRole); | ||
288 | } | ||
289 | else | ||
290 | { | ||
291 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | /// <summary> | ||
297 | /// Decompile the ComPlusPartitionUser table. | ||
298 | /// </summary> | ||
299 | /// <param name="table">The table to decompile.</param> | ||
300 | private void DecompileComPlusPartitionUserTable(Table table) | ||
301 | { | ||
302 | foreach (Row row in table.Rows) | ||
303 | { | ||
304 | ComPlus.ComPlusPartitionUser partitionUser = new ComPlus.ComPlusPartitionUser(); | ||
305 | |||
306 | partitionUser.Id = (string)row[0]; | ||
307 | partitionUser.Partition = (string)row[1]; | ||
308 | partitionUser.User = (string)row[3]; | ||
309 | |||
310 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
311 | if (null != component) | ||
312 | { | ||
313 | component.AddChild(partitionUser); | ||
314 | } | ||
315 | else | ||
316 | { | ||
317 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
318 | } | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /// <summary> | ||
323 | /// Decompile the ComPlusApplication table. | ||
324 | /// </summary> | ||
325 | /// <param name="table">The table to decompile.</param> | ||
326 | private void DecompileComPlusApplicationTable(Table table) | ||
327 | { | ||
328 | foreach (Row row in table.Rows) | ||
329 | { | ||
330 | ComPlus.ComPlusApplication application = new ComPlus.ComPlusApplication(); | ||
331 | |||
332 | application.Id = (string)row[0]; | ||
333 | application.Partition = (string)row[1]; | ||
334 | |||
335 | if (null != row[3]) | ||
336 | { | ||
337 | application.ApplicationId = (string)row[3]; | ||
338 | } | ||
339 | |||
340 | if (null != row[4]) | ||
341 | { | ||
342 | application.Name = (string)row[4]; | ||
343 | } | ||
344 | |||
345 | if (null != row[2]) | ||
346 | { | ||
347 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); | ||
348 | if (null != component) | ||
349 | { | ||
350 | component.AddChild(application); | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
355 | } | ||
356 | } | ||
357 | else | ||
358 | { | ||
359 | this.Core.RootElement.AddChild(application); | ||
360 | } | ||
361 | this.Core.IndexElement(row, application); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | /// <summary> | ||
366 | /// Decompile the ComPlusApplicationProperty table. | ||
367 | /// </summary> | ||
368 | /// <param name="table">The table to decompile.</param> | ||
369 | private void DecompileComPlusApplicationPropertyTable(Table table) | ||
370 | { | ||
371 | foreach (Row row in table.Rows) | ||
372 | { | ||
373 | ComPlus.ComPlusApplication application = (ComPlus.ComPlusApplication)this.Core.GetIndexedElement("ComPlusApplication", (string)row[0]); | ||
374 | if (null == application) | ||
375 | { | ||
376 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Application_", (string)row[0], "ComPlusApplication")); | ||
377 | } | ||
378 | |||
379 | switch ((string)row[1]) | ||
380 | { | ||
381 | case "3GigSupportEnabled": | ||
382 | switch ((string)row[2]) | ||
383 | { | ||
384 | case "1": | ||
385 | application.ThreeGigSupportEnabled = ComPlus.YesNoType.yes; | ||
386 | break; | ||
387 | case "0": | ||
388 | application.ThreeGigSupportEnabled = ComPlus.YesNoType.no; | ||
389 | break; | ||
390 | default: | ||
391 | // TODO: Warning | ||
392 | break; | ||
393 | } | ||
394 | break; | ||
395 | case "AccessChecksLevel": | ||
396 | switch ((string)row[2]) | ||
397 | { | ||
398 | case "0": | ||
399 | application.AccessChecksLevel = ComPlus.ComPlusApplication.AccessChecksLevelType.applicationLevel; | ||
400 | break; | ||
401 | case "1": | ||
402 | application.AccessChecksLevel = ComPlus.ComPlusApplication.AccessChecksLevelType.applicationComponentLevel; | ||
403 | break; | ||
404 | default: | ||
405 | // TODO: Warning | ||
406 | break; | ||
407 | } | ||
408 | break; | ||
409 | case "Activation": | ||
410 | switch ((string)row[2]) | ||
411 | { | ||
412 | case "Inproc": | ||
413 | application.Activation = ComPlus.ComPlusApplication.ActivationType.inproc; | ||
414 | break; | ||
415 | case "Local": | ||
416 | application.Activation = ComPlus.ComPlusApplication.ActivationType.local; | ||
417 | break; | ||
418 | default: | ||
419 | // TODO: Warning | ||
420 | break; | ||
421 | } | ||
422 | break; | ||
423 | case "ApplicationAccessChecksEnabled": | ||
424 | switch ((string)row[2]) | ||
425 | { | ||
426 | case "1": | ||
427 | application.ApplicationAccessChecksEnabled = ComPlus.YesNoType.yes; | ||
428 | break; | ||
429 | case "0": | ||
430 | application.ApplicationAccessChecksEnabled = ComPlus.YesNoType.no; | ||
431 | break; | ||
432 | default: | ||
433 | // TODO: Warning | ||
434 | break; | ||
435 | } | ||
436 | break; | ||
437 | case "ApplicationDirectory": | ||
438 | application.ApplicationDirectory = (string)row[2]; | ||
439 | break; | ||
440 | case "Authentication": | ||
441 | switch ((string)row[2]) | ||
442 | { | ||
443 | case "0": | ||
444 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.@default; | ||
445 | break; | ||
446 | case "1": | ||
447 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.none; | ||
448 | break; | ||
449 | case "2": | ||
450 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.connect; | ||
451 | break; | ||
452 | case "3": | ||
453 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.call; | ||
454 | break; | ||
455 | case "4": | ||
456 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.packet; | ||
457 | break; | ||
458 | case "5": | ||
459 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.integrity; | ||
460 | break; | ||
461 | case "6": | ||
462 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.privacy; | ||
463 | break; | ||
464 | default: | ||
465 | // TODO: Warning | ||
466 | break; | ||
467 | } | ||
468 | break; | ||
469 | case "AuthenticationCapability": | ||
470 | switch ((string)row[2]) | ||
471 | { | ||
472 | case "0": | ||
473 | application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.none; | ||
474 | break; | ||
475 | case "2": | ||
476 | application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.secureReference; | ||
477 | break; | ||
478 | case "32": | ||
479 | application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.staticCloaking; | ||
480 | break; | ||
481 | case "64": | ||
482 | application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.dynamicCloaking; | ||
483 | break; | ||
484 | default: | ||
485 | // TODO: Warning | ||
486 | break; | ||
487 | } | ||
488 | break; | ||
489 | case "Changeable": | ||
490 | switch ((string)row[2]) | ||
491 | { | ||
492 | case "1": | ||
493 | application.Changeable = ComPlus.YesNoType.yes; | ||
494 | break; | ||
495 | case "0": | ||
496 | application.Changeable = ComPlus.YesNoType.no; | ||
497 | break; | ||
498 | default: | ||
499 | // TODO: Warning | ||
500 | break; | ||
501 | } | ||
502 | break; | ||
503 | case "CommandLine": | ||
504 | application.CommandLine = (string)row[2]; | ||
505 | break; | ||
506 | case "ConcurrentApps": | ||
507 | int concurrentApps; | ||
508 | if (Int32.TryParse((string)row[2], out concurrentApps)) | ||
509 | { | ||
510 | application.ConcurrentApps = concurrentApps; | ||
511 | } | ||
512 | else | ||
513 | { | ||
514 | // TODO: Warning | ||
515 | } | ||
516 | break; | ||
517 | case "CreatedBy": | ||
518 | application.CreatedBy = (string)row[2]; | ||
519 | break; | ||
520 | case "CRMEnabled": | ||
521 | switch ((string)row[2]) | ||
522 | { | ||
523 | case "1": | ||
524 | application.CRMEnabled = ComPlus.YesNoType.yes; | ||
525 | break; | ||
526 | case "0": | ||
527 | application.CRMEnabled = ComPlus.YesNoType.no; | ||
528 | break; | ||
529 | default: | ||
530 | // TODO: Warning | ||
531 | break; | ||
532 | } | ||
533 | break; | ||
534 | case "CRMLogFile": | ||
535 | application.CRMLogFile = (string)row[2]; | ||
536 | break; | ||
537 | case "Deleteable": | ||
538 | switch ((string)row[2]) | ||
539 | { | ||
540 | case "1": | ||
541 | application.Deleteable = ComPlus.YesNoType.yes; | ||
542 | break; | ||
543 | case "0": | ||
544 | application.Deleteable = ComPlus.YesNoType.no; | ||
545 | break; | ||
546 | default: | ||
547 | // TODO: Warning | ||
548 | break; | ||
549 | } | ||
550 | break; | ||
551 | case "Description": | ||
552 | application.Description = (string)row[2]; | ||
553 | break; | ||
554 | case "DumpEnabled": | ||
555 | switch ((string)row[2]) | ||
556 | { | ||
557 | case "1": | ||
558 | application.DumpEnabled = ComPlus.YesNoType.yes; | ||
559 | break; | ||
560 | case "0": | ||
561 | application.DumpEnabled = ComPlus.YesNoType.no; | ||
562 | break; | ||
563 | default: | ||
564 | // TODO: Warning | ||
565 | break; | ||
566 | } | ||
567 | break; | ||
568 | case "DumpOnException": | ||
569 | switch ((string)row[2]) | ||
570 | { | ||
571 | case "1": | ||
572 | application.DumpOnException = ComPlus.YesNoType.yes; | ||
573 | break; | ||
574 | case "0": | ||
575 | application.DumpOnException = ComPlus.YesNoType.no; | ||
576 | break; | ||
577 | default: | ||
578 | // TODO: Warning | ||
579 | break; | ||
580 | } | ||
581 | break; | ||
582 | case "DumpOnFailfast": | ||
583 | switch ((string)row[2]) | ||
584 | { | ||
585 | case "1": | ||
586 | application.DumpOnFailfast = ComPlus.YesNoType.yes; | ||
587 | break; | ||
588 | case "0": | ||
589 | application.DumpOnFailfast = ComPlus.YesNoType.no; | ||
590 | break; | ||
591 | default: | ||
592 | // TODO: Warning | ||
593 | break; | ||
594 | } | ||
595 | break; | ||
596 | case "DumpPath": | ||
597 | application.DumpPath = (string)row[2]; | ||
598 | break; | ||
599 | case "EventsEnabled": | ||
600 | switch ((string)row[2]) | ||
601 | { | ||
602 | case "1": | ||
603 | application.EventsEnabled = ComPlus.YesNoType.yes; | ||
604 | break; | ||
605 | case "0": | ||
606 | application.EventsEnabled = ComPlus.YesNoType.no; | ||
607 | break; | ||
608 | default: | ||
609 | // TODO: Warning | ||
610 | break; | ||
611 | } | ||
612 | break; | ||
613 | case "Identity": | ||
614 | application.Identity = (string)row[2]; | ||
615 | break; | ||
616 | case "ImpersonationLevel": | ||
617 | switch ((string)row[2]) | ||
618 | { | ||
619 | case "1": | ||
620 | application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.anonymous; | ||
621 | break; | ||
622 | case "2": | ||
623 | application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.identify; | ||
624 | break; | ||
625 | case "3": | ||
626 | application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.impersonate; | ||
627 | break; | ||
628 | case "4": | ||
629 | application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.@delegate; | ||
630 | break; | ||
631 | default: | ||
632 | // TODO: Warning | ||
633 | break; | ||
634 | } | ||
635 | break; | ||
636 | case "IsEnabled": | ||
637 | switch ((string)row[2]) | ||
638 | { | ||
639 | case "1": | ||
640 | application.IsEnabled = ComPlus.YesNoType.yes; | ||
641 | break; | ||
642 | case "0": | ||
643 | application.IsEnabled = ComPlus.YesNoType.no; | ||
644 | break; | ||
645 | default: | ||
646 | // TODO: Warning | ||
647 | break; | ||
648 | } | ||
649 | break; | ||
650 | case "MaxDumpCount": | ||
651 | int maxDumpCount; | ||
652 | if (Int32.TryParse((string)row[2], out maxDumpCount)) | ||
653 | { | ||
654 | application.MaxDumpCount = maxDumpCount; | ||
655 | } | ||
656 | else | ||
657 | { | ||
658 | // TODO: Warning | ||
659 | } | ||
660 | break; | ||
661 | case "Password": | ||
662 | application.Password = (string)row[2]; | ||
663 | break; | ||
664 | case "QCAuthenticateMsgs": | ||
665 | switch ((string)row[2]) | ||
666 | { | ||
667 | case "0": | ||
668 | application.QCAuthenticateMsgs = ComPlus.ComPlusApplication.QCAuthenticateMsgsType.secureApps; | ||
669 | break; | ||
670 | case "1": | ||
671 | application.QCAuthenticateMsgs = ComPlus.ComPlusApplication.QCAuthenticateMsgsType.off; | ||
672 | break; | ||
673 | case "2": | ||
674 | application.QCAuthenticateMsgs = ComPlus.ComPlusApplication.QCAuthenticateMsgsType.on; | ||
675 | break; | ||
676 | default: | ||
677 | // TODO: Warning | ||
678 | break; | ||
679 | } | ||
680 | break; | ||
681 | case "QCListenerMaxThreads": | ||
682 | int qcListenerMaxThreads; | ||
683 | if (Int32.TryParse((string)row[2], out qcListenerMaxThreads)) | ||
684 | { | ||
685 | application.QCListenerMaxThreads = qcListenerMaxThreads; | ||
686 | } | ||
687 | else | ||
688 | { | ||
689 | // TODO: Warning | ||
690 | } | ||
691 | break; | ||
692 | case "QueueListenerEnabled": | ||
693 | switch ((string)row[2]) | ||
694 | { | ||
695 | case "1": | ||
696 | application.QueueListenerEnabled = ComPlus.YesNoType.yes; | ||
697 | break; | ||
698 | case "0": | ||
699 | application.QueueListenerEnabled = ComPlus.YesNoType.no; | ||
700 | break; | ||
701 | default: | ||
702 | // TODO: Warning | ||
703 | break; | ||
704 | } | ||
705 | break; | ||
706 | case "QueuingEnabled": | ||
707 | switch ((string)row[2]) | ||
708 | { | ||
709 | case "1": | ||
710 | application.QueuingEnabled = ComPlus.YesNoType.yes; | ||
711 | break; | ||
712 | case "0": | ||
713 | application.QueuingEnabled = ComPlus.YesNoType.no; | ||
714 | break; | ||
715 | default: | ||
716 | // TODO: Warning | ||
717 | break; | ||
718 | } | ||
719 | break; | ||
720 | case "RecycleActivationLimit": | ||
721 | int recycleActivationLimit; | ||
722 | if (Int32.TryParse((string)row[2], out recycleActivationLimit)) | ||
723 | { | ||
724 | application.RecycleActivationLimit = recycleActivationLimit; | ||
725 | } | ||
726 | else | ||
727 | { | ||
728 | // TODO: Warning | ||
729 | } | ||
730 | break; | ||
731 | case "RecycleCallLimit": | ||
732 | int recycleCallLimit; | ||
733 | if (Int32.TryParse((string)row[2], out recycleCallLimit)) | ||
734 | { | ||
735 | application.RecycleCallLimit = recycleCallLimit; | ||
736 | } | ||
737 | else | ||
738 | { | ||
739 | // TODO: Warning | ||
740 | } | ||
741 | break; | ||
742 | case "RecycleExpirationTimeout": | ||
743 | int recycleExpirationTimeout; | ||
744 | if (Int32.TryParse((string)row[2], out recycleExpirationTimeout)) | ||
745 | { | ||
746 | application.RecycleExpirationTimeout = recycleExpirationTimeout; | ||
747 | } | ||
748 | else | ||
749 | { | ||
750 | // TODO: Warning | ||
751 | } | ||
752 | break; | ||
753 | case "RecycleLifetimeLimit": | ||
754 | int recycleLifetimeLimit; | ||
755 | if (Int32.TryParse((string)row[2], out recycleLifetimeLimit)) | ||
756 | { | ||
757 | application.RecycleLifetimeLimit = recycleLifetimeLimit; | ||
758 | } | ||
759 | else | ||
760 | { | ||
761 | // TODO: Warning | ||
762 | } | ||
763 | break; | ||
764 | case "RecycleMemoryLimit": | ||
765 | int recycleMemoryLimit; | ||
766 | if (Int32.TryParse((string)row[2], out recycleMemoryLimit)) | ||
767 | { | ||
768 | application.RecycleMemoryLimit = recycleMemoryLimit; | ||
769 | } | ||
770 | else | ||
771 | { | ||
772 | // TODO: Warning | ||
773 | } | ||
774 | break; | ||
775 | case "Replicable": | ||
776 | switch ((string)row[2]) | ||
777 | { | ||
778 | case "1": | ||
779 | application.Replicable = ComPlus.YesNoType.yes; | ||
780 | break; | ||
781 | case "0": | ||
782 | application.Replicable = ComPlus.YesNoType.no; | ||
783 | break; | ||
784 | default: | ||
785 | // TODO: Warning | ||
786 | break; | ||
787 | } | ||
788 | break; | ||
789 | case "RunForever": | ||
790 | switch ((string)row[2]) | ||
791 | { | ||
792 | case "1": | ||
793 | application.RunForever = ComPlus.YesNoType.yes; | ||
794 | break; | ||
795 | case "0": | ||
796 | application.RunForever = ComPlus.YesNoType.no; | ||
797 | break; | ||
798 | default: | ||
799 | // TODO: Warning | ||
800 | break; | ||
801 | } | ||
802 | break; | ||
803 | case "ShutdownAfter": | ||
804 | int shutdownAfter; | ||
805 | if (Int32.TryParse((string)row[2], out shutdownAfter)) | ||
806 | { | ||
807 | application.ShutdownAfter = shutdownAfter; | ||
808 | } | ||
809 | else | ||
810 | { | ||
811 | // TODO: Warning | ||
812 | } | ||
813 | break; | ||
814 | case "SoapActivated": | ||
815 | switch ((string)row[2]) | ||
816 | { | ||
817 | case "1": | ||
818 | application.SoapActivated = ComPlus.YesNoType.yes; | ||
819 | break; | ||
820 | case "0": | ||
821 | application.SoapActivated = ComPlus.YesNoType.no; | ||
822 | break; | ||
823 | default: | ||
824 | // TODO: Warning | ||
825 | break; | ||
826 | } | ||
827 | break; | ||
828 | case "SoapBaseUrl": | ||
829 | application.SoapBaseUrl = (string)row[2]; | ||
830 | break; | ||
831 | case "SoapMailTo": | ||
832 | application.SoapMailTo = (string)row[2]; | ||
833 | break; | ||
834 | case "SoapVRoot": | ||
835 | application.SoapVRoot = (string)row[2]; | ||
836 | break; | ||
837 | case "SRPEnabled": | ||
838 | switch ((string)row[2]) | ||
839 | { | ||
840 | case "1": | ||
841 | application.SRPEnabled = ComPlus.YesNoType.yes; | ||
842 | break; | ||
843 | case "0": | ||
844 | application.SRPEnabled = ComPlus.YesNoType.no; | ||
845 | break; | ||
846 | default: | ||
847 | // TODO: Warning | ||
848 | break; | ||
849 | } | ||
850 | break; | ||
851 | case "SRPTrustLevel": | ||
852 | switch ((string)row[2]) | ||
853 | { | ||
854 | case "0": | ||
855 | application.SRPTrustLevel = ComPlus.ComPlusApplication.SRPTrustLevelType.disallowed; | ||
856 | break; | ||
857 | case "262144": | ||
858 | application.SRPTrustLevel = ComPlus.ComPlusApplication.SRPTrustLevelType.fullyTrusted; | ||
859 | break; | ||
860 | default: | ||
861 | // TODO: Warning | ||
862 | break; | ||
863 | } | ||
864 | break; | ||
865 | default: | ||
866 | // TODO: Warning | ||
867 | break; | ||
868 | } | ||
869 | } | ||
870 | } | ||
871 | |||
872 | /// <summary> | ||
873 | /// Decompile the ComPlusApplicationRole table. | ||
874 | /// </summary> | ||
875 | /// <param name="table">The table to decompile.</param> | ||
876 | private void DecompileComPlusApplicationRoleTable(Table table) | ||
877 | { | ||
878 | foreach (Row row in table.Rows) | ||
879 | { | ||
880 | ComPlus.ComPlusApplicationRole applicationRole = new ComPlus.ComPlusApplicationRole(); | ||
881 | |||
882 | applicationRole.Id = (string)row[0]; | ||
883 | applicationRole.Application = (string)row[1]; | ||
884 | |||
885 | if (null != row[3]) | ||
886 | { | ||
887 | applicationRole.Name = (string)row[3]; | ||
888 | } | ||
889 | |||
890 | if (null != row[2]) | ||
891 | { | ||
892 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
893 | if (null != component) | ||
894 | { | ||
895 | component.AddChild(applicationRole); | ||
896 | } | ||
897 | else | ||
898 | { | ||
899 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
900 | } | ||
901 | } | ||
902 | else | ||
903 | { | ||
904 | this.Core.RootElement.AddChild(applicationRole); | ||
905 | } | ||
906 | this.Core.IndexElement(row, applicationRole); | ||
907 | } | ||
908 | } | ||
909 | |||
910 | /// <summary> | ||
911 | /// Decompile the ComPlusApplicationRoleProperty table. | ||
912 | /// </summary> | ||
913 | /// <param name="table">The table to decompile.</param> | ||
914 | private void DecompileComPlusApplicationRolePropertyTable(Table table) | ||
915 | { | ||
916 | foreach (Row row in table.Rows) | ||
917 | { | ||
918 | ComPlus.ComPlusApplicationRole applicationRole = (ComPlus.ComPlusApplicationRole)this.Core.GetIndexedElement("ComPlusApplicationRole", (string)row[0]); | ||
919 | if (null == applicationRole) | ||
920 | { | ||
921 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ApplicationRole_", (string)row[0], "ComPlusApplicationRole")); | ||
922 | } | ||
923 | |||
924 | switch ((string)row[1]) | ||
925 | { | ||
926 | case "Description": | ||
927 | applicationRole.Description = (string)row[2]; | ||
928 | break; | ||
929 | default: | ||
930 | // TODO: Warning | ||
931 | break; | ||
932 | } | ||
933 | } | ||
934 | } | ||
935 | |||
936 | /// <summary> | ||
937 | /// Decompile the ComPlusUserInApplicationRole table. | ||
938 | /// </summary> | ||
939 | /// <param name="table">The table to decompile.</param> | ||
940 | private void DecompileComPlusUserInApplicationRoleTable(Table table) | ||
941 | { | ||
942 | foreach (Row row in table.Rows) | ||
943 | { | ||
944 | ComPlus.ComPlusUserInApplicationRole userInApplicationRole = new ComPlus.ComPlusUserInApplicationRole(); | ||
945 | |||
946 | userInApplicationRole.Id = (string)row[0]; | ||
947 | userInApplicationRole.ApplicationRole = (string)row[1]; | ||
948 | userInApplicationRole.User = (string)row[3]; | ||
949 | |||
950 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
951 | if (null != component) | ||
952 | { | ||
953 | component.AddChild(userInApplicationRole); | ||
954 | } | ||
955 | else | ||
956 | { | ||
957 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
958 | } | ||
959 | } | ||
960 | } | ||
961 | |||
962 | /// <summary> | ||
963 | /// Decompile the ComPlusGroupInApplicationRole table. | ||
964 | /// </summary> | ||
965 | /// <param name="table">The table to decompile.</param> | ||
966 | private void DecompileComPlusGroupInApplicationRoleTable(Table table) | ||
967 | { | ||
968 | foreach (Row row in table.Rows) | ||
969 | { | ||
970 | ComPlus.ComPlusGroupInApplicationRole groupInApplicationRole = new ComPlus.ComPlusGroupInApplicationRole(); | ||
971 | |||
972 | groupInApplicationRole.Id = (string)row[0]; | ||
973 | groupInApplicationRole.ApplicationRole = (string)row[1]; | ||
974 | groupInApplicationRole.Group = (string)row[3]; | ||
975 | |||
976 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
977 | if (null != component) | ||
978 | { | ||
979 | component.AddChild(groupInApplicationRole); | ||
980 | } | ||
981 | else | ||
982 | { | ||
983 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
984 | } | ||
985 | } | ||
986 | } | ||
987 | |||
988 | /// <summary> | ||
989 | /// Decompile the ComPlusAssembly table. | ||
990 | /// </summary> | ||
991 | /// <param name="table">The table to decompile.</param> | ||
992 | private void DecompileComPlusAssemblyTable(Table table) | ||
993 | { | ||
994 | foreach (Row row in table.Rows) | ||
995 | { | ||
996 | ComPlus.ComPlusAssembly assembly = new ComPlus.ComPlusAssembly(); | ||
997 | |||
998 | assembly.Id = (string)row[0]; | ||
999 | assembly.Application = (string)row[1]; | ||
1000 | |||
1001 | if (null != row[3]) | ||
1002 | { | ||
1003 | assembly.AssemblyName = (string)row[3]; | ||
1004 | } | ||
1005 | |||
1006 | if (null != row[4]) | ||
1007 | { | ||
1008 | assembly.DllPath = (string)row[4]; | ||
1009 | } | ||
1010 | |||
1011 | if (null != row[5]) | ||
1012 | { | ||
1013 | assembly.TlbPath = (string)row[5]; | ||
1014 | } | ||
1015 | |||
1016 | if (null != row[6]) | ||
1017 | { | ||
1018 | assembly.PSDllPath = (string)row[6]; | ||
1019 | } | ||
1020 | |||
1021 | int attributes = (int)row[7]; | ||
1022 | |||
1023 | if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.EventClass)) | ||
1024 | { | ||
1025 | assembly.EventClass = ComPlus.YesNoType.yes; | ||
1026 | } | ||
1027 | |||
1028 | if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.DotNetAssembly)) | ||
1029 | { | ||
1030 | assembly.Type = ComPlus.ComPlusAssembly.TypeType.net; | ||
1031 | } | ||
1032 | |||
1033 | if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.DllPathFromGAC)) | ||
1034 | { | ||
1035 | assembly.DllPathFromGAC = ComPlus.YesNoType.yes; | ||
1036 | } | ||
1037 | |||
1038 | if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.RegisterInCommit)) | ||
1039 | { | ||
1040 | assembly.RegisterInCommit = ComPlus.YesNoType.yes; | ||
1041 | } | ||
1042 | |||
1043 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
1044 | if (null != component) | ||
1045 | { | ||
1046 | component.AddChild(assembly); | ||
1047 | } | ||
1048 | else | ||
1049 | { | ||
1050 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
1051 | } | ||
1052 | this.Core.IndexElement(row, assembly); | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | /// <summary> | ||
1057 | /// Decompile the ComPlusAssemblyDependency table. | ||
1058 | /// </summary> | ||
1059 | /// <param name="table">The table to decompile.</param> | ||
1060 | private void DecompileComPlusAssemblyDependencyTable(Table table) | ||
1061 | { | ||
1062 | foreach (Row row in table.Rows) | ||
1063 | { | ||
1064 | ComPlus.ComPlusAssemblyDependency assemblyDependency = new ComPlus.ComPlusAssemblyDependency(); | ||
1065 | |||
1066 | assemblyDependency.RequiredAssembly = (string)row[1]; | ||
1067 | |||
1068 | ComPlus.ComPlusAssembly assembly = (ComPlus.ComPlusAssembly)this.Core.GetIndexedElement("ComPlusAssembly", (string)row[0]); | ||
1069 | if (null != assembly) | ||
1070 | { | ||
1071 | assembly.AddChild(assemblyDependency); | ||
1072 | } | ||
1073 | else | ||
1074 | { | ||
1075 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Assembly_", (string)row[0], "ComPlusAssembly")); | ||
1076 | } | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1080 | /// <summary> | ||
1081 | /// Decompile the ComPlusComponent table. | ||
1082 | /// </summary> | ||
1083 | /// <param name="table">The table to decompile.</param> | ||
1084 | private void DecompileComPlusComponentTable(Table table) | ||
1085 | { | ||
1086 | foreach (Row row in table.Rows) | ||
1087 | { | ||
1088 | ComPlus.ComPlusComponent comPlusComponent = new ComPlus.ComPlusComponent(); | ||
1089 | |||
1090 | comPlusComponent.Id = (string)row[0]; | ||
1091 | |||
1092 | try | ||
1093 | { | ||
1094 | Guid clsid = new Guid((string)row[2]); | ||
1095 | comPlusComponent.CLSID = clsid.ToString().ToUpper(); | ||
1096 | } | ||
1097 | catch | ||
1098 | { | ||
1099 | // TODO: Warning | ||
1100 | } | ||
1101 | |||
1102 | ComPlus.ComPlusAssembly assembly = (ComPlus.ComPlusAssembly)this.Core.GetIndexedElement("ComPlusAssembly", (string)row[1]); | ||
1103 | if (null != assembly) | ||
1104 | { | ||
1105 | assembly.AddChild(comPlusComponent); | ||
1106 | } | ||
1107 | else | ||
1108 | { | ||
1109 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Assembly_", (string)row[1], "ComPlusAssembly")); | ||
1110 | } | ||
1111 | this.Core.IndexElement(row, comPlusComponent); | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | /// <summary> | ||
1116 | /// Decompile the ComPlusComponentProperty table. | ||
1117 | /// </summary> | ||
1118 | /// <param name="table">The table to decompile.</param> | ||
1119 | private void DecompileComPlusComponentPropertyTable(Table table) | ||
1120 | { | ||
1121 | foreach (Row row in table.Rows) | ||
1122 | { | ||
1123 | ComPlus.ComPlusComponent comPlusComponent = (ComPlus.ComPlusComponent)this.Core.GetIndexedElement("ComPlusComponent", (string)row[0]); | ||
1124 | if (null == comPlusComponent) | ||
1125 | { | ||
1126 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ComPlusComponent_", (string)row[0], "ComPlusComponent")); | ||
1127 | } | ||
1128 | |||
1129 | switch ((string)row[1]) | ||
1130 | { | ||
1131 | case "AllowInprocSubscribers": | ||
1132 | switch ((string)row[2]) | ||
1133 | { | ||
1134 | case "1": | ||
1135 | comPlusComponent.AllowInprocSubscribers = ComPlus.YesNoType.yes; | ||
1136 | break; | ||
1137 | case "0": | ||
1138 | comPlusComponent.AllowInprocSubscribers = ComPlus.YesNoType.no; | ||
1139 | break; | ||
1140 | default: | ||
1141 | // TODO: Warning | ||
1142 | break; | ||
1143 | } | ||
1144 | break; | ||
1145 | case "ComponentAccessChecksEnabled": | ||
1146 | switch ((string)row[2]) | ||
1147 | { | ||
1148 | case "1": | ||
1149 | comPlusComponent.ComponentAccessChecksEnabled = ComPlus.YesNoType.yes; | ||
1150 | break; | ||
1151 | case "0": | ||
1152 | comPlusComponent.ComponentAccessChecksEnabled = ComPlus.YesNoType.no; | ||
1153 | break; | ||
1154 | default: | ||
1155 | // TODO: Warning | ||
1156 | break; | ||
1157 | } | ||
1158 | break; | ||
1159 | case "ComponentTransactionTimeout": | ||
1160 | int componentTransactionTimeout; | ||
1161 | if (Int32.TryParse((string)row[2], out componentTransactionTimeout)) | ||
1162 | { | ||
1163 | comPlusComponent.ComponentTransactionTimeout = componentTransactionTimeout; | ||
1164 | } | ||
1165 | else | ||
1166 | { | ||
1167 | // TODO: Warning | ||
1168 | } | ||
1169 | break; | ||
1170 | case "ComponentTransactionTimeoutEnabled": | ||
1171 | switch ((string)row[2]) | ||
1172 | { | ||
1173 | case "1": | ||
1174 | comPlusComponent.ComponentTransactionTimeoutEnabled = ComPlus.YesNoType.yes; | ||
1175 | break; | ||
1176 | case "0": | ||
1177 | comPlusComponent.ComponentTransactionTimeoutEnabled = ComPlus.YesNoType.no; | ||
1178 | break; | ||
1179 | default: | ||
1180 | // TODO: Warning | ||
1181 | break; | ||
1182 | } | ||
1183 | break; | ||
1184 | case "COMTIIntrinsics": | ||
1185 | switch ((string)row[2]) | ||
1186 | { | ||
1187 | case "1": | ||
1188 | comPlusComponent.COMTIIntrinsics = ComPlus.YesNoType.yes; | ||
1189 | break; | ||
1190 | case "0": | ||
1191 | comPlusComponent.COMTIIntrinsics = ComPlus.YesNoType.no; | ||
1192 | break; | ||
1193 | default: | ||
1194 | // TODO: Warning | ||
1195 | break; | ||
1196 | } | ||
1197 | break; | ||
1198 | case "ConstructionEnabled": | ||
1199 | switch ((string)row[2]) | ||
1200 | { | ||
1201 | case "1": | ||
1202 | comPlusComponent.ConstructionEnabled = ComPlus.YesNoType.yes; | ||
1203 | break; | ||
1204 | case "0": | ||
1205 | comPlusComponent.ConstructionEnabled = ComPlus.YesNoType.no; | ||
1206 | break; | ||
1207 | default: | ||
1208 | // TODO: Warning | ||
1209 | break; | ||
1210 | } | ||
1211 | break; | ||
1212 | case "ConstructorString": | ||
1213 | comPlusComponent.ConstructorString = (string)row[2]; | ||
1214 | break; | ||
1215 | case "CreationTimeout": | ||
1216 | int creationTimeout; | ||
1217 | if (Int32.TryParse((string)row[2], out creationTimeout)) | ||
1218 | { | ||
1219 | comPlusComponent.CreationTimeout = creationTimeout; | ||
1220 | } | ||
1221 | else | ||
1222 | { | ||
1223 | // TODO: Warning | ||
1224 | } | ||
1225 | break; | ||
1226 | case "Description": | ||
1227 | comPlusComponent.Description = (string)row[2]; | ||
1228 | break; | ||
1229 | case "EventTrackingEnabled": | ||
1230 | switch ((string)row[2]) | ||
1231 | { | ||
1232 | case "1": | ||
1233 | comPlusComponent.EventTrackingEnabled = ComPlus.YesNoType.yes; | ||
1234 | break; | ||
1235 | case "0": | ||
1236 | comPlusComponent.EventTrackingEnabled = ComPlus.YesNoType.no; | ||
1237 | break; | ||
1238 | default: | ||
1239 | // TODO: Warning | ||
1240 | break; | ||
1241 | } | ||
1242 | break; | ||
1243 | case "ExceptionClass": | ||
1244 | comPlusComponent.ExceptionClass = (string)row[2]; | ||
1245 | break; | ||
1246 | case "FireInParallel": | ||
1247 | switch ((string)row[2]) | ||
1248 | { | ||
1249 | case "1": | ||
1250 | comPlusComponent.FireInParallel = ComPlus.YesNoType.yes; | ||
1251 | break; | ||
1252 | case "0": | ||
1253 | comPlusComponent.FireInParallel = ComPlus.YesNoType.no; | ||
1254 | break; | ||
1255 | default: | ||
1256 | // TODO: Warning | ||
1257 | break; | ||
1258 | } | ||
1259 | break; | ||
1260 | case "IISIntrinsics": | ||
1261 | switch ((string)row[2]) | ||
1262 | { | ||
1263 | case "1": | ||
1264 | comPlusComponent.IISIntrinsics = ComPlus.YesNoType.yes; | ||
1265 | break; | ||
1266 | case "0": | ||
1267 | comPlusComponent.IISIntrinsics = ComPlus.YesNoType.no; | ||
1268 | break; | ||
1269 | default: | ||
1270 | // TODO: Warning | ||
1271 | break; | ||
1272 | } | ||
1273 | break; | ||
1274 | case "InitializesServerApplication": | ||
1275 | switch ((string)row[2]) | ||
1276 | { | ||
1277 | case "1": | ||
1278 | comPlusComponent.InitializesServerApplication = ComPlus.YesNoType.yes; | ||
1279 | break; | ||
1280 | case "0": | ||
1281 | comPlusComponent.InitializesServerApplication = ComPlus.YesNoType.no; | ||
1282 | break; | ||
1283 | default: | ||
1284 | // TODO: Warning | ||
1285 | break; | ||
1286 | } | ||
1287 | break; | ||
1288 | case "IsEnabled": | ||
1289 | switch ((string)row[2]) | ||
1290 | { | ||
1291 | case "1": | ||
1292 | comPlusComponent.IsEnabled = ComPlus.YesNoType.yes; | ||
1293 | break; | ||
1294 | case "0": | ||
1295 | comPlusComponent.IsEnabled = ComPlus.YesNoType.no; | ||
1296 | break; | ||
1297 | default: | ||
1298 | // TODO: Warning | ||
1299 | break; | ||
1300 | } | ||
1301 | break; | ||
1302 | case "IsPrivateComponent": | ||
1303 | switch ((string)row[2]) | ||
1304 | { | ||
1305 | case "1": | ||
1306 | comPlusComponent.IsPrivateComponent = ComPlus.YesNoType.yes; | ||
1307 | break; | ||
1308 | case "0": | ||
1309 | comPlusComponent.IsPrivateComponent = ComPlus.YesNoType.no; | ||
1310 | break; | ||
1311 | default: | ||
1312 | // TODO: Warning | ||
1313 | break; | ||
1314 | } | ||
1315 | break; | ||
1316 | case "JustInTimeActivation": | ||
1317 | switch ((string)row[2]) | ||
1318 | { | ||
1319 | case "1": | ||
1320 | comPlusComponent.JustInTimeActivation = ComPlus.YesNoType.yes; | ||
1321 | break; | ||
1322 | case "0": | ||
1323 | comPlusComponent.JustInTimeActivation = ComPlus.YesNoType.no; | ||
1324 | break; | ||
1325 | default: | ||
1326 | // TODO: Warning | ||
1327 | break; | ||
1328 | } | ||
1329 | break; | ||
1330 | case "LoadBalancingSupported": | ||
1331 | switch ((string)row[2]) | ||
1332 | { | ||
1333 | case "1": | ||
1334 | comPlusComponent.LoadBalancingSupported = ComPlus.YesNoType.yes; | ||
1335 | break; | ||
1336 | case "0": | ||
1337 | comPlusComponent.LoadBalancingSupported = ComPlus.YesNoType.no; | ||
1338 | break; | ||
1339 | default: | ||
1340 | // TODO: Warning | ||
1341 | break; | ||
1342 | } | ||
1343 | break; | ||
1344 | case "MaxPoolSize": | ||
1345 | int maxPoolSize; | ||
1346 | if (Int32.TryParse((string)row[2], out maxPoolSize)) | ||
1347 | { | ||
1348 | comPlusComponent.MaxPoolSize = maxPoolSize; | ||
1349 | } | ||
1350 | else | ||
1351 | { | ||
1352 | // TODO: Warning | ||
1353 | } | ||
1354 | break; | ||
1355 | case "MinPoolSize": | ||
1356 | int minPoolSize; | ||
1357 | if (Int32.TryParse((string)row[2], out minPoolSize)) | ||
1358 | { | ||
1359 | comPlusComponent.MinPoolSize = minPoolSize; | ||
1360 | } | ||
1361 | else | ||
1362 | { | ||
1363 | // TODO: Warning | ||
1364 | } | ||
1365 | break; | ||
1366 | case "MultiInterfacePublisherFilterCLSID": | ||
1367 | comPlusComponent.MultiInterfacePublisherFilterCLSID = (string)row[2]; | ||
1368 | break; | ||
1369 | case "MustRunInClientContext": | ||
1370 | switch ((string)row[2]) | ||
1371 | { | ||
1372 | case "1": | ||
1373 | comPlusComponent.MustRunInClientContext = ComPlus.YesNoType.yes; | ||
1374 | break; | ||
1375 | case "0": | ||
1376 | comPlusComponent.MustRunInClientContext = ComPlus.YesNoType.no; | ||
1377 | break; | ||
1378 | default: | ||
1379 | // TODO: Warning | ||
1380 | break; | ||
1381 | } | ||
1382 | break; | ||
1383 | case "MustRunInDefaultContext": | ||
1384 | switch ((string)row[2]) | ||
1385 | { | ||
1386 | case "1": | ||
1387 | comPlusComponent.MustRunInDefaultContext = ComPlus.YesNoType.yes; | ||
1388 | break; | ||
1389 | case "0": | ||
1390 | comPlusComponent.MustRunInDefaultContext = ComPlus.YesNoType.no; | ||
1391 | break; | ||
1392 | default: | ||
1393 | // TODO: Warning | ||
1394 | break; | ||
1395 | } | ||
1396 | break; | ||
1397 | case "ObjectPoolingEnabled": | ||
1398 | switch ((string)row[2]) | ||
1399 | { | ||
1400 | case "1": | ||
1401 | comPlusComponent.ObjectPoolingEnabled = ComPlus.YesNoType.yes; | ||
1402 | break; | ||
1403 | case "0": | ||
1404 | comPlusComponent.ObjectPoolingEnabled = ComPlus.YesNoType.no; | ||
1405 | break; | ||
1406 | default: | ||
1407 | // TODO: Warning | ||
1408 | break; | ||
1409 | } | ||
1410 | break; | ||
1411 | case "PublisherID": | ||
1412 | comPlusComponent.PublisherID = (string)row[2]; | ||
1413 | break; | ||
1414 | case "SoapAssemblyName": | ||
1415 | comPlusComponent.SoapAssemblyName = (string)row[2]; | ||
1416 | break; | ||
1417 | case "SoapTypeName": | ||
1418 | comPlusComponent.SoapTypeName = (string)row[2]; | ||
1419 | break; | ||
1420 | case "Synchronization": | ||
1421 | switch ((string)row[2]) | ||
1422 | { | ||
1423 | case "0": | ||
1424 | comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.ignored; | ||
1425 | break; | ||
1426 | case "1": | ||
1427 | comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.none; | ||
1428 | break; | ||
1429 | case "2": | ||
1430 | comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.supported; | ||
1431 | break; | ||
1432 | case "3": | ||
1433 | comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.required; | ||
1434 | break; | ||
1435 | case "4": | ||
1436 | comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.requiresNew; | ||
1437 | break; | ||
1438 | default: | ||
1439 | // TODO: Warning | ||
1440 | break; | ||
1441 | } | ||
1442 | break; | ||
1443 | case "Transaction": | ||
1444 | switch ((string)row[2]) | ||
1445 | { | ||
1446 | case "0": | ||
1447 | comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.ignored; | ||
1448 | break; | ||
1449 | case "1": | ||
1450 | comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.none; | ||
1451 | break; | ||
1452 | case "2": | ||
1453 | comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.supported; | ||
1454 | break; | ||
1455 | case "3": | ||
1456 | comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.required; | ||
1457 | break; | ||
1458 | case "4": | ||
1459 | comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.requiresNew; | ||
1460 | break; | ||
1461 | default: | ||
1462 | // TODO: Warning | ||
1463 | break; | ||
1464 | } | ||
1465 | break; | ||
1466 | case "TxIsolationLevel": | ||
1467 | switch ((string)row[2]) | ||
1468 | { | ||
1469 | case "0": | ||
1470 | comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.any; | ||
1471 | break; | ||
1472 | case "1": | ||
1473 | comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.readUnCommitted; | ||
1474 | break; | ||
1475 | case "2": | ||
1476 | comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.readCommitted; | ||
1477 | break; | ||
1478 | case "3": | ||
1479 | comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.repeatableRead; | ||
1480 | break; | ||
1481 | case "4": | ||
1482 | comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.serializable; | ||
1483 | break; | ||
1484 | default: | ||
1485 | // TODO: Warning | ||
1486 | break; | ||
1487 | } | ||
1488 | break; | ||
1489 | default: | ||
1490 | // TODO: Warning | ||
1491 | break; | ||
1492 | } | ||
1493 | } | ||
1494 | } | ||
1495 | |||
1496 | /// <summary> | ||
1497 | /// Decompile the ComPlusRoleForComponent table. | ||
1498 | /// </summary> | ||
1499 | /// <param name="table">The table to decompile.</param> | ||
1500 | private void DecompileComPlusRoleForComponentTable(Table table) | ||
1501 | { | ||
1502 | foreach (Row row in table.Rows) | ||
1503 | { | ||
1504 | ComPlus.ComPlusRoleForComponent roleForComponent = new ComPlus.ComPlusRoleForComponent(); | ||
1505 | |||
1506 | roleForComponent.Id = (string)row[0]; | ||
1507 | roleForComponent.Component = (string)row[1]; | ||
1508 | roleForComponent.ApplicationRole = (string)row[2]; | ||
1509 | |||
1510 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[3]); | ||
1511 | if (null != component) | ||
1512 | { | ||
1513 | component.AddChild(roleForComponent); | ||
1514 | } | ||
1515 | else | ||
1516 | { | ||
1517 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[3], "Component")); | ||
1518 | } | ||
1519 | } | ||
1520 | } | ||
1521 | |||
1522 | /// <summary> | ||
1523 | /// Decompile the ComPlusInterface table. | ||
1524 | /// </summary> | ||
1525 | /// <param name="table">The table to decompile.</param> | ||
1526 | private void DecompileComPlusInterfaceTable(Table table) | ||
1527 | { | ||
1528 | foreach (Row row in table.Rows) | ||
1529 | { | ||
1530 | ComPlus.ComPlusInterface comPlusInterface = new ComPlus.ComPlusInterface(); | ||
1531 | |||
1532 | comPlusInterface.Id = (string)row[0]; | ||
1533 | |||
1534 | try | ||
1535 | { | ||
1536 | Guid iid = new Guid((string)row[2]); | ||
1537 | comPlusInterface.IID = iid.ToString().ToUpper(); | ||
1538 | } | ||
1539 | catch | ||
1540 | { | ||
1541 | // TODO: Warning | ||
1542 | } | ||
1543 | |||
1544 | ComPlus.ComPlusComponent comPlusComponent = (ComPlus.ComPlusComponent)this.Core.GetIndexedElement("ComPlusComponent", (string)row[1]); | ||
1545 | if (null != comPlusComponent) | ||
1546 | { | ||
1547 | comPlusComponent.AddChild(comPlusInterface); | ||
1548 | } | ||
1549 | else | ||
1550 | { | ||
1551 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ComPlusComponent_", (string)row[1], "ComPlusComponent")); | ||
1552 | } | ||
1553 | this.Core.IndexElement(row, comPlusInterface); | ||
1554 | } | ||
1555 | } | ||
1556 | |||
1557 | /// <summary> | ||
1558 | /// Decompile the ComPlusInterfaceProperty table. | ||
1559 | /// </summary> | ||
1560 | /// <param name="table">The table to decompile.</param> | ||
1561 | private void DecompileComPlusInterfacePropertyTable(Table table) | ||
1562 | { | ||
1563 | foreach (Row row in table.Rows) | ||
1564 | { | ||
1565 | ComPlus.ComPlusInterface comPlusInterface = (ComPlus.ComPlusInterface)this.Core.GetIndexedElement("ComPlusInterface", (string)row[0]); | ||
1566 | if (null == comPlusInterface) | ||
1567 | { | ||
1568 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Interface_", (string)row[0], "ComPlusInterface")); | ||
1569 | } | ||
1570 | |||
1571 | switch ((string)row[1]) | ||
1572 | { | ||
1573 | case "Description": | ||
1574 | comPlusInterface.Description = (string)row[2]; | ||
1575 | break; | ||
1576 | case "QueuingEnabled": | ||
1577 | switch ((string)row[2]) | ||
1578 | { | ||
1579 | case "1": | ||
1580 | comPlusInterface.QueuingEnabled = ComPlus.YesNoType.yes; | ||
1581 | break; | ||
1582 | case "0": | ||
1583 | comPlusInterface.QueuingEnabled = ComPlus.YesNoType.no; | ||
1584 | break; | ||
1585 | default: | ||
1586 | // TODO: Warning | ||
1587 | break; | ||
1588 | } | ||
1589 | break; | ||
1590 | default: | ||
1591 | // TODO: Warning | ||
1592 | break; | ||
1593 | } | ||
1594 | } | ||
1595 | } | ||
1596 | |||
1597 | /// <summary> | ||
1598 | /// Decompile the ComPlusRoleForInterface table. | ||
1599 | /// </summary> | ||
1600 | /// <param name="table">The table to decompile.</param> | ||
1601 | private void DecompileComPlusRoleForInterfaceTable(Table table) | ||
1602 | { | ||
1603 | foreach (Row row in table.Rows) | ||
1604 | { | ||
1605 | ComPlus.ComPlusRoleForInterface roleForInterface = new ComPlus.ComPlusRoleForInterface(); | ||
1606 | |||
1607 | roleForInterface.Id = (string)row[0]; | ||
1608 | roleForInterface.Interface = (string)row[1]; | ||
1609 | roleForInterface.ApplicationRole = (string)row[2]; | ||
1610 | |||
1611 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[3]); | ||
1612 | if (null != component) | ||
1613 | { | ||
1614 | component.AddChild(roleForInterface); | ||
1615 | } | ||
1616 | else | ||
1617 | { | ||
1618 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[3], "Component")); | ||
1619 | } | ||
1620 | } | ||
1621 | } | ||
1622 | |||
1623 | /// <summary> | ||
1624 | /// Decompile the ComPlusMethod table. | ||
1625 | /// </summary> | ||
1626 | /// <param name="table">The table to decompile.</param> | ||
1627 | private void DecompileComPlusMethodTable(Table table) | ||
1628 | { | ||
1629 | foreach (Row row in table.Rows) | ||
1630 | { | ||
1631 | ComPlus.ComPlusMethod comPlusMethod = new ComPlus.ComPlusMethod(); | ||
1632 | |||
1633 | comPlusMethod.Id = (string)row[0]; | ||
1634 | |||
1635 | if (null != row[2]) | ||
1636 | { | ||
1637 | comPlusMethod.Index = (int)row[2]; | ||
1638 | } | ||
1639 | |||
1640 | if (null != row[3]) | ||
1641 | { | ||
1642 | comPlusMethod.Name = (string)row[3]; | ||
1643 | } | ||
1644 | |||
1645 | ComPlus.ComPlusInterface comPlusInterface = (ComPlus.ComPlusInterface)this.Core.GetIndexedElement("ComPlusInterface", (string)row[1]); | ||
1646 | if (null != comPlusInterface) | ||
1647 | { | ||
1648 | comPlusInterface.AddChild(comPlusMethod); | ||
1649 | } | ||
1650 | else | ||
1651 | { | ||
1652 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Interface_", (string)row[1], "ComPlusInterface")); | ||
1653 | } | ||
1654 | this.Core.IndexElement(row, comPlusMethod); | ||
1655 | } | ||
1656 | } | ||
1657 | |||
1658 | /// <summary> | ||
1659 | /// Decompile the ComPlusMethodProperty table. | ||
1660 | /// </summary> | ||
1661 | /// <param name="table">The table to decompile.</param> | ||
1662 | private void DecompileComPlusMethodPropertyTable(Table table) | ||
1663 | { | ||
1664 | foreach (Row row in table.Rows) | ||
1665 | { | ||
1666 | ComPlus.ComPlusMethod comPlusMethod = (ComPlus.ComPlusMethod)this.Core.GetIndexedElement("ComPlusMethod", (string)row[0]); | ||
1667 | if (null == comPlusMethod) | ||
1668 | { | ||
1669 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Method_", (string)row[0], "ComPlusMethod")); | ||
1670 | } | ||
1671 | |||
1672 | switch ((string)row[1]) | ||
1673 | { | ||
1674 | case "AutoComplete": | ||
1675 | switch ((string)row[2]) | ||
1676 | { | ||
1677 | case "1": | ||
1678 | comPlusMethod.AutoComplete = ComPlus.YesNoType.yes; | ||
1679 | break; | ||
1680 | case "0": | ||
1681 | comPlusMethod.AutoComplete = ComPlus.YesNoType.no; | ||
1682 | break; | ||
1683 | default: | ||
1684 | // TODO: Warning | ||
1685 | break; | ||
1686 | } | ||
1687 | break; | ||
1688 | case "Description": | ||
1689 | comPlusMethod.Description = (string)row[2]; | ||
1690 | break; | ||
1691 | default: | ||
1692 | // TODO: Warning | ||
1693 | break; | ||
1694 | } | ||
1695 | } | ||
1696 | } | ||
1697 | |||
1698 | /// <summary> | ||
1699 | /// Decompile the ComPlusRoleForMethod table. | ||
1700 | /// </summary> | ||
1701 | /// <param name="table">The table to decompile.</param> | ||
1702 | private void DecompileComPlusRoleForMethodTable(Table table) | ||
1703 | { | ||
1704 | foreach (Row row in table.Rows) | ||
1705 | { | ||
1706 | ComPlus.ComPlusRoleForMethod roleForMethod = new ComPlus.ComPlusRoleForMethod(); | ||
1707 | |||
1708 | roleForMethod.Id = (string)row[0]; | ||
1709 | roleForMethod.Method = (string)row[1]; | ||
1710 | roleForMethod.ApplicationRole = (string)row[2]; | ||
1711 | |||
1712 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[3]); | ||
1713 | if (null != component) | ||
1714 | { | ||
1715 | component.AddChild(roleForMethod); | ||
1716 | } | ||
1717 | else | ||
1718 | { | ||
1719 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[3], "Component")); | ||
1720 | } | ||
1721 | } | ||
1722 | } | ||
1723 | |||
1724 | /// <summary> | ||
1725 | /// Decompile the ComPlusSubscription table. | ||
1726 | /// </summary> | ||
1727 | /// <param name="table">The table to decompile.</param> | ||
1728 | private void DecompileComPlusSubscriptionTable(Table table) | ||
1729 | { | ||
1730 | foreach (Row row in table.Rows) | ||
1731 | { | ||
1732 | ComPlus.ComPlusSubscription subscription = new ComPlus.ComPlusSubscription(); | ||
1733 | |||
1734 | subscription.Id = (string)row[0]; | ||
1735 | subscription.Component = (string)row[1]; | ||
1736 | subscription.SubscriptionId = (string)row[3]; | ||
1737 | subscription.Name = (string)row[4]; | ||
1738 | subscription.EventCLSID = (string)row[5]; | ||
1739 | subscription.PublisherID = (string)row[6]; | ||
1740 | |||
1741 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
1742 | if (null != component) | ||
1743 | { | ||
1744 | component.AddChild(subscription); | ||
1745 | } | ||
1746 | else | ||
1747 | { | ||
1748 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
1749 | } | ||
1750 | this.Core.IndexElement(row, subscription); | ||
1751 | } | ||
1752 | } | ||
1753 | |||
1754 | /// <summary> | ||
1755 | /// Decompile the ComPlusSubscriptionProperty table. | ||
1756 | /// </summary> | ||
1757 | /// <param name="table">The table to decompile.</param> | ||
1758 | private void DecompileComPlusSubscriptionPropertyTable(Table table) | ||
1759 | { | ||
1760 | foreach (Row row in table.Rows) | ||
1761 | { | ||
1762 | ComPlus.ComPlusSubscription subscription = (ComPlus.ComPlusSubscription)this.Core.GetIndexedElement("ComPlusSubscription", (string)row[0]); | ||
1763 | if (null == subscription) | ||
1764 | { | ||
1765 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Subscription_", (string)row[0], "ComPlusSubscription")); | ||
1766 | } | ||
1767 | |||
1768 | switch ((string)row[1]) | ||
1769 | { | ||
1770 | case "Description": | ||
1771 | subscription.Description = (string)row[2]; | ||
1772 | break; | ||
1773 | case "Enabled": | ||
1774 | switch ((string)row[2]) | ||
1775 | { | ||
1776 | case "1": | ||
1777 | subscription.Enabled = ComPlus.YesNoType.yes; | ||
1778 | break; | ||
1779 | case "0": | ||
1780 | subscription.Enabled = ComPlus.YesNoType.no; | ||
1781 | break; | ||
1782 | default: | ||
1783 | // TODO: Warning | ||
1784 | break; | ||
1785 | } | ||
1786 | break; | ||
1787 | case "EventClassPartitionID": | ||
1788 | subscription.EventClassPartitionID = (string)row[2]; | ||
1789 | break; | ||
1790 | case "FilterCriteria": | ||
1791 | subscription.FilterCriteria = (string)row[2]; | ||
1792 | break; | ||
1793 | case "InterfaceID": | ||
1794 | subscription.InterfaceID = (string)row[2]; | ||
1795 | break; | ||
1796 | case "MachineName": | ||
1797 | subscription.MachineName = (string)row[2]; | ||
1798 | break; | ||
1799 | case "MethodName": | ||
1800 | subscription.MethodName = (string)row[2]; | ||
1801 | break; | ||
1802 | case "PerUser": | ||
1803 | switch ((string)row[2]) | ||
1804 | { | ||
1805 | case "1": | ||
1806 | subscription.PerUser = ComPlus.YesNoType.yes; | ||
1807 | break; | ||
1808 | case "0": | ||
1809 | subscription.PerUser = ComPlus.YesNoType.no; | ||
1810 | break; | ||
1811 | default: | ||
1812 | // TODO: Warning | ||
1813 | break; | ||
1814 | } | ||
1815 | break; | ||
1816 | case "Queued": | ||
1817 | switch ((string)row[2]) | ||
1818 | { | ||
1819 | case "1": | ||
1820 | subscription.Queued = ComPlus.YesNoType.yes; | ||
1821 | break; | ||
1822 | case "0": | ||
1823 | subscription.Queued = ComPlus.YesNoType.no; | ||
1824 | break; | ||
1825 | default: | ||
1826 | // TODO: Warning | ||
1827 | break; | ||
1828 | } | ||
1829 | break; | ||
1830 | case "SubscriberMoniker": | ||
1831 | subscription.SubscriberMoniker = (string)row[2]; | ||
1832 | break; | ||
1833 | case "UserName": | ||
1834 | subscription.UserName = (string)row[2]; | ||
1835 | break; | ||
1836 | default: | ||
1837 | // TODO: Warning | ||
1838 | break; | ||
1839 | } | ||
1840 | } | ||
1841 | } | ||
1842 | } | ||
1843 | } | ||
diff --git a/src/wixext/ComPlusExtensionData.cs b/src/wixext/ComPlusExtensionData.cs new file mode 100644 index 00000000..cedc2474 --- /dev/null +++ b/src/wixext/ComPlusExtensionData.cs | |||
@@ -0,0 +1,64 @@ | |||
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 | namespace WixToolset.Extensions | ||
4 | { | ||
5 | using System; | ||
6 | using System.Reflection; | ||
7 | using WixToolset.Data; | ||
8 | using WixToolset.Extensibility; | ||
9 | |||
10 | /// <summary> | ||
11 | /// The WiX Toolset COM+ Extension. | ||
12 | /// </summary> | ||
13 | public sealed class ComPlusExtensionData : ExtensionData | ||
14 | { | ||
15 | /// <summary> | ||
16 | /// Gets the default culture. | ||
17 | /// </summary> | ||
18 | /// <value>The default culture.</value> | ||
19 | public override string DefaultCulture | ||
20 | { | ||
21 | get { return "en-us"; } | ||
22 | } | ||
23 | |||
24 | /// <summary> | ||
25 | /// Gets the optional table definitions for this extension. | ||
26 | /// </summary> | ||
27 | /// <value>The optional table definitions for this extension.</value> | ||
28 | public override TableDefinitionCollection TableDefinitions | ||
29 | { | ||
30 | get | ||
31 | { | ||
32 | return ComPlusExtensionData.GetExtensionTableDefinitions(); | ||
33 | } | ||
34 | } | ||
35 | |||
36 | /// <summary> | ||
37 | /// Gets the library associated with this extension. | ||
38 | /// </summary> | ||
39 | /// <param name="tableDefinitions">The table definitions to use while loading the library.</param> | ||
40 | /// <returns>The loaded library.</returns> | ||
41 | public override Library GetLibrary(TableDefinitionCollection tableDefinitions) | ||
42 | { | ||
43 | return ComPlusExtensionData.GetExtensionLibrary(tableDefinitions); | ||
44 | } | ||
45 | |||
46 | /// <summary> | ||
47 | /// Internal mechanism to access the extension's table definitions. | ||
48 | /// </summary> | ||
49 | /// <returns>Extension's table definitions.</returns> | ||
50 | internal static TableDefinitionCollection GetExtensionTableDefinitions() | ||
51 | { | ||
52 | return ExtensionData.LoadTableDefinitionHelper(Assembly.GetExecutingAssembly(), "WixToolset.Extensions.Data.tables.xml"); | ||
53 | } | ||
54 | |||
55 | /// <summary> | ||
56 | /// Internal mechanism to access the extension's library. | ||
57 | /// </summary> | ||
58 | /// <returns>Extension's library.</returns> | ||
59 | internal static Library GetExtensionLibrary(TableDefinitionCollection tableDefinitions) | ||
60 | { | ||
61 | return ExtensionData.LoadLibraryHelper(Assembly.GetExecutingAssembly(), "WixToolset.Extensions.Data.complus.wixlib", tableDefinitions); | ||
62 | } | ||
63 | } | ||
64 | } | ||
diff --git a/src/wixext/WixComPlusExtension.csproj b/src/wixext/WixComPlusExtension.csproj new file mode 100644 index 00000000..92cbacae --- /dev/null +++ b/src/wixext/WixComPlusExtension.csproj | |||
@@ -0,0 +1,50 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- 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. --> | ||
3 | |||
4 | |||
5 | <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | ||
6 | <PropertyGroup> | ||
7 | <ProjectGuid>{1497B777-330B-4CFE-927A-22850CD24D64}</ProjectGuid> | ||
8 | <AssemblyName>WixComPlusExtension</AssemblyName> | ||
9 | <OutputType>Library</OutputType> | ||
10 | <RootNamespace>WixToolset.Extensions</RootNamespace> | ||
11 | </PropertyGroup> | ||
12 | <ItemGroup> | ||
13 | <Compile Include="AssemblyInfo.cs" /> | ||
14 | <Compile Include="ComPlusCompiler.cs" /> | ||
15 | <Compile Include="ComPlusDecompiler.cs" /> | ||
16 | <Compile Include="ComPlusExtensionData.cs" /> | ||
17 | <MsgGenSource Include="Data\messages.xml"> | ||
18 | <ResourcesLogicalName>$(RootNamespace).Data.Messages.resources</ResourcesLogicalName> | ||
19 | </MsgGenSource> | ||
20 | <EmbeddedFlattenedResource Include="Data\tables.xml"> | ||
21 | <LogicalName>$(RootNamespace).Data.tables.xml</LogicalName> | ||
22 | </EmbeddedFlattenedResource> | ||
23 | <EmbeddedFlattenedResource Include="Xsd\complus.xsd"> | ||
24 | <LogicalName>$(RootNamespace).Xsd.complus.xsd</LogicalName> | ||
25 | </EmbeddedFlattenedResource> | ||
26 | <XsdGenSource Include="Xsd\complus.xsd"> | ||
27 | <CommonNamespace>WixToolset.Data.Serialize</CommonNamespace> | ||
28 | <Namespace>WixToolset.Extensions.Serialize.ComPlus</Namespace> | ||
29 | </XsdGenSource> | ||
30 | <None Include="Xsd\complus.xsd"> | ||
31 | <Link>complus.xsd</Link> | ||
32 | <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
33 | </None> | ||
34 | <EmbeddedResource Include="$(OutputPath)\complus.wixlib"> | ||
35 | <Link>Data\complus.wixlib</Link> | ||
36 | </EmbeddedResource> | ||
37 | </ItemGroup> | ||
38 | <ItemGroup> | ||
39 | <Reference Include="System" /> | ||
40 | <Reference Include="System.Xml" /> | ||
41 | <Reference Include="System.Xml.Linq" /> | ||
42 | <ProjectReference Include="..\..\..\libs\WixToolset.Data\WixToolset.Data.csproj" /> | ||
43 | <ProjectReference Include="..\..\..\libs\WixToolset.Extensibility\WixToolset.Extensibility.csproj" /> | ||
44 | <ProjectReference Include="..\..\..\tools\wix\Wix.csproj" /> | ||
45 | <ProjectReference Include="..\wixlib\ComPlusExtension.wixproj"> | ||
46 | <ReferenceOutputAssembly>false</ReferenceOutputAssembly> | ||
47 | </ProjectReference> | ||
48 | </ItemGroup> | ||
49 | <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.targets" /> | ||
50 | </Project> | ||
diff --git a/src/wixext/complus.xsd b/src/wixext/complus.xsd new file mode 100644 index 00000000..f7ddacc6 --- /dev/null +++ b/src/wixext/complus.xsd | |||
@@ -0,0 +1,944 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- 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. --> | ||
3 | |||
4 | |||
5 | <xs:schema xmlns:html="http://www.w3.org/1999/xhtml" | ||
6 | xmlns:wix="http://wixtoolset.org/schemas/v4/wxs" | ||
7 | xmlns:xs="http://www.w3.org/2001/XMLSchema" | ||
8 | xmlns:xse=" http://wixtoolset.org/schemas/XmlSchemaExtension" | ||
9 | targetNamespace="http://wixtoolset.org/schemas/v4/wxs/complus" | ||
10 | xmlns="http://wixtoolset.org/schemas/v4/wxs/complus"> | ||
11 | <xs:annotation> | ||
12 | <xs:documentation> | ||
13 | The source code schema for the WiX Toolset COM+ Extension. | ||
14 | </xs:documentation> | ||
15 | </xs:annotation> | ||
16 | |||
17 | <xs:import namespace="http://wixtoolset.org/schemas/v4/wxs" /> | ||
18 | |||
19 | <xs:element name="ComPlusPartition"> | ||
20 | <xs:annotation> | ||
21 | <xs:appinfo> | ||
22 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
23 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Fragment" /> | ||
24 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Module" /> | ||
25 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Product" /> | ||
26 | </xs:appinfo> | ||
27 | <xs:documentation> | ||
28 | Defines a COM+ partition. If this element is a child of a | ||
29 | Component element, the partition will be created in association with this | ||
30 | component. If the element is a child of any of the Fragment, Module or Product | ||
31 | elements it is considered to be a locater, referencing an existing partition. | ||
32 | </xs:documentation> | ||
33 | </xs:annotation> | ||
34 | <xs:complexType> | ||
35 | <xs:sequence> | ||
36 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
37 | <xs:element ref="ComPlusPartitionRole" /> | ||
38 | <xs:element ref="ComPlusPartitionUser" /> | ||
39 | <xs:element ref="ComPlusApplication" /> | ||
40 | </xs:choice> | ||
41 | </xs:sequence> | ||
42 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
43 | <xs:annotation><xs:documentation> | ||
44 | Identifier for the element. | ||
45 | </xs:documentation></xs:annotation> | ||
46 | </xs:attribute> | ||
47 | <xs:attribute name="PartitionId" use="optional" type="xs:string"> | ||
48 | <xs:annotation><xs:documentation> | ||
49 | Id for the partition. This attribute can be omitted, in | ||
50 | which case an id will be generated on install. If the element is a locater, | ||
51 | this attribute can be omitted if a value is provided for the Name attribute. | ||
52 | </xs:documentation></xs:annotation> | ||
53 | </xs:attribute> | ||
54 | <xs:attribute name="Name" use="optional" type="xs:string"> | ||
55 | <xs:annotation><xs:documentation> | ||
56 | Name of the partition. This attribute can be omitted if | ||
57 | the element is a locater, and a value is provided for the PartitionId | ||
58 | attribute. | ||
59 | </xs:documentation></xs:annotation> | ||
60 | </xs:attribute> | ||
61 | <xs:attribute name="Changeable" use="optional" type="YesNoType" /> | ||
62 | <xs:attribute name="Deleteable" use="optional" type="YesNoType" /> | ||
63 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
64 | </xs:complexType> | ||
65 | </xs:element> | ||
66 | |||
67 | <xs:element name="ComPlusPartitionRole"> | ||
68 | <xs:annotation> | ||
69 | <xs:appinfo> | ||
70 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
71 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Fragment" /> | ||
72 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Module" /> | ||
73 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Product" /> | ||
74 | </xs:appinfo> | ||
75 | <xs:documentation> | ||
76 | Defines a COM+ partition role. Partition roles can not be | ||
77 | created; this element can only be used as a locater to reference an existing | ||
78 | role. | ||
79 | </xs:documentation> | ||
80 | </xs:annotation> | ||
81 | <xs:complexType> | ||
82 | <xs:sequence> | ||
83 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
84 | <xs:element ref="ComPlusUserInPartitionRole" /> | ||
85 | <xs:element ref="ComPlusGroupInPartitionRole" /> | ||
86 | </xs:choice> | ||
87 | </xs:sequence> | ||
88 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
89 | <xs:annotation><xs:documentation> | ||
90 | Identifier for the element. | ||
91 | </xs:documentation></xs:annotation> | ||
92 | </xs:attribute> | ||
93 | <xs:attribute name="Partition" use="optional" type="xs:string"> | ||
94 | <xs:annotation><xs:documentation> | ||
95 | The id of a ComPlusPartition element representing the partition | ||
96 | the role belongs to. | ||
97 | </xs:documentation></xs:annotation> | ||
98 | </xs:attribute> | ||
99 | <xs:attribute name="Name" use="required" type="xs:string"> | ||
100 | <xs:annotation><xs:documentation> | ||
101 | Name of the partition role. | ||
102 | </xs:documentation></xs:annotation> | ||
103 | </xs:attribute> | ||
104 | </xs:complexType> | ||
105 | </xs:element> | ||
106 | |||
107 | <xs:element name="ComPlusUserInPartitionRole"> | ||
108 | <xs:annotation> | ||
109 | <xs:appinfo> | ||
110 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
111 | </xs:appinfo> | ||
112 | <xs:documentation> | ||
113 | This element represents a user membership in a partition | ||
114 | role. When the parent component of this element is installed, the user will be | ||
115 | added to the associated partition role. | ||
116 | </xs:documentation> | ||
117 | </xs:annotation> | ||
118 | <xs:complexType> | ||
119 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
120 | <xs:annotation><xs:documentation> | ||
121 | Identifier for the element. | ||
122 | </xs:documentation></xs:annotation> | ||
123 | </xs:attribute> | ||
124 | <xs:attribute name="PartitionRole" use="optional" type="xs:string"> | ||
125 | <xs:annotation><xs:documentation> | ||
126 | The id of a ComPlusPartitionRole element representing the | ||
127 | partition the user should be added to. | ||
128 | </xs:documentation></xs:annotation> | ||
129 | </xs:attribute> | ||
130 | <xs:attribute name="User" use="required" type="xs:string"> | ||
131 | <xs:annotation><xs:documentation> | ||
132 | Foreign key into the User table. | ||
133 | </xs:documentation></xs:annotation> | ||
134 | </xs:attribute> | ||
135 | </xs:complexType> | ||
136 | </xs:element> | ||
137 | |||
138 | <xs:element name="ComPlusGroupInPartitionRole"> | ||
139 | <xs:annotation> | ||
140 | <xs:appinfo> | ||
141 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
142 | </xs:appinfo> | ||
143 | <xs:documentation> | ||
144 | This element represents a security group membership in a | ||
145 | partition role. When the parent component of this element is installed, the | ||
146 | security group will be added to the associated partition role. | ||
147 | </xs:documentation> | ||
148 | </xs:annotation> | ||
149 | <xs:complexType> | ||
150 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
151 | <xs:annotation><xs:documentation> | ||
152 | Identifier for the element. | ||
153 | </xs:documentation></xs:annotation> | ||
154 | </xs:attribute> | ||
155 | <xs:attribute name="PartitionRole" use="optional" type="xs:string"> | ||
156 | <xs:annotation><xs:documentation> | ||
157 | The id of a ComPlusPartitionRole element representing the | ||
158 | partition the user should be added to. | ||
159 | </xs:documentation></xs:annotation> | ||
160 | </xs:attribute> | ||
161 | <xs:attribute name="Group" use="required" type="xs:string"> | ||
162 | <xs:annotation><xs:documentation> | ||
163 | Foreign key into the Group table. | ||
164 | </xs:documentation></xs:annotation> | ||
165 | </xs:attribute> | ||
166 | </xs:complexType> | ||
167 | </xs:element> | ||
168 | |||
169 | <xs:element name="ComPlusPartitionUser"> | ||
170 | <xs:annotation> | ||
171 | <xs:appinfo> | ||
172 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
173 | </xs:appinfo> | ||
174 | <xs:documentation> | ||
175 | Represents a default partition definition for a user. When | ||
176 | the parent component of this element is installed, the default partition of the | ||
177 | user will be set to the referenced partition. | ||
178 | </xs:documentation> | ||
179 | </xs:annotation> | ||
180 | <xs:complexType> | ||
181 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
182 | <xs:annotation><xs:documentation> | ||
183 | Identifier for the element. | ||
184 | </xs:documentation></xs:annotation> | ||
185 | </xs:attribute> | ||
186 | <xs:attribute name="Partition" use="optional" type="xs:string"> | ||
187 | <xs:annotation><xs:documentation> | ||
188 | The id of a ComPlusPartition element representing the | ||
189 | partition that will be the default partition for the user. | ||
190 | </xs:documentation></xs:annotation> | ||
191 | </xs:attribute> | ||
192 | <xs:attribute name="User" use="required" type="xs:string"> | ||
193 | <xs:annotation><xs:documentation> | ||
194 | Foreign key into the User table. | ||
195 | </xs:documentation></xs:annotation> | ||
196 | </xs:attribute> | ||
197 | </xs:complexType> | ||
198 | </xs:element> | ||
199 | |||
200 | <xs:element name="ComPlusApplication"> | ||
201 | <xs:annotation> | ||
202 | <xs:appinfo> | ||
203 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
204 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Fragment" /> | ||
205 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Module" /> | ||
206 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Product" /> | ||
207 | </xs:appinfo> | ||
208 | <xs:documentation> | ||
209 | Defines a COM+ application. If this element is a descendent | ||
210 | of a Component element, the application will be created in association with | ||
211 | this component. If the element is a child of any of the Fragment, Module or | ||
212 | Product elements it is considered to be a locater, referencing an existing | ||
213 | application. | ||
214 | |||
215 | If the element is a child of a ComPlusPartition element, | ||
216 | or have its Partition attribute set, the application will be installed under | ||
217 | the referenced partition. | ||
218 | </xs:documentation> | ||
219 | </xs:annotation> | ||
220 | <xs:complexType> | ||
221 | <xs:sequence> | ||
222 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
223 | <xs:element ref="ComPlusApplicationRole" /> | ||
224 | <xs:element ref="ComPlusAssembly" /> | ||
225 | </xs:choice> | ||
226 | </xs:sequence> | ||
227 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
228 | <xs:annotation><xs:documentation> | ||
229 | Identifier for the element. | ||
230 | </xs:documentation></xs:annotation> | ||
231 | </xs:attribute> | ||
232 | <xs:attribute name="Partition" use="optional" type="xs:string"> | ||
233 | <xs:annotation><xs:documentation> | ||
234 | If the element is not a child of a ComPlusPartition | ||
235 | element, this attribute can be provided with the id of a ComPlusPartition | ||
236 | element representing the partition the application belongs to. | ||
237 | </xs:documentation></xs:annotation> | ||
238 | </xs:attribute> | ||
239 | <xs:attribute name="ApplicationId" use="optional" type="xs:string"> | ||
240 | <xs:annotation><xs:documentation> | ||
241 | Id for the application. This attribute can be omitted, in | ||
242 | which case an id will be generated on install. If the element is a locater, | ||
243 | this attribute can be omitted if a value is provided for the Name attribute. | ||
244 | </xs:documentation></xs:annotation> | ||
245 | </xs:attribute> | ||
246 | <xs:attribute name="Name" use="optional" type="xs:string"> | ||
247 | <xs:annotation><xs:documentation> | ||
248 | Name of the application. This attribute can be omitted if | ||
249 | the element is a locater, and a value is provided for the PartitionId | ||
250 | attribute. | ||
251 | </xs:documentation></xs:annotation> | ||
252 | </xs:attribute> | ||
253 | <xs:attribute name="ThreeGigSupportEnabled" use="optional" type="YesNoType" /> | ||
254 | <xs:attribute name="AccessChecksLevel" use="optional"> | ||
255 | <xs:simpleType> | ||
256 | <xs:restriction base="xs:NMTOKEN"> | ||
257 | <xs:enumeration value="applicationLevel" /> | ||
258 | <xs:enumeration value="applicationComponentLevel" /> | ||
259 | </xs:restriction> | ||
260 | </xs:simpleType> | ||
261 | </xs:attribute> | ||
262 | <xs:attribute name="Activation" use="optional"> | ||
263 | <xs:simpleType> | ||
264 | <xs:restriction base="xs:NMTOKEN"> | ||
265 | <xs:enumeration value="inproc" /> | ||
266 | <xs:enumeration value="local" /> | ||
267 | </xs:restriction> | ||
268 | </xs:simpleType> | ||
269 | </xs:attribute> | ||
270 | <xs:attribute name="ApplicationAccessChecksEnabled" use="optional" type="YesNoType" /> | ||
271 | <xs:attribute name="ApplicationDirectory" use="optional" type="xs:string" /> | ||
272 | <xs:attribute name="Authentication" use="optional"> | ||
273 | <xs:simpleType> | ||
274 | <xs:restriction base="xs:NMTOKEN"> | ||
275 | <xs:enumeration value="default" /> | ||
276 | <xs:enumeration value="none" /> | ||
277 | <xs:enumeration value="connect" /> | ||
278 | <xs:enumeration value="call" /> | ||
279 | <xs:enumeration value="packet" /> | ||
280 | <xs:enumeration value="integrity" /> | ||
281 | <xs:enumeration value="privacy" /> | ||
282 | </xs:restriction> | ||
283 | </xs:simpleType> | ||
284 | </xs:attribute> | ||
285 | <xs:attribute name="AuthenticationCapability" use="optional"> | ||
286 | <xs:simpleType> | ||
287 | <xs:restriction base="xs:NMTOKEN"> | ||
288 | <xs:enumeration value="none" /> | ||
289 | <xs:enumeration value="secureReference" /> | ||
290 | <xs:enumeration value="staticCloaking" /> | ||
291 | <xs:enumeration value="dynamicCloaking" /> | ||
292 | </xs:restriction> | ||
293 | </xs:simpleType> | ||
294 | </xs:attribute> | ||
295 | <xs:attribute name="Changeable" use="optional" type="YesNoType" /> | ||
296 | <xs:attribute name="CommandLine" use="optional" type="xs:string" /> | ||
297 | <xs:attribute name="ConcurrentApps" use="optional" type="xs:int" /> | ||
298 | <xs:attribute name="CreatedBy" use="optional" type="xs:string" /> | ||
299 | <xs:attribute name="CRMEnabled" use="optional" type="YesNoType" /> | ||
300 | <xs:attribute name="CRMLogFile" use="optional" type="xs:string" /> | ||
301 | <xs:attribute name="Deleteable" use="optional" type="YesNoType" /> | ||
302 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
303 | <xs:attribute name="DumpEnabled" use="optional" type="YesNoType" /> | ||
304 | <xs:attribute name="DumpOnException" use="optional" type="YesNoType" /> | ||
305 | <xs:attribute name="DumpOnFailfast" use="optional" type="YesNoType" /> | ||
306 | <xs:attribute name="DumpPath" use="optional" type="xs:string" /> | ||
307 | <xs:attribute name="EventsEnabled" use="optional" type="YesNoType" /> | ||
308 | <xs:attribute name="Identity" use="optional" type="xs:string" /> | ||
309 | <xs:attribute name="ImpersonationLevel" use="optional"> | ||
310 | <xs:simpleType> | ||
311 | <xs:restriction base="xs:NMTOKEN"> | ||
312 | <xs:enumeration value="anonymous" /> | ||
313 | <xs:enumeration value="identify" /> | ||
314 | <xs:enumeration value="impersonate" /> | ||
315 | <xs:enumeration value="delegate" /> | ||
316 | </xs:restriction> | ||
317 | </xs:simpleType> | ||
318 | </xs:attribute> | ||
319 | <xs:attribute name="IsEnabled" use="optional" type="YesNoType" /> | ||
320 | <xs:attribute name="MaxDumpCount" use="optional" type="xs:int" /> | ||
321 | <xs:attribute name="Password" use="optional" type="xs:string" /> | ||
322 | <xs:attribute name="QCAuthenticateMsgs" use="optional"> | ||
323 | <xs:simpleType> | ||
324 | <xs:restriction base="xs:NMTOKEN"> | ||
325 | <xs:enumeration value="secureApps" /> | ||
326 | <xs:enumeration value="off" /> | ||
327 | <xs:enumeration value="on" /> | ||
328 | </xs:restriction> | ||
329 | </xs:simpleType> | ||
330 | </xs:attribute> | ||
331 | <xs:attribute name="QCListenerMaxThreads" use="optional" type="xs:int" /> | ||
332 | <xs:attribute name="QueueListenerEnabled" use="optional" type="YesNoType" /> | ||
333 | <xs:attribute name="QueuingEnabled" use="optional" type="YesNoType" /> | ||
334 | <xs:attribute name="RecycleActivationLimit" use="optional" type="xs:int" /> | ||
335 | <xs:attribute name="RecycleCallLimit" use="optional" type="xs:int" /> | ||
336 | <xs:attribute name="RecycleExpirationTimeout" use="optional" type="xs:int" /> | ||
337 | <xs:attribute name="RecycleLifetimeLimit" use="optional" type="xs:int" /> | ||
338 | <xs:attribute name="RecycleMemoryLimit" use="optional" type="xs:int" /> | ||
339 | <xs:attribute name="Replicable" use="optional" type="YesNoType" /> | ||
340 | <xs:attribute name="RunForever" use="optional" type="YesNoType" /> | ||
341 | <xs:attribute name="ShutdownAfter" use="optional" type="xs:int" /> | ||
342 | <xs:attribute name="SoapActivated" use="optional" type="YesNoType" /> | ||
343 | <xs:attribute name="SoapBaseUrl" use="optional" type="xs:string" /> | ||
344 | <xs:attribute name="SoapMailTo" use="optional" type="xs:string" /> | ||
345 | <xs:attribute name="SoapVRoot" use="optional" type="xs:string" /> | ||
346 | <xs:attribute name="SRPEnabled" use="optional" type="YesNoType" /> | ||
347 | <xs:attribute name="SRPTrustLevel" use="optional"> | ||
348 | <xs:simpleType> | ||
349 | <xs:restriction base="xs:NMTOKEN"> | ||
350 | <xs:enumeration value="disallowed" /> | ||
351 | <xs:enumeration value="fullyTrusted" /> | ||
352 | </xs:restriction> | ||
353 | </xs:simpleType> | ||
354 | </xs:attribute> | ||
355 | </xs:complexType> | ||
356 | </xs:element> | ||
357 | |||
358 | <xs:element name="ComPlusApplicationRole"> | ||
359 | <xs:annotation> | ||
360 | <xs:appinfo> | ||
361 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
362 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Fragment" /> | ||
363 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Module" /> | ||
364 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Product" /> | ||
365 | </xs:appinfo> | ||
366 | <xs:documentation> | ||
367 | Defines an application role. If this element is a descendent | ||
368 | of a Component element, the application role will be created in association | ||
369 | with this component. If the element is a child of any of the Fragment, Module | ||
370 | or Product elements it is considered to be a locater, referencing an existing | ||
371 | application role. | ||
372 | </xs:documentation> | ||
373 | </xs:annotation> | ||
374 | <xs:complexType> | ||
375 | <xs:sequence> | ||
376 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
377 | <xs:element ref="ComPlusUserInApplicationRole" /> | ||
378 | <xs:element ref="ComPlusGroupInApplicationRole" /> | ||
379 | </xs:choice> | ||
380 | </xs:sequence> | ||
381 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
382 | <xs:annotation><xs:documentation> | ||
383 | Identifier for the element. | ||
384 | </xs:documentation></xs:annotation> | ||
385 | </xs:attribute> | ||
386 | <xs:attribute name="Application" use="optional" type="xs:string"> | ||
387 | <xs:annotation><xs:documentation> | ||
388 | If the element is not a child of a ComPlusApplication | ||
389 | element, this attribute should be provided with the id of a | ||
390 | ComPlusApplication element representing the application the role belongs to. | ||
391 | </xs:documentation></xs:annotation> | ||
392 | </xs:attribute> | ||
393 | <xs:attribute name="Name" use="required" type="xs:string"> | ||
394 | <xs:annotation><xs:documentation> | ||
395 | Name of the application role. | ||
396 | </xs:documentation></xs:annotation> | ||
397 | </xs:attribute> | ||
398 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
399 | </xs:complexType> | ||
400 | </xs:element> | ||
401 | |||
402 | <xs:element name="ComPlusUserInApplicationRole"> | ||
403 | <xs:annotation> | ||
404 | <xs:appinfo> | ||
405 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
406 | </xs:appinfo> | ||
407 | <xs:documentation> | ||
408 | This element represents a user membership in an | ||
409 | application role. When the parent component of this element is installed, the | ||
410 | user will be added to the associated application role. This element must be a descendent | ||
411 | of a Component element; it can not be a child of a ComPlusApplicationRole | ||
412 | locater element. To reference a locater element use the ApplicationRole | ||
413 | attribute. | ||
414 | </xs:documentation> | ||
415 | </xs:annotation> | ||
416 | <xs:complexType> | ||
417 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
418 | <xs:annotation><xs:documentation> | ||
419 | Identifier for the element. | ||
420 | </xs:documentation></xs:annotation> | ||
421 | </xs:attribute> | ||
422 | <xs:attribute name="ApplicationRole" use="optional" type="xs:string"> | ||
423 | <xs:annotation><xs:documentation> | ||
424 | If the element is not a child of a ComPlusApplicationRole | ||
425 | element, this attribute should be provided with the id of a | ||
426 | ComPlusApplicationRole element representing the application role the user is | ||
427 | to be added to. | ||
428 | </xs:documentation></xs:annotation> | ||
429 | </xs:attribute> | ||
430 | <xs:attribute name="User" use="required" type="xs:string"> | ||
431 | <xs:annotation><xs:documentation> | ||
432 | Foreign key into the User table. | ||
433 | </xs:documentation></xs:annotation> | ||
434 | </xs:attribute> | ||
435 | </xs:complexType> | ||
436 | </xs:element> | ||
437 | |||
438 | <xs:element name="ComPlusGroupInApplicationRole"> | ||
439 | <xs:annotation> | ||
440 | <xs:appinfo> | ||
441 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
442 | </xs:appinfo> | ||
443 | <xs:documentation> | ||
444 | This element represents a security group membership in an | ||
445 | application role. When the parent component of this element is installed, the | ||
446 | user will be added to the associated application role. This element must be a | ||
447 | descendent of a Component element; it can not be a child of a | ||
448 | ComPlusApplicationRole locater element. To reference a locater element use the | ||
449 | ApplicationRole attribute. | ||
450 | </xs:documentation> | ||
451 | </xs:annotation> | ||
452 | <xs:complexType> | ||
453 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
454 | <xs:annotation><xs:documentation> | ||
455 | Identifier for the element. | ||
456 | </xs:documentation></xs:annotation> | ||
457 | </xs:attribute> | ||
458 | <xs:attribute name="ApplicationRole" use="optional" type="xs:string"> | ||
459 | <xs:annotation><xs:documentation> | ||
460 | If the element is not a child of a ComPlusApplicationRole | ||
461 | element, this attribute should be provided with the id of a | ||
462 | ComPlusApplicationRole element representing the application role the user is | ||
463 | to be added to. | ||
464 | </xs:documentation></xs:annotation> | ||
465 | </xs:attribute> | ||
466 | <xs:attribute name="Group" use="required" type="xs:string"> | ||
467 | <xs:annotation><xs:documentation> | ||
468 | Foreign key into the Group table. | ||
469 | </xs:documentation></xs:annotation> | ||
470 | </xs:attribute> | ||
471 | </xs:complexType> | ||
472 | </xs:element> | ||
473 | |||
474 | <xs:element name="ComPlusAssembly"> | ||
475 | <xs:annotation> | ||
476 | <xs:documentation> | ||
477 | Represents a DLL or assembly to be registered with COM+. If | ||
478 | this element is a child of a ComPlusApplication element, the assembly will be | ||
479 | registered in this application. Other ways the Application attribute must be | ||
480 | set to an application. The element must be a descendent of a Component element, | ||
481 | it can not be a child of a ComPlusApplication locator element. | ||
482 | </xs:documentation> | ||
483 | <xs:appinfo> | ||
484 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
485 | <xse:remarks> | ||
486 | <html:p> | ||
487 | When installing a native assembly, all components | ||
488 | contained in the assembly must be represented as ComPlusComponent elements | ||
489 | under this element. Any component not listed will not be removed during | ||
490 | uninstall. | ||
491 | </html:p> | ||
492 | |||
493 | <html:p> | ||
494 | The fields DllPath, TlbPath and PSDllPath are formatted | ||
495 | fields that should contain file paths to there respective file types. A typical | ||
496 | value for DllPath for example, should be something like “[#MyAssembly_dll]”, | ||
497 | where “MyAssembly_dll” is the key of the dll file in the File table. | ||
498 | </html:p> | ||
499 | |||
500 | <html:p> | ||
501 | <html:b>Warning</html:b>: The assembly name provided in the AssemblyName | ||
502 | attribute must be a fully specified assembly name, if a partial name is | ||
503 | provided a random assembly matching the partial name will be selected. | ||
504 | </html:p> | ||
505 | </xse:remarks> | ||
506 | </xs:appinfo> | ||
507 | </xs:annotation> | ||
508 | <xs:complexType> | ||
509 | <xs:sequence> | ||
510 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
511 | <xs:element ref="ComPlusAssemblyDependency" /> | ||
512 | <xs:element ref="ComPlusComponent" /> | ||
513 | </xs:choice> | ||
514 | </xs:sequence> | ||
515 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
516 | <xs:annotation><xs:documentation> | ||
517 | Identifier for the element. | ||
518 | </xs:documentation></xs:annotation> | ||
519 | </xs:attribute> | ||
520 | <xs:attribute name="Application" use="optional" type="xs:string"> | ||
521 | <xs:annotation><xs:documentation> | ||
522 | If the element is not a child of a ComPlusApplication | ||
523 | element, this attribute should be provided with the id of a ComPlusApplication | ||
524 | element representing the application the assembly is to be registered in. | ||
525 | This attribute can be omitted for a .NET assembly even if the application is | ||
526 | not a child of a ComPlusApplication element. | ||
527 | </xs:documentation></xs:annotation> | ||
528 | </xs:attribute> | ||
529 | <xs:attribute name="AssemblyName" use="optional" type="xs:string"> | ||
530 | <xs:annotation><xs:documentation> | ||
531 | The name of the assembly used to identify the assembly in | ||
532 | the GAC. This attribute can be provided only if DllPathFromGAC is set to | ||
533 | “yes”. | ||
534 | </xs:documentation></xs:annotation> | ||
535 | </xs:attribute> | ||
536 | <xs:attribute name="DllPath" use="optional" type="xs:string"> | ||
537 | <xs:annotation><xs:documentation> | ||
538 | The path to locate the assembly DLL during registration. | ||
539 | This attribute should be provided if DllPathFromGAC is not set to “yes”. | ||
540 | </xs:documentation></xs:annotation> | ||
541 | </xs:attribute> | ||
542 | <xs:attribute name="TlbPath" use="optional" type="xs:string"> | ||
543 | <xs:annotation><xs:documentation> | ||
544 | An optional path to an external type lib for the assembly. | ||
545 | This attribute must be provided if the Type attribute is set to “.net”. | ||
546 | </xs:documentation></xs:annotation> | ||
547 | </xs:attribute> | ||
548 | <xs:attribute name="PSDllPath" use="optional" type="xs:string"> | ||
549 | <xs:annotation><xs:documentation> | ||
550 | An optional path to an external proxy/stub DLL for the assembly. | ||
551 | </xs:documentation></xs:annotation> | ||
552 | </xs:attribute> | ||
553 | <xs:attribute name="Type" use="required"> | ||
554 | <xs:annotation><xs:documentation> | ||
555 | </xs:documentation></xs:annotation> | ||
556 | <xs:simpleType> | ||
557 | <xs:restriction base="xs:NMTOKEN"> | ||
558 | <xs:enumeration value="native" /> | ||
559 | <xs:enumeration value=".net" /> | ||
560 | </xs:restriction> | ||
561 | </xs:simpleType> | ||
562 | </xs:attribute> | ||
563 | <xs:attribute name="EventClass" use="optional" type="YesNoType"> | ||
564 | <xs:annotation><xs:documentation> | ||
565 | Indicates that the assembly is to be installed as an event | ||
566 | class DLL. This attribute is only valid for native assemblies. The assembly | ||
567 | will be installed with the COM+ catalog’s InstallEventClass() function. | ||
568 | </xs:documentation></xs:annotation> | ||
569 | </xs:attribute> | ||
570 | <xs:attribute name="DllPathFromGAC" use="optional" type="YesNoType"> | ||
571 | <xs:annotation><xs:documentation> | ||
572 | Indicates that the DLL path should be extracted from the | ||
573 | GAC instead for being provided in the DllPath attribute. If this attribute is | ||
574 | set to “yes”, the name of the assembly can be provided using the AssemblyName | ||
575 | attribute. Or, if this AssemblyName attribute is missing, the name will be | ||
576 | extracted from the MsiAssemblyName table using the id of the parent Component | ||
577 | element. | ||
578 | </xs:documentation></xs:annotation> | ||
579 | </xs:attribute> | ||
580 | <xs:attribute name="RegisterInCommit" use="optional" type="YesNoType"> | ||
581 | <xs:annotation><xs:documentation> | ||
582 | Indicates that the assembly should be installed in the | ||
583 | commit custom action instead of the normal deferred custom action. This is | ||
584 | necessary when installing .NET assemblies to the GAC in the same | ||
585 | installation, as the assemblies are not visible in the GAC until after the | ||
586 | InstallFinalize action has run. | ||
587 | </xs:documentation></xs:annotation> | ||
588 | </xs:attribute> | ||
589 | </xs:complexType> | ||
590 | </xs:element> | ||
591 | |||
592 | <xs:element name="ComPlusAssemblyDependency"> | ||
593 | <xs:annotation> | ||
594 | <xs:documentation> | ||
595 | Defines a dependency between two assemblies. This element | ||
596 | affects the order in which assembles are registered. Any assemblies referenced | ||
597 | by this element are guarantied to be registered before, and unregistered after, | ||
598 | the assembly referenced by the parent ComPlusAssembly element. | ||
599 | </xs:documentation> | ||
600 | <xs:appinfo> | ||
601 | <xse:remarks> | ||
602 | It is only necessary to explicitly specify dependencies between | ||
603 | assemblies contained in the same package (MSI or MSM). Assemblies merged in to a | ||
604 | package from a merge module will always be installed before any assemblies | ||
605 | specified in the base package. Assemblies merged in from different merge | ||
606 | modules are sequenced using the ModuleDependency MSI table. It is not possible | ||
607 | to have cross dependencies between merge modules or have an assembly in a merge | ||
608 | module depend on an assembly in the base package. | ||
609 | </xse:remarks> | ||
610 | </xs:appinfo> | ||
611 | </xs:annotation> | ||
612 | <xs:complexType> | ||
613 | <xs:attribute name="RequiredAssembly" use="required" type="xs:string"> | ||
614 | <xs:annotation><xs:documentation> | ||
615 | Reference to the id of the assembly required by the parent | ||
616 | ComPlusAssembly element. | ||
617 | </xs:documentation></xs:annotation> | ||
618 | </xs:attribute> | ||
619 | </xs:complexType> | ||
620 | </xs:element> | ||
621 | |||
622 | <xs:element name="ComPlusComponent"> | ||
623 | <xs:annotation><xs:documentation> | ||
624 | Represents a COM+ component in an assembly. | ||
625 | </xs:documentation></xs:annotation> | ||
626 | <xs:complexType> | ||
627 | <xs:sequence> | ||
628 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
629 | <xs:element ref="ComPlusRoleForComponent" /> | ||
630 | <xs:element ref="ComPlusInterface" /> | ||
631 | <xs:element ref="ComPlusSubscription" /> | ||
632 | </xs:choice> | ||
633 | </xs:sequence> | ||
634 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
635 | <xs:annotation><xs:documentation> | ||
636 | Identifier for the element. | ||
637 | </xs:documentation></xs:annotation> | ||
638 | </xs:attribute> | ||
639 | <xs:attribute name="CLSID" use="required" type="uuid"> | ||
640 | <xs:annotation><xs:documentation> | ||
641 | CLSID of the component. | ||
642 | </xs:documentation></xs:annotation> | ||
643 | </xs:attribute> | ||
644 | <xs:attribute name="AllowInprocSubscribers" use="optional" type="YesNoType" /> | ||
645 | <xs:attribute name="ComponentAccessChecksEnabled" use="optional" type="YesNoType" /> | ||
646 | <xs:attribute name="ComponentTransactionTimeout" use="optional" type="xs:int" /> | ||
647 | <xs:attribute name="ComponentTransactionTimeoutEnabled" use="optional" type="YesNoType" /> | ||
648 | <xs:attribute name="COMTIIntrinsics" use="optional" type="YesNoType" /> | ||
649 | <xs:attribute name="ConstructionEnabled" use="optional" type="YesNoType" /> | ||
650 | <xs:attribute name="ConstructorString" use="optional" type="xs:string" /> | ||
651 | <xs:attribute name="CreationTimeout" use="optional" type="xs:int" /> | ||
652 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
653 | <xs:attribute name="EventTrackingEnabled" use="optional" type="YesNoType" /> | ||
654 | <xs:attribute name="ExceptionClass" use="optional" type="xs:string" /> | ||
655 | <xs:attribute name="FireInParallel" use="optional" type="YesNoType" /> | ||
656 | <xs:attribute name="IISIntrinsics" use="optional" type="YesNoType" /> | ||
657 | <xs:attribute name="InitializesServerApplication" use="optional" type="YesNoType" /> | ||
658 | <xs:attribute name="IsEnabled" use="optional" type="YesNoType" /> | ||
659 | <xs:attribute name="IsPrivateComponent" use="optional" type="YesNoType" /> | ||
660 | <xs:attribute name="JustInTimeActivation" use="optional" type="YesNoType" /> | ||
661 | <xs:attribute name="LoadBalancingSupported" use="optional" type="YesNoType" /> | ||
662 | <xs:attribute name="MaxPoolSize" use="optional" type="xs:int" /> | ||
663 | <xs:attribute name="MinPoolSize" use="optional" type="xs:int" /> | ||
664 | <xs:attribute name="MultiInterfacePublisherFilterCLSID" use="optional" type="xs:string" /> | ||
665 | <xs:attribute name="MustRunInClientContext" use="optional" type="YesNoType" /> | ||
666 | <xs:attribute name="MustRunInDefaultContext" use="optional" type="YesNoType" /> | ||
667 | <xs:attribute name="ObjectPoolingEnabled" use="optional" type="YesNoType" /> | ||
668 | <xs:attribute name="PublisherID" use="optional" type="xs:string" /> | ||
669 | <xs:attribute name="SoapAssemblyName" use="optional" type="xs:string" /> | ||
670 | <xs:attribute name="SoapTypeName" use="optional" type="xs:string" /> | ||
671 | <xs:attribute name="Synchronization" use="optional"> | ||
672 | <xs:simpleType> | ||
673 | <xs:restriction base="xs:NMTOKEN"> | ||
674 | <xs:enumeration value="ignored" /> | ||
675 | <xs:enumeration value="none" /> | ||
676 | <xs:enumeration value="supported" /> | ||
677 | <xs:enumeration value="required" /> | ||
678 | <xs:enumeration value="requiresNew" /> | ||
679 | </xs:restriction> | ||
680 | </xs:simpleType> | ||
681 | </xs:attribute> | ||
682 | <xs:attribute name="Transaction" use="optional"> | ||
683 | <xs:simpleType> | ||
684 | <xs:restriction base="xs:NMTOKEN"> | ||
685 | <xs:enumeration value="ignored" /> | ||
686 | <xs:enumeration value="none" /> | ||
687 | <xs:enumeration value="supported" /> | ||
688 | <xs:enumeration value="required" /> | ||
689 | <xs:enumeration value="requiresNew" /> | ||
690 | </xs:restriction> | ||
691 | </xs:simpleType> | ||
692 | </xs:attribute> | ||
693 | <xs:attribute name="TxIsolationLevel" use="optional"> | ||
694 | <xs:simpleType> | ||
695 | <xs:restriction base="xs:NMTOKEN"> | ||
696 | <xs:enumeration value="any" /> | ||
697 | <xs:enumeration value="readUnCommitted" /> | ||
698 | <xs:enumeration value="readCommitted" /> | ||
699 | <xs:enumeration value="repeatableRead" /> | ||
700 | <xs:enumeration value="serializable" /> | ||
701 | </xs:restriction> | ||
702 | </xs:simpleType> | ||
703 | </xs:attribute> | ||
704 | </xs:complexType> | ||
705 | </xs:element> | ||
706 | |||
707 | <xs:element name="ComPlusRoleForComponent"> | ||
708 | <xs:annotation> | ||
709 | <xs:appinfo> | ||
710 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
711 | </xs:appinfo> | ||
712 | <xs:documentation> | ||
713 | Represents a role assignment to a COM+ component. | ||
714 | </xs:documentation> | ||
715 | </xs:annotation> | ||
716 | <xs:complexType> | ||
717 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
718 | <xs:annotation><xs:documentation> | ||
719 | Identifier for the element. | ||
720 | </xs:documentation></xs:annotation> | ||
721 | </xs:attribute> | ||
722 | <xs:attribute name="Component" use="optional" type="xs:string"> | ||
723 | <xs:annotation><xs:documentation> | ||
724 | If the element is not a child of a ComPlusComponent | ||
725 | element, this attribute should be provided with the id of a ComPlusComponent | ||
726 | element representing the component the role is to be added to. | ||
727 | </xs:documentation></xs:annotation> | ||
728 | </xs:attribute> | ||
729 | <xs:attribute name="ApplicationRole" use="required" type="xs:string"> | ||
730 | <xs:annotation><xs:documentation> | ||
731 | Id of the ComPlusApplicationRole element representing the | ||
732 | role that shall be granted access to the component. | ||
733 | </xs:documentation></xs:annotation> | ||
734 | </xs:attribute> | ||
735 | </xs:complexType> | ||
736 | </xs:element> | ||
737 | |||
738 | <xs:element name="ComPlusInterface"> | ||
739 | <xs:annotation><xs:documentation> | ||
740 | Represents an interface for a COM+ component. | ||
741 | </xs:documentation></xs:annotation> | ||
742 | <xs:complexType> | ||
743 | <xs:sequence> | ||
744 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
745 | <xs:element ref="ComPlusRoleForInterface" /> | ||
746 | <xs:element ref="ComPlusMethod" /> | ||
747 | </xs:choice> | ||
748 | </xs:sequence> | ||
749 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
750 | <xs:annotation><xs:documentation> | ||
751 | Identifier for the element. | ||
752 | </xs:documentation></xs:annotation> | ||
753 | </xs:attribute> | ||
754 | <xs:attribute name="IID" use="required" type="uuid"> | ||
755 | <xs:annotation><xs:documentation> | ||
756 | IID of the interface. | ||
757 | </xs:documentation></xs:annotation> | ||
758 | </xs:attribute> | ||
759 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
760 | <xs:attribute name="QueuingEnabled" use="optional" type="YesNoType" /> | ||
761 | </xs:complexType> | ||
762 | </xs:element> | ||
763 | |||
764 | <xs:element name="ComPlusRoleForInterface"> | ||
765 | <xs:annotation> | ||
766 | <xs:appinfo> | ||
767 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
768 | </xs:appinfo> | ||
769 | <xs:documentation> | ||
770 | Represents a role assignment to an interface. | ||
771 | </xs:documentation> | ||
772 | </xs:annotation> | ||
773 | <xs:complexType> | ||
774 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
775 | <xs:annotation><xs:documentation> | ||
776 | Identifier for the element. | ||
777 | </xs:documentation></xs:annotation> | ||
778 | </xs:attribute> | ||
779 | <xs:attribute name="Interface" use="optional" type="xs:string"> | ||
780 | <xs:annotation><xs:documentation> | ||
781 | If the element is not a child of a ComPlusInterface | ||
782 | element, this attribute should be provided with the id of a ComPlusInterface | ||
783 | element representing the interface the role is to be added to. | ||
784 | </xs:documentation></xs:annotation> | ||
785 | </xs:attribute> | ||
786 | <xs:attribute name="ApplicationRole" use="required" type="xs:string"> | ||
787 | <xs:annotation><xs:documentation> | ||
788 | Id of the ComPlusApplicationRole element representing the | ||
789 | role that shall be granted access to the interface. | ||
790 | </xs:documentation></xs:annotation> | ||
791 | </xs:attribute> | ||
792 | </xs:complexType> | ||
793 | </xs:element> | ||
794 | |||
795 | <xs:element name="ComPlusMethod"> | ||
796 | <xs:annotation> | ||
797 | <xs:documentation> | ||
798 | Represents a method for an interface. | ||
799 | </xs:documentation> | ||
800 | </xs:annotation> | ||
801 | <xs:complexType> | ||
802 | <xs:sequence> | ||
803 | <xs:element ref="ComPlusRoleForMethod" minOccurs="0" maxOccurs="unbounded" /> | ||
804 | </xs:sequence> | ||
805 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
806 | <xs:annotation> | ||
807 | <xs:documentation> | ||
808 | Identifier for the element. | ||
809 | </xs:documentation> | ||
810 | </xs:annotation> | ||
811 | </xs:attribute> | ||
812 | <xs:attribute name="Index" use="optional" type="xs:int"> | ||
813 | <xs:annotation> | ||
814 | <xs:documentation> | ||
815 | Dispatch id of the method. If this attribute is not set a | ||
816 | value must be provided for the Name attribute. | ||
817 | </xs:documentation> | ||
818 | </xs:annotation> | ||
819 | </xs:attribute> | ||
820 | <xs:attribute name="Name" use="optional" type="xs:string"> | ||
821 | <xs:annotation> | ||
822 | <xs:documentation> | ||
823 | Name of the method. If this attribute is not set a value | ||
824 | must be provided for the Index attribute. | ||
825 | </xs:documentation> | ||
826 | </xs:annotation> | ||
827 | </xs:attribute> | ||
828 | <xs:attribute name="AutoComplete" use="optional" type="YesNoType" /> | ||
829 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
830 | </xs:complexType> | ||
831 | </xs:element> | ||
832 | |||
833 | <xs:element name="ComPlusRoleForMethod"> | ||
834 | <xs:annotation> | ||
835 | <xs:appinfo> | ||
836 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
837 | </xs:appinfo> | ||
838 | <xs:documentation> | ||
839 | Represents a role assignment to a COM+ method. | ||
840 | </xs:documentation> | ||
841 | </xs:annotation> | ||
842 | <xs:complexType> | ||
843 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
844 | <xs:annotation><xs:documentation> | ||
845 | Identifier for the element. | ||
846 | </xs:documentation></xs:annotation> | ||
847 | </xs:attribute> | ||
848 | <xs:attribute name="Method" use="optional" type="xs:string"> | ||
849 | <xs:annotation><xs:documentation> | ||
850 | If the element is not a child of a ComPlusMethod element, | ||
851 | this attribute should be provided with the id of a ComPlusMethod element | ||
852 | representing the method the role is to be added to. | ||
853 | </xs:documentation></xs:annotation> | ||
854 | </xs:attribute> | ||
855 | <xs:attribute name="ApplicationRole" use="required" type="xs:string"> | ||
856 | <xs:annotation><xs:documentation> | ||
857 | Id of the ComPlusApplicationRole element representing the | ||
858 | role that shall be granted access to the method. | ||
859 | </xs:documentation></xs:annotation> | ||
860 | </xs:attribute> | ||
861 | </xs:complexType> | ||
862 | </xs:element> | ||
863 | |||
864 | <xs:element name="ComPlusSubscription"> | ||
865 | <xs:annotation> | ||
866 | <xs:appinfo> | ||
867 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
868 | </xs:appinfo> | ||
869 | <xs:documentation> | ||
870 | Defines an event subscription for a COM+ component. | ||
871 | </xs:documentation> | ||
872 | </xs:annotation> | ||
873 | <xs:complexType> | ||
874 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
875 | <xs:annotation><xs:documentation> | ||
876 | Identifier for the element. | ||
877 | </xs:documentation></xs:annotation> | ||
878 | </xs:attribute> | ||
879 | <xs:attribute name="Component" use="optional" type="xs:string"> | ||
880 | <xs:annotation><xs:documentation> | ||
881 | If the element is not a child of a ComPlusComponent | ||
882 | element, this attribute should be provided with the id of a ComPlusComponent | ||
883 | element representing the component the subscription is to be created for. | ||
884 | </xs:documentation></xs:annotation> | ||
885 | </xs:attribute> | ||
886 | <xs:attribute name="SubscriptionId" use="optional" type="xs:string"> | ||
887 | <xs:annotation><xs:documentation> | ||
888 | Id of the subscription. If a value is not provided for | ||
889 | this attribute, an id will be generated during installation. | ||
890 | </xs:documentation></xs:annotation> | ||
891 | </xs:attribute> | ||
892 | <xs:attribute name="Name" use="required" type="xs:string"> | ||
893 | <xs:annotation><xs:documentation> | ||
894 | Name of the subscription. | ||
895 | </xs:documentation></xs:annotation> | ||
896 | </xs:attribute> | ||
897 | <xs:attribute name="EventCLSID" use="optional" type="xs:string"> | ||
898 | <xs:annotation><xs:documentation> | ||
899 | CLSID of the event class for the subscription. If a value | ||
900 | for this attribute is not provided, a value for the PublisherID attribute | ||
901 | must be provided. | ||
902 | </xs:documentation></xs:annotation> | ||
903 | </xs:attribute> | ||
904 | <xs:attribute name="PublisherID" use="optional" type="xs:string"> | ||
905 | <xs:annotation><xs:documentation> | ||
906 | Publisher id for the subscription. If a value for this | ||
907 | attribute is not provided, a value for the EventCLSID attribute must be | ||
908 | provided. | ||
909 | </xs:documentation></xs:annotation> | ||
910 | </xs:attribute> | ||
911 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
912 | <xs:attribute name="Enabled" use="optional" type="YesNoType" /> | ||
913 | <xs:attribute name="EventClassPartitionID" use="optional" type="xs:string" /> | ||
914 | <xs:attribute name="FilterCriteria" use="optional" type="xs:string" /> | ||
915 | <xs:attribute name="InterfaceID" use="optional" type="xs:string" /> | ||
916 | <xs:attribute name="MachineName" use="optional" type="xs:string" /> | ||
917 | <xs:attribute name="MethodName" use="optional" type="xs:string" /> | ||
918 | <xs:attribute name="PerUser" use="optional" type="YesNoType" /> | ||
919 | <xs:attribute name="Queued" use="optional" type="YesNoType" /> | ||
920 | <xs:attribute name="SubscriberMoniker" use="optional" type="xs:string" /> | ||
921 | <xs:attribute name="UserName" use="optional" type="xs:string" /> | ||
922 | </xs:complexType> | ||
923 | </xs:element> | ||
924 | |||
925 | <xs:simpleType name="YesNoType"> | ||
926 | <xs:annotation> | ||
927 | <xs:documentation>Values of this type will either be "yes" or "no".</xs:documentation> | ||
928 | </xs:annotation> | ||
929 | <xs:restriction base="xs:NMTOKEN"> | ||
930 | <xs:enumeration value="no" /> | ||
931 | <xs:enumeration value="yes" /> | ||
932 | </xs:restriction> | ||
933 | </xs:simpleType> | ||
934 | |||
935 | <xs:simpleType name="uuid"> | ||
936 | <xs:annotation> | ||
937 | <xs:documentation>Values of this type will look like: "01234567-89AB-CDEF-0123-456789ABCDEF".</xs:documentation> | ||
938 | </xs:annotation> | ||
939 | <xs:restriction base="xs:string"> | ||
940 | <xs:pattern value="[0-9A-Fa-f]{8}\-?[0-9A-Fa-f]{4}\-?[0-9A-Fa-f]{4}\-?[0-9A-Fa-f]{4}\-?[0-9A-Fa-f]{12}" /> | ||
941 | </xs:restriction> | ||
942 | </xs:simpleType> | ||
943 | |||
944 | </xs:schema> | ||
diff --git a/src/wixext/messages.xml b/src/wixext/messages.xml new file mode 100644 index 00000000..66c0a9e6 --- /dev/null +++ b/src/wixext/messages.xml | |||
@@ -0,0 +1,77 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- 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. --> | ||
3 | |||
4 | |||
5 | <Messages Namespace="WixToolset.Extensions" Resources="Data.Messages" xmlns="http://schemas.microsoft.com/genmsgs/2004/07/messages"> | ||
6 | <Class Name="ComPlusErrors" ContainerName="ComPlusErrorEventArgs" BaseContainerName="MessageEventArgs"> | ||
7 | <Message Id="IllegalAttributeWithoutComponent" Number="6000"> | ||
8 | <Instance> | ||
9 | The {0}/@{1} attribute cannot be specified unless the element has a component as an ancestor. A {0} that does not have a component ancestor is not installed. | ||
10 | <Parameter Type="System.String" Name="elementName" /> | ||
11 | <Parameter Type="System.String" Name="attributeName" /> | ||
12 | </Instance> | ||
13 | </Message> | ||
14 | <Message Id="IllegalElementWithoutComponent" Number="6001"> | ||
15 | <Instance> | ||
16 | The {0} element cannot be specified unless the element has a component as an ancestor. A {0} that does not have a component ancestor is not installed. | ||
17 | <Parameter Type="System.String" Name="elementName" /> | ||
18 | </Instance> | ||
19 | </Message> | ||
20 | <Message Id="UnexpectedAttributeWithOtherValue" Number="6002"> | ||
21 | <Instance> | ||
22 | The {0}/@{1} attribute cannot coexist with the {2} attribute's value of '{3}'. | ||
23 | <Parameter Type="System.String" Name="elementName" /> | ||
24 | <Parameter Type="System.String" Name="attributeName" /> | ||
25 | <Parameter Type="System.String" Name="otherAttributeName" /> | ||
26 | <Parameter Type="System.String" Name="otherValue" /> | ||
27 | </Instance> | ||
28 | <Instance> | ||
29 | The {0}/@{1} attribute's value, '{2}', cannot coexist with the {3} attribute's value of '{4}'. | ||
30 | <Parameter Type="System.String" Name="elementName" /> | ||
31 | <Parameter Type="System.String" Name="attributeName" /> | ||
32 | <Parameter Type="System.String" Name="value" /> | ||
33 | <Parameter Type="System.String" Name="otherAttributeName" /> | ||
34 | <Parameter Type="System.String" Name="otherValue" /> | ||
35 | </Instance> | ||
36 | </Message> | ||
37 | <Message Id="UnexpectedAttributeWithoutOtherValue" Number="6003"> | ||
38 | <Instance> | ||
39 | The {0}/@{1} cannot be provided unless the {2} attribute is provided with a value of '{3}'. | ||
40 | <Parameter Type="System.String" Name="elementName" /> | ||
41 | <Parameter Type="System.String" Name="attributeName" /> | ||
42 | <Parameter Type="System.String" Name="otherAttributeName" /> | ||
43 | <Parameter Type="System.String" Name="otherValue" /> | ||
44 | </Instance> | ||
45 | </Message> | ||
46 | <Message Id="RequiredAttributeUnderComponent" Number="6004"> | ||
47 | <Instance> | ||
48 | The {0}/@{1} attribute must be provided when {0} element is nested under a component. | ||
49 | <Parameter Type="System.String" Name="elementName" /> | ||
50 | <Parameter Type="System.String" Name="attributeName" /> | ||
51 | </Instance> | ||
52 | </Message> | ||
53 | <Message Id="RequiredAttribute" Number="6005"> | ||
54 | <Instance> | ||
55 | A {0} element must have either a {1} attribute or a {2} attribute, or both set. | ||
56 | <Parameter Type="System.String" Name="elementName" /> | ||
57 | <Parameter Type="System.String" Name="attributeName1" /> | ||
58 | <Parameter Type="System.String" Name="attributeName2" /> | ||
59 | </Instance> | ||
60 | </Message> | ||
61 | <Message Id="RequiredAttributeNotUnderComponent" Number="6006"> | ||
62 | <Instance> | ||
63 | A {0} element not nested under a component must have either a {1} attribute or a {2} attribute, or both set. | ||
64 | <Parameter Type="System.String" Name="elementName" /> | ||
65 | <Parameter Type="System.String" Name="attributeName1" /> | ||
66 | <Parameter Type="System.String" Name="attributeName2" /> | ||
67 | </Instance> | ||
68 | </Message> | ||
69 | </Class> | ||
70 | <Class Name="ComPlusWarnings" ContainerName="ComPlusWarningEventArgs" BaseContainerName="MessageEventArgs"> | ||
71 | <Message Id="MissingComponents" Number="6007"> | ||
72 | <Instance>The ComPlusAssembly element has a Type attribute with a value of 'native', but the element does not contain any ComPlusComponent elements. All components contained in a native assembly must be listed, or they will not be correctly removed during uninstall.</Instance> | ||
73 | </Message> | ||
74 | </Class> | ||
75 | <Class Name="ComPlusVerboses" ContainerName="ComPlusVerboseEventArgs" BaseContainerName="MessageEventArgs"> | ||
76 | </Class> | ||
77 | </Messages> | ||
diff --git a/src/wixext/tables.xml b/src/wixext/tables.xml new file mode 100644 index 00000000..3c3d1728 --- /dev/null +++ b/src/wixext/tables.xml | |||
@@ -0,0 +1,250 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- 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. --> | ||
3 | |||
4 | |||
5 | <tableDefinitions xmlns="http://wixtoolset.org/schemas/v4/wi/tables"> | ||
6 | <tableDefinition name="ComPlusPartition" createSymbols="yes"> | ||
7 | <columnDefinition name="Partition" type="string" length="72" primaryKey="yes" modularize="column" | ||
8 | category="identifier" description=""/> | ||
9 | <columnDefinition name="Component_" type="string" length="72" nullable="yes" modularize="column" | ||
10 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
11 | <columnDefinition name="Id" type="string" length="72" nullable="yes" modularize="property" | ||
12 | category="formatted" description=""/> | ||
13 | <columnDefinition name="Name" type="string" length="255" nullable="yes" modularize="property" | ||
14 | category="formatted" description=""/> | ||
15 | </tableDefinition> | ||
16 | <tableDefinition name="ComPlusPartitionProperty"> | ||
17 | <columnDefinition name="Partition_" type="string" length="72" primaryKey="yes" modularize="column" | ||
18 | keyTable="ComPlusPartition" keyColumn="1" category="identifier" description=""/> | ||
19 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
20 | category="formatted" description=""/> | ||
21 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
22 | category="formatted" description=""/> | ||
23 | </tableDefinition> | ||
24 | <tableDefinition name="ComPlusPartitionRole" createSymbols="yes"> | ||
25 | <columnDefinition name="PartitionRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
26 | category="identifier" description=""/> | ||
27 | <columnDefinition name="Partition_" type="string" length="72" modularize="column" | ||
28 | keyTable="ComPlusPartition" keyColumn="1" category="identifier" description=""/> | ||
29 | <columnDefinition name="Component_" type="string" length="72" nullable="yes" modularize="column" | ||
30 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
31 | <columnDefinition name="Name" type="string" length="255" modularize="property" | ||
32 | category="formatted" description=""/> | ||
33 | </tableDefinition> | ||
34 | <tableDefinition name="ComPlusUserInPartitionRole" createSymbols="yes"> | ||
35 | <columnDefinition name="UserInPartitionRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
36 | category="identifier" description=""/> | ||
37 | <columnDefinition name="PartitionRole_" type="string" length="72" modularize="column" | ||
38 | keyTable="ComPlusPartitionRole" keyColumn="1" category="identifier" description=""/> | ||
39 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
40 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
41 | <columnDefinition name="User_" type="string" length="72" modularize="column" | ||
42 | category="identifier" description=""/> | ||
43 | </tableDefinition> | ||
44 | <tableDefinition name="ComPlusGroupInPartitionRole" createSymbols="yes"> | ||
45 | <columnDefinition name="GroupInPartitionRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
46 | category="identifier" description=""/> | ||
47 | <columnDefinition name="PartitionRole_" type="string" length="72" modularize="column" | ||
48 | keyTable="ComPlusPartitionRole" keyColumn="1" category="identifier" description=""/> | ||
49 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
50 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
51 | <columnDefinition name="Group_" type="string" length="72" modularize="column" | ||
52 | category="identifier" description=""/> | ||
53 | </tableDefinition> | ||
54 | <tableDefinition name="ComPlusPartitionUser" createSymbols="yes"> | ||
55 | <columnDefinition name="PartitionUser" type="string" length="72" primaryKey="yes" modularize="column" | ||
56 | category="identifier" description=""/> | ||
57 | <columnDefinition name="Partition_" type="string" length="72" modularize="column" | ||
58 | keyTable="ComPlusPartition" keyColumn="1" category="identifier" description=""/> | ||
59 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
60 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
61 | <columnDefinition name="User_" type="string" length="72" modularize="column" | ||
62 | category="identifier" description=""/> | ||
63 | </tableDefinition> | ||
64 | <tableDefinition name="ComPlusApplication" createSymbols="yes"> | ||
65 | <columnDefinition name="Application" type="string" length="72" primaryKey="yes" modularize="column" | ||
66 | category="identifier" description=""/> | ||
67 | <columnDefinition name="Partition_" type="string" length="72" nullable="yes" modularize="column" | ||
68 | keyTable="ComPlusPartition" keyColumn="1" category="identifier" description=""/> | ||
69 | <columnDefinition name="Component_" type="string" length="72" nullable="yes" modularize="column" | ||
70 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
71 | <columnDefinition name="Id" type="string" length="72" nullable="yes" modularize="property" | ||
72 | category="formatted" description=""/> | ||
73 | <columnDefinition name="Name" type="string" length="255" nullable="yes" modularize="property" | ||
74 | category="formatted" description=""/> | ||
75 | </tableDefinition> | ||
76 | <tableDefinition name="ComPlusApplicationProperty"> | ||
77 | <columnDefinition name="Application_" type="string" length="72" primaryKey="yes" modularize="column" | ||
78 | keyTable="ComPlusApplication" keyColumn="1" category="identifier" description=""/> | ||
79 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
80 | category="formatted" description=""/> | ||
81 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
82 | category="formatted" description=""/> | ||
83 | </tableDefinition> | ||
84 | <tableDefinition name="ComPlusApplicationRole" createSymbols="yes"> | ||
85 | <columnDefinition name="ApplicationRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
86 | category="identifier" description=""/> | ||
87 | <columnDefinition name="Application_" type="string" length="72" modularize="column" | ||
88 | keyTable="ComPlusApplication" keyColumn="1" category="identifier" description=""/> | ||
89 | <columnDefinition name="Component_" type="string" length="72" nullable="yes" modularize="column" | ||
90 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
91 | <columnDefinition name="Name" type="string" length="255" modularize="property" | ||
92 | category="formatted" description=""/> | ||
93 | </tableDefinition> | ||
94 | <tableDefinition name="ComPlusApplicationRoleProperty"> | ||
95 | <columnDefinition name="ApplicationRole_" type="string" length="72" primaryKey="yes" modularize="column" | ||
96 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
97 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
98 | category="formatted" description=""/> | ||
99 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
100 | category="formatted" description=""/> | ||
101 | </tableDefinition> | ||
102 | <tableDefinition name="ComPlusUserInApplicationRole" createSymbols="yes"> | ||
103 | <columnDefinition name="UserInApplicationRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
104 | category="identifier" description=""/> | ||
105 | <columnDefinition name="ApplicationRole_" type="string" length="72" modularize="column" | ||
106 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
107 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
108 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
109 | <columnDefinition name="User_" type="string" length="72" modularize="column" | ||
110 | category="identifier" description=""/> | ||
111 | </tableDefinition> | ||
112 | <tableDefinition name="ComPlusGroupInApplicationRole" createSymbols="yes"> | ||
113 | <columnDefinition name="GroupInApplicationRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
114 | category="identifier" description=""/> | ||
115 | <columnDefinition name="ApplicationRole_" type="string" length="72" modularize="column" | ||
116 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
117 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
118 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
119 | <columnDefinition name="Group_" type="string" length="72" modularize="column" | ||
120 | category="identifier" description=""/> | ||
121 | </tableDefinition> | ||
122 | <tableDefinition name="ComPlusAssembly" createSymbols="yes"> | ||
123 | <columnDefinition name="Assembly" type="string" length="72" primaryKey="yes" modularize="column" | ||
124 | category="identifier" description=""/> | ||
125 | <columnDefinition name="Application_" type="string" length="72" nullable="yes" modularize="column" | ||
126 | keyTable="ComPlusApplication" keyColumn="1" category="identifier" description=""/> | ||
127 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
128 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
129 | <columnDefinition name="AssemblyName" type="string" length="255" nullable="yes" modularize="property" | ||
130 | category="formatted" description=""/> | ||
131 | <columnDefinition name="DllPath" type="string" length="255" nullable="yes" modularize="property" | ||
132 | category="formatted" description=""/> | ||
133 | <columnDefinition name="TlbPath" type="string" length="255" nullable="yes" modularize="property" | ||
134 | category="formatted" description=""/> | ||
135 | <columnDefinition name="PSDllPath" type="string" length="255" nullable="yes" modularize="property" | ||
136 | category="formatted" description=""/> | ||
137 | <columnDefinition name="Attributes" type="number" length="4" | ||
138 | description=""/> | ||
139 | </tableDefinition> | ||
140 | <tableDefinition name="ComPlusAssemblyDependency"> | ||
141 | <columnDefinition name="Assembly_" type="string" length="72" primaryKey="yes" modularize="column" | ||
142 | keyTable="ComPlusAssembly" keyColumn="1" category="identifier" description=""/> | ||
143 | <columnDefinition name="RequiredAssembly_" type="string" length="72" primaryKey="yes" modularize="column" | ||
144 | keyTable="ComPlusAssembly" keyColumn="1" category="identifier" description=""/> | ||
145 | </tableDefinition> | ||
146 | <tableDefinition name="ComPlusComponent" createSymbols="yes"> | ||
147 | <columnDefinition name="ComPlusComponent" type="string" length="72" primaryKey="yes" modularize="column" | ||
148 | category="identifier" description=""/> | ||
149 | <columnDefinition name="Assembly_" type="string" length="72" modularize="column" | ||
150 | keyTable="ComPlusAssembly" keyColumn="1" category="identifier" description=""/> | ||
151 | <columnDefinition name="CLSID" type="string" length="72" modularize="property" | ||
152 | category="formatted" description=""/> | ||
153 | </tableDefinition> | ||
154 | <tableDefinition name="ComPlusComponentProperty"> | ||
155 | <columnDefinition name="ComPlusComponent_" type="string" length="72" primaryKey="yes" modularize="column" | ||
156 | keyTable="ComPlusComponent" keyColumn="1" category="identifier" description=""/> | ||
157 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
158 | category="formatted" description=""/> | ||
159 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
160 | category="formatted" description=""/> | ||
161 | </tableDefinition> | ||
162 | <tableDefinition name="ComPlusRoleForComponent" createSymbols="yes"> | ||
163 | <columnDefinition name="RoleForComponent" type="string" length="72" primaryKey="yes" modularize="column" | ||
164 | category="identifier" description=""/> | ||
165 | <columnDefinition name="ComPlusComponent_" type="string" length="72" modularize="column" | ||
166 | keyTable="ComPlusComponent" keyColumn="1" category="identifier" description=""/> | ||
167 | <columnDefinition name="ApplicationRole_" type="string" length="72" modularize="column" | ||
168 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
169 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
170 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
171 | </tableDefinition> | ||
172 | <tableDefinition name="ComPlusInterface" createSymbols="yes"> | ||
173 | <columnDefinition name="Interface" type="string" length="72" primaryKey="yes" modularize="column" | ||
174 | category="identifier" description=""/> | ||
175 | <columnDefinition name="ComPlusComponent_" type="string" length="72" modularize="column" | ||
176 | keyTable="ComPlusComponent" keyColumn="1" category="identifier" description=""/> | ||
177 | <columnDefinition name="IID" type="string" length="72" modularize="property" | ||
178 | category="formatted" description=""/> | ||
179 | </tableDefinition> | ||
180 | <tableDefinition name="ComPlusInterfaceProperty"> | ||
181 | <columnDefinition name="Interface_" type="string" length="72" primaryKey="yes" modularize="column" | ||
182 | keyTable="ComPlusInterface" keyColumn="1" category="identifier" description=""/> | ||
183 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
184 | category="formatted" description=""/> | ||
185 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
186 | category="formatted" description=""/> | ||
187 | </tableDefinition> | ||
188 | <tableDefinition name="ComPlusRoleForInterface" createSymbols="yes"> | ||
189 | <columnDefinition name="RoleForInterface" type="string" length="72" primaryKey="yes" modularize="column" | ||
190 | category="identifier" description=""/> | ||
191 | <columnDefinition name="Interface_" type="string" length="72" modularize="column" | ||
192 | keyTable="ComPlusInterface" keyColumn="1" category="identifier" description=""/> | ||
193 | <columnDefinition name="ApplicationRole_" type="string" length="72" modularize="column" | ||
194 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
195 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
196 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
197 | </tableDefinition> | ||
198 | <tableDefinition name="ComPlusMethod" createSymbols="yes"> | ||
199 | <columnDefinition name="Method" type="string" length="72" primaryKey="yes" modularize="column" | ||
200 | category="identifier" description=""/> | ||
201 | <columnDefinition name="Interface_" type="string" length="72" modularize="column" | ||
202 | keyTable="ComPlusInterface" keyColumn="1" category="identifier" description=""/> | ||
203 | <columnDefinition name="Index" type="number" length="4" nullable="yes" | ||
204 | description=""/> | ||
205 | <columnDefinition name="Name" type="string" length="255" nullable="yes" modularize="property" | ||
206 | category="formatted" description=""/> | ||
207 | </tableDefinition> | ||
208 | <tableDefinition name="ComPlusMethodProperty"> | ||
209 | <columnDefinition name="Method_" type="string" length="72" primaryKey="yes" modularize="column" | ||
210 | keyTable="ComPlusMethod" keyColumn="1" category="identifier" description=""/> | ||
211 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
212 | category="formatted" description=""/> | ||
213 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
214 | category="formatted" description=""/> | ||
215 | </tableDefinition> | ||
216 | <tableDefinition name="ComPlusRoleForMethod" createSymbols="yes"> | ||
217 | <columnDefinition name="RoleForMethod" type="string" length="72" primaryKey="yes" modularize="column" | ||
218 | category="identifier" description=""/> | ||
219 | <columnDefinition name="Method_" type="string" length="72" modularize="column" | ||
220 | keyTable="ComPlusMethod" keyColumn="1" category="identifier" description=""/> | ||
221 | <columnDefinition name="ApplicationRole_" type="string" length="72" modularize="column" | ||
222 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
223 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
224 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
225 | </tableDefinition> | ||
226 | <tableDefinition name="ComPlusSubscription" createSymbols="yes"> | ||
227 | <columnDefinition name="Subscription" type="string" length="72" primaryKey="yes" modularize="column" | ||
228 | category="identifier" description=""/> | ||
229 | <columnDefinition name="ComPlusComponent_" type="string" length="72" primaryKey="yes" modularize="column" | ||
230 | keyTable="ComPlusComponent" keyColumn="1" category="identifier" description=""/> | ||
231 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
232 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
233 | <columnDefinition name="Id" type="string" length="72" nullable="yes" modularize="property" | ||
234 | category="formatted" description=""/> | ||
235 | <columnDefinition name="Name" type="string" length="255" modularize="property" | ||
236 | category="formatted" description=""/> | ||
237 | <columnDefinition name="EventCLSID" type="string" length="72" nullable="yes" modularize="property" | ||
238 | category="formatted" description=""/> | ||
239 | <columnDefinition name="PublisherID" type="string" length="72" nullable="yes" modularize="property" | ||
240 | category="formatted" description=""/> | ||
241 | </tableDefinition> | ||
242 | <tableDefinition name="ComPlusSubscriptionProperty"> | ||
243 | <columnDefinition name="Subscription_" type="string" length="72" primaryKey="yes" modularize="column" | ||
244 | keyTable="ComPlusSubscription" keyColumn="1" category="identifier" description=""/> | ||
245 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
246 | category="formatted" description=""/> | ||
247 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
248 | category="formatted" description=""/> | ||
249 | </tableDefinition> | ||
250 | </tableDefinitions> | ||
diff --git a/src/wixlib/ComPlusExtension.wixproj b/src/wixlib/ComPlusExtension.wixproj new file mode 100644 index 00000000..49c688cd --- /dev/null +++ b/src/wixlib/ComPlusExtension.wixproj | |||
@@ -0,0 +1,26 @@ | |||
1 | <?xml version="1.0" encoding="utf-8" ?> | ||
2 | <!-- 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. --> | ||
3 | |||
4 | |||
5 | <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | ||
6 | <PropertyGroup> | ||
7 | <ProjectGuid>{E191E61E-E098-4F71-888F-51A79F952022}</ProjectGuid> | ||
8 | <OutputName>complus</OutputName> | ||
9 | <OutputType>Library</OutputType> | ||
10 | <BindFiles>true</BindFiles> | ||
11 | <SuppressSpecificWarnings>1086</SuppressSpecificWarnings> | ||
12 | </PropertyGroup> | ||
13 | |||
14 | <ItemGroup> | ||
15 | <Compile Include="ComPlusExtension.wxs" /> | ||
16 | <EmbeddedResource Include="en-us.wxl" /> | ||
17 | <EmbeddedResource Include="es-es.wxl" /> | ||
18 | <EmbeddedResource Include="ja-jp.wxl" /> | ||
19 | </ItemGroup> | ||
20 | |||
21 | <ItemGroup> | ||
22 | <ProjectReference Include="..\ca\complusca.proj" /> | ||
23 | </ItemGroup> | ||
24 | |||
25 | <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.targets" /> | ||
26 | </Project> | ||
diff --git a/src/wixlib/ComPlusExtension.wxs b/src/wixlib/ComPlusExtension.wxs new file mode 100644 index 00000000..3a5c1512 --- /dev/null +++ b/src/wixlib/ComPlusExtension.wxs | |||
@@ -0,0 +1,139 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- 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. --> | ||
3 | |||
4 | |||
5 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
6 | <?include caerr.wxi ?> | ||
7 | |||
8 | <Fragment> | ||
9 | <UI Id="ComPlusUI"> | ||
10 | <Error Id="$(var.msierrComPlusCannotConnect)">!(loc.msierrComPlusCannotConnect)</Error> | ||
11 | <Error Id="$(var.msierrComPlusPartitionReadFailed)">!(loc.msierrComPlusPartitionReadFailed)</Error> | ||
12 | <Error Id="$(var.msierrComPlusPartitionRoleReadFailed)">!(loc.msierrComPlusPartitionRoleReadFailed)</Error> | ||
13 | <Error Id="$(var.msierrComPlusUserInPartitionRoleReadFailed)">!(loc.msierrComPlusUserInPartitionRoleReadFailed)</Error> | ||
14 | <Error Id="$(var.msierrComPlusPartitionUserReadFailed)">!(loc.msierrComPlusPartitionUserReadFailed)</Error> | ||
15 | <Error Id="$(var.msierrComPlusApplicationReadFailed)">!(loc.msierrComPlusApplicationReadFailed)</Error> | ||
16 | <Error Id="$(var.msierrComPlusApplicationRoleReadFailed)">!(loc.msierrComPlusApplicationRoleReadFailed)</Error> | ||
17 | <Error Id="$(var.msierrComPlusUserInApplicationRoleReadFailed)">!(loc.msierrComPlusUserInApplicationRoleReadFailed)</Error> | ||
18 | <Error Id="$(var.msierrComPlusAssembliesReadFailed)">!(loc.msierrComPlusAssembliesReadFailed)</Error> | ||
19 | <Error Id="$(var.msierrComPlusSubscriptionReadFailed)">!(loc.msierrComPlusSubscriptionReadFailed)</Error> | ||
20 | <Error Id="$(var.msierrComPlusPartitionDependency)">!(loc.msierrComPlusPartitionDependency)</Error> | ||
21 | <Error Id="$(var.msierrComPlusPartitionNotFound)">!(loc.msierrComPlusPartitionNotFound)</Error> | ||
22 | <Error Id="$(var.msierrComPlusPartitionIdConflict)">!(loc.msierrComPlusPartitionIdConflict)</Error> | ||
23 | <Error Id="$(var.msierrComPlusPartitionNameConflict)">!(loc.msierrComPlusPartitionNameConflict)</Error> | ||
24 | <Error Id="$(var.msierrComPlusApplicationDependency)">!(loc.msierrComPlusApplicationDependency)</Error> | ||
25 | <Error Id="$(var.msierrComPlusApplicationNotFound)">!(loc.msierrComPlusApplicationNotFound)</Error> | ||
26 | <Error Id="$(var.msierrComPlusApplicationIdConflict)">!(loc.msierrComPlusApplicationIdConflict)</Error> | ||
27 | <Error Id="$(var.msierrComPlusApplicationNameConflict)">!(loc.msierrComPlusApplicationNameConflict)</Error> | ||
28 | <Error Id="$(var.msierrComPlusApplicationRoleDependency)">!(loc.msierrComPlusApplicationRoleDependency)</Error> | ||
29 | <Error Id="$(var.msierrComPlusApplicationRoleNotFound)">!(loc.msierrComPlusApplicationRoleNotFound)</Error> | ||
30 | <Error Id="$(var.msierrComPlusApplicationRoleConflict)">!(loc.msierrComPlusApplicationRoleConflict)</Error> | ||
31 | <Error Id="$(var.msierrComPlusAssemblyDependency)">!(loc.msierrComPlusAssemblyDependency)</Error> | ||
32 | <Error Id="$(var.msierrComPlusSubscriptionIdConflict)">!(loc.msierrComPlusSubscriptionIdConflict)</Error> | ||
33 | <Error Id="$(var.msierrComPlusSubscriptionNameConflict)">!(loc.msierrComPlusSubscriptionNameConflict)</Error> | ||
34 | <Error Id="$(var.msierrComPlusFailedLookupNames)">!(loc.msierrComPlusFailedLookupNames)</Error> | ||
35 | |||
36 | <ProgressText Action="ComPlusInstallExecute">!(loc.ComPlusInstallExecute)</ProgressText> | ||
37 | <ProgressText Action="ComPlusUninstallExecute">!(loc.ComPlusUninstallExecute)</ProgressText> | ||
38 | |||
39 | <ProgressText Action="CreateComPlusPartitions" Template="!(loc.CreateComPlusPartitionsTemplate)">!(loc.CreateComPlusPartitions)</ProgressText> | ||
40 | <ProgressText Action="RemoveComPlusPartitions" Template="!(loc.RemoveComPlusPartitionsTemplate)">!(loc.RemoveComPlusPartitions)</ProgressText> | ||
41 | <ProgressText Action="AddUsersToComPlusPartitionRoles" Template="!(loc.AddUsersToComPlusPartitionRolesTemplate)">!(loc.AddUsersToComPlusPartitionRoles)</ProgressText> | ||
42 | <ProgressText Action="RemoveUsersFromComPlusPartRoles" Template="!(loc.RemoveUsersFromComPlusPartitionRolesTemplate)">!(loc.RemoveUsersFromComPlusPartitionRoles)</ProgressText> | ||
43 | <ProgressText Action="AddComPlusPartitionUsers" Template="!(loc.AddComPlusPartitionUsersTemplate)">!(loc.AddComPlusPartitionUsers)</ProgressText> | ||
44 | <ProgressText Action="RemoveComPlusPartitionUsers" Template="!(loc.RemoveComPlusPartitionUsersTemplate)">!(loc.RemoveComPlusPartitionUsers)</ProgressText> | ||
45 | <ProgressText Action="CreateComPlusApplications" Template="!(loc.CreateComPlusApplicationsTemplate)">!(loc.CreateComPlusApplications)</ProgressText> | ||
46 | <ProgressText Action="RemoveComPlusApplications" Template="!(loc.RemoveComPlusApplicationsTemplate)">!(loc.RemoveComPlusApplications)</ProgressText> | ||
47 | <ProgressText Action="CreateComPlusApplicationRoles" Template="!(loc.CreateComPlusApplicationRolesTemplate)">!(loc.CreateComPlusApplicationRoles)</ProgressText> | ||
48 | <ProgressText Action="RemoveComPlusApplicationRoles" Template="!(loc.RemoveComPlusApplicationRolesTemplate)">!(loc.RemoveComPlusApplicationRoles)</ProgressText> | ||
49 | <ProgressText Action="AddUsersToComPlusApplicationRoles" Template="!(loc.AddUsersToComPlusApplicationRolesTemplate)">!(loc.AddUsersToComPlusApplicationRoles)</ProgressText> | ||
50 | <ProgressText Action="RemoveUsersFromComPlusAppRoles" Template="!(loc.RemoveUsersFromComPlusApplicationRolesTemplate)">!(loc.RemoveUsersFromComPlusApplicationRoles)</ProgressText> | ||
51 | <ProgressText Action="RegisterComPlusAssemblies" Template="!(loc.RegisterComPlusAssembliesTemplate)">!(loc.RegisterComPlusAssemblies)</ProgressText> | ||
52 | <ProgressText Action="UnregisterComPlusAssemblies" Template="!(loc.UnregisterComPlusAssembliesTemplate)">!(loc.UnregisterComPlusAssemblies)</ProgressText> | ||
53 | <ProgressText Action="AddComPlusRoleAssignments" Template="!(loc.AddComPlusRoleAssignmentsTemplate)">!(loc.AddComPlusRoleAssignments)</ProgressText> | ||
54 | <ProgressText Action="RemoveComPlusRoleAssignments" Template="!(loc.RemoveComPlusRoleAssignmentsTemplate)">!(loc.RemoveComPlusRoleAssignments)</ProgressText> | ||
55 | <ProgressText Action="CreateSubscrComPlusComponents" Template="!(loc.CreateSubscriptionsComPlusComponentsTemplate)">!(loc.CreateSubscriptionsComPlusComponents)</ProgressText> | ||
56 | <ProgressText Action="RemoveSubscrComPlusComponents" Template="!(loc.RemoveSubscriptionsComPlusComponentsTemplate)">!(loc.RemoveSubscriptionsComPlusComponents)</ProgressText> | ||
57 | </UI> | ||
58 | </Fragment> | ||
59 | |||
60 | <Fragment> | ||
61 | <UIRef Id="ComPlusUI" /> | ||
62 | |||
63 | <CustomAction Id="ConfigureComPlusInstall" BinaryKey="WixCPSched_x86" DllEntry="ConfigureComPlusInstall" Execute="immediate" Return="check" SuppressModularization="yes" /> | ||
64 | <CustomAction Id="ConfigureComPlusUninstall" BinaryKey="WixCPSched_x86" DllEntry="ConfigureComPlusUninstall" Execute="immediate" Return="check" SuppressModularization="yes" /> | ||
65 | <CustomAction Id="ComPlusInstallPrepare" BinaryKey="WixCPExec_x86" DllEntry="ComPlusPrepare" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
66 | <CustomAction Id="ComPlusRollbackInstallPrepare" BinaryKey="WixCPExec_x86" DllEntry="ComPlusCleanup" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
67 | <CustomAction Id="ComPlusInstallExecute" BinaryKey="WixCPExec_x86" DllEntry="ComPlusInstallExecute" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
68 | <CustomAction Id="ComPlusInstallExecuteCommit" BinaryKey="WixCPExec_x86" DllEntry="ComPlusInstallExecuteCommit" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
69 | <CustomAction Id="ComPlusRollbackInstallExecute" BinaryKey="WixCPExec_x86" DllEntry="ComPlusRollbackInstallExecute" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
70 | <CustomAction Id="ComPlusInstallCommit" BinaryKey="WixCPExec_x86" DllEntry="ComPlusCleanup" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
71 | <CustomAction Id="ComPlusUninstallPrepare" BinaryKey="WixCPExec_x86" DllEntry="ComPlusPrepare" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
72 | <CustomAction Id="ComPlusRollbackUninstallPrepare" BinaryKey="WixCPExec_x86" DllEntry="ComPlusCleanup" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
73 | <CustomAction Id="ComPlusUninstallExecute" BinaryKey="WixCPExec_x86" DllEntry="ComPlusUninstallExecute" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
74 | <CustomAction Id="ComPlusRollbackUninstallExecute" BinaryKey="WixCPExec_x86" DllEntry="ComPlusInstallExecute" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
75 | <CustomAction Id="ComPlusUninstallCommit" BinaryKey="WixCPExec_x86" DllEntry="ComPlusCleanup" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
76 | |||
77 | <Property Id="ComPlusInstallPrepare" Hidden="yes" SuppressModularization="yes" /> | ||
78 | <Property Id="ComPlusRollbackInstallPrepare" Hidden="yes" SuppressModularization="yes" /> | ||
79 | <Property Id="ComPlusInstallExecute" Hidden="yes" SuppressModularization="yes" /> | ||
80 | <Property Id="ComPlusInstallExecuteCommit" Hidden="yes" SuppressModularization="yes" /> | ||
81 | <Property Id="ComPlusRollbackInstallExecute" Hidden="yes" SuppressModularization="yes" /> | ||
82 | <Property Id="ComPlusInstallCommit" Hidden="yes" SuppressModularization="yes" /> | ||
83 | <Property Id="ComPlusUninstallPrepare" Hidden="yes" SuppressModularization="yes" /> | ||
84 | <Property Id="ComPlusRollbackUninstallPrepare" Hidden="yes" SuppressModularization="yes" /> | ||
85 | <Property Id="ComPlusUninstallExecute" Hidden="yes" SuppressModularization="yes" /> | ||
86 | <Property Id="ComPlusRollbackUninstallExecute" Hidden="yes" SuppressModularization="yes" /> | ||
87 | <Property Id="ComPlusUninstallCommit" Hidden="yes" SuppressModularization="yes" /> | ||
88 | |||
89 | <InstallExecuteSequence> | ||
90 | <Custom Action="ConfigureComPlusUninstall" After="DeleteServices" Overridable="yes">VersionNT >= 500</Custom> | ||
91 | <Custom Action="ConfigureComPlusInstall" Before="InstallServices" Overridable="yes">VersionNT >= 500</Custom> | ||
92 | </InstallExecuteSequence> | ||
93 | </Fragment> | ||
94 | |||
95 | <Fragment> | ||
96 | <UIRef Id="ComPlusUI" /> | ||
97 | |||
98 | <CustomAction Id="ConfigureComPlusInstall_x64" BinaryKey="WixCPSched_x64" DllEntry="ConfigureComPlusInstall" Execute="immediate" Return="check" SuppressModularization="yes" /> | ||
99 | <CustomAction Id="ConfigureComPlusUninstall_x64" BinaryKey="WixCPSched_x64" DllEntry="ConfigureComPlusUninstall" Execute="immediate" Return="check" SuppressModularization="yes" /> | ||
100 | <CustomAction Id="ComPlusInstallPrepare_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusPrepare" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
101 | <CustomAction Id="ComPlusRollbackInstallPrepare_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusCleanup" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
102 | <CustomAction Id="ComPlusInstallExecute_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusInstallExecute" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
103 | <CustomAction Id="ComPlusInstallExecuteCommit_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusInstallExecuteCommit" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
104 | <CustomAction Id="ComPlusRollbackInstallExecute_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusRollbackInstallExecute" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
105 | <CustomAction Id="ComPlusInstallCommit_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusCleanup" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
106 | <CustomAction Id="ComPlusUninstallPrepare_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusPrepare" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
107 | <CustomAction Id="ComPlusRollbackUninstallPrepare_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusCleanup" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
108 | <CustomAction Id="ComPlusUninstallExecute_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusUninstallExecute" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
109 | <CustomAction Id="ComPlusRollbackUninstallExecute_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusInstallExecute" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
110 | <CustomAction Id="ComPlusUninstallCommit_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusCleanup" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
111 | |||
112 | <Property Id="ComPlusInstallPrepare_64" Hidden="yes" SuppressModularization="yes" /> | ||
113 | <Property Id="ComPlusRollbackInstallPrepare_64" Hidden="yes" SuppressModularization="yes" /> | ||
114 | <Property Id="ComPlusInstallExecute_64" Hidden="yes" SuppressModularization="yes" /> | ||
115 | <Property Id="ComPlusInstallExecuteCommit_64" Hidden="yes" SuppressModularization="yes" /> | ||
116 | <Property Id="ComPlusRollbackInstallExecute_64" Hidden="yes" SuppressModularization="yes" /> | ||
117 | <Property Id="ComPlusInstallCommit_64" Hidden="yes" SuppressModularization="yes" /> | ||
118 | <Property Id="ComPlusUninstallPrepare_64" Hidden="yes" SuppressModularization="yes" /> | ||
119 | <Property Id="ComPlusRollbackUninstallPrepare_64" Hidden="yes" SuppressModularization="yes" /> | ||
120 | <Property Id="ComPlusUninstallExecute_64" Hidden="yes" SuppressModularization="yes" /> | ||
121 | <Property Id="ComPlusRollbackUninstallExecute_64" Hidden="yes" SuppressModularization="yes" /> | ||
122 | <Property Id="ComPlusUninstallCommit_64" Hidden="yes" SuppressModularization="yes" /> | ||
123 | |||
124 | <InstallExecuteSequence> | ||
125 | <Custom Action="ConfigureComPlusUninstall_x64" After="DeleteServices" Overridable="yes">VersionNT >= 500</Custom> | ||
126 | <Custom Action="ConfigureComPlusInstall_x64" Before="InstallServices" Overridable="yes">VersionNT >= 500</Custom> | ||
127 | </InstallExecuteSequence> | ||
128 | </Fragment> | ||
129 | |||
130 | <Fragment> | ||
131 | <Binary Id="WixCPExec_x86" SourceFile="!(bindpath.x86)\cpexec.dll"/> | ||
132 | <Binary Id="WixCPSched_x86" SourceFile="!(bindpath.x86)\cpsched.dll"/> | ||
133 | </Fragment> | ||
134 | |||
135 | <Fragment> | ||
136 | <Binary Id="WixCPExec_x64" SourceFile="!(bindpath.x64)\cpexec.dll"/> | ||
137 | <Binary Id="WixCPSched_x64" SourceFile="!(bindpath.x64)\cpsched.dll"/> | ||
138 | </Fragment> | ||
139 | </Wix> | ||
diff --git a/src/wixlib/en-us.wxl b/src/wixlib/en-us.wxl new file mode 100644 index 00000000..8f6f38fc --- /dev/null +++ b/src/wixlib/en-us.wxl | |||
@@ -0,0 +1,71 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- 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. --> | ||
3 | |||
4 | |||
5 | <WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
6 | <String Id="msierrComPlusCannotConnect" Overridable="yes">Cannot connect to the COM+ admin catalog. ([2] [3] [4] [5])</String> | ||
7 | <String Id="msierrComPlusPartitionReadFailed" Overridable="yes">Failed to read COM+ partitions. ([2] [3] [4] [5])</String> | ||
8 | <String Id="msierrComPlusPartitionRoleReadFailed" Overridable="yes">Failed to read COM+ partition roles. ([2] [3] [4] [5])</String> | ||
9 | <String Id="msierrComPlusUserInPartitionRoleReadFailed" Overridable="yes">Failed to read COM+ users in partition roles. ([2] [3] [4] [5])</String> | ||
10 | <String Id="msierrComPlusPartitionUserReadFailed" Overridable="yes">Failed to read COM+ partition users. ([2] [3] [4] [5])</String> | ||
11 | <String Id="msierrComPlusApplicationReadFailed" Overridable="yes">Failed to read COM+ applications. ([2] [3] [4] [5])</String> | ||
12 | <String Id="msierrComPlusApplicationRoleReadFailed" Overridable="yes">Failed to read COM+ application roles. ([2] [3] [4] [5])</String> | ||
13 | <String Id="msierrComPlusUserInApplicationRoleReadFailed" Overridable="yes">Failed to read COM+ users in application roles. ([2] [3] [4] [5])</String> | ||
14 | <String Id="msierrComPlusAssembliesReadFailed" Overridable="yes">Failed to read COM+ assemblies. ([2] [3] [4] [5])</String> | ||
15 | <String Id="msierrComPlusSubscriptionReadFailed" Overridable="yes">Failed to read COM+ event subscriptions. ([2] [3] [4] [5])</String> | ||
16 | <String Id="msierrComPlusPartitionDependency" Overridable="yes">Another entity is dependent on a COM+ partition that is not being installed. ([2] [3] [4] [5])</String> | ||
17 | <String Id="msierrComPlusPartitionNotFound" Overridable="yes">The COM+ partition was not found. ([2] [3] [4] [5])</String> | ||
18 | <String Id="msierrComPlusPartitionIdConflict" Overridable="yes">A COM+ partition with the same id already exists. ([2] [3] [4] [5])</String> | ||
19 | <String Id="msierrComPlusPartitionNameConflict" Overridable="yes">A COM+ partition with the same name already exists. ([2] [3] [4] [5])</String> | ||
20 | <String Id="msierrComPlusApplicationDependency" Overridable="yes">Another entity is dependent on a COM+ application that is not being installed. ([2] [3] [4] [5])</String> | ||
21 | <String Id="msierrComPlusApplicationNotFound" Overridable="yes">The COM+ application was not found. ([2] [3] [4] [5])</String> | ||
22 | <String Id="msierrComPlusApplicationIdConflict" Overridable="yes">A COM+ application with the same id already exists. ([2] [3] [4] [5])</String> | ||
23 | <String Id="msierrComPlusApplicationNameConflict" Overridable="yes">A COM+ application with the same name already exists. ([2] [3] [4] [5])</String> | ||
24 | <String Id="msierrComPlusApplicationRoleDependency" Overridable="yes">Another entity is dependent on a COM+ application role that is not being installed. ([2] [3] [4] [5])</String> | ||
25 | <String Id="msierrComPlusApplicationRoleNotFound" Overridable="yes">The COM+ application role was not found. ([2] [3] [4] [5])</String> | ||
26 | <String Id="msierrComPlusApplicationRoleConflict" Overridable="yes">A COM+ application role with the same name already exists. ([2] [3] [4] [5])</String> | ||
27 | <String Id="msierrComPlusAssemblyDependency" Overridable="yes">Another entity is dependent on a COM+ assembly that is not being installed. ([2] [3] [4] [5])</String> | ||
28 | <String Id="msierrComPlusSubscriptionIdConflict" Overridable="yes">A COM+ component event subscription with the same id already exists. ([2] [3] [4] [5])</String> | ||
29 | <String Id="msierrComPlusSubscriptionNameConflict" Overridable="yes">A COM+ component event subscription with the same name already exists. ([2] [3] [4] [5])</String> | ||
30 | <String Id="msierrComPlusFailedLookupNames" Overridable="yes">Failed to lookup user account names. ([2] [3] [4] [5])</String> | ||
31 | |||
32 | <String Id="ComPlusInstallExecute" Overridable="yes">Registering COM+ components</String> | ||
33 | <String Id="ComPlusUninstallExecute" Overridable="yes">Unregistering COM+ components</String> | ||
34 | |||
35 | <String Id="CreateComPlusPartitions" Overridable="yes">Creating COM+ partitions</String> | ||
36 | <String Id="CreateComPlusPartitionsTemplate" Overridable="yes">Partition: [1]</String> | ||
37 | <String Id="RemoveComPlusPartitions" Overridable="yes">Removing COM+ partitions</String> | ||
38 | <String Id="RemoveComPlusPartitionsTemplate" Overridable="yes">Partition: [1]</String> | ||
39 | <String Id="AddUsersToComPlusPartitionRoles" Overridable="yes">Adding users to COM+ partition roles</String> | ||
40 | <String Id="AddUsersToComPlusPartitionRolesTemplate" Overridable="yes">Role: [1]</String> | ||
41 | <String Id="RemoveUsersFromComPlusPartitionRoles" Overridable="yes">Removing users from COM+ partition roles</String> | ||
42 | <String Id="RemoveUsersFromComPlusPartitionRolesTemplate" Overridable="yes">Role: [1]</String> | ||
43 | <String Id="AddComPlusPartitionUsers" Overridable="yes">Setting default COM+ partitions for users</String> | ||
44 | <String Id="AddComPlusPartitionUsersTemplate" Overridable="yes">User: [1]</String> | ||
45 | <String Id="RemoveComPlusPartitionUsers" Overridable="yes">Removing default COM+ partitions for users</String> | ||
46 | <String Id="RemoveComPlusPartitionUsersTemplate" Overridable="yes">User: [1]</String> | ||
47 | <String Id="CreateComPlusApplications" Overridable="yes">Creating COM+ applications</String> | ||
48 | <String Id="CreateComPlusApplicationsTemplate" Overridable="yes">Application: [1]</String> | ||
49 | <String Id="RemoveComPlusApplications" Overridable="yes">Removing COM+ applications</String> | ||
50 | <String Id="RemoveComPlusApplicationsTemplate" Overridable="yes">Application: [1]</String> | ||
51 | <String Id="CreateComPlusApplicationRoles" Overridable="yes">Creating COM+ application roles</String> | ||
52 | <String Id="CreateComPlusApplicationRolesTemplate" Overridable="yes">Role: [1]</String> | ||
53 | <String Id="RemoveComPlusApplicationRoles" Overridable="yes">Removing COM+ application roles</String> | ||
54 | <String Id="RemoveComPlusApplicationRolesTemplate" Overridable="yes">Role: [1]</String> | ||
55 | <String Id="AddUsersToComPlusApplicationRoles" Overridable="yes">Adding users to COM+ application roles</String> | ||
56 | <String Id="AddUsersToComPlusApplicationRolesTemplate" Overridable="yes">User: [1]</String> | ||
57 | <String Id="RemoveUsersFromComPlusApplicationRoles" Overridable="yes">Removing users from COM+ application roles</String> | ||
58 | <String Id="RemoveUsersFromComPlusApplicationRolesTemplate" Overridable="yes">User: [1]</String> | ||
59 | <String Id="RegisterComPlusAssemblies" Overridable="yes">Registering COM+ components</String> | ||
60 | <String Id="RegisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
61 | <String Id="UnregisterComPlusAssemblies" Overridable="yes">Unregistering COM+ components</String> | ||
62 | <String Id="UnregisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
63 | <String Id="AddComPlusRoleAssignments" Overridable="yes">Assigning roles to COM+ components</String> | ||
64 | <String Id="AddComPlusRoleAssignmentsTemplate" Overridable="yes">Component: [1]</String> | ||
65 | <String Id="RemoveComPlusRoleAssignments" Overridable="yes">Removing role assignments from COM+ components</String> | ||
66 | <String Id="RemoveComPlusRoleAssignmentsTemplate" Overridable="yes">Component: [1]</String> | ||
67 | <String Id="CreateSubscriptionsComPlusComponents" Overridable="yes">Creating subscriptions for COM+ components</String> | ||
68 | <String Id="CreateSubscriptionsComPlusComponentsTemplate" Overridable="yes">Subscription: [1]</String> | ||
69 | <String Id="RemoveSubscriptionsComPlusComponents" Overridable="yes">Removing subscriptions for COM+ components</String> | ||
70 | <String Id="RemoveSubscriptionsComPlusComponentsTemplate" Overridable="yes">Subscription: [1]</String> | ||
71 | </WixLocalization> | ||
diff --git a/src/wixlib/es-es.wxl b/src/wixlib/es-es.wxl new file mode 100644 index 00000000..5e7eba66 --- /dev/null +++ b/src/wixlib/es-es.wxl | |||
@@ -0,0 +1,72 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- 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. --> | ||
3 | |||
4 | |||
5 | <WixLocalization Culture="es-es" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
6 | <String Id="msierrComPlusCannotConnect" Overridable="yes">No se puede conectar al catálogo de administración de COM+. ([2] [3] [4] [5])</String> | ||
7 | <String Id="msierrComPlusPartitionReadFailed" Overridable="yes">Falla al leer las particiones COM+. ([2] [3] [4] [5])</String> | ||
8 | <String Id="msierrComPlusPartitionRoleReadFailed" Overridable="yes">Falla al leer los roles de las particiones COM+. ([2] [3] [4] [5])</String> | ||
9 | <String Id="msierrComPlusUserInPartitionRoleReadFailed" Overridable="yes">Falla al leer los usuario en los roles de las particiones COM+. ([2] [3] [4] [5])</String> | ||
10 | <String Id="msierrComPlusPartitionUserReadFailed" Overridable="yes">Falla al leer los usuario de las particiones COM+. ([2] [3] [4] [5])</String> | ||
11 | <String Id="msierrComPlusApplicationReadFailed" Overridable="yes">Falla al leer las aplicaciones COM+. ([2] [3] [4] [5])</String> | ||
12 | <String Id="msierrComPlusApplicationRoleReadFailed" Overridable="yes">Falla al leer los roles de las aplicaciones COM+. ([2] [3] [4] [5])</String> | ||
13 | <String Id="msierrComPlusUserInApplicationRoleReadFailed" Overridable="yes">Falla al leer los usuario de las aplicaciones COM+. ([2] [3] [4] [5])</String> | ||
14 | <String Id="msierrComPlusAssembliesReadFailed" Overridable="yes">Falla al leer los ensamblados COM+. ([2] [3] [4] [5])</String> | ||
15 | <String Id="msierrComPlusSubscriptionReadFailed" Overridable="yes">Falla al leer las suscripciones a eventos COM+. ([2] [3] [4] [5])</String> | ||
16 | <String Id="msierrComPlusPartitionDependency" Overridable="yes">Otra entidad es dependiente de una partición COM+ que no está siendo instalada. ([2] [3] [4] [5])</String> | ||
17 | <String Id="msierrComPlusPartitionNotFound" Overridable="yes">La partición COM+ no pudo ser encontrada. ([2] [3] [4] [5])</String> | ||
18 | <String Id="msierrComPlusPartitionIdConflict" Overridable="yes">Ya existe otra partición COM+ con el mismo id. ([2] [3] [4] [5])</String> | ||
19 | <String Id="msierrComPlusPartitionNameConflict" Overridable="yes">Ya existe otra partición COM+ con el mismo nombre. ([2] [3] [4] [5])</String> | ||
20 | <String Id="msierrComPlusApplicationDependency" Overridable="yes">Otra entidad es dependiente de una aplicación COM+ que no está siendo instalada. ([2] [3] [4] [5])</String> | ||
21 | <String Id="msierrComPlusApplicationNotFound" Overridable="yes">La aplicación COM+ no pudo ser encontrada. ([2] [3] [4] [5])</String> | ||
22 | <String Id="msierrComPlusApplicationIdConflict" Overridable="yes">Ya existe otra aplicación COM+ con el mismo id. ([2] [3] [4] [5])</String> | ||
23 | <String Id="msierrComPlusApplicationNameConflict" Overridable="yes">Ya existe otra aplicación COM+ con el mismo nombre. ([2] [3] [4] [5])</String> | ||
24 | <String Id="msierrComPlusApplicationRoleDependency" Overridable="yes">Otra entidad es dependiente de un rol de aplicación COM+ que no está siendo instalado. ([2] [3] [4] [5])</String> | ||
25 | <String Id="msierrComPlusApplicationRoleNotFound" Overridable="yes">El rol de aplicación COM+ no pudo ser encontrado. ([2] [3] [4] [5])</String> | ||
26 | <String Id="msierrComPlusApplicationRoleConflict" Overridable="yes">Ya existe otro rol de aplicación COM+ con el mismo nombre. ([2] [3] [4] [5])</String> | ||
27 | <String Id="msierrComPlusAssemblyDependency" Overridable="yes">Otra entidad es dependiente de un ensamblado COM+ que no está siendo instalado. ([2] [3] [4] [5])</String> | ||
28 | <String Id="msierrComPlusSubscriptionIdConflict" Overridable="yes">Ya existe otra suscripción de evento al componente COM+ con el mismo id. ([2] [3] [4] [5])</String> | ||
29 | <String Id="msierrComPlusSubscriptionNameConflict" Overridable="yes">Ya existe otra suscripción de evento al componente COM+ con el mismo nombre. ([2] [3] [4] [5])</String> | ||
30 | <String Id="msierrComPlusFailedLookupNames" Overridable="yes">Falla el la búsqueda de los nombres de usuario. ([2] [3] [4] [5])</String> | ||
31 | |||
32 | <String Id="ComPlusInstallExecute" Overridable="yes">Registrando componentes COM+</String> | ||
33 | <String Id="ComPlusUninstallExecute" Overridable="yes">Anular el registro de componentes COM+</String> | ||
34 | |||
35 | <String Id="CreateComPlusPartitions" Overridable="yes">Creando particiones COM+</String> | ||
36 | <String Id="CreateComPlusPartitionsTemplate" Overridable="yes">Particiones: [1]</String> | ||
37 | <String Id="RemoveComPlusPartitions" Overridable="yes">Borrando particiones COM+</String> | ||
38 | <String Id="RemoveComPlusPartitionsTemplate" Overridable="yes">Particiones: [1]</String> | ||
39 | <String Id="AddUsersToComPlusPartitionRoles" Overridable="yes">Agregando usuarios a los roles de las particiones COM+</String> | ||
40 | <String Id="AddUsersToComPlusPartitionRolesTemplate" Overridable="yes">Rol: [1]</String> | ||
41 | <String Id="RemoveUsersFromComPlusPartitionRoles" Overridable="yes">Borrando usuarios a los roles de las particiones COM+</String> | ||
42 | <String Id="RemoveUsersFromComPlusPartitionRolesTemplate" Overridable="yes">Rol: [1]</String> | ||
43 | <String Id="AddComPlusPartitionUsers" Overridable="yes">Ajustando partición COM+ por omisión para los usuarios</String> | ||
44 | <String Id="AddComPlusPartitionUsersTemplate" Overridable="yes">Usuario: [1]</String> | ||
45 | <String Id="RemoveComPlusPartitionUsers" Overridable="yes">Borrando partición COM+ por omisión para los usuarios</String> | ||
46 | <String Id="RemoveComPlusPartitionUsersTemplate" Overridable="yes">Usuario: [1]</String> | ||
47 | <String Id="CreateComPlusApplications" Overridable="yes">Creando aplicación COM+</String> | ||
48 | <String Id="CreateComPlusApplicationsTemplate" Overridable="yes">Aplicación: [1]</String> | ||
49 | <String Id="RemoveComPlusApplications" Overridable="yes">Borrando aplicación COM+</String> | ||
50 | <String Id="RemoveComPlusApplicationsTemplate" Overridable="yes">Aplicación: [1]</String> | ||
51 | <String Id="CreateComPlusApplicationRoles" Overridable="yes">Creando roles de aplicación COM+</String> | ||
52 | <String Id="CreateComPlusApplicationRolesTemplate" Overridable="yes">Rol: [1]</String> | ||
53 | <String Id="RemoveComPlusApplicationRoles" Overridable="yes">Borrando roles de aplicación COM+</String> | ||
54 | <String Id="RemoveComPlusApplicationRolesTemplate" Overridable="yes">Rol: [1]</String> | ||
55 | <String Id="AddUsersToComPlusApplicationRoles" Overridable="yes">Agregando usuarios a los roles de aplicación COM+</String> | ||
56 | <String Id="AddUsersToComPlusApplicationRolesTemplate" Overridable="yes">Usuario: [1]</String> | ||
57 | <String Id="RemoveUsersFromComPlusApplicationRoles" Overridable="yes">Borrando usuarios a los roles de aplicación COM</String> | ||
58 | <String Id="RemoveUsersFromComPlusApplicationRolesTemplate" Overridable="yes">Usuario: [1]</String> | ||
59 | <String Id="RegisterComPlusAssemblies" Overridable="yes">Registrando componente COM+</String> | ||
60 | <String Id="RegisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
61 | <String Id="UnregisterComPlusAssemblies" Overridable="yes">Anulando el registro de componentes COM+</String> | ||
62 | <String Id="UnregisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
63 | <String Id="AddComPlusRoleAssignments" Overridable="yes">Asignando roles a los componentes COM+</String> | ||
64 | <String Id="AddComPlusRoleAssignmentsTemplate" Overridable="yes">Componente: [1]</String> | ||
65 | <String Id="RemoveComPlusRoleAssignments" Overridable="yes">Borrando asignación de roles a los componentes COM+</String> | ||
66 | <String Id="RemoveComPlusRoleAssignmentsTemplate" Overridable="yes">Componente: [1]</String> | ||
67 | <String Id="CreateSubscriptionsComPlusComponents" Overridable="yes">Creando suscripción a componentes COM+</String> | ||
68 | <String Id="CreateSubscriptionsComPlusComponentsTemplate" Overridable="yes">Suscripción: [1]</String> | ||
69 | <String Id="RemoveSubscriptionsComPlusComponents" Overridable="yes">Borrando suscripción a componentes COM+</String> | ||
70 | <String Id="RemoveSubscriptionsComPlusComponentsTemplate" Overridable="yes">Suscripción: [1]</String> | ||
71 | </WixLocalization> | ||
72 | |||
diff --git a/src/wixlib/ja-jp.wxl b/src/wixlib/ja-jp.wxl new file mode 100644 index 00000000..03b2cf1c --- /dev/null +++ b/src/wixlib/ja-jp.wxl | |||
@@ -0,0 +1,71 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- 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. --> | ||
3 | |||
4 | |||
5 | <WixLocalization Culture="ja-jp" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
6 | <String Id="msierrComPlusCannotConnect" Overridable="yes">COM+ 管理カタログへ接続できません。 ([2] [3] [4] [5])</String> | ||
7 | <String Id="msierrComPlusPartitionReadFailed" Overridable="yes">COM+ パーティションの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
8 | <String Id="msierrComPlusPartitionRoleReadFailed" Overridable="yes">COM+ パーティション役割の読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
9 | <String Id="msierrComPlusUserInPartitionRoleReadFailed" Overridable="yes">COM+ パーティション役割内ユーザーの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
10 | <String Id="msierrComPlusPartitionUserReadFailed" Overridable="yes">COM+ パーティション ユーザーの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
11 | <String Id="msierrComPlusApplicationReadFailed" Overridable="yes">COM+ アプリケーションの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
12 | <String Id="msierrComPlusApplicationRoleReadFailed" Overridable="yes">COM+ アプリケーション役割の読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
13 | <String Id="msierrComPlusUserInApplicationRoleReadFailed" Overridable="yes">COM+ アプリケーション役割内ユーザーの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
14 | <String Id="msierrComPlusAssembliesReadFailed" Overridable="yes">COM+ アセンブリの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
15 | <String Id="msierrComPlusSubscriptionReadFailed" Overridable="yes">COM+ イベント登録の読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
16 | <String Id="msierrComPlusPartitionDependency" Overridable="yes">他のエンティティはインストールされない COM+ パーティションに依存します。 ([2] [3] [4] [5])</String> | ||
17 | <String Id="msierrComPlusPartitionNotFound" Overridable="yes">COM+ パーティションは見つかりません ([2] [3] [4] [5])</String> | ||
18 | <String Id="msierrComPlusPartitionIdConflict" Overridable="yes">同一 ID を持つ COM+ パーティションが既に存在します。 ([2] [3] [4] [5])</String> | ||
19 | <String Id="msierrComPlusPartitionNameConflict" Overridable="yes">同一名称を持つ COM+ パーティションが既に存在します。 ([2] [3] [4] [5])</String> | ||
20 | <String Id="msierrComPlusApplicationDependency" Overridable="yes">他のエンティティはインストールされない COM+ アプリケーションに依存します。 ([2] [3] [4] [5])</String> | ||
21 | <String Id="msierrComPlusApplicationNotFound" Overridable="yes">COM+ アプリケーションは見つかりません。 ([2] [3] [4] [5])</String> | ||
22 | <String Id="msierrComPlusApplicationIdConflict" Overridable="yes">同一 ID を持つ COM+ アプリケーションが既に存在します。 ([2] [3] [4] [5])</String> | ||
23 | <String Id="msierrComPlusApplicationNameConflict" Overridable="yes">同一名称を持つ COM+ アプリケーションが既に存在します。 ([2] [3] [4] [5])</String> | ||
24 | <String Id="msierrComPlusApplicationRoleDependency" Overridable="yes">他のエンティティはインストールされない COM+ アプリケーション役割に依存します。 ([2] [3] [4] [5])</String> | ||
25 | <String Id="msierrComPlusApplicationRoleNotFound" Overridable="yes">COM+ アプリケーション役割は見つかりません。 ([2] [3] [4] [5])</String> | ||
26 | <String Id="msierrComPlusApplicationRoleConflict" Overridable="yes">同一名称を持つ COM+ アプリケーション役割が既に存在します。 ([2] [3] [4] [5])</String> | ||
27 | <String Id="msierrComPlusAssemblyDependency" Overridable="yes">他のエンティティはインストールされない COM+ アセンブリに依存します。 ([2] [3] [4] [5])</String> | ||
28 | <String Id="msierrComPlusSubscriptionIdConflict" Overridable="yes">同一 ID を持つ COM+ コンポーネントのイベント登録が既に存在します。 ([2] [3] [4] [5])</String> | ||
29 | <String Id="msierrComPlusSubscriptionNameConflict" Overridable="yes">同一名称を持つ COM+ コンポーネントのイベント登録が既に存在します。 ([2] [3] [4] [5])</String> | ||
30 | <String Id="msierrComPlusFailedLookupNames" Overridable="yes">ユーザー アカウント名の照合に失敗しました。 ([2] [3] [4] [5])</String> | ||
31 | |||
32 | <String Id="ComPlusInstallExecute" Overridable="yes">COM+ コンポーネントを登録しています</String> | ||
33 | <String Id="ComPlusUninstallExecute" Overridable="yes">COM+ コンポーネント登録を解除しています</String> | ||
34 | |||
35 | <String Id="CreateComPlusPartitions" Overridable="yes">COM+ パーティションを作成しています</String> | ||
36 | <String Id="CreateComPlusPartitionsTemplate" Overridable="yes">パーティション: [1]</String> | ||
37 | <String Id="RemoveComPlusPartitions" Overridable="yes">COM+ パーティションを削除しています</String> | ||
38 | <String Id="RemoveComPlusPartitionsTemplate" Overridable="yes">パーティション: [1]</String> | ||
39 | <String Id="AddUsersToComPlusPartitionRoles" Overridable="yes">ユーザーを COM+ パーティション役割に追加しています</String> | ||
40 | <String Id="AddUsersToComPlusPartitionRolesTemplate" Overridable="yes">役割: [1]</String> | ||
41 | <String Id="RemoveUsersFromComPlusPartitionRoles" Overridable="yes">ユーザを COM+ パーティション役割より削除しています</String> | ||
42 | <String Id="RemoveUsersFromComPlusPartitionRolesTemplate" Overridable="yes">役割: [1]</String> | ||
43 | <String Id="AddComPlusPartitionUsers" Overridable="yes">ユーザーのデフォルト COM+ 役割を設定しています</String> | ||
44 | <String Id="AddComPlusPartitionUsersTemplate" Overridable="yes">ユーザー: [1]</String> | ||
45 | <String Id="RemoveComPlusPartitionUsers" Overridable="yes">ユーザーのデフォルト COM+ パーティション役割を削除しています</String> | ||
46 | <String Id="RemoveComPlusPartitionUsersTemplate" Overridable="yes">ユーザー: [1]</String> | ||
47 | <String Id="CreateComPlusApplications" Overridable="yes">COM+ アプリケーションを作成しています</String> | ||
48 | <String Id="CreateComPlusApplicationsTemplate" Overridable="yes">アプリケーション: [1]</String> | ||
49 | <String Id="RemoveComPlusApplications" Overridable="yes">COM+ アプリケーションを削除しています</String> | ||
50 | <String Id="RemoveComPlusApplicationsTemplate" Overridable="yes">アプリケーション: [1]</String> | ||
51 | <String Id="CreateComPlusApplicationRoles" Overridable="yes">COM+ アプリケーション役割を作成しています</String> | ||
52 | <String Id="CreateComPlusApplicationRolesTemplate" Overridable="yes">役割: [1]</String> | ||
53 | <String Id="RemoveComPlusApplicationRoles" Overridable="yes">COM+ アプリケーション役割を削除しています</String> | ||
54 | <String Id="RemoveComPlusApplicationRolesTemplate" Overridable="yes">役割: [1]</String> | ||
55 | <String Id="AddUsersToComPlusApplicationRoles" Overridable="yes">ユーザーを COM+ アプリケーション役割に追加しています</String> | ||
56 | <String Id="AddUsersToComPlusApplicationRolesTemplate" Overridable="yes">ユーザー: [1]</String> | ||
57 | <String Id="RemoveUsersFromComPlusApplicationRoles" Overridable="yes">ユーザーを COM+ アプリケーション役割より削除しています</String> | ||
58 | <String Id="RemoveUsersFromComPlusApplicationRolesTemplate" Overridable="yes">ユーザー: [1]</String> | ||
59 | <String Id="RegisterComPlusAssemblies" Overridable="yes">COM+ コンポーネントを登録しています</String> | ||
60 | <String Id="RegisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
61 | <String Id="UnregisterComPlusAssemblies" Overridable="yes">COM+ コンポーネント登録を解除しています</String> | ||
62 | <String Id="UnregisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
63 | <String Id="AddComPlusRoleAssignments" Overridable="yes">COM+ コンポーネントへ役割を割り当てています</String> | ||
64 | <String Id="AddComPlusRoleAssignmentsTemplate" Overridable="yes">コンポーネント: [1]</String> | ||
65 | <String Id="RemoveComPlusRoleAssignments" Overridable="yes">COM+ コンポーネントより役割割当を削除しています</String> | ||
66 | <String Id="RemoveComPlusRoleAssignmentsTemplate" Overridable="yes">コンポーネント: [1]</String> | ||
67 | <String Id="CreateSubscriptionsComPlusComponents" Overridable="yes">COM+ コンポーネント用登録を作成しています</String> | ||
68 | <String Id="CreateSubscriptionsComPlusComponentsTemplate" Overridable="yes">登録: [1]</String> | ||
69 | <String Id="RemoveSubscriptionsComPlusComponents" Overridable="yes">COM+ コンポーネント用登録を削除しています</String> | ||
70 | <String Id="RemoveSubscriptionsComPlusComponentsTemplate" Overridable="yes">登録: [1]</String> | ||
71 | </WixLocalization> | ||