aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2019-02-04 20:05:54 -0600
committerSean Hall <r.sean.hall@gmail.com>2019-02-04 20:05:54 -0600
commitcbc09b6cd6d0d0b8bf095a88d4d8333616637f71 (patch)
treea0893e8b8772765747630052018312a2d77f97e4
parentc94f50e3d8dc958f8a0b9540e63e920a079c1779 (diff)
downloadwix-cbc09b6cd6d0d0b8bf095a88d4d8333616637f71.tar.gz
wix-cbc09b6cd6d0d0b8bf095a88d4d8333616637f71.tar.bz2
wix-cbc09b6cd6d0d0b8bf095a88d4d8333616637f71.zip
Import code from old v4 repo
-rw-r--r--src/ca/cpappexec.cpp344
-rw-r--r--src/ca/cpappexec.h12
-rw-r--r--src/ca/cpapproleexec.cpp720
-rw-r--r--src/ca/cpapproleexec.h20
-rw-r--r--src/ca/cpapprolesched.cpp843
-rw-r--r--src/ca/cpapprolesched.h112
-rw-r--r--src/ca/cpappsched.cpp752
-rw-r--r--src/ca/cpappsched.h83
-rw-r--r--src/ca/cpasmexec.cpp1888
-rw-r--r--src/ca/cpasmexec.h20
-rw-r--r--src/ca/cpasmsched.cpp2135
-rw-r--r--src/ca/cpasmsched.h168
-rw-r--r--src/ca/cpcost.h30
-rw-r--r--src/ca/cpexec.cpp704
-rw-r--r--src/ca/cpexec.def11
-rw-r--r--src/ca/cppartexec.cpp690
-rw-r--r--src/ca/cppartexec.h20
-rw-r--r--src/ca/cppartroleexec.cpp397
-rw-r--r--src/ca/cppartroleexec.h12
-rw-r--r--src/ca/cppartrolesched.cpp421
-rw-r--r--src/ca/cppartrolesched.h76
-rw-r--r--src/ca/cppartsched.cpp912
-rw-r--r--src/ca/cppartsched.h125
-rw-r--r--src/ca/cpsched.cpp590
-rw-r--r--src/ca/cpsubsexec.cpp411
-rw-r--r--src/ca/cpsubsexec.h12
-rw-r--r--src/ca/cpsubssched.cpp606
-rw-r--r--src/ca/cpsubssched.h62
-rw-r--r--src/ca/cputilexec.cpp1881
-rw-r--r--src/ca/cputilexec.h193
-rw-r--r--src/ca/cputilsched.cpp885
-rw-r--r--src/ca/cputilsched.h144
-rw-r--r--src/wixext/ComPlusCompiler.cs2188
-rw-r--r--src/wixext/ComPlusDecompiler.cs1843
-rw-r--r--src/wixext/ComPlusExtensionData.cs64
-rw-r--r--src/wixext/WixComPlusExtension.csproj50
-rw-r--r--src/wixext/complus.xsd944
-rw-r--r--src/wixext/messages.xml77
-rw-r--r--src/wixext/tables.xml250
-rw-r--r--src/wixlib/ComPlusExtension.wixproj26
-rw-r--r--src/wixlib/ComPlusExtension.wxs139
-rw-r--r--src/wixlib/en-us.wxl71
-rw-r--r--src/wixlib/es-es.wxl72
-rw-r--r--src/wixlib/ja-jp.wxl71
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
8struct 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
22static HRESULT ReadApplicationAttributes(
23 LPWSTR* ppwzData,
24 CPI_APPLICATION_ATTRIBUTES* pAttrs
25 );
26static void FreeApplicationAttributes(
27 CPI_APPLICATION_ATTRIBUTES* pAttrs
28 );
29static HRESULT CreateApplication(
30 CPI_APPLICATION_ATTRIBUTES* pAttrs
31 );
32static HRESULT RemoveApplication(
33 CPI_APPLICATION_ATTRIBUTES* pAttrs
34 );
35
36
37// function definitions
38
39HRESULT 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
103LExit:
104 // clean up
105 FreeApplicationAttributes(&attrs);
106
107 return hr;
108}
109
110HRESULT 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
176LExit:
177 // clean up
178 FreeApplicationAttributes(&attrs);
179
180 return hr;
181}
182
183
184// helper function definitions
185
186static 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
210LExit:
211 return hr;
212}
213
214static 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
227static 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
285LExit:
286 // clean up
287 ReleaseObject(piAppColl);
288 ReleaseObject(piAppObj);
289
290 return hr;
291}
292
293static 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
339LExit:
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
5HRESULT CpiConfigureApplications(
6 LPWSTR* ppwzData,
7 HANDLE hRollbackFile
8 );
9HRESULT 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
8struct 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
19struct 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
33static HRESULT ReadApplicationRoleAttributes(
34 LPWSTR* ppwzData,
35 CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
36 );
37static void FreeApplicationRoleAttributes(
38 CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
39 );
40static HRESULT CreateApplicationRole(
41 CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
42 );
43static HRESULT RemoveApplicationRole(
44 CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
45 );
46static HRESULT ReadUsersInApplicationRoleAttributes(
47 LPWSTR* ppwzData,
48 CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
49 );
50static void FreeUsersInApplicationRoleAttributes(
51 CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
52 );
53static HRESULT CreateUsersInApplicationRole(
54 CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
55 );
56static HRESULT RemoveUsersInApplicationRole(
57 CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
58 );
59
60
61// function definitions
62
63HRESULT 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
127LExit:
128 // clean up
129 FreeApplicationRoleAttributes(&attrs);
130
131 return hr;
132}
133
134HRESULT 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
200LExit:
201 // clean up
202 FreeApplicationRoleAttributes(&attrs);
203
204 return hr;
205}
206
207HRESULT 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
271LExit:
272 // clean up
273 FreeUsersInApplicationRoleAttributes(&attrs);
274
275 return hr;
276}
277
278HRESULT 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
344LExit:
345 // clean up
346 FreeUsersInApplicationRoleAttributes(&attrs);
347
348 return hr;
349}
350
351
352// helper function definitions
353
354static 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
378LExit:
379 return hr;
380}
381
382static 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
395static 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
444LExit:
445 // clean up
446 ReleaseObject(piRolesColl);
447 ReleaseObject(piRoleObj);
448
449 return hr;
450}
451
452static 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
498LExit:
499 // clean up
500 ReleaseObject(piRolesColl);
501
502 return hr;
503}
504
505static 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
529LExit:
530 return hr;
531}
532
533static 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
544static 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
624LExit:
625 // clean up
626 ReleaseObject(piUsrInRoleColl);
627 ReleaseObject(piUsrInRoleObj);
628
629 if (pSid)
630 ::HeapFree(::GetProcessHeap(), 0, pSid);
631
632 return hr;
633}
634
635static 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
712LExit:
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
5HRESULT CpiConfigureApplicationRoles(
6 LPWSTR* ppwzData,
7 HANDLE hRollbackFile
8 );
9HRESULT CpiRollbackConfigureApplicationRoles(
10 LPWSTR* ppwzData,
11 CPI_ROLLBACK_DATA* pRollbackDataList
12 );
13HRESULT CpiConfigureUsersInApplicationRoles(
14 LPWSTR* ppwzData,
15 HANDLE hRollbackFile
16 );
17HRESULT 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
8LPCWSTR vcsApplicationRoleQuery =
9 L"SELECT `ApplicationRole`, `Application_`, `Component_`, `Name` FROM `ComPlusApplicationRole`";
10enum eApplicationRoleQuery { arqApplicationRole = 1, arqApplication, arqComponent, arqName };
11
12LPCWSTR vcsUserInApplicationRoleQuery =
13 L"SELECT `UserInApplicationRole`, `ApplicationRole_`, `ComPlusUserInApplicationRole`.`Component_`, `Domain`, `Name` FROM `ComPlusUserInApplicationRole`, `User` WHERE `User_` = `User`";
14LPCWSTR vcsGroupInApplicationRoleQuery =
15 L"SELECT `GroupInApplicationRole`, `ApplicationRole_`, `ComPlusGroupInApplicationRole`.`Component_`, `Domain`, `Name` FROM `ComPlusGroupInApplicationRole`, `Group` WHERE `Group_` = `Group`";
16enum eTrusteeInApplicationRoleQuery { tiarqUserInApplicationRole = 1, tiarqApplicationRole, tiarqComponent, tiarqDomain, tiarqName };
17
18LPCWSTR vcsApplicationRolePropertyQuery =
19 L"SELECT `Name`, `Value` FROM `ComPlusApplicationRoleProperty` WHERE `ApplicationRole_` = ?";
20
21
22// property definitions
23
24CPI_PROPERTY_DEFINITION pdlApplicationRoleProperties[] =
25{
26 {L"Description", cpptString, 500},
27 {NULL, cpptNone, 0}
28};
29
30
31// prototypes for private helper functions
32
33static HRESULT TrusteesInApplicationRolesRead(
34 LPCWSTR pwzQuery,
35 CPI_APPLICATION_ROLE_LIST* pAppRoleList,
36 CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList
37 );
38static void FreeApplicationRole(
39 CPI_APPLICATION_ROLE* pItm
40 );
41static void FreeUserInApplicationRole(
42 CPI_USER_IN_APPLICATION_ROLE* pItm
43 );
44//static HRESULT GetUsersCollForApplicationRole(
45// CPI_APPLICATION_ROLE* pAppRole,
46// ICatalogCollection** ppiUsersColl
47// );
48static HRESULT FindObjectForApplicationRole(
49 CPI_APPLICATION_ROLE* pItm,
50 ICatalogObject** ppiRoleObj
51 );
52static HRESULT AddApplicationRoleToActionData(
53 CPI_APPLICATION_ROLE* pItm,
54 int iActionType,
55 int iActionCost,
56 LPWSTR* ppwzActionData
57 );
58static 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
68void 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
82HRESULT 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
183LExit:
184 // clean up
185 if (pItm)
186 FreeApplicationRole(pItm);
187
188 ReleaseStr(pwzData);
189
190 return hr;
191}
192
193HRESULT 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
256LExit:
257 // clean up
258 ReleaseObject(piRoleObj);
259
260 return hr;
261}
262
263HRESULT 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
290LExit:
291 return hr;
292}
293
294void CpiApplicationRoleAddReferenceInstall(
295 CPI_APPLICATION_ROLE* pItm
296 )
297{
298 pItm->fReferencedForInstall = TRUE;
299 CpiApplicationAddReferenceInstall(pItm->pApplication);
300}
301
302void CpiApplicationRoleAddReferenceUninstall(
303 CPI_APPLICATION_ROLE* pItm
304 )
305{
306 pItm->fReferencedForUninstall = TRUE;
307 CpiApplicationAddReferenceUninstall(pItm->pApplication);
308}
309
310HRESULT 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
358LExit:
359 return hr;
360}
361
362HRESULT 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
405LExit:
406 return hr;
407}
408
409HRESULT 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
427void 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
441HRESULT 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
464LExit:
465 return hr;
466}
467
468HRESULT 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
516LExit:
517 return hr;
518}
519
520HRESULT 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
563LExit:
564 return hr;
565}
566
567
568// helper function definitions
569
570static 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
663LExit:
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
675static 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
687static 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
739static 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
761LExit:
762 // clean up
763 ReleaseObject(piRoleColl);
764
765 return hr;
766}
767
768static 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
803LExit:
804 return hr;
805}
806
807static 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
841LExit:
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
5struct 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
27struct CPI_APPLICATION_ROLE_LIST
28{
29 CPI_APPLICATION_ROLE* pFirst;
30
31 int iInstallCount;
32 int iUninstallCount;
33};
34
35struct 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
47struct 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
58void CpiApplicationRoleListFree(
59 CPI_APPLICATION_ROLE_LIST* pList
60 );
61HRESULT CpiApplicationRolesRead(
62 CPI_APPLICATION_LIST* pAppList,
63 CPI_APPLICATION_ROLE_LIST* pAppRoleList
64 );
65HRESULT CpiApplicationRolesVerifyInstall(
66 CPI_APPLICATION_ROLE_LIST* pList
67 );
68HRESULT CpiApplicationRolesVerifyUninstall(
69 CPI_APPLICATION_ROLE_LIST* pList
70 );
71void CpiApplicationRoleAddReferenceInstall(
72 CPI_APPLICATION_ROLE* pItm
73 );
74void CpiApplicationRoleAddReferenceUninstall(
75 CPI_APPLICATION_ROLE* pItm
76 );
77HRESULT CpiApplicationRolesInstall(
78 CPI_APPLICATION_ROLE_LIST* pList,
79 int iRunMode,
80 LPWSTR* ppwzActionData,
81 int* piProgress
82 );
83HRESULT CpiApplicationRolesUninstall(
84 CPI_APPLICATION_ROLE_LIST* pList,
85 int iRunMode,
86 LPWSTR* ppwzActionData,
87 int* piProgress
88 );
89HRESULT CpiApplicationRoleFindByKey(
90 CPI_APPLICATION_ROLE_LIST* pList,
91 LPCWSTR pwzKey,
92 CPI_APPLICATION_ROLE** ppAppRole
93 );
94void CpiUserInApplicationRoleListFree(
95 CPI_USER_IN_APPLICATION_ROLE_LIST* pList
96 );
97HRESULT CpiUsersInApplicationRolesRead(
98 CPI_APPLICATION_ROLE_LIST* pAppRoleList,
99 CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList
100 );
101HRESULT CpiUsersInApplicationRolesInstall(
102 CPI_USER_IN_APPLICATION_ROLE_LIST* pList,
103 int iRunMode,
104 LPWSTR* ppwzActionData,
105 int* piProgress
106 );
107HRESULT 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
8LPCWSTR vcsApplicationQuery =
9 L"SELECT `Application`, `Component_`, `Partition_`, `Id`, `Name` FROM `ComPlusApplication`";
10enum eApplicationQuery { aqApplication = 1, aqComponent, aqPartition, aqID, aqName };
11
12LPCWSTR vcsApplicationPropertyQuery =
13 L"SELECT `Name`, `Value` FROM `ComPlusApplicationProperty` WHERE `Application_` = ?";
14
15
16// property definitions
17
18CPI_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
69static void FreeApplication(
70 CPI_APPLICATION* pItm
71 );
72static HRESULT FindObjectForApplication(
73 CPI_APPLICATION* pItm,
74 BOOL fFindId,
75 BOOL fFindName,
76 ICatalogObject** ppiAppObj
77 );
78static HRESULT AddApplicationToActionData(
79 CPI_APPLICATION* pItm,
80 int iActionType,
81 int iActionCost,
82 LPWSTR* ppwzActionData
83 );
84
85
86// function definitions
87
88void 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
102HRESULT 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
233LExit:
234 // clean up
235 if (pItm)
236 FreeApplication(pItm);
237
238 ReleaseStr(pwzData);
239
240 return hr;
241}
242
243HRESULT 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
370LExit:
371 // clean up
372 ReleaseObject(piAppObj);
373
374 return hr;
375}
376
377HRESULT 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
419LExit:
420 // clean up
421 ReleaseObject(piAppObj);
422
423 return hr;
424}
425
426void CpiApplicationAddReferenceInstall(
427 CPI_APPLICATION* pItm
428 )
429{
430 pItm->fReferencedForInstall = TRUE;
431 if (pItm->pPartition)
432 CpiPartitionAddReferenceInstall(pItm->pPartition);
433}
434
435void CpiApplicationAddReferenceUninstall(
436 CPI_APPLICATION* pItm
437 )
438{
439 pItm->fReferencedForUninstall = TRUE;
440 if (pItm->pPartition)
441 CpiPartitionAddReferenceUninstall(pItm->pPartition);
442}
443
444HRESULT 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
492LExit:
493 return hr;
494}
495
496HRESULT 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
539LExit:
540 return hr;
541}
542
543HRESULT 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
561HRESULT 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
606LExit:
607 // clean up
608 ReleaseObject(piAppColl);
609 ReleaseObject(piAppObj);
610
611 return hr;
612}
613
614HRESULT 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
659LExit:
660 // clean up
661 ReleaseObject(piAppColl);
662 ReleaseObject(piAppObj);
663
664 return hr;
665}
666
667
668// helper function definitions
669
670static 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
683static 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
710LExit:
711 // clean up
712 ReleaseObject(piAppColl);
713
714 return hr;
715}
716
717static 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
750LExit:
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
5struct 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
29struct CPI_APPLICATION_LIST
30{
31 CPI_APPLICATION* pFirst;
32
33 int iInstallCount;
34 int iUninstallCount;
35};
36
37
38// function prototypes
39
40void CpiApplicationListFree(
41 CPI_APPLICATION_LIST* pList
42 );
43HRESULT CpiApplicationsRead(
44 CPI_PARTITION_LIST* pPartList,
45 CPI_APPLICATION_LIST* pAppList
46 );
47HRESULT CpiApplicationsVerifyInstall(
48 CPI_APPLICATION_LIST* pList
49 );
50HRESULT CpiApplicationsVerifyUninstall(
51 CPI_APPLICATION_LIST* pList
52 );
53void CpiApplicationAddReferenceInstall(
54 CPI_APPLICATION* pItm
55 );
56void CpiApplicationAddReferenceUninstall(
57 CPI_APPLICATION* pItm
58 );
59HRESULT CpiApplicationsInstall(
60 CPI_APPLICATION_LIST* pList,
61 int iRunMode,
62 LPWSTR* ppwzActionData,
63 int* piProgress
64 );
65HRESULT CpiApplicationsUninstall(
66 CPI_APPLICATION_LIST* pList,
67 int iRunMode,
68 LPWSTR* ppwzActionData,
69 int* piProgress
70 );
71HRESULT CpiApplicationFindByKey(
72 CPI_APPLICATION_LIST* pList,
73 LPCWSTR pwzKey,
74 CPI_APPLICATION** ppApp
75 );
76HRESULT CpiGetRolesCollForApplication(
77 CPI_APPLICATION* pApp,
78 ICatalogCollection** ppiRolesColl
79 );
80HRESULT 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
8typedef 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
17typedef struct _FUSION_INSTALL_REFERENCE_ *LPFUSION_INSTALL_REFERENCE;
18
19typedef const FUSION_INSTALL_REFERENCE *LPCFUSION_INSTALL_REFERENCE;
20
21typedef struct _ASSEMBLY_INFO
22{
23 ULONG cbAssemblyInfo;
24 DWORD dwAssemblyFlags;
25 ULARGE_INTEGER uliAssemblySizeInKB;
26 LPWSTR pszCurrentAssemblyPathBuf;
27 ULONG cchBuf;
28} ASSEMBLY_INFO;
29
30typedef interface IAssemblyCacheItem IAssemblyCacheItem;
31
32MIDL_INTERFACE("e707dcde-d1cd-11d2-bab9-00c04f8eceae")
33IAssemblyCache : public IUnknown
34{
35public:
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
62typedef HRESULT (__stdcall *LoadLibraryShimFunc)(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll);
63typedef HRESULT (__stdcall *CreateAssemblyCacheFunc)(IAssemblyCache **ppAsmCache, DWORD dwReserved);
64
65
66// RegistrationHelper related declarations
67
68static const GUID CLSID_RegistrationHelper =
69 { 0x89a86e7b, 0xc229, 0x4008, { 0x9b, 0xaa, 0x2f, 0x5c, 0x84, 0x11, 0xd7, 0xe0 } };
70
71enum eInstallationFlags {
72 ifConfigureComponentsOnly = 16,
73 ifFindOrCreateTargetApplication = 4,
74 ifExpectExistingTypeLib = 1
75};
76
77
78// private constants
79
80enum 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
91struct 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
99struct 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
110struct 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
121struct 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
132struct 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
147struct 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
161static HRESULT RegisterAssembly(
162 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
163 );
164static HRESULT UnregisterAssembly(
165 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
166 );
167static void InitAssemblyExec();
168static void UninitAssemblyExec();
169static HRESULT GetRegistrationHelper(
170 IDispatch** ppiRegHlp
171 );
172static HRESULT GetAssemblyCacheObject(
173 IAssemblyCache** ppAssemblyCache
174 );
175static HRESULT GetAssemblyPathFromGAC(
176 LPCWSTR pwzAssemblyName,
177 LPWSTR* ppwzAssemblyPath
178 );
179static HRESULT RegisterDotNetAssembly(
180 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
181 );
182static HRESULT RegisterNativeAssembly(
183 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
184 );
185static HRESULT UnregisterDotNetAssembly(
186 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
187 );
188static HRESULT RemoveComponents(
189 ICatalogCollection* piCompColl,
190 CPI_COMPONENT* pCompList
191 );
192static HRESULT ReadAssemblyAttributes(
193 LPWSTR* ppwzData,
194 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
195 );
196static void FreeAssemblyAttributes(
197 CPI_ASSEMBLY_ATTRIBUTES* pAttrs
198 );
199static HRESULT ReadRoleAssignmentsAttributes(
200 LPWSTR* ppwzData,
201 CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs
202 );
203static void FreeRoleAssignmentsAttributes(
204 CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs
205 );
206static HRESULT ConfigureComponents(
207 LPCWSTR pwzPartID,
208 LPCWSTR pwzAppID,
209 CPI_COMPONENT* pCompList,
210 BOOL fCreate,
211 BOOL fProgress
212 );
213static HRESULT ConfigureInterfaces(
214 ICatalogCollection* piCompColl,
215 ICatalogObject* piCompObj,
216 CPI_INTERFACE* pIntfList,
217 BOOL fCreate
218 );
219static HRESULT ConfigureMethods(
220 ICatalogCollection* piIntfColl,
221 ICatalogObject* piIntfObj,
222 CPI_METHOD* pMethList,
223 BOOL fCreate
224 );
225static HRESULT ConfigureRoleAssignments(
226 LPCWSTR pwzCollName,
227 ICatalogCollection* piCompColl,
228 ICatalogObject* piCompObj,
229 CPI_ROLE_ASSIGNMENT* pRoleList,
230 BOOL fCreate
231 );
232static HRESULT ReadComponentList(
233 LPWSTR* ppwzData,
234 CPI_COMPONENT** ppCompList
235 );
236static HRESULT ReadInterfaceList(
237 LPWSTR* ppwzData,
238 CPI_INTERFACE** ppIntfList
239 );
240static HRESULT ReadMethodList(
241 LPWSTR* ppwzData,
242 CPI_METHOD** ppMethList
243 );
244static HRESULT ReadRoleAssignmentList(
245 LPWSTR* ppwzData,
246 CPI_ROLE_ASSIGNMENT** ppRoleList
247 );
248static void FreeComponentList(
249 CPI_COMPONENT* pList
250 );
251static void FreeInterfaceList(
252 CPI_INTERFACE* pList
253 );
254static void FreeMethodList(
255 CPI_METHOD* pList
256 );
257static void FreeRoleAssignmentList(
258 CPI_ROLE_ASSIGNMENT* pList
259 );
260
261
262// variables
263
264static IDispatch* gpiRegHlp;
265static IAssemblyCache* gpAssemblyCache;
266static HMODULE ghMscoree;
267static HMODULE ghFusion;
268
269
270// function definitions
271
272HRESULT 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
338LExit:
339 // clean up
340 FreeAssemblyAttributes(&attrs);
341
342 // uninitialize
343 UninitAssemblyExec();
344
345 return hr;
346}
347
348HRESULT 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
410LExit:
411 // clean up
412 FreeAssemblyAttributes(&attrs);
413
414 // uninitialize
415 UninitAssemblyExec();
416
417 return hr;
418}
419
420HRESULT 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
474LExit:
475 // clean up
476 FreeRoleAssignmentsAttributes(&attrs);
477
478 return hr;
479}
480
481HRESULT 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
535LExit:
536 // clean up
537 FreeRoleAssignmentsAttributes(&attrs);
538
539 return hr;
540}
541
542
543// helper function definitions
544
545static 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
596LExit:
597 return hr;
598}
599
600static 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
709LExit:
710 // clean up
711 ReleaseObject(piColl);
712 ReleaseObject(piObj);
713
714 return hr;
715}
716
717static void InitAssemblyExec()
718{
719 gpiRegHlp = NULL;
720 gpAssemblyCache = NULL;
721 ghMscoree = NULL;
722 ghFusion = NULL;
723}
724
725static void UninitAssemblyExec()
726{
727 ReleaseObject(gpiRegHlp);
728 ReleaseObject(gpAssemblyCache);
729 if (ghFusion)
730 ::FreeLibrary(ghFusion);
731 if (ghMscoree)
732 ::FreeLibrary(ghMscoree);
733}
734
735static 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
753LExit:
754 return hr;
755}
756
757static 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
799LExit:
800 return hr;
801}
802
803static 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
838LExit:
839 // clean up
840 ReleaseObject(pAssemblyCache);
841
842 return hr;
843}
844
845static 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
942LExit:
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
960static 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
1048LExit:
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
1063static 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
1138LExit:
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
1155static 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
1174LExit:
1175 return hr;
1176}
1177
1178static 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
1220LExit:
1221 return hr;
1222}
1223
1224static 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
1240static 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
1274LExit:
1275 return hr;
1276}
1277
1278static 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
1291static 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
1367LExit:
1368 // clean up
1369 ReleaseObject(piCompColl);
1370 ReleaseObject(piCompObj);
1371
1372 return hr;
1373}
1374
1375static 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
1440LExit:
1441 // clean up
1442 ReleaseObject(piIntfColl);
1443 ReleaseObject(piIntfObj);
1444
1445 return hr;
1446}
1447
1448static 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
1510LExit:
1511 // clean up
1512 ReleaseObject(piMethColl);
1513 ReleaseObject(piMethObj);
1514
1515 return hr;
1516}
1517
1518static 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
1581LExit:
1582 // clean up
1583 ReleaseObject(piRoleColl);
1584 ReleaseObject(piRoleObj);
1585
1586 return hr;
1587}
1588
1589static 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
1639LExit:
1640 // clean up
1641 ReleaseStr(pwzData);
1642
1643 if (pItm)
1644 FreeComponentList(pItm);
1645
1646 return hr;
1647}
1648
1649static 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
1699LExit:
1700 // clean up
1701 ReleaseStr(pwzData);
1702
1703 if (pItm)
1704 FreeInterfaceList(pItm);
1705
1706 return hr;
1707}
1708
1709static 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
1760LExit:
1761 // clean up
1762 ReleaseStr(pwzData);
1763
1764 if (pItm)
1765 FreeMethodList(pItm);
1766
1767 return hr;
1768}
1769
1770static 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
1813LExit:
1814 // clean up
1815 ReleaseStr(pwzData);
1816
1817 if (pItm)
1818 FreeRoleAssignmentList(pItm);
1819
1820 return hr;
1821}
1822
1823static 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
1842static 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
1861static 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
1878static 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
5HRESULT CpiConfigureAssemblies(
6 LPWSTR* ppwzData,
7 HANDLE hRollbackFile
8 );
9HRESULT CpiRollbackConfigureAssemblies(
10 LPWSTR* ppwzData,
11 CPI_ROLLBACK_DATA* pRollbackDataList
12 );
13HRESULT CpiConfigureRoleAssignments(
14 LPWSTR* ppwzData,
15 HANDLE hRollbackFile
16 );
17HRESULT 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
8LPCWSTR vcsMsiAssemblyNameQuery =
9 L"SELECT `Name`, `Value` FROM `MsiAssemblyName` WHERE `Component_` = ?";
10enum eMsiAssemblyNameQuery { manqName = 1, manqValue };
11
12LPCWSTR vcsModuleQuery =
13 L"SELECT `ModuleID` FROM `ModuleSignature`";
14enum eModuleQuery { mqModule = 1 };
15
16LPCWSTR vcsAssemblyQuery =
17 L"SELECT `Assembly`, `Component_`, `Application_`, `AssemblyName`, `DllPath`, `TlbPath`, `PSDllPath`, `Attributes` FROM `ComPlusAssembly`";
18enum eAssemblyQuery { aqAssembly = 1, aqComponent, aqApplication, aqAssemblyName, aqDllPath, aqTlbPath, aqPSDllPath, aqAttributes };
19
20LPCWSTR vcsComponentQuery =
21 L"SELECT `ComPlusComponent`, `CLSID` FROM `ComPlusComponent` WHERE `Assembly_` = ?";
22enum eComponentQuery { cqComponent = 1, cqCLSID };
23
24LPCWSTR vcsComponentPropertyQuery =
25 L"SELECT `Name`, `Value` FROM `ComPlusComponentProperty` WHERE `ComPlusComponent_` = ?";
26
27LPCWSTR vcsInterfaceQuery =
28 L"SELECT `Interface`, `IID` FROM `ComPlusInterface` WHERE `ComPlusComponent_` = ?";
29enum eInterfaceQuery { iqInterface = 1, iqIID };
30
31LPCWSTR vcsInterfacePropertyQuery =
32 L"SELECT `Name`, `Value` FROM `ComPlusInterfaceProperty` WHERE `Interface_` = ?";
33
34LPCWSTR vcsMethodQuery =
35 L"SELECT `Method`, `Index`, `Name` FROM `ComPlusMethod` WHERE `Interface_` = ?";
36enum eMethodQuery { mqMethod = 1, mqIndex, mqName };
37
38LPCWSTR vcsMethodPropertyQuery =
39 L"SELECT `Name`, `Value` FROM `ComPlusMethodProperty` WHERE `Method_` = ?";
40
41LPCWSTR vcsRoleForComponentQuery =
42 L"SELECT `RoleForComponent`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForComponent` WHERE `ComPlusComponent_` = ?";
43LPCWSTR vcsRoleForInterfaceQuery =
44 L"SELECT `RoleForInterface`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForInterface` WHERE `Interface_` = ?";
45LPCWSTR vcsRoleForMethodQuery =
46 L"SELECT `RoleForMethod`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForMethod` WHERE `Method_` = ?";
47
48enum eRoleAssignmentQuery { raqKey = 1, raqApplicationRole, raqComponent };
49
50LPCWSTR vcsModuleComponentsQuery =
51 L"SELECT `Component`, `ModuleID` FROM `ModuleComponents`";
52LPCWSTR vcsModuleDependencyQuery =
53 L"SELECT `ModuleID`, `RequiredID` FROM `ModuleDependency`";
54LPCWSTR vcsAssemblyDependencyQuery =
55 L"SELECT `Assembly_`, `RequiredAssembly_` FROM `ComPlusAssemblyDependency`";
56
57enum eKeyPairQuery { kpqFirstKey = 1, kpqSecondKey };
58
59
60// private structs
61
62struct 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
70struct CPI_DEPENDENCY_CHAIN
71{
72 LPCWSTR pwzKey;
73
74 CPI_DEPENDENCY_CHAIN* pPrev;
75};
76
77struct CPI_MODULE
78{
79 WCHAR wzKey[MAX_DARWIN_KEY + 1];
80
81 CPI_MODULE* pPrev;
82 CPI_MODULE* pNext;
83};
84
85struct CPI_MODULE_LIST
86{
87 CPI_MODULE* pFirst;
88 CPI_MODULE* pLast;
89};
90
91
92// property definitions
93
94CPI_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
129CPI_PROPERTY_DEFINITION pdlInterfaceProperties[] =
130{
131 {L"Description", cpptString, 500},
132 {L"QueuingEnabled", cpptBoolean, 500},
133 {NULL, cpptNone, 0}
134};
135
136CPI_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
146static HRESULT GetAssemblyName(
147 LPCWSTR pwzComponent,
148 LPWSTR* ppwzAssemblyName
149 );
150static HRESULT KeyPairsRead(
151 LPCWSTR pwzQuery,
152 CPI_KEY_PAIR** ppKeyPairList
153 );
154static HRESULT ModulesRead(
155 CPI_MODULE_LIST* pModList
156 );
157static HRESULT AssembliesRead(
158 CPI_KEY_PAIR* pModCompList,
159 CPI_APPLICATION_LIST* pAppList,
160 CPI_APPLICATION_ROLE_LIST* pAppRoleList,
161 CPI_ASSEMBLY_LIST* pAsmList
162 );
163static HRESULT ComponentsRead(
164 LPCWSTR pwzAsmKey,
165 CPI_APPLICATION_ROLE_LIST* pAppRoleList,
166 CPI_ASSEMBLY* pAsm
167 );
168static HRESULT InterfacesRead(
169 LPCWSTR pwzCompKey,
170 CPI_APPLICATION_ROLE_LIST* pAppRoleList,
171 CPI_ASSEMBLY* pAsm,
172 CPI_COMPONENT* pComp
173 );
174static HRESULT MethodsRead(
175 LPCWSTR pwzIntfKey,
176 CPI_APPLICATION_ROLE_LIST* pAppRoleList,
177 CPI_ASSEMBLY* pAsm,
178 CPI_INTERFACE* pIntf
179 );
180static 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 );
188static HRESULT TopSortModuleList(
189 CPI_KEY_PAIR* pDepList,
190 CPI_MODULE_LIST* pList
191 );
192static 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 );
199static HRESULT ModuleFindByKey(
200 CPI_MODULE* pItm,
201 LPCWSTR pwzKey,
202 BOOL fReverse,
203 CPI_MODULE** ppItm
204 );
205static void SortAssemblyListByModule(
206 CPI_MODULE_LIST* pModList,
207 CPI_ASSEMBLY_LIST* pAsmList
208 );
209static HRESULT TopSortAssemblyList(
210 CPI_KEY_PAIR* pDepList,
211 CPI_ASSEMBLY_LIST* pList
212 );
213static 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 );
220static HRESULT AssemblyFindByKey(
221 CPI_ASSEMBLY* pItm,
222 LPCWSTR pwzKey,
223 BOOL fReverse,
224 CPI_ASSEMBLY** ppItm
225 );
226static HRESULT AddAssemblyToActionData(
227 CPI_ASSEMBLY* pItm,
228 BOOL fInstall,
229 int iActionType,
230 int iActionCost,
231 LPWSTR* ppwzActionData
232 );
233static HRESULT AddRoleAssignmentsToActionData(
234 CPI_ASSEMBLY* pItm,
235 BOOL fInstall,
236 int iActionType,
237 int iActionCost,
238 LPWSTR* ppwzActionData
239 );
240static HRESULT AddComponentToActionData(
241 CPI_COMPONENT* pItm,
242 BOOL fInstall,
243 BOOL fProps,
244 BOOL fRoles,
245 LPWSTR* ppwzActionData
246 );
247static HRESULT AddInterfaceToActionData(
248 CPI_INTERFACE* pItm,
249 BOOL fInstall,
250 BOOL fProps,
251 BOOL fRoles,
252 LPWSTR* ppwzActionData
253 );
254static HRESULT AddMethodToActionData(
255 CPI_METHOD* pItm,
256 BOOL fInstall,
257 BOOL fProps,
258 BOOL fRoles,
259 LPWSTR* ppwzActionData
260 );
261static HRESULT AddRolesToActionData(
262 int iRoleInstallCount,
263 int iRoleUninstallCount,
264 CPI_ROLE_ASSIGNMENT* pRoleList,
265 BOOL fInstall,
266 BOOL fRoles,
267 LPWSTR* ppwzActionData
268 );
269static HRESULT KeyPairFindByFirstKey(
270 CPI_KEY_PAIR* pList,
271 LPCWSTR pwzKey,
272 CPI_KEY_PAIR** ppItm
273 );
274static void AssemblyFree(
275 CPI_ASSEMBLY* pItm
276 );
277static void KeyPairsFreeList(
278 CPI_KEY_PAIR* pList
279 );
280void ModuleListFree(
281 CPI_MODULE_LIST* pList
282 );
283static void ModuleFree(
284 CPI_MODULE* pItm
285 );
286static void ComponentsFreeList(
287 CPI_COMPONENT* pList
288 );
289static void InterfacesFreeList(
290 CPI_INTERFACE* pList
291 );
292static void MethodsFreeList(
293 CPI_METHOD* pList
294 );
295static void RoleAssignmentsFreeList(
296 CPI_ROLE_ASSIGNMENT* pList
297 );
298
299
300// function definitions
301
302void 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
316HRESULT 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
386LExit:
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
399HRESULT 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
418LExit:
419 return hr;
420}
421
422HRESULT 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
449HRESULT 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
517LExit:
518 return hr;
519}
520
521HRESULT 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
564LExit:
565 return hr;
566}
567
568HRESULT 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
636LExit:
637 return hr;
638}
639
640HRESULT 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
683LExit:
684 return hr;
685}
686
687HRESULT 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
726LExit:
727 // clean up
728 ReleaseObject(piCompColl);
729 ReleaseObject(piCompObj);
730
731 return hr;
732}
733
734
735// helper function definitions
736
737static 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
805LExit:
806 // clean up
807 ReleaseStr(pwzKey);
808 ReleaseStr(pwzName);
809 ReleaseStr(pwzVersion);
810 ReleaseStr(pwzCulture);
811 ReleaseStr(pwzPublicKeyToken);
812
813 return hr;
814}
815
816static 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
859LExit:
860 // clean up
861 if (pItm)
862 KeyPairsFreeList(pItm);
863
864 ReleaseStr(pwzData);
865
866 return hr;
867}
868
869static 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
911LExit:
912 // clean up
913 if (pItm)
914 ModuleFree(pItm);
915
916 ReleaseStr(pwzData);
917
918 return hr;
919}
920
921static 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
1067LExit:
1068 // clean up
1069 if (pItm)
1070 AssemblyFree(pItm);
1071
1072 ReleaseStr(pwzData);
1073 ReleaseStr(pwzComponent);
1074
1075 return hr;
1076}
1077
1078static 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
1095LExit:
1096 return hr;
1097}
1098
1099static 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
1172LExit:
1173 return hr;
1174}
1175
1176static 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
1195static 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
1241static 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
1258LExit:
1259 return hr;
1260}
1261
1262static 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
1342LExit:
1343 return hr;
1344}
1345
1346static 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
1365static 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
1444LExit:
1445 // clean up
1446 if (pItm)
1447 ComponentsFreeList(pItm);
1448
1449 ReleaseStr(pwzData);
1450
1451 return hr;
1452}
1453
1454static 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
1534LExit:
1535 // clean up
1536 if (pItm)
1537 InterfacesFreeList(pItm);
1538
1539 ReleaseStr(pwzData);
1540
1541 return hr;
1542}
1543
1544static 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
1624LExit:
1625 // clean up
1626 if (pItm)
1627 MethodsFreeList(pItm);
1628
1629 ReleaseStr(pwzData);
1630
1631 return hr;
1632}
1633
1634static 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
1724LExit:
1725 // clean up
1726 if (pItm)
1727 RoleAssignmentsFreeList(pItm);
1728
1729 ReleaseStr(pwzData);
1730
1731 return hr;
1732}
1733
1734static 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
1798LExit:
1799 return hr;
1800}
1801
1802static 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
1845LExit:
1846 return hr;
1847}
1848
1849static 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
1887LExit:
1888 return hr;
1889}
1890
1891static 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
1925LExit:
1926 return hr;
1927}
1928
1929static 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
1956LExit:
1957 return hr;
1958}
1959
1960static 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
1993LExit:
1994 return hr;
1995}
1996
1997static 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
2015static 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
2030static 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
2042void 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
2056static void ModuleFree(
2057 CPI_MODULE* pItm
2058 )
2059{
2060 ::HeapFree(::GetProcessHeap(), 0, pItm);
2061}
2062
2063static 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
2086static 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
2107static 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
2125static 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
5enum eAssemblyAttributes
6{
7 aaEventClass = (1 << 0),
8 aaDotNetAssembly = (1 << 1),
9 aaPathFromGAC = (1 << 2),
10 aaRunInCommit = (1 << 3)
11};
12
13
14// structs
15
16struct 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
27struct 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
43struct 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
61struct 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
81struct 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
109struct 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
126void CpiAssemblyListFree(
127 CPI_ASSEMBLY_LIST* pList
128 );
129HRESULT CpiAssembliesRead(
130 CPI_APPLICATION_LIST* pAppList,
131 CPI_APPLICATION_ROLE_LIST* pAppRoleList,
132 CPI_ASSEMBLY_LIST* pAsmList
133 );
134HRESULT CpiAssembliesVerifyInstall(
135 CPI_ASSEMBLY_LIST* pList
136 );
137HRESULT CpiAssembliesVerifyUninstall(
138 CPI_ASSEMBLY_LIST* pList
139 );
140HRESULT CpiAssembliesInstall(
141 CPI_ASSEMBLY_LIST* pList,
142 int iRunMode,
143 LPWSTR* ppwzActionData,
144 int* piProgress
145 );
146HRESULT CpiAssembliesUninstall(
147 CPI_ASSEMBLY_LIST* pList,
148 int iRunMode,
149 LPWSTR* ppwzActionData,
150 int* piProgress
151 );
152HRESULT CpiRoleAssignmentsInstall(
153 CPI_ASSEMBLY_LIST* pList,
154 int iRunMode,
155 LPWSTR* ppwzActionData,
156 int* piProgress
157 );
158HRESULT CpiRoleAssignmentsUninstall(
159 CPI_ASSEMBLY_LIST* pList,
160 int iRunMode,
161 LPWSTR* ppwzActionData,
162 int* piProgress
163 );
164HRESULT 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********************************************************************/
9extern "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********************************************************************/
33extern "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
59LExit:
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********************************************************************/
75extern "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
102LExit:
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********************************************************************/
115extern "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
198LExit:
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********************************************************************/
221extern "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
277LExit:
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********************************************************************/
299extern "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
414LExit:
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********************************************************************/
456extern "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
539LExit:
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********************************************************************/
562extern "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
669LExit:
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
4EXPORTS
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
8struct 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
18struct 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
30static HRESULT ReadPartitionAttributes(
31 LPWSTR* ppwzData,
32 CPI_PARTITION_ATTRIBUTES* pAttrs
33 );
34static void FreePartitionAttributes(
35 CPI_PARTITION_ATTRIBUTES* pAttrs
36 );
37static HRESULT CreatePartition(
38 CPI_PARTITION_ATTRIBUTES* pAttrs
39 );
40static HRESULT RemovePartition(
41 CPI_PARTITION_ATTRIBUTES* pAttrs
42 );
43static HRESULT ReadPartitionUserAttributes(
44 LPWSTR* ppwzData,
45 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
46 );
47static void FreePartitionUserAttributes(
48 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
49 );
50static HRESULT CreatePartitionUser(
51 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
52 );
53static HRESULT RemovePartitionUser(
54 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
55 );
56
57
58// function definitions
59
60HRESULT 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
124LExit:
125 // clean up
126 FreePartitionAttributes(&attrs);
127
128 return hr;
129}
130
131HRESULT 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
197LExit:
198 // clean up
199 FreePartitionAttributes(&attrs);
200
201 return hr;
202}
203
204HRESULT 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
268LExit:
269 // clean up
270 FreePartitionUserAttributes(&attrs);
271
272 return hr;
273}
274
275HRESULT 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
339LExit:
340 // clean up
341 FreePartitionUserAttributes(&attrs);
342
343 return hr;
344}
345
346
347// helper function definitions
348
349static 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
371LExit:
372 return hr;
373}
374
375static 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
387static 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
437LExit:
438 // clean up
439 ReleaseObject(piPartColl);
440 ReleaseObject(piPartObj);
441
442 return hr;
443}
444
445static 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
484LExit:
485 // clean up
486 ReleaseObject(piPartColl);
487
488 return hr;
489}
490
491static 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
511LExit:
512 return hr;
513}
514
515static void FreePartitionUserAttributes(
516 CPI_PARTITION_USER_ATTRIBUTES* pAttrs
517 )
518{
519 ReleaseStr(pAttrs->pwzKey);
520 ReleaseStr(pAttrs->pwzAccount);
521 ReleaseStr(pAttrs->pwzPartID);
522}
523
524static 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
601LExit:
602 // clean up
603 ReleaseObject(piUserColl);
604 ReleaseObject(piUserObj);
605
606 if (pSid)
607 ::HeapFree(::GetProcessHeap(), 0, pSid);
608
609 return hr;
610}
611
612static 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
682LExit:
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
5HRESULT CpiConfigurePartitions(
6 LPWSTR* ppwzData,
7 HANDLE hRollbackFile
8 );
9HRESULT CpiRollbackConfigurePartitions(
10 LPWSTR* ppwzData,
11 CPI_ROLLBACK_DATA* pRollbackDataList
12 );
13HRESULT CpiConfigurePartitionUsers(
14 LPWSTR* ppwzData,
15 HANDLE hRollbackFile
16 );
17HRESULT 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
8struct 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
21static HRESULT ReadUserInPartitionRoleAttributes(
22 LPWSTR* ppwzData,
23 CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
24 );
25static void FreeUserInPartitionRoleAttributes(
26 CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
27 );
28static HRESULT CreateUserInPartitionRole(
29 CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
30 );
31static HRESULT RemoveUserInPartitionRole(
32 CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
33 );
34
35
36// function definitions
37
38HRESULT 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
102LExit:
103 // clean up
104 FreeUserInPartitionRoleAttributes(&attrs);
105
106 return hr;
107}
108
109HRESULT 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
175LExit:
176 // clean up
177 FreeUserInPartitionRoleAttributes(&attrs);
178
179 return hr;
180}
181
182
183// helper function definitions
184
185static 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
207LExit:
208 return hr;
209}
210
211static 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
221static 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
301LExit:
302 // clean up
303 ReleaseObject(piUsrInRoleColl);
304 ReleaseObject(piUsrInRoleObj);
305
306 if (pSid)
307 ::HeapFree(::GetProcessHeap(), 0, pSid);
308
309 return hr;
310}
311
312static 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
389LExit:
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
5HRESULT CpiConfigureUsersInPartitionRoles(
6 LPWSTR* ppwzData,
7 HANDLE hRollbackFile
8 );
9HRESULT 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
8LPCWSTR vcsPartitionRoleQuery =
9 L"SELECT `PartitionRole`, `Partition_`, `Component_`, `Name` FROM `ComPlusPartitionRole`";
10enum ePartitionRoleQuery { prqPartitionRole = 1, prqPartition, prqComponent, prqName };
11
12LPCWSTR vcsUserInPartitionRoleQuery =
13 L"SELECT `UserInPartitionRole`, `PartitionRole_`, `ComPlusUserInPartitionRole`.`Component_`, `Domain`, `Name` FROM `ComPlusUserInPartitionRole`, `User` WHERE `User_` = `User`";
14LPCWSTR vcsGroupInPartitionRoleQuery =
15 L"SELECT `GroupInPartitionRole`, `PartitionRole_`, `ComPlusGroupInPartitionRole`.`Component_`, `Domain`, `Name` FROM `ComPlusGroupInPartitionRole`, `Group` WHERE `Group_` = `Group`";
16enum eTrusteeInPartitionRoleQuery { tiprqUserInPartitionRole = 1, tiprqPartitionRole, tiprqComponent, tiprqDomain, tiprqName };
17
18
19// prototypes for private helper functions
20
21static HRESULT TrusteesInPartitionRolesRead(
22 LPCWSTR pwzQuery,
23 CPI_PARTITION_ROLE_LIST* pPartRoleList,
24 CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList
25 );
26static void FreePartitionRole(
27 CPI_PARTITION_ROLE* pItm
28 );
29static void FreeUserInPartitionRole(
30 CPI_USER_IN_PARTITION_ROLE* pItm
31 );
32static 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
42void 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
56HRESULT 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
106LExit:
107 // clean up
108 if (pItm)
109 FreePartitionRole(pItm);
110
111 ReleaseStr(pwzData);
112
113 return hr;
114}
115
116HRESULT 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
134void 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
148HRESULT 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
171LExit:
172 return hr;
173}
174
175HRESULT 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
223LExit:
224 return hr;
225}
226
227HRESULT 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
270LExit:
271 return hr;
272}
273
274
275// helper function definitions
276
277static 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
362LExit:
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
374static void FreePartitionRole(
375 CPI_PARTITION_ROLE* pItm
376 )
377{
378 ::HeapFree(::GetProcessHeap(), 0, pItm);
379}
380
381static void FreeUserInPartitionRole(
382 CPI_USER_IN_PARTITION_ROLE* pItm
383 )
384{
385 ReleaseStr(pItm->pwzAccount);
386
387 ::HeapFree(::GetProcessHeap(), 0, pItm);
388}
389
390static 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
419LExit:
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
5struct 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
17struct CPI_PARTITION_ROLE_LIST
18{
19 CPI_PARTITION_ROLE* pFirst;
20};
21
22struct 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
34struct 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
45void CpiPartitionRoleListFree(
46 CPI_PARTITION_ROLE_LIST* pList
47 );
48HRESULT CpiPartitionRolesRead(
49 CPI_PARTITION_LIST* pPartList,
50 CPI_PARTITION_ROLE_LIST* pPartRoleList
51 );
52HRESULT CpiPartitionRoleFindByKey(
53 CPI_PARTITION_ROLE_LIST* pList,
54 LPCWSTR pwzKey,
55 CPI_PARTITION_ROLE** ppPartRole
56 );
57
58void CpiUserInPartitionRoleListFree(
59 CPI_USER_IN_PARTITION_ROLE_LIST* pList
60 );
61HRESULT CpiUsersInPartitionRolesRead(
62 CPI_PARTITION_ROLE_LIST* pPartRoleList,
63 CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList
64 );
65HRESULT CpiUsersInPartitionRolesInstall(
66 CPI_USER_IN_PARTITION_ROLE_LIST* pList,
67 int iRunMode,
68 LPWSTR* ppwzActionData,
69 int* piProgress
70 );
71HRESULT 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
8LPCWSTR vcsPartitionQuery =
9 L"SELECT `Partition`, `Component_`, `Id`, `Name` FROM `ComPlusPartition`";
10enum ePartitionQuery { pqPartition = 1, pqComponent, pqID, pqName };
11
12LPCWSTR vcsPartitionPropertyQuery =
13 L"SELECT `Name`, `Value` FROM `ComPlusPartitionProperty` WHERE `Partition_` = ?";
14
15LPCWSTR vcsPartitionUserQuery =
16 L"SELECT `PartitionUser`, `Partition_`, `ComPlusPartitionUser`.`Component_`, `Domain`, `Name` FROM `ComPlusPartitionUser`, `User` WHERE `User_` = `User`";
17enum ePartitionUserQuery { puqPartitionUser = 1, puqPartition, puqComponent, puqDomain, puqName };
18
19
20// property definitions
21
22CPI_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
33static void FreePartition(
34 CPI_PARTITION* pItm
35 );
36static void FreePartitionUser(
37 CPI_PARTITION_USER* pItm
38 );
39static HRESULT AddPartitionToActionData(
40 CPI_PARTITION* pItm,
41 int iActionType,
42 int iActionCost,
43 LPWSTR* ppwzActionData
44 );
45static HRESULT AddPartitionUserToActionData(
46 CPI_PARTITION_USER* pItm,
47 int iActionType,
48 int iActionCost,
49 LPWSTR* ppwzActionData
50 );
51
52
53// function definitions
54
55void 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
69HRESULT 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
169LExit:
170 // clean up
171 if (pItm)
172 FreePartition(pItm);
173
174 ReleaseStr(pwzData);
175
176 return hr;
177}
178
179HRESULT 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
314LExit:
315 // clean up
316 ReleaseObject(piPartColl);
317 ReleaseObject(piPartObj);
318
319 return hr;
320}
321
322HRESULT 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
372LExit:
373 // clean up
374 ReleaseObject(piPartColl);
375 ReleaseObject(piPartObj);
376
377 return hr;
378}
379
380void CpiPartitionAddReferenceInstall(
381 CPI_PARTITION* pItm
382 )
383{
384 pItm->fReferencedForInstall = TRUE;
385}
386
387void CpiPartitionAddReferenceUninstall(
388 CPI_PARTITION* pItm
389 )
390{
391 pItm->fReferencedForUninstall = TRUE;
392}
393
394HRESULT 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
442LExit:
443 return hr;
444}
445
446HRESULT 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
489LExit:
490 return hr;
491}
492
493HRESULT 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
511HRESULT 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
553LExit:
554 // clean up
555 ReleaseObject(piPartColl);
556 ReleaseObject(piPartObj);
557
558 return hr;
559}
560
561HRESULT 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
600LExit:
601 // clean up
602 ReleaseObject(piPartColl);
603 ReleaseObject(piPartObj);
604
605 return hr;
606}
607
608void 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
622HRESULT 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
714LExit:
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
726HRESULT 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
774LExit:
775 return hr;
776}
777
778HRESULT 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
821LExit:
822 return hr;
823}
824
825
826// helper function definitions
827
828static 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
841static void FreePartitionUser(
842 CPI_PARTITION_USER* pItm
843 )
844{
845 ReleaseStr(pItm->pwzAccount);
846
847 ::HeapFree(::GetProcessHeap(), 0, pItm);
848}
849
850static 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
879LExit:
880 return hr;
881}
882
883static 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
910LExit:
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
5struct 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
27struct CPI_PARTITION_LIST
28{
29 CPI_PARTITION* pFirst;
30
31 int iInstallCount;
32 int iUninstallCount;
33};
34
35struct 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
49struct CPI_PARTITION_USER_LIST
50{
51 CPI_PARTITION_USER* pFirst;
52
53 int iInstallCount;
54 int iUninstallCount;
55};
56
57
58// function prototypes
59
60void CpiPartitionListFree(
61 CPI_PARTITION_LIST* pList
62 );
63HRESULT CpiPartitionsRead(
64 CPI_PARTITION_LIST* pPartList
65 );
66HRESULT CpiPartitionsVerifyInstall(
67 CPI_PARTITION_LIST* pList
68 );
69HRESULT CpiPartitionsVerifyUninstall(
70 CPI_PARTITION_LIST* pList
71 );
72void CpiPartitionAddReferenceInstall(
73 CPI_PARTITION* pItm
74 );
75void CpiPartitionAddReferenceUninstall(
76 CPI_PARTITION* pItm
77 );
78HRESULT CpiPartitionsInstall(
79 CPI_PARTITION_LIST* pList,
80 int iRunMode,
81 LPWSTR* ppwzActionData,
82 int* piProgress
83 );
84HRESULT CpiPartitionsUninstall(
85 CPI_PARTITION_LIST* pList,
86 int iRunMode,
87 LPWSTR* ppwzActionData,
88 int* piProgress
89 );
90HRESULT CpiPartitionFindByKey(
91 CPI_PARTITION_LIST* pList,
92 LPCWSTR wzKey,
93 CPI_PARTITION** ppItm
94 );
95HRESULT CpiGetApplicationsCollForPartition(
96 CPI_PARTITION* pPart,
97 ICatalogCollection** ppiAppColl
98 );
99HRESULT CpiGetPartitionUsersCollection(
100 CPI_PARTITION* pPart,
101 ICatalogCollection** ppiPartUsrColl
102 );
103HRESULT CpiGetRolesCollForPartition(
104 CPI_PARTITION* pPart,
105 ICatalogCollection** ppiRolesColl
106 );
107void CpiPartitionUserListFree(
108 CPI_PARTITION_USER_LIST* pList
109 );
110HRESULT CpiPartitionUsersRead(
111 CPI_PARTITION_LIST* pPartList,
112 CPI_PARTITION_USER_LIST* pPartUsrList
113 );
114HRESULT CpiPartitionUsersInstall(
115 CPI_PARTITION_USER_LIST* pList,
116 int iRunMode,
117 LPWSTR* ppwzActionData,
118 int* piProgress
119 );
120HRESULT 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********************************************************************/
37extern "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********************************************************************/
60extern "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
303LExit:
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********************************************************************/
337extern "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
564LExit:
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
8struct 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
26static HRESULT ReadSubscriptionAttributes(
27 LPWSTR* ppwzData,
28 CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
29 );
30static void FreeSubscriptionAttributes(
31 CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
32 );
33static HRESULT CreateSubscription(
34 CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
35 );
36static HRESULT RemoveSubscription(
37 CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
38 );
39
40
41// function definitions
42
43HRESULT 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
107LExit:
108 // clean up
109 FreeSubscriptionAttributes(&attrs);
110
111 return hr;
112}
113
114HRESULT 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
180LExit:
181 // clean up
182 FreeSubscriptionAttributes(&attrs);
183
184 return hr;
185}
186
187
188// helper function definitions
189
190static 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
223LExit:
224 return hr;
225}
226
227static 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
244static 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
356LExit:
357 // clean up
358 ReleaseObject(piSubsColl);
359 ReleaseObject(piSubsObj);
360
361 if (pSid)
362 ::HeapFree(::GetProcessHeap(), 0, pSid);
363
364 return hr;
365}
366
367static 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
406LExit:
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
5HRESULT CpiConfigureSubscriptions(
6 LPWSTR* ppwzData,
7 HANDLE hRollbackFile
8 );
9HRESULT 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
8LPCWSTR vcsSubscriptionQuery =
9 L"SELECT `Subscription`, `ComPlusComponent_`, `Component_`, `Id`, `Name`, `EventCLSID`, `PublisherID` FROM `ComPlusSubscription`";
10enum eSubscriptionQuery { sqSubscription = 1, sqComPlusComponent, sqComponent, sqID, sqName, sqEventCLSID, sqPublisherID };
11
12LPCWSTR vcsSubscriptionPropertyQuery =
13 L"SELECT `Name`, `Value` FROM `ComPlusSubscriptionProperty` WHERE `Subscription_` = ?";
14
15
16// property definitions
17
18CPI_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
37static void FreeSubscription(
38 CPI_SUBSCRIPTION* pItm
39 );
40static HRESULT FindObjectForSubscription(
41 CPI_SUBSCRIPTION* pItm,
42 BOOL fFindId,
43 BOOL fFindName,
44 ICatalogObject** ppiSubsObj
45 );
46static HRESULT AddSubscriptionToActionData(
47 CPI_SUBSCRIPTION* pItm,
48 int iActionType,
49 int iActionCost,
50 LPWSTR* ppwzActionData
51 );
52static 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
62void 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
76HRESULT 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
193LExit:
194 // clean up
195 if (pItm)
196 FreeSubscription(pItm);
197
198 ReleaseStr(pwzData);
199
200 return hr;
201}
202
203HRESULT 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
320LExit:
321 // clean up
322 ReleaseObject(piSubsObj);
323
324 return hr;
325}
326
327HRESULT 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
368LExit:
369 // clean up
370 ReleaseObject(piSubsObj);
371
372 return hr;
373}
374
375HRESULT 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
440LExit:
441 return hr;
442}
443
444HRESULT 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
487LExit:
488 return hr;
489}
490
491
492// helper function definitions
493
494static void FreeSubscription(
495 CPI_SUBSCRIPTION* pItm
496 )
497{
498 if (pItm->pProperties)
499 CpiPropertiesFreeList(pItm->pProperties);
500
501 ::HeapFree(::GetProcessHeap(), 0, pItm);
502}
503
504static 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
528LExit:
529 // clean up
530 ReleaseObject(piSubsColl);
531
532 return hr;
533}
534
535static 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
581LExit:
582 return hr;
583}
584
585static 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
5struct 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
26struct 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
38void CpiSubscriptionListFree(
39 CPI_SUBSCRIPTION_LIST* pList
40 );
41HRESULT CpiSubscriptionsRead(
42 CPI_ASSEMBLY_LIST* pAsmList,
43 CPI_SUBSCRIPTION_LIST* pSubList
44 );
45HRESULT CpiSubscriptionsVerifyInstall(
46 CPI_SUBSCRIPTION_LIST* pList
47 );
48HRESULT CpiSubscriptionsVerifyUninstall(
49 CPI_SUBSCRIPTION_LIST* pList
50 );
51HRESULT CpiSubscriptionsInstall(
52 CPI_SUBSCRIPTION_LIST* pList,
53 int iRunMode,
54 LPWSTR* ppwzActionData,
55 int* piProgress
56 );
57HRESULT 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
8struct 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
19CPI_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
35static HRESULT FindUserCollectionObjectIndex(
36 ICatalogCollection* piColl,
37 PSID pSid,
38 int* pi
39 );
40static HRESULT CreateSidFromDomainRidPair(
41 PSID pDomainSid,
42 DWORD dwRid,
43 PSID* ppSid
44 );
45static HRESULT InitLsaUnicodeString(
46 PLSA_UNICODE_STRING plusStr,
47 LPCWSTR pwzStr,
48 DWORD dwLen
49 );
50static void FreeLsaUnicodeString(
51 PLSA_UNICODE_STRING plusStr
52 );
53static HRESULT WriteFileAll(
54 HANDLE hFile,
55 PBYTE pbBuffer,
56 DWORD dwBufferLength
57 );
58static HRESULT ReadFileAll(
59 HANDLE hFile,
60 PBYTE pbBuffer,
61 DWORD dwBufferLength
62 );
63
64
65// variables
66
67static ICOMAdminCatalog* gpiCatalog;
68
69
70// function definitions
71
72void CpiInitialize()
73{
74 // collections
75 gpiCatalog = NULL;
76}
77
78void CpiFinalize()
79{
80 // collections
81 ReleaseObject(gpiCatalog);
82}
83
84HRESULT 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
138LExit:
139 // clean up
140 ReleaseStr(pwzData);
141
142 return hr;
143}
144
145HRESULT 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
186LExit:
187 return hr;
188}
189
190HRESULT 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
209LExit:
210 return hr;
211}
212
213HRESULT 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
270LExit:
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
285HRESULT 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
320LExit:
321 // clean up
322 ReleaseObject(piCatalog);
323 ReleaseObject(piDisp);
324 ReleaseBSTR(bstrName);
325
326 return hr;
327}
328
329HRESULT 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
373LExit:
374 // clean up
375 ReleaseObject(piCatalog);
376 ReleaseObject(piDisp);
377 ReleaseBSTR(bstrName);
378 ::VariantClear(&vtKey);
379
380 return hr;
381}
382
383HRESULT 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
400LExit:
401 // clean up
402 ReleaseObject(piDisp);
403
404 return hr;
405}
406
407HRESULT 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
435LExit:
436 // clean up
437 ReleaseBSTR(bstrPropName);
438 ::VariantClear(&vtVal);
439
440 return hr;
441}
442
443HRESULT 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
459LExit:
460 return hr;
461}
462
463HRESULT 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
492LExit:
493 // clean up
494 ReleaseBSTR(bstrPropName);
495 ::VariantClear(&vtVal);
496
497 return hr;
498}
499
500HRESULT 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
544LExit:
545 // clean up
546 ReleaseBSTR(bstrPropName);
547 ::VariantClear(&vtVal);
548
549 return hr;
550}
551
552HRESULT 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
634LExit:
635 // clean up
636 ReleaseObject(piDisp);
637 ReleaseObject(piObj);
638
639 ::VariantClear(&vtVal);
640
641 return hr;
642}
643
644HRESULT 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
666LExit:
667 return hr;
668}
669
670HRESULT 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
723LExit:
724 // clean up
725 ReleaseObject(piDisp);
726 ReleaseObject(piObj);
727
728 ::VariantClear(&vtVal);
729
730 return hr;
731}
732
733HRESULT 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
786LExit:
787 // clean up
788 ReleaseObject(piDisp);
789 ReleaseObject(piObj);
790
791 ::VariantClear(&vtVal);
792
793 return hr;
794}
795
796HRESULT 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
849LExit:
850 // clean up
851 ReleaseObject(piDisp);
852 ReleaseObject(piObj);
853
854 ::VariantClear(&vtVal);
855
856 return hr;
857}
858
859HRESULT 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
890LExit:
891 // clean up
892 ReleaseObject(piDisp);
893
894 return hr;
895}
896
897HRESULT 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
909LExit:
910 return hr;
911}
912
913HRESULT 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
943LExit:
944 // clean up
945 ReleaseObject(piPartColl);
946 ReleaseObject(piPartObj);
947
948 return hr;
949}
950
951HRESULT 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
982LExit:
983 // clean up
984 ReleaseObject(piRoleColl);
985 ReleaseObject(piRoleObj);
986
987 return hr;
988}
989
990HRESULT 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
1002LExit:
1003 return hr;
1004}
1005
1006HRESULT 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
1070LExit:
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
1082HRESULT 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
1113LExit:
1114 // clean up
1115 ReleaseObject(piAppColl);
1116 ReleaseObject(piAppObj);
1117
1118 return hr;
1119}
1120
1121HRESULT 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
1153LExit:
1154 // clean up
1155 ReleaseObject(piRoleColl);
1156 ReleaseObject(piRoleObj);
1157
1158 return hr;
1159}
1160
1161HRESULT 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
1192LExit:
1193 // clean up
1194 ReleaseObject(piAppColl);
1195 ReleaseObject(piAppObj);
1196
1197 return hr;
1198}
1199
1200HRESULT 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
1214LExit:
1215 return hr;
1216}
1217
1218HRESULT 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
1232LExit:
1233 return hr;
1234}
1235
1236HRESULT 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
1268LExit:
1269 // clean up
1270 ReleaseObject(piCompColl);
1271 ReleaseObject(piCompObj);
1272
1273 return hr;
1274}
1275
1276HRESULT 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
1321LExit:
1322 // clean up
1323 ReleaseStr(pwzName);
1324
1325 if (pItm)
1326 CpiFreePropertyList(pItm);
1327
1328 return hr;
1329}
1330
1331void 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
1345HRESULT 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
1364LExit:
1365 return hr;
1366}
1367
1368HRESULT 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
1382LExit:
1383 return hr;
1384}
1385
1386HRESULT 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
1431LExit:
1432 // clean up
1433 if (pItm)
1434 CpiFreeRollbackDataList(pItm);
1435
1436 return hr;
1437}
1438
1439void 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
1451HRESULT 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
1470LExit:
1471 return hr;
1472}
1473
1474HRESULT 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
1543LExit:
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
1558HRESULT 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
1606LExit:
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
1623static 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
1726LExit:
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
1752static 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
1795LExit:
1796 return hr;
1797}
1798
1799static 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
1818LExit:
1819 return hr;
1820}
1821
1822static void FreeLsaUnicodeString(
1823 PLSA_UNICODE_STRING plusStr
1824 )
1825{
1826 if (plusStr->Buffer)
1827 ::HeapFree(::GetProcessHeap(), 0, plusStr->Buffer);
1828}
1829
1830static 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
1851LExit:
1852 return hr;
1853}
1854
1855static 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
1879LExit:
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
7enum eActionType { atNoOp = 0, atCreate, atRemove };
8
9
10// structs
11
12struct CPI_PROPERTY
13{
14 WCHAR wzName[MAX_DARWIN_KEY + 1];
15 LPWSTR pwzValue;
16
17 CPI_PROPERTY* pNext;
18};
19
20struct 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
31void CpiInitialize();
32void CpiFinalize();
33HRESULT CpiActionStartMessage(
34 LPWSTR* ppwzActionData,
35 BOOL fSuppress
36 );
37HRESULT CpiActionDataMessage(
38 DWORD cArgs,
39 ...
40 );
41HRESULT CpiGetAdminCatalog(
42 ICOMAdminCatalog** ppiCatalog
43 );
44HRESULT CpiLogCatalogErrorInfo();
45HRESULT CpiGetCatalogCollection(
46 LPCWSTR pwzName,
47 ICatalogCollection** ppiColl
48 );
49HRESULT CpiGetCatalogCollection(
50 ICatalogCollection* piColl,
51 ICatalogObject* piObj,
52 LPCWSTR pwzName,
53 ICatalogCollection** ppiColl
54 );
55HRESULT CpiAddCollectionObject(
56 ICatalogCollection* piColl,
57 ICatalogObject** ppiObj
58 );
59HRESULT CpiPutCollectionObjectValue(
60 ICatalogObject* piObj,
61 LPCWSTR pwzPropName,
62 LPCWSTR pwzValue
63 );
64HRESULT CpiPutCollectionObjectValues(
65 ICatalogObject* piObj,
66 CPI_PROPERTY* pPropList
67 );
68HRESULT CpiGetCollectionObjectValue(
69 ICatalogObject* piObj,
70 LPCWSTR szPropName,
71 LPWSTR* ppwzValue
72 );
73HRESULT CpiResetObjectProperty(
74 ICatalogCollection* piColl,
75 ICatalogObject* piObj,
76 LPCWSTR pwzPropName
77 );
78HRESULT CpiRemoveCollectionObject(
79 ICatalogCollection* piColl,
80 LPCWSTR pwzID,
81 LPCWSTR pwzName,
82 BOOL fResetDeleteable
83 );
84HRESULT CpiRemoveUserCollectionObject(
85 ICatalogCollection* piColl,
86 PSID pSid
87 );
88HRESULT CpiFindCollectionObjectByStringKey(
89 ICatalogCollection* piColl,
90 LPCWSTR pwzKey,
91 ICatalogObject** ppiObj
92 );
93HRESULT CpiFindCollectionObjectByIntegerKey(
94 ICatalogCollection* piColl,
95 long lKey,
96 ICatalogObject** ppiObj
97 );
98HRESULT CpiFindCollectionObjectByName(
99 ICatalogCollection* piColl,
100 LPCWSTR pwzName,
101 ICatalogObject** ppiObj
102 );
103HRESULT CpiFindUserCollectionObject(
104 ICatalogCollection* piColl,
105 PSID pSid,
106 ICatalogObject** ppiObj
107 );
108HRESULT CpiGetPartitionsCollection(
109 ICatalogCollection** ppiPartColl
110 );
111HRESULT CpiGetPartitionRolesCollection(
112 LPCWSTR pwzPartID,
113 ICatalogCollection** ppiRolesColl
114 );
115HRESULT CpiGetUsersInPartitionRoleCollection(
116 LPCWSTR pwzPartID,
117 LPCWSTR pwzRoleName,
118 ICatalogCollection** ppiUsrInRoleColl
119 );
120HRESULT CpiGetPartitionUsersCollection(
121 ICatalogCollection** ppiUserColl
122 );
123HRESULT CpiGetApplicationsCollection(
124 LPCWSTR pwzPartID,
125 ICatalogCollection** ppiAppColl
126 );
127HRESULT CpiGetRolesCollection(
128 LPCWSTR pwzPartID,
129 LPCWSTR pwzAppID,
130 ICatalogCollection** ppiRolesColl
131 );
132HRESULT CpiGetUsersInRoleCollection(
133 LPCWSTR pwzPartID,
134 LPCWSTR pwzAppID,
135 LPCWSTR pwzRoleName,
136 ICatalogCollection** ppiUsrInRoleColl
137 );
138HRESULT CpiGetComponentsCollection(
139 LPCWSTR pwzPartID,
140 LPCWSTR pwzAppID,
141 ICatalogCollection** ppiCompsColl
142 );
143HRESULT CpiGetInterfacesCollection(
144 ICatalogCollection* piCompColl,
145 ICatalogObject* piCompObj,
146 ICatalogCollection** ppiIntfColl
147 );
148HRESULT CpiGetMethodsCollection(
149 ICatalogCollection* piIntfColl,
150 ICatalogObject* piIntfObj,
151 ICatalogCollection** ppiMethColl
152 );
153HRESULT CpiGetSubscriptionsCollection(
154 LPCWSTR pwzPartID,
155 LPCWSTR pwzAppID,
156 LPCWSTR pwzCompCLSID,
157 ICatalogCollection** ppiCompsColl
158 );
159HRESULT CpiReadPropertyList(
160 LPWSTR* ppwzData,
161 CPI_PROPERTY** ppPropList
162 );
163void CpiFreePropertyList(
164 CPI_PROPERTY* pList
165 );
166HRESULT CpiWriteKeyToRollbackFile(
167 HANDLE hFile,
168 LPCWSTR pwzKey
169 );
170HRESULT CpiWriteIntegerToRollbackFile(
171 HANDLE hFile,
172 int i
173 );
174HRESULT CpiReadRollbackDataList(
175 HANDLE hFile,
176 CPI_ROLLBACK_DATA** pprdList
177 );
178void CpiFreeRollbackDataList(
179 CPI_ROLLBACK_DATA* pList
180 );
181HRESULT CpiFindRollbackStatus(
182 CPI_ROLLBACK_DATA* pList,
183 LPCWSTR pwzKey,
184 int* piStatus
185 );
186HRESULT CpiAccountNameToSid(
187 LPCWSTR pwzAccountName,
188 PSID* ppSid
189 );
190HRESULT 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
8LPCWSTR vcsActionTextQuery =
9 L"SELECT `Description`, `Template` FROM `ActionText` WHERE `Action` = ?";
10enum eActionTextQuery { atqDescription = 1, atqTemplate };
11
12LPCWSTR vcsComponentAttributesQuery =
13 L"SELECT `Attributes` FROM `Component` WHERE `Component` = ?";
14enum eComponentAttributesQuery { caqAttributes = 1 };
15
16LPCWSTR vcsUserQuery = L"SELECT `Domain`, `Name` FROM `User` WHERE `User` = ?";
17enum eUserQuery { uqDomain = 1, uqName };
18
19enum ePropertyQuery { pqName = 1, pqValue };
20
21
22// prototypes for private helper functions
23
24static HRESULT FindPropertyDefinition(
25 CPI_PROPERTY_DEFINITION* pPropDefList,
26 LPCWSTR pwzName,
27 CPI_PROPERTY_DEFINITION** ppPropDef
28 );
29static HRESULT GetUserAccountName(
30 LPCWSTR pwzKey,
31 LPWSTR* ppwzAccount
32 );
33
34
35// variables
36
37static ICOMAdminCatalog* gpiCatalog;
38static ICatalogCollection* gpiPartColl;
39static ICatalogCollection* gpiAppColl;
40
41static int giTables;
42
43
44// function definitions
45
46void 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
83void CpiFinalize()
84{
85 // collections
86 ReleaseObject(gpiCatalog);
87 ReleaseObject(gpiPartColl);
88 ReleaseObject(gpiAppColl);
89}
90
91BOOL CpiTableExists(
92 int iTable
93 )
94{
95 return (giTables & iTable) == iTable;
96}
97
98HRESULT 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
117LExit:
118 return hr;
119}
120
121HRESULT 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
153LExit:
154 // clean up
155 ReleaseObject(piCatalog);
156 ReleaseObject(piDisp);
157 ReleaseBSTR(bstrName);
158
159 return hr;
160}
161
162HRESULT 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
203LExit:
204 // clean up
205 ReleaseObject(piCatalog);
206 ReleaseObject(piDisp);
207 ReleaseBSTR(bstrName);
208 ::VariantClear(&vtKey);
209
210 return hr;
211}
212
213HRESULT 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
238LExit:
239 // clean up
240 ::VariantClear(&vtKey);
241
242 return hr;
243}
244
245HRESULT 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
324LExit:
325 // clean up
326 ReleaseObject(piDisp);
327 ReleaseObject(piObj);
328
329 ::VariantClear(&vtVal);
330
331 return hr;
332}
333
334HRESULT 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
353LExit:
354 return hr;
355}
356
357HRESULT 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
418LExit:
419 // clean up
420 ReleaseObject(piCatalog);
421 ReleaseObject(piCatalog2);
422 ReleaseObject(piPartColl);
423 ReleaseObject(piPartObj);
424 ReleaseBSTR(bstrGlobPartID);
425
426 return hr;
427}
428
429HRESULT 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
485LExit:
486 // clean up
487 ReleaseStr(pwzDescription);
488 ReleaseStr(pwzTemplate);
489
490 return hr;
491}
492
493HRESULT 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
538LExit:
539 return hr;
540}
541
542HRESULT 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
629LExit:
630 // clean up
631 if (pItm)
632 CpiPropertiesFreeList(pItm);
633
634 ReleaseStr(pwzData);
635
636 return hr;
637}
638
639void 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
653HRESULT 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
678LExit:
679 return hr;
680}
681
682HRESULT 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
707LExit:
708 return hr;
709}
710
711HRESULT 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
734LExit:
735 return hr;
736}
737
738HRESULT 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
757LExit:
758 return hr;
759}
760
761BOOL CpiIsInstalled(
762 INSTALLSTATE isInstalled
763 )
764{
765 return INSTALLSTATE_LOCAL == isInstalled || INSTALLSTATE_SOURCE == isInstalled;
766}
767
768BOOL CpiWillBeInstalled(
769 INSTALLSTATE isInstalled,
770 INSTALLSTATE isAction
771 )
772{
773 return WcaIsInstalling(isInstalled, isAction) ||
774 (CpiIsInstalled(isInstalled) && !WcaIsUninstalling(isInstalled, isAction));
775}
776
777HRESULT 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
810LExit:
811 return hr;
812}
813
814
815// helper function definitions
816
817static 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
835static 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
879LExit:
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
7enum eRunMode { rmDeferred = 1, rmCommit, rmRollback };
8
9enum eActionType { atNoOp = 0, atCreate, atRemove };
10
11enum eComPlusPropertyType { cpptNone = 0, cpptBoolean, cpptInteger, cpptString, cpptUser };
12
13enum 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
45struct CPI_PROPERTY
46{
47 WCHAR wzName[MAX_DARWIN_KEY + 1];
48 LPWSTR pwzValue;
49
50 CPI_PROPERTY* pNext;
51};
52
53struct CPI_PROPERTY_DEFINITION
54{
55 LPCWSTR pwzName;
56 int iType;
57 int iMinVersionNT;
58};
59
60
61// function prototypes
62
63void CpiInitialize();
64void CpiFinalize();
65BOOL CpiTableExists(
66 int iTable
67 );
68HRESULT CpiGetAdminCatalog(
69 ICOMAdminCatalog** ppiCatalog
70 );
71HRESULT CpiGetCatalogCollection(
72 LPCWSTR pwzName,
73 ICatalogCollection** ppiColl
74 );
75HRESULT CpiGetCatalogCollection(
76 ICatalogCollection* piColl,
77 ICatalogObject* piObj,
78 LPCWSTR pwzName,
79 ICatalogCollection** ppiColl
80 );
81HRESULT CpiGetKeyForObject(
82 ICatalogObject* piObj,
83 LPWSTR pwzKey,
84 SIZE_T cchKey
85 );
86HRESULT CpiFindCollectionObject(
87 ICatalogCollection* piColl,
88 LPCWSTR pwzID,
89 LPCWSTR pwzName,
90 ICatalogObject** ppiObj
91 );
92HRESULT CpiGetPartitionsCollection(
93 ICatalogCollection** ppiPartColl
94 );
95HRESULT CpiGetApplicationsCollection(
96 ICatalogCollection** ppiAppColl
97 );
98HRESULT CpiAddActionTextToActionData(
99 LPCWSTR pwzAction,
100 LPWSTR* ppwzActionData
101 );
102HRESULT CpiVerifyComponentArchitecure(
103 LPCWSTR pwzComponent,
104 BOOL* pfMatchingArchitecture
105 );
106HRESULT CpiPropertiesRead(
107 LPCWSTR pwzQuery,
108 LPCWSTR pwzKey,
109 CPI_PROPERTY_DEFINITION* pPropDefList,
110 CPI_PROPERTY** ppPropList,
111 int* piCount
112 );
113void CpiPropertiesFreeList(
114 CPI_PROPERTY* pList
115 );
116HRESULT CpiAddPropertiesToActionData(
117 int iPropCount,
118 CPI_PROPERTY* pPropList,
119 LPWSTR* ppwzActionData
120 );
121HRESULT CpiBuildAccountName(
122 LPCWSTR pwzDomain,
123 LPCWSTR pwzName,
124 LPWSTR* ppwzAccount
125 );
126HRESULT CpiGetTempFileName(
127 LPWSTR* ppwzTempFile
128 );
129HRESULT CpiCreateId(
130 LPWSTR pwzDest,
131 SIZE_T cchDest
132 );
133BOOL CpiIsInstalled(
134 INSTALLSTATE isInstalled
135 );
136BOOL CpiWillBeInstalled(
137 INSTALLSTATE isInstalled,
138 INSTALLSTATE isAction
139 );
140HRESULT 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
3namespace 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
3namespace 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
3namespace 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>