Import code from old v4 repo
Sean Hall committed
Feb 4, 2019 at 20:05 UTC
cbc09b6cd6d0d0b8bf095a88d4d8333616637f71
44 files changed
+21074
src/ca/cpappexec.cpp
new
+344
@@ -0,0 +1,344 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// private structs
7
+
8
+struct CPI_APPLICATION_ATTRIBUTES
9
+{
10
+ int iActionType;
11
+ int iActionCost;
12
+ LPWSTR pwzKey;
13
+ LPWSTR pwzID;
14
+ LPWSTR pwzName;
15
+ LPWSTR pwzPartID;
16
+ CPI_PROPERTY* pPropList;
17
+};
18
+
19
+
20
+// prototypes for private helper functions
21
+
22
+static HRESULT ReadApplicationAttributes(
23
+ LPWSTR* ppwzData,
24
+ CPI_APPLICATION_ATTRIBUTES* pAttrs
25
+ );
26
+static void FreeApplicationAttributes(
27
+ CPI_APPLICATION_ATTRIBUTES* pAttrs
28
+ );
29
+static HRESULT CreateApplication(
30
+ CPI_APPLICATION_ATTRIBUTES* pAttrs
31
+ );
32
+static HRESULT RemoveApplication(
33
+ CPI_APPLICATION_ATTRIBUTES* pAttrs
34
+ );
35
+
36
+
37
+// function definitions
38
+
39
+HRESULT CpiConfigureApplications(
40
+ LPWSTR* ppwzData,
41
+ HANDLE hRollbackFile
42
+ )
43
+{
44
+ HRESULT hr = S_OK;
45
+
46
+ CPI_APPLICATION_ATTRIBUTES attrs;
47
+ ::ZeroMemory(&attrs, sizeof(attrs));
48
+
49
+ // read action text
50
+ hr = CpiActionStartMessage(ppwzData, FALSE);
51
+ ExitOnFailure(hr, "Failed to send action start message");
52
+
53
+ // get count
54
+ int iCnt = 0;
55
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
56
+ ExitOnFailure(hr, "Failed to read count");
57
+
58
+ // write count to rollback file
59
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
60
+ ExitOnFailure(hr, "Failed to write count to rollback file");
61
+
62
+ for (int i = 0; i < iCnt; i++)
63
+ {
64
+ // read attributes from CustomActionData
65
+ hr = ReadApplicationAttributes(ppwzData, &attrs);
66
+ ExitOnFailure(hr, "Failed to read attributes");
67
+
68
+ // progress message
69
+ hr = CpiActionDataMessage(1, attrs.pwzName);
70
+ ExitOnFailure(hr, "Failed to send progress messages");
71
+
72
+ if (S_FALSE == hr)
73
+ ExitFunction();
74
+
75
+ // write key to rollback file
76
+ hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
77
+ ExitOnFailure(hr, "Failed to write key to rollback file");
78
+
79
+ // action
80
+ switch (attrs.iActionType)
81
+ {
82
+ case atCreate:
83
+ hr = CreateApplication(&attrs);
84
+ ExitOnFailure(hr, "Failed to create application, key: %S", attrs.pwzKey);
85
+ break;
86
+ case atRemove:
87
+ hr = RemoveApplication(&attrs);
88
+ ExitOnFailure(hr, "Failed to remove application, key: %S", attrs.pwzKey);
89
+ break;
90
+ }
91
+
92
+ // write completion status to rollback file
93
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
94
+ ExitOnFailure(hr, "Failed to write completion status to rollback file");
95
+
96
+ // progress
97
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
98
+ ExitOnFailure(hr, "Failed to update progress");
99
+ }
100
+
101
+ hr = S_OK;
102
+
103
+LExit:
104
+ // clean up
105
+ FreeApplicationAttributes(&attrs);
106
+
107
+ return hr;
108
+}
109
+
110
+HRESULT CpiRollbackConfigureApplications(
111
+ LPWSTR* ppwzData,
112
+ CPI_ROLLBACK_DATA* pRollbackDataList
113
+ )
114
+{
115
+ HRESULT hr = S_OK;
116
+
117
+ int iRollbackStatus;
118
+
119
+ CPI_APPLICATION_ATTRIBUTES attrs;
120
+ ::ZeroMemory(&attrs, sizeof(attrs));
121
+
122
+ // read action text
123
+ hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
124
+ ExitOnFailure(hr, "Failed to send action start message");
125
+
126
+ // get count
127
+ int iCnt = 0;
128
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
129
+ ExitOnFailure(hr, "Failed to read count");
130
+
131
+ for (int i = 0; i < iCnt; i++)
132
+ {
133
+ // read attributes from CustomActionData
134
+ hr = ReadApplicationAttributes(ppwzData, &attrs);
135
+ ExitOnFailure(hr, "Failed to read attributes");
136
+
137
+ // rollback status
138
+ hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
139
+
140
+ if (S_FALSE == hr)
141
+ continue; // not found, nothing to rollback
142
+
143
+ // progress message
144
+ hr = CpiActionDataMessage(1, attrs.pwzName);
145
+ ExitOnFailure(hr, "Failed to send progress messages");
146
+
147
+ if (S_FALSE == hr)
148
+ ExitFunction();
149
+
150
+ // action
151
+ switch (attrs.iActionType)
152
+ {
153
+ case atCreate:
154
+ hr = CreateApplication(&attrs);
155
+ if (FAILED(hr))
156
+ WcaLog(LOGMSG_STANDARD, "Failed to create application, hr: 0x%x, key: %S", hr, attrs.pwzKey);
157
+ break;
158
+ case atRemove:
159
+ hr = RemoveApplication(&attrs);
160
+ if (FAILED(hr))
161
+ WcaLog(LOGMSG_STANDARD, "Failed to remove application, hr: 0x%x, key: %S", hr, attrs.pwzKey);
162
+ break;
163
+ }
164
+
165
+ // check rollback status
166
+ if (0 == iRollbackStatus)
167
+ continue; // operation did not complete, skip progress
168
+
169
+ // progress
170
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
171
+ ExitOnFailure(hr, "Failed to update progress");
172
+ }
173
+
174
+ hr = S_OK;
175
+
176
+LExit:
177
+ // clean up
178
+ FreeApplicationAttributes(&attrs);
179
+
180
+ return hr;
181
+}
182
+
183
+
184
+// helper function definitions
185
+
186
+static HRESULT ReadApplicationAttributes(
187
+ LPWSTR* ppwzData,
188
+ CPI_APPLICATION_ATTRIBUTES* pAttrs
189
+ )
190
+{
191
+ HRESULT hr = S_OK;
192
+
193
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
194
+ ExitOnFailure(hr, "Failed to read action type");
195
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
196
+ ExitOnFailure(hr, "Failed to read action cost");
197
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
198
+ ExitOnFailure(hr, "Failed to read key");
199
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzID);
200
+ ExitOnFailure(hr, "Failed to read id");
201
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName);
202
+ ExitOnFailure(hr, "Failed to read name");
203
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
204
+ ExitOnFailure(hr, "Failed to read partition id");
205
+ hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList);
206
+ ExitOnFailure(hr, "Failed to read properties");
207
+
208
+ hr = S_OK;
209
+
210
+LExit:
211
+ return hr;
212
+}
213
+
214
+static void FreeApplicationAttributes(
215
+ CPI_APPLICATION_ATTRIBUTES* pAttrs
216
+ )
217
+{
218
+ ReleaseStr(pAttrs->pwzKey);
219
+ ReleaseStr(pAttrs->pwzID);
220
+ ReleaseStr(pAttrs->pwzName);
221
+ ReleaseStr(pAttrs->pwzPartID);
222
+
223
+ if (pAttrs->pPropList)
224
+ CpiFreePropertyList(pAttrs->pPropList);
225
+}
226
+
227
+static HRESULT CreateApplication(
228
+ CPI_APPLICATION_ATTRIBUTES* pAttrs
229
+ )
230
+{
231
+ HRESULT hr = S_OK;
232
+
233
+ ICatalogCollection* piAppColl = NULL;
234
+ ICatalogObject* piAppObj = NULL;
235
+
236
+ long lChanges = 0;
237
+
238
+ // log
239
+ WcaLog(LOGMSG_VERBOSE, "Creating application, key: %S", pAttrs->pwzKey);
240
+
241
+ // get applications collection
242
+ hr = CpiGetApplicationsCollection(pAttrs->pwzPartID, &piAppColl);
243
+ if (S_FALSE == hr)
244
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
245
+ ExitOnFailure(hr, "Failed to get applications collection");
246
+
247
+ // check if application exists
248
+ hr = CpiFindCollectionObjectByStringKey(piAppColl, pAttrs->pwzID, &piAppObj);
249
+ ExitOnFailure(hr, "Failed to find application");
250
+
251
+ if (S_FALSE == hr)
252
+ {
253
+ // create application
254
+ hr = CpiAddCollectionObject(piAppColl, &piAppObj);
255
+ ExitOnFailure(hr, "Failed to add application to collection");
256
+
257
+ hr = CpiPutCollectionObjectValue(piAppObj, L"ID", pAttrs->pwzID);
258
+ ExitOnFailure(hr, "Failed to set application id property");
259
+
260
+ hr = CpiPutCollectionObjectValue(piAppObj, L"Name", pAttrs->pwzName);
261
+ ExitOnFailure(hr, "Failed to set application name property");
262
+
263
+ // save changes
264
+ hr = piAppColl->SaveChanges(&lChanges);
265
+ if (COMADMIN_E_OBJECTERRORS == hr)
266
+ CpiLogCatalogErrorInfo();
267
+ ExitOnFailure(hr, "Failed to add application");
268
+ }
269
+
270
+ // properties
271
+ hr = CpiPutCollectionObjectValues(piAppObj, pAttrs->pPropList);
272
+ ExitOnFailure(hr, "Failed to write properties");
273
+
274
+ // save changes
275
+ hr = piAppColl->SaveChanges(&lChanges);
276
+ if (COMADMIN_E_OBJECTERRORS == hr)
277
+ CpiLogCatalogErrorInfo();
278
+ ExitOnFailure(hr, "Failed to save changes");
279
+
280
+ // log
281
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
282
+
283
+ hr = S_OK;
284
+
285
+LExit:
286
+ // clean up
287
+ ReleaseObject(piAppColl);
288
+ ReleaseObject(piAppObj);
289
+
290
+ return hr;
291
+}
292
+
293
+static HRESULT RemoveApplication(
294
+ CPI_APPLICATION_ATTRIBUTES* pAttrs
295
+ )
296
+{
297
+ HRESULT hr = S_OK;
298
+
299
+ ICatalogCollection* piAppColl = NULL;
300
+
301
+ long lChanges = 0;
302
+
303
+ // log
304
+ WcaLog(LOGMSG_VERBOSE, "Removing application, key: %S", pAttrs->pwzKey);
305
+
306
+ // get applications collection
307
+ hr = CpiGetApplicationsCollection(pAttrs->pwzPartID, &piAppColl);
308
+ ExitOnFailure(hr, "Failed to get applications collection");
309
+
310
+ if (S_FALSE == hr)
311
+ {
312
+ // applications collection not found
313
+ WcaLog(LOGMSG_VERBOSE, "Unable to retrieve applications collection, nothing to delete, key: %S", pAttrs->pwzKey);
314
+ ExitFunction1(hr = S_OK);
315
+ }
316
+
317
+ // remove
318
+ hr = CpiRemoveCollectionObject(piAppColl, pAttrs->pwzID, NULL, TRUE);
319
+ ExitOnFailure(hr, "Failed to remove application");
320
+
321
+ if (S_FALSE == hr)
322
+ {
323
+ // application not found
324
+ WcaLog(LOGMSG_VERBOSE, "Application not found, nothing to delete, key: %S", pAttrs->pwzKey);
325
+ ExitFunction1(hr = S_OK);
326
+ }
327
+
328
+ // save changes
329
+ hr = piAppColl->SaveChanges(&lChanges);
330
+ if (COMADMIN_E_OBJECTERRORS == hr)
331
+ CpiLogCatalogErrorInfo();
332
+ ExitOnFailure(hr, "Failed to save changes");
333
+
334
+ // log
335
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
336
+
337
+ hr = S_OK;
338
+
339
+LExit:
340
+ // clean up
341
+ ReleaseObject(piAppColl);
342
+
343
+ return hr;
344
+}
src/ca/cpappexec.h
new
+12
@@ -0,0 +1,12 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+HRESULT CpiConfigureApplications(
6
+ LPWSTR* ppwzData,
7
+ HANDLE hRollbackFile
8
+ );
9
+HRESULT CpiRollbackConfigureApplications(
10
+ LPWSTR* ppwzData,
11
+ CPI_ROLLBACK_DATA* pRollbackDataList
12
+ );
src/ca/cpapproleexec.cpp
new
+720
@@ -0,0 +1,720 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// private structs
7
+
8
+struct CPI_APPLICATION_ROLE_ATTRIBUTES
9
+{
10
+ int iActionType;
11
+ int iActionCost;
12
+ LPWSTR pwzKey;
13
+ LPWSTR pwzName;
14
+ LPWSTR pwzAppID;
15
+ LPWSTR pwzPartID;
16
+ CPI_PROPERTY* pPropList;
17
+};
18
+
19
+struct CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES
20
+{
21
+ int iActionType;
22
+ int iActionCost;
23
+ LPWSTR pwzKey;
24
+ LPWSTR pwzRoleName;
25
+ LPWSTR pwzAccount;
26
+ LPWSTR pwzAppID;
27
+ LPWSTR pwzPartID;
28
+};
29
+
30
+
31
+// prototypes for private helper functions
32
+
33
+static HRESULT ReadApplicationRoleAttributes(
34
+ LPWSTR* ppwzData,
35
+ CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
36
+ );
37
+static void FreeApplicationRoleAttributes(
38
+ CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
39
+ );
40
+static HRESULT CreateApplicationRole(
41
+ CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
42
+ );
43
+static HRESULT RemoveApplicationRole(
44
+ CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
45
+ );
46
+static HRESULT ReadUsersInApplicationRoleAttributes(
47
+ LPWSTR* ppwzData,
48
+ CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
49
+ );
50
+static void FreeUsersInApplicationRoleAttributes(
51
+ CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
52
+ );
53
+static HRESULT CreateUsersInApplicationRole(
54
+ CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
55
+ );
56
+static HRESULT RemoveUsersInApplicationRole(
57
+ CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
58
+ );
59
+
60
+
61
+// function definitions
62
+
63
+HRESULT CpiConfigureApplicationRoles(
64
+ LPWSTR* ppwzData,
65
+ HANDLE hRollbackFile
66
+ )
67
+{
68
+ HRESULT hr = S_OK;
69
+
70
+ CPI_APPLICATION_ROLE_ATTRIBUTES attrs;
71
+ ::ZeroMemory(&attrs, sizeof(attrs));
72
+
73
+ // read action text
74
+ hr = CpiActionStartMessage(ppwzData, FALSE);
75
+ ExitOnFailure(hr, "Failed to send action start message");
76
+
77
+ // ger count
78
+ int iCnt = 0;
79
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
80
+ ExitOnFailure(hr, "Failed to read count");
81
+
82
+ // write count to rollback file
83
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
84
+ ExitOnFailure(hr, "Failed to write count to rollback file");
85
+
86
+ for (int i = 0; i < iCnt; i++)
87
+ {
88
+ // read attributes from CustomActionData
89
+ hr = ReadApplicationRoleAttributes(ppwzData, &attrs);
90
+ ExitOnFailure(hr, "Failed to read attributes");
91
+
92
+ // progress message
93
+ hr = CpiActionDataMessage(1, attrs.pwzName);
94
+ ExitOnFailure(hr, "Failed to send progress messages");
95
+
96
+ if (S_FALSE == hr)
97
+ ExitFunction();
98
+
99
+ // write key to rollback file
100
+ hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
101
+ ExitOnFailure(hr, "Failed to write key to rollback file");
102
+
103
+ // action
104
+ switch (attrs.iActionType)
105
+ {
106
+ case atCreate:
107
+ hr = CreateApplicationRole(&attrs);
108
+ ExitOnFailure(hr, "Failed to create application role, key: %S", attrs.pwzKey);
109
+ break;
110
+ case atRemove:
111
+ hr = RemoveApplicationRole(&attrs);
112
+ ExitOnFailure(hr, "Failed to remove application role, key: %S", attrs.pwzKey);
113
+ break;
114
+ }
115
+
116
+ // write completion status to rollback file
117
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
118
+ ExitOnFailure(hr, "Failed to write completion status to rollback file");
119
+
120
+ // progress
121
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
122
+ ExitOnFailure(hr, "Failed to update progress");
123
+ }
124
+
125
+ hr = S_OK;
126
+
127
+LExit:
128
+ // clean up
129
+ FreeApplicationRoleAttributes(&attrs);
130
+
131
+ return hr;
132
+}
133
+
134
+HRESULT CpiRollbackConfigureApplicationRoles(
135
+ LPWSTR* ppwzData,
136
+ CPI_ROLLBACK_DATA* pRollbackDataList
137
+ )
138
+{
139
+ HRESULT hr = S_OK;
140
+
141
+ int iRollbackStatus;
142
+
143
+ CPI_APPLICATION_ROLE_ATTRIBUTES attrs;
144
+ ::ZeroMemory(&attrs, sizeof(attrs));
145
+
146
+ // read action text
147
+ hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
148
+ ExitOnFailure(hr, "Failed to send action start message");
149
+
150
+ // get count
151
+ int iCnt = 0;
152
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
153
+ ExitOnFailure(hr, "Failed to read count");
154
+
155
+ for (int i = 0; i < iCnt; i++)
156
+ {
157
+ // read attributes from CustomActionData
158
+ hr = ReadApplicationRoleAttributes(ppwzData, &attrs);
159
+ ExitOnFailure(hr, "Failed to read attributes");
160
+
161
+ // rollback status
162
+ hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
163
+
164
+ if (S_FALSE == hr)
165
+ continue; // not found, nothing to rollback
166
+
167
+ // progress message
168
+ hr = CpiActionDataMessage(1, attrs.pwzName);
169
+ ExitOnFailure(hr, "Failed to send progress messages");
170
+
171
+ if (S_FALSE == hr)
172
+ ExitFunction();
173
+
174
+ // action
175
+ switch (attrs.iActionType)
176
+ {
177
+ case atCreate:
178
+ hr = CreateApplicationRole(&attrs);
179
+ if (FAILED(hr))
180
+ WcaLog(LOGMSG_STANDARD, "Failed to create application role, hr: 0x%x, key: %S", hr, attrs.pwzKey);
181
+ break;
182
+ case atRemove:
183
+ hr = RemoveApplicationRole(&attrs);
184
+ if (FAILED(hr))
185
+ WcaLog(LOGMSG_STANDARD, "Failed to remove application role, hr: 0x%x, key: %S", hr, attrs.pwzKey);
186
+ break;
187
+ }
188
+
189
+ // check rollback status
190
+ if (0 == iRollbackStatus)
191
+ continue; // operation did not complete, skip progress
192
+
193
+ // progress
194
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
195
+ ExitOnFailure(hr, "Failed to update progress");
196
+ }
197
+
198
+ hr = S_OK;
199
+
200
+LExit:
201
+ // clean up
202
+ FreeApplicationRoleAttributes(&attrs);
203
+
204
+ return hr;
205
+}
206
+
207
+HRESULT CpiConfigureUsersInApplicationRoles(
208
+ LPWSTR* ppwzData,
209
+ HANDLE hRollbackFile
210
+ )
211
+{
212
+ HRESULT hr = S_OK;
213
+
214
+ CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES attrs;
215
+ ::ZeroMemory(&attrs, sizeof(attrs));
216
+
217
+ // read action text
218
+ hr = CpiActionStartMessage(ppwzData, FALSE);
219
+ ExitOnFailure(hr, "Failed to send action start message");
220
+
221
+ // ger count
222
+ int iCnt = 0;
223
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
224
+ ExitOnFailure(hr, "Failed to read count");
225
+
226
+ // write count to rollback file
227
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
228
+ ExitOnFailure(hr, "Failed to write count to rollback file");
229
+
230
+ for (int i = 0; i < iCnt; i++)
231
+ {
232
+ // read attributes from CustomActionData
233
+ hr = ReadUsersInApplicationRoleAttributes(ppwzData, &attrs);
234
+ ExitOnFailure(hr, "Failed to read attributes");
235
+
236
+ // progress message
237
+ hr = CpiActionDataMessage(1, attrs.pwzRoleName);
238
+ ExitOnFailure(hr, "Failed to send progress messages");
239
+
240
+ if (S_FALSE == hr)
241
+ ExitFunction();
242
+
243
+ // write key to rollback file
244
+ hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
245
+ ExitOnFailure(hr, "Failed to write key to rollback file");
246
+
247
+ // action
248
+ switch (attrs.iActionType)
249
+ {
250
+ case atCreate:
251
+ hr = CreateUsersInApplicationRole(&attrs);
252
+ ExitOnFailure(hr, "Failed to create user in application role, key: %S", attrs.pwzKey);
253
+ break;
254
+ case atRemove:
255
+ hr = RemoveUsersInApplicationRole(&attrs);
256
+ ExitOnFailure(hr, "Failed to remove user from application role, key: %S", attrs.pwzKey);
257
+ break;
258
+ }
259
+
260
+ // write completion status to rollback file
261
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
262
+ ExitOnFailure(hr, "Failed to write completion status to rollback file");
263
+
264
+ // progress
265
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
266
+ ExitOnFailure(hr, "Failed to update progress");
267
+ }
268
+
269
+ hr = S_OK;
270
+
271
+LExit:
272
+ // clean up
273
+ FreeUsersInApplicationRoleAttributes(&attrs);
274
+
275
+ return hr;
276
+}
277
+
278
+HRESULT CpiRollbackConfigureUsersInApplicationRoles(
279
+ LPWSTR* ppwzData,
280
+ CPI_ROLLBACK_DATA* pRollbackDataList
281
+ )
282
+{
283
+ HRESULT hr = S_OK;
284
+
285
+ int iRollbackStatus;
286
+
287
+ CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES attrs;
288
+ ::ZeroMemory(&attrs, sizeof(attrs));
289
+
290
+ // read action text
291
+ hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
292
+ ExitOnFailure(hr, "Failed to send action start message");
293
+
294
+ // get count
295
+ int iCnt = 0;
296
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
297
+ ExitOnFailure(hr, "Failed to read count");
298
+
299
+ for (int i = 0; i < iCnt; i++)
300
+ {
301
+ // read attributes from CustomActionData
302
+ hr = ReadUsersInApplicationRoleAttributes(ppwzData, &attrs);
303
+ ExitOnFailure(hr, "Failed to read attributes");
304
+
305
+ // rollback status
306
+ hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
307
+
308
+ if (S_FALSE == hr)
309
+ continue; // not found, nothing to rollback
310
+
311
+ // progress message
312
+ hr = CpiActionDataMessage(1, attrs.pwzRoleName);
313
+ ExitOnFailure(hr, "Failed to send progress messages");
314
+
315
+ if (S_FALSE == hr)
316
+ ExitFunction();
317
+
318
+ // action
319
+ switch (attrs.iActionType)
320
+ {
321
+ case atCreate:
322
+ hr = CreateUsersInApplicationRole(&attrs);
323
+ if (FAILED(hr))
324
+ WcaLog(LOGMSG_STANDARD, "Failed to add user to application role, hr: 0x%x, key: %S", hr, attrs.pwzKey);
325
+ break;
326
+ case atRemove:
327
+ hr = RemoveUsersInApplicationRole(&attrs);
328
+ if (FAILED(hr))
329
+ WcaLog(LOGMSG_STANDARD, "Failed to remove user from application role, hr: 0x%x, key: %S", hr, attrs.pwzKey);
330
+ break;
331
+ }
332
+
333
+ // check rollback status
334
+ if (0 == iRollbackStatus)
335
+ continue; // operation did not complete, skip progress
336
+
337
+ // progress
338
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
339
+ ExitOnFailure(hr, "Failed to update progress");
340
+ }
341
+
342
+ hr = S_OK;
343
+
344
+LExit:
345
+ // clean up
346
+ FreeUsersInApplicationRoleAttributes(&attrs);
347
+
348
+ return hr;
349
+}
350
+
351
+
352
+// helper function definitions
353
+
354
+static HRESULT ReadApplicationRoleAttributes(
355
+ LPWSTR* ppwzData,
356
+ CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
357
+ )
358
+{
359
+ HRESULT hr = S_OK;
360
+
361
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
362
+ ExitOnFailure(hr, "Failed to read action type");
363
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
364
+ ExitOnFailure(hr, "Failed to read action cost");
365
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
366
+ ExitOnFailure(hr, "Failed to read key");
367
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName);
368
+ ExitOnFailure(hr, "Failed to read name");
369
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID);
370
+ ExitOnFailure(hr, "Failed to read application id");
371
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
372
+ ExitOnFailure(hr, "Failed to read partition id");
373
+ hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList);
374
+ ExitOnFailure(hr, "Failed to read properties");
375
+
376
+ hr = S_OK;
377
+
378
+LExit:
379
+ return hr;
380
+}
381
+
382
+static void FreeApplicationRoleAttributes(
383
+ CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
384
+ )
385
+{
386
+ ReleaseStr(pAttrs->pwzKey);
387
+ ReleaseStr(pAttrs->pwzName);
388
+ ReleaseStr(pAttrs->pwzAppID);
389
+ ReleaseStr(pAttrs->pwzPartID);
390
+
391
+ if (pAttrs->pPropList)
392
+ CpiFreePropertyList(pAttrs->pPropList);
393
+}
394
+
395
+static HRESULT CreateApplicationRole(
396
+ CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
397
+ )
398
+{
399
+ HRESULT hr = S_OK;
400
+
401
+ ICatalogCollection* piRolesColl = NULL;
402
+ ICatalogObject* piRoleObj = NULL;
403
+
404
+ long lChanges = 0;
405
+
406
+ // log
407
+ WcaLog(LOGMSG_VERBOSE, "Creating application role, key: %S", pAttrs->pwzKey);
408
+
409
+ // get roles collection
410
+ hr = CpiGetRolesCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piRolesColl);
411
+ if (S_FALSE == hr)
412
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
413
+ ExitOnFailure(hr, "Failed to get roles collection");
414
+
415
+ // check if role exists
416
+ hr = CpiFindCollectionObjectByName(piRolesColl, pAttrs->pwzName, &piRoleObj);
417
+ ExitOnFailure(hr, "Failed to find role");
418
+
419
+ if (S_FALSE == hr)
420
+ {
421
+ // create role
422
+ hr = CpiAddCollectionObject(piRolesColl, &piRoleObj);
423
+ ExitOnFailure(hr, "Failed to add role to collection");
424
+
425
+ hr = CpiPutCollectionObjectValue(piRoleObj, L"Name", pAttrs->pwzName);
426
+ ExitOnFailure(hr, "Failed to set role name property");
427
+ }
428
+
429
+ // properties
430
+ hr = CpiPutCollectionObjectValues(piRoleObj, pAttrs->pPropList);
431
+ ExitOnFailure(hr, "Failed to write properties");
432
+
433
+ // save changes
434
+ hr = piRolesColl->SaveChanges(&lChanges);
435
+ if (COMADMIN_E_OBJECTERRORS == hr)
436
+ CpiLogCatalogErrorInfo();
437
+ ExitOnFailure(hr, "Failed to save changes");
438
+
439
+ // log
440
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
441
+
442
+ hr = S_OK;
443
+
444
+LExit:
445
+ // clean up
446
+ ReleaseObject(piRolesColl);
447
+ ReleaseObject(piRoleObj);
448
+
449
+ return hr;
450
+}
451
+
452
+static HRESULT RemoveApplicationRole(
453
+ CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs
454
+ )
455
+{
456
+ HRESULT hr = S_OK;
457
+
458
+ ICatalogCollection* piRolesColl = NULL;
459
+
460
+ long lChanges = 0;
461
+
462
+ // log
463
+ WcaLog(LOGMSG_VERBOSE, "Removing application role, key: %S", pAttrs->pwzKey);
464
+
465
+ // get roles collection
466
+ hr = CpiGetRolesCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piRolesColl);
467
+ ExitOnFailure(hr, "Failed to get roles collection");
468
+
469
+ if (S_FALSE == hr)
470
+ {
471
+ // roles collection not found
472
+ WcaLog(LOGMSG_VERBOSE, "Unable to retrieve roles collection, nothing to delete, key: %S", pAttrs->pwzKey);
473
+ ExitFunction1(hr = S_OK);
474
+ }
475
+
476
+ // remove
477
+ hr = CpiRemoveCollectionObject(piRolesColl, NULL, pAttrs->pwzName, FALSE);
478
+ ExitOnFailure(hr, "Failed to remove role");
479
+
480
+ if (S_FALSE == hr)
481
+ {
482
+ // role not found
483
+ WcaLog(LOGMSG_VERBOSE, "Role not found, nothing to delete, key: %S", pAttrs->pwzKey);
484
+ ExitFunction1(hr = S_OK);
485
+ }
486
+
487
+ // save changes
488
+ hr = piRolesColl->SaveChanges(&lChanges);
489
+ if (COMADMIN_E_OBJECTERRORS == hr)
490
+ CpiLogCatalogErrorInfo();
491
+ ExitOnFailure(hr, "Failed to save changes");
492
+
493
+ // log
494
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
495
+
496
+ hr = S_OK;
497
+
498
+LExit:
499
+ // clean up
500
+ ReleaseObject(piRolesColl);
501
+
502
+ return hr;
503
+}
504
+
505
+static HRESULT ReadUsersInApplicationRoleAttributes(
506
+ LPWSTR* ppwzData,
507
+ CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
508
+ )
509
+{
510
+ HRESULT hr = S_OK;
511
+
512
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
513
+ ExitOnFailure(hr, "Failed to read action type");
514
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
515
+ ExitOnFailure(hr, "Failed to read action cost");
516
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
517
+ ExitOnFailure(hr, "Failed to read key");
518
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzRoleName);
519
+ ExitOnFailure(hr, "Failed to read role name");
520
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount);
521
+ ExitOnFailure(hr, "Failed to read account name");
522
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID);
523
+ ExitOnFailure(hr, "Failed to read application id");
524
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
525
+ ExitOnFailure(hr, "Failed to read partition id");
526
+
527
+ hr = S_OK;
528
+
529
+LExit:
530
+ return hr;
531
+}
532
+
533
+static void FreeUsersInApplicationRoleAttributes(
534
+ CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
535
+ )
536
+{
537
+ ReleaseStr(pAttrs->pwzKey);
538
+ ReleaseStr(pAttrs->pwzRoleName);
539
+ ReleaseStr(pAttrs->pwzAccount);
540
+ ReleaseStr(pAttrs->pwzAppID);
541
+ ReleaseStr(pAttrs->pwzPartID);
542
+}
543
+
544
+static HRESULT CreateUsersInApplicationRole(
545
+ CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
546
+ )
547
+{
548
+ HRESULT hr = S_OK;
549
+ UINT er = ERROR_SUCCESS;
550
+
551
+ ICatalogCollection* piUsrInRoleColl = NULL;
552
+ ICatalogObject* piUsrInRoleObj = NULL;
553
+
554
+ PSID pSid = NULL;
555
+ long lChanges = 0;
556
+
557
+ // log
558
+ WcaLog(LOGMSG_VERBOSE, "Adding user to application role, key: %S", pAttrs->pwzKey);
559
+
560
+ // get users in role collection
561
+ hr = CpiGetUsersInRoleCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzRoleName, &piUsrInRoleColl);
562
+ if (S_FALSE == hr)
563
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
564
+ ExitOnFailure(hr, "Failed to get users in role collection");
565
+
566
+ // get SID for account
567
+ do {
568
+ er = ERROR_SUCCESS;
569
+ hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid);
570
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
571
+ {
572
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount);
573
+ er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
574
+ switch (er)
575
+ {
576
+ case IDABORT:
577
+ ExitFunction(); // exit with error code from CpiAccountNameToSid()
578
+ case IDRETRY:
579
+ break;
580
+ case IDIGNORE:
581
+ default:
582
+ ExitFunction1(hr = S_OK);
583
+ }
584
+ }
585
+ else
586
+ ExitOnFailure(hr, "Failed to get SID for account");
587
+ } while (IDRETRY == er);
588
+
589
+ // find any existing entry
590
+ hr = CpiFindUserCollectionObject(piUsrInRoleColl, pSid, NULL);
591
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr)
592
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr);
593
+ else
594
+ ExitOnFailure(hr, "Failed to find user in application role");
595
+
596
+ if (S_OK == hr)
597
+ {
598
+ WcaLog(LOGMSG_VERBOSE, "User already assigned to application role, key: %S", pAttrs->pwzKey);
599
+ ExitFunction(); // exit with hr = S_OK
600
+ }
601
+
602
+ // convert SID back to account name
603
+ hr = CpiSidToAccountName(pSid, &pAttrs->pwzAccount);
604
+ ExitOnFailure(hr, "Failed to convert SID to account name");
605
+
606
+ // add user
607
+ hr = CpiAddCollectionObject(piUsrInRoleColl, &piUsrInRoleObj);
608
+ ExitOnFailure(hr, "Failed to add user in role to collection");
609
+
610
+ hr = CpiPutCollectionObjectValue(piUsrInRoleObj, L"User", pAttrs->pwzAccount);
611
+ ExitOnFailure(hr, "Failed to set role name property");
612
+
613
+ // save changes
614
+ hr = piUsrInRoleColl->SaveChanges(&lChanges);
615
+ if (COMADMIN_E_OBJECTERRORS == hr)
616
+ CpiLogCatalogErrorInfo();
617
+ ExitOnFailure(hr, "Failed to save changes");
618
+
619
+ // log
620
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
621
+
622
+ hr = S_OK;
623
+
624
+LExit:
625
+ // clean up
626
+ ReleaseObject(piUsrInRoleColl);
627
+ ReleaseObject(piUsrInRoleObj);
628
+
629
+ if (pSid)
630
+ ::HeapFree(::GetProcessHeap(), 0, pSid);
631
+
632
+ return hr;
633
+}
634
+
635
+static HRESULT RemoveUsersInApplicationRole(
636
+ CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs
637
+ )
638
+{
639
+ HRESULT hr = S_OK;
640
+ UINT er = ERROR_SUCCESS;
641
+
642
+ ICatalogCollection* piUsrInRoleColl = NULL;
643
+
644
+ PSID pSid = NULL;
645
+ long lChanges = 0;
646
+
647
+ // log
648
+ WcaLog(LOGMSG_VERBOSE, "Removing user from application role, key: %S", pAttrs->pwzKey);
649
+
650
+ // get users in role collection
651
+ hr = CpiGetUsersInRoleCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzRoleName, &piUsrInRoleColl);
652
+ ExitOnFailure(hr, "Failed to get users in role collection");
653
+
654
+ if (S_FALSE == hr)
655
+ {
656
+ // users in role collection not found
657
+ WcaLog(LOGMSG_VERBOSE, "Unable to retrieve users in role collection, nothing to delete, key: %S", pAttrs->pwzKey);
658
+ ExitFunction1(hr = S_OK);
659
+ }
660
+
661
+ // get SID for account
662
+ do {
663
+ er = ERROR_SUCCESS;
664
+ hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid);
665
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
666
+ {
667
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount);
668
+ er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
669
+ switch (er)
670
+ {
671
+ case IDABORT:
672
+ ExitFunction(); // exit with error code from CpiAccountNameToSid()
673
+ case IDRETRY:
674
+ break;
675
+ case IDIGNORE:
676
+ default:
677
+ ExitFunction1(hr = S_OK);
678
+ }
679
+ }
680
+ else
681
+ ExitOnFailure(hr, "Failed to get SID for account");
682
+ } while (IDRETRY == er);
683
+
684
+ // remove
685
+ hr = CpiRemoveUserCollectionObject(piUsrInRoleColl, pSid);
686
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr)
687
+ {
688
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr);
689
+ hr = S_FALSE;
690
+ }
691
+ else
692
+ ExitOnFailure(hr, "Failed to remove user");
693
+
694
+ if (S_FALSE == hr)
695
+ {
696
+ // role not found
697
+ WcaLog(LOGMSG_VERBOSE, "User not found for application role, nothing to delete, key: %S", pAttrs->pwzKey);
698
+ ExitFunction1(hr = S_OK);
699
+ }
700
+
701
+ // save changes
702
+ hr = piUsrInRoleColl->SaveChanges(&lChanges);
703
+ if (COMADMIN_E_OBJECTERRORS == hr)
704
+ CpiLogCatalogErrorInfo();
705
+ ExitOnFailure(hr, "Failed to save changes");
706
+
707
+ // log
708
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
709
+
710
+ hr = S_OK;
711
+
712
+LExit:
713
+ // clean up
714
+ ReleaseObject(piUsrInRoleColl);
715
+
716
+ if (pSid)
717
+ ::HeapFree(::GetProcessHeap(), 0, pSid);
718
+
719
+ return hr;
720
+}
src/ca/cpapproleexec.h
new
+20
@@ -0,0 +1,20 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+HRESULT CpiConfigureApplicationRoles(
6
+ LPWSTR* ppwzData,
7
+ HANDLE hRollbackFile
8
+ );
9
+HRESULT CpiRollbackConfigureApplicationRoles(
10
+ LPWSTR* ppwzData,
11
+ CPI_ROLLBACK_DATA* pRollbackDataList
12
+ );
13
+HRESULT CpiConfigureUsersInApplicationRoles(
14
+ LPWSTR* ppwzData,
15
+ HANDLE hRollbackFile
16
+ );
17
+HRESULT CpiRollbackConfigureUsersInApplicationRoles(
18
+ LPWSTR* ppwzData,
19
+ CPI_ROLLBACK_DATA* pRollbackDataList
20
+ );
src/ca/cpapprolesched.cpp
new
+843
@@ -0,0 +1,843 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// sql queries
7
+
8
+LPCWSTR vcsApplicationRoleQuery =
9
+ L"SELECT `ApplicationRole`, `Application_`, `Component_`, `Name` FROM `ComPlusApplicationRole`";
10
+enum eApplicationRoleQuery { arqApplicationRole = 1, arqApplication, arqComponent, arqName };
11
+
12
+LPCWSTR vcsUserInApplicationRoleQuery =
13
+ L"SELECT `UserInApplicationRole`, `ApplicationRole_`, `ComPlusUserInApplicationRole`.`Component_`, `Domain`, `Name` FROM `ComPlusUserInApplicationRole`, `User` WHERE `User_` = `User`";
14
+LPCWSTR vcsGroupInApplicationRoleQuery =
15
+ L"SELECT `GroupInApplicationRole`, `ApplicationRole_`, `ComPlusGroupInApplicationRole`.`Component_`, `Domain`, `Name` FROM `ComPlusGroupInApplicationRole`, `Group` WHERE `Group_` = `Group`";
16
+enum eTrusteeInApplicationRoleQuery { tiarqUserInApplicationRole = 1, tiarqApplicationRole, tiarqComponent, tiarqDomain, tiarqName };
17
+
18
+LPCWSTR vcsApplicationRolePropertyQuery =
19
+ L"SELECT `Name`, `Value` FROM `ComPlusApplicationRoleProperty` WHERE `ApplicationRole_` = ?";
20
+
21
+
22
+// property definitions
23
+
24
+CPI_PROPERTY_DEFINITION pdlApplicationRoleProperties[] =
25
+{
26
+ {L"Description", cpptString, 500},
27
+ {NULL, cpptNone, 0}
28
+};
29
+
30
+
31
+// prototypes for private helper functions
32
+
33
+static HRESULT TrusteesInApplicationRolesRead(
34
+ LPCWSTR pwzQuery,
35
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
36
+ CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList
37
+ );
38
+static void FreeApplicationRole(
39
+ CPI_APPLICATION_ROLE* pItm
40
+ );
41
+static void FreeUserInApplicationRole(
42
+ CPI_USER_IN_APPLICATION_ROLE* pItm
43
+ );
44
+//static HRESULT GetUsersCollForApplicationRole(
45
+// CPI_APPLICATION_ROLE* pAppRole,
46
+// ICatalogCollection** ppiUsersColl
47
+// );
48
+static HRESULT FindObjectForApplicationRole(
49
+ CPI_APPLICATION_ROLE* pItm,
50
+ ICatalogObject** ppiRoleObj
51
+ );
52
+static HRESULT AddApplicationRoleToActionData(
53
+ CPI_APPLICATION_ROLE* pItm,
54
+ int iActionType,
55
+ int iActionCost,
56
+ LPWSTR* ppwzActionData
57
+ );
58
+static HRESULT AddUserInApplicationRoleToActionData(
59
+ CPI_USER_IN_APPLICATION_ROLE* pItm,
60
+ int iActionType,
61
+ int iActionCost,
62
+ LPWSTR* ppwzActionData
63
+ );
64
+
65
+
66
+// function definitions
67
+
68
+void CpiApplicationRoleListFree(
69
+ CPI_APPLICATION_ROLE_LIST* pList
70
+ )
71
+{
72
+ CPI_APPLICATION_ROLE* pItm = pList->pFirst;
73
+
74
+ while (pItm)
75
+ {
76
+ CPI_APPLICATION_ROLE* pDelete = pItm;
77
+ pItm = pItm->pNext;
78
+ FreeApplicationRole(pDelete);
79
+ }
80
+}
81
+
82
+HRESULT CpiApplicationRolesRead(
83
+ CPI_APPLICATION_LIST* pAppList,
84
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList
85
+ )
86
+{
87
+ HRESULT hr = S_OK;
88
+ UINT er = ERROR_SUCCESS;
89
+
90
+ PMSIHANDLE hView, hRec;
91
+
92
+ CPI_APPLICATION_ROLE* pItm = NULL;
93
+ LPWSTR pwzData = NULL;
94
+ BOOL fMatchingArchitecture = FALSE;
95
+
96
+ // loop through all application roles
97
+ hr = WcaOpenExecuteView(vcsApplicationRoleQuery, &hView);
98
+ ExitOnFailure(hr, "Failed to execute view on ComPlusApplicationRole table");
99
+
100
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
101
+ {
102
+ // get component
103
+ hr = WcaGetRecordString(hRec, arqComponent, &pwzData);
104
+ ExitOnFailure(hr, "Failed to get component");
105
+
106
+ // check if the component is our processor architecture
107
+ if (pwzData && *pwzData)
108
+ {
109
+ hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
110
+ ExitOnFailure(hr, "Failed to get component architecture.");
111
+
112
+ if (!fMatchingArchitecture)
113
+ {
114
+ continue; // not the same architecture, ignore
115
+ }
116
+ }
117
+
118
+ // create entry
119
+ pItm = (CPI_APPLICATION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_APPLICATION_ROLE));
120
+ if (!pItm)
121
+ ExitFunction1(hr = E_OUTOFMEMORY);
122
+
123
+ // get component install state
124
+ if (pwzData && *pwzData)
125
+ {
126
+ pItm->fHasComponent = TRUE;
127
+
128
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
129
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
130
+ }
131
+
132
+ // get key
133
+ hr = WcaGetRecordString(hRec, arqApplicationRole, &pwzData);
134
+ ExitOnFailure(hr, "Failed to get key");
135
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
136
+
137
+ // get application
138
+ hr = WcaGetRecordString(hRec, arqApplication, &pwzData);
139
+ ExitOnFailure(hr, "Failed to get application");
140
+
141
+ hr = CpiApplicationFindByKey(pAppList, pwzData, &pItm->pApplication);
142
+ if (S_FALSE == hr)
143
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
144
+ ExitOnFailure(hr, "Failed to find application, key: %S", pwzData);
145
+
146
+ // get name
147
+ hr = WcaGetRecordFormattedString(hRec, arqName, &pwzData);
148
+ ExitOnFailure(hr, "Failed to get name");
149
+ StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
150
+
151
+ // get properties
152
+ if (CpiTableExists(cptComPlusApplicationRoleProperty))
153
+ {
154
+ hr = CpiPropertiesRead(vcsApplicationRolePropertyQuery, pItm->wzKey, pdlApplicationRoleProperties, &pItm->pProperties, &pItm->iPropertyCount);
155
+ ExitOnFailure(hr, "Failed to get properties");
156
+ }
157
+
158
+ // set references & increment counters
159
+ if (pItm->fHasComponent)
160
+ {
161
+ if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
162
+ {
163
+ CpiApplicationAddReferenceInstall(pItm->pApplication);
164
+ pAppRoleList->iInstallCount++;
165
+ }
166
+ if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
167
+ {
168
+ CpiApplicationAddReferenceUninstall(pItm->pApplication);
169
+ pAppRoleList->iUninstallCount++;
170
+ }
171
+ }
172
+
173
+ // add entry
174
+ if (pAppRoleList->pFirst)
175
+ pItm->pNext = pAppRoleList->pFirst;
176
+ pAppRoleList->pFirst = pItm;
177
+ pItm = NULL;
178
+ }
179
+
180
+ if (E_NOMOREITEMS == hr)
181
+ hr = S_OK;
182
+
183
+LExit:
184
+ // clean up
185
+ if (pItm)
186
+ FreeApplicationRole(pItm);
187
+
188
+ ReleaseStr(pwzData);
189
+
190
+ return hr;
191
+}
192
+
193
+HRESULT CpiApplicationRolesVerifyInstall(
194
+ CPI_APPLICATION_ROLE_LIST* pList
195
+ )
196
+{
197
+ HRESULT hr = S_OK;
198
+ UINT er = ERROR_SUCCESS;
199
+
200
+ ICatalogObject* piRoleObj = NULL;
201
+
202
+ for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
203
+ {
204
+ // referenced locaters or roles that are being installed
205
+ if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction)))
206
+ continue;
207
+
208
+ // if the role is referensed and is not a locater, it must be installed
209
+ if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction))
210
+ MessageExitOnFailure(hr = E_FAIL, msierrComPlusApplicationRoleDependency, "An application role is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey);
211
+
212
+ // role is a locater
213
+ if (!pItm->fHasComponent)
214
+ {
215
+ // get collection object for role
216
+ hr = FindObjectForApplicationRole(pItm, &piRoleObj);
217
+ ExitOnFailure(hr, "Failed to find collection object for role");
218
+
219
+ // if the role was not found
220
+ if (S_FALSE == hr)
221
+ MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusApplicationRoleNotFound, "An application role required by this installation was not found, key: %S", pItm->wzKey);
222
+ }
223
+
224
+ // role is supposed to be created
225
+ else if (!CpiIsInstalled(pItm->isInstalled))
226
+ {
227
+ do {
228
+ // find roles with conflicting name or id
229
+ hr = FindObjectForApplicationRole(pItm, NULL);
230
+ ExitOnFailure(hr, "Failed to find collection object for role");
231
+
232
+ if (S_OK == hr)
233
+ {
234
+ er = WcaErrorMessage(msierrComPlusApplicationRoleConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
235
+ switch (er)
236
+ {
237
+ case IDABORT:
238
+ ExitOnFailure(hr = E_FAIL, "An application with a conflictiong name exists, key: %S", pItm->wzKey);
239
+ break;
240
+ case IDRETRY:
241
+ break;
242
+ case IDIGNORE:
243
+ default:
244
+ hr = S_FALSE; // indicate that this is not a conflict
245
+ }
246
+ }
247
+ } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts
248
+ }
249
+
250
+ // clean up
251
+ ReleaseNullObject(piRoleObj);
252
+ }
253
+
254
+ hr = S_OK;
255
+
256
+LExit:
257
+ // clean up
258
+ ReleaseObject(piRoleObj);
259
+
260
+ return hr;
261
+}
262
+
263
+HRESULT CpiApplicationRolesVerifyUninstall(
264
+ CPI_APPLICATION_ROLE_LIST* pList
265
+ )
266
+{
267
+ HRESULT hr = S_OK;
268
+
269
+ for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
270
+ {
271
+ // referenced locaters or roles that are being installed
272
+ if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction)))
273
+ continue;
274
+
275
+ // get collection object for role
276
+ hr = FindObjectForApplicationRole(pItm, NULL);
277
+ ExitOnFailure(hr, "Failed to find collection object for role");
278
+
279
+ // if the role was not found
280
+ if (S_FALSE == hr)
281
+ {
282
+ pItm->fObjectNotFound = TRUE;
283
+ if (pItm->fHasComponent)
284
+ pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall
285
+ }
286
+ }
287
+
288
+ hr = S_OK;
289
+
290
+LExit:
291
+ return hr;
292
+}
293
+
294
+void CpiApplicationRoleAddReferenceInstall(
295
+ CPI_APPLICATION_ROLE* pItm
296
+ )
297
+{
298
+ pItm->fReferencedForInstall = TRUE;
299
+ CpiApplicationAddReferenceInstall(pItm->pApplication);
300
+}
301
+
302
+void CpiApplicationRoleAddReferenceUninstall(
303
+ CPI_APPLICATION_ROLE* pItm
304
+ )
305
+{
306
+ pItm->fReferencedForUninstall = TRUE;
307
+ CpiApplicationAddReferenceUninstall(pItm->pApplication);
308
+}
309
+
310
+HRESULT CpiApplicationRolesInstall(
311
+ CPI_APPLICATION_ROLE_LIST* pList,
312
+ int iRunMode,
313
+ LPWSTR* ppwzActionData,
314
+ int* piProgress
315
+ )
316
+{
317
+ HRESULT hr = S_OK;
318
+
319
+ int iActionType;
320
+
321
+ // add action text
322
+ hr = CpiAddActionTextToActionData(L"CreateComPlusApplicationRoles", ppwzActionData);
323
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
324
+
325
+ // add count to action data
326
+ hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
327
+ ExitOnFailure(hr, "Failed to add count to custom action data");
328
+
329
+ // add roles to custom action data
330
+ for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
331
+ {
332
+ // roles that are being installed only
333
+ if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction))
334
+ continue;
335
+
336
+ // action type
337
+ if (rmRollback == iRunMode)
338
+ {
339
+ if (CpiIsInstalled(pItm->isInstalled))
340
+ iActionType = atNoOp;
341
+ else
342
+ iActionType = atRemove;
343
+ }
344
+ else
345
+ iActionType = atCreate;
346
+
347
+ // add to action data
348
+ hr = AddApplicationRoleToActionData(pItm, iActionType, COST_APPLICATION_ROLE_CREATE, ppwzActionData);
349
+ ExitOnFailure(hr, "Failed to add application role to custom action data, key: %S", pItm->wzKey);
350
+ }
351
+
352
+ // add progress tics
353
+ if (piProgress)
354
+ *piProgress += COST_APPLICATION_ROLE_CREATE * pList->iInstallCount;
355
+
356
+ hr = S_OK;
357
+
358
+LExit:
359
+ return hr;
360
+}
361
+
362
+HRESULT CpiApplicationRolesUninstall(
363
+ CPI_APPLICATION_ROLE_LIST* pList,
364
+ int iRunMode,
365
+ LPWSTR* ppwzActionData,
366
+ int* piProgress
367
+ )
368
+{
369
+ HRESULT hr = S_OK;
370
+
371
+ int iActionType;
372
+
373
+ // add action text
374
+ hr = CpiAddActionTextToActionData(L"RemoveComPlusApplicationRoles", ppwzActionData);
375
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
376
+
377
+ // add count to action data
378
+ hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
379
+ ExitOnFailure(hr, "Failed to add count to custom action data");
380
+
381
+ // add roles to custom action data
382
+ for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
383
+ {
384
+ // roles that are being uninstalled only
385
+ if (pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
386
+ continue;
387
+
388
+ // action type
389
+ if (rmRollback == iRunMode)
390
+ iActionType = atCreate;
391
+ else
392
+ iActionType = atRemove;
393
+
394
+ // add to action data
395
+ hr = AddApplicationRoleToActionData(pItm, iActionType, COST_APPLICATION_ROLE_DELETE, ppwzActionData);
396
+ ExitOnFailure(hr, "Failed to add application role to custom action data, key: %S", pItm->wzKey);
397
+ }
398
+
399
+ // add progress tics
400
+ if (piProgress)
401
+ *piProgress += COST_APPLICATION_ROLE_DELETE * pList->iUninstallCount;
402
+
403
+ hr = S_OK;
404
+
405
+LExit:
406
+ return hr;
407
+}
408
+
409
+HRESULT CpiApplicationRoleFindByKey(
410
+ CPI_APPLICATION_ROLE_LIST* pList,
411
+ LPCWSTR pwzKey,
412
+ CPI_APPLICATION_ROLE** ppAppRole
413
+ )
414
+{
415
+ for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
416
+ {
417
+ if (0 == lstrcmpW(pItm->wzKey, pwzKey))
418
+ {
419
+ *ppAppRole = pItm;
420
+ return S_OK;
421
+ }
422
+ }
423
+
424
+ return S_FALSE;
425
+}
426
+
427
+void CpiUserInApplicationRoleListFree(
428
+ CPI_USER_IN_APPLICATION_ROLE_LIST* pList
429
+ )
430
+{
431
+ CPI_USER_IN_APPLICATION_ROLE* pItm = pList->pFirst;
432
+
433
+ while (pItm)
434
+ {
435
+ CPI_USER_IN_APPLICATION_ROLE* pDelete = pItm;
436
+ pItm = pItm->pNext;
437
+ FreeUserInApplicationRole(pDelete);
438
+ }
439
+}
440
+
441
+HRESULT CpiUsersInApplicationRolesRead(
442
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
443
+ CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList
444
+ )
445
+{
446
+ HRESULT hr = S_OK;
447
+
448
+ // read users in application roles
449
+ if (CpiTableExists(cptComPlusUserInApplicationRole))
450
+ {
451
+ hr = TrusteesInApplicationRolesRead(vcsUserInApplicationRoleQuery, pAppRoleList, pUsrInAppRoleList);
452
+ ExitOnFailure(hr, "Failed to read users in application roles");
453
+ }
454
+
455
+ // read groups in application roles
456
+ if (CpiTableExists(cptComPlusGroupInApplicationRole))
457
+ {
458
+ hr = TrusteesInApplicationRolesRead(vcsGroupInApplicationRoleQuery, pAppRoleList, pUsrInAppRoleList);
459
+ ExitOnFailure(hr, "Failed to read groups in application roles");
460
+ }
461
+
462
+ hr = S_OK;
463
+
464
+LExit:
465
+ return hr;
466
+}
467
+
468
+HRESULT CpiUsersInApplicationRolesInstall(
469
+ CPI_USER_IN_APPLICATION_ROLE_LIST* pList,
470
+ int iRunMode,
471
+ LPWSTR* ppwzActionData,
472
+ int* piProgress
473
+ )
474
+{
475
+ HRESULT hr = S_OK;
476
+
477
+ int iActionType;
478
+
479
+ // add action text
480
+ hr = CpiAddActionTextToActionData(L"AddUsersToComPlusApplicationRoles", ppwzActionData);
481
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
482
+
483
+ // add count to action data
484
+ hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
485
+ ExitOnFailure(hr, "Failed to add count to custom action data");
486
+
487
+ // add roles to custom action data
488
+ for (CPI_USER_IN_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
489
+ {
490
+ // roles that are being installed only
491
+ if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction))
492
+ continue;
493
+
494
+ // action type
495
+ if (rmRollback == iRunMode)
496
+ {
497
+ if (CpiIsInstalled(pItm->isInstalled))
498
+ iActionType = atNoOp;
499
+ else
500
+ iActionType = atRemove;
501
+ }
502
+ else
503
+ iActionType = atCreate;
504
+
505
+ // add to action data
506
+ hr = AddUserInApplicationRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_CREATE, ppwzActionData);
507
+ ExitOnFailure(hr, "Failed to add user in application role to custom action data, key: %S", pItm->wzKey);
508
+ }
509
+
510
+ // add progress tics
511
+ if (piProgress)
512
+ *piProgress += COST_USER_IN_APPLICATION_ROLE_CREATE * pList->iInstallCount;
513
+
514
+ hr = S_OK;
515
+
516
+LExit:
517
+ return hr;
518
+}
519
+
520
+HRESULT CpiUsersInApplicationRolesUninstall(
521
+ CPI_USER_IN_APPLICATION_ROLE_LIST* pList,
522
+ int iRunMode,
523
+ LPWSTR* ppwzActionData,
524
+ int* piProgress
525
+ )
526
+{
527
+ HRESULT hr = S_OK;
528
+
529
+ int iActionType;
530
+
531
+ // add action text
532
+ hr = CpiAddActionTextToActionData(L"RemoveUsersFromComPlusAppRoles", ppwzActionData);
533
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
534
+
535
+ // add count to action data
536
+ hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
537
+ ExitOnFailure(hr, "Failed to add count to custom action data");
538
+
539
+ // add roles to custom action data
540
+ for (CPI_USER_IN_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
541
+ {
542
+ // roles that are being uninstalled only
543
+ if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
544
+ continue;
545
+
546
+ // action type
547
+ if (rmRollback == iRunMode)
548
+ iActionType = atCreate;
549
+ else
550
+ iActionType = atRemove;
551
+
552
+ // add to action data
553
+ hr = AddUserInApplicationRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_DELETE, ppwzActionData);
554
+ ExitOnFailure(hr, "Failed to add user in application role to custom action data, key: %S", pItm->wzKey);
555
+ }
556
+
557
+ // add progress tics
558
+ if (piProgress)
559
+ *piProgress += COST_USER_IN_APPLICATION_ROLE_DELETE * pList->iUninstallCount;
560
+
561
+ hr = S_OK;
562
+
563
+LExit:
564
+ return hr;
565
+}
566
+
567
+
568
+// helper function definitions
569
+
570
+static HRESULT TrusteesInApplicationRolesRead(
571
+ LPCWSTR pwzQuery,
572
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
573
+ CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList
574
+ )
575
+{
576
+ HRESULT hr = S_OK;
577
+ UINT er = ERROR_SUCCESS;
578
+
579
+ PMSIHANDLE hView, hRec;
580
+
581
+ CPI_USER_IN_APPLICATION_ROLE* pItm = NULL;
582
+ LPWSTR pwzData = NULL;
583
+ LPWSTR pwzDomain = NULL;
584
+ LPWSTR pwzName = NULL;
585
+ BOOL fMatchingArchitecture = FALSE;
586
+
587
+ // loop through all application roles
588
+ hr = WcaOpenExecuteView(pwzQuery, &hView);
589
+ ExitOnFailure(hr, "Failed to execute view on table");
590
+
591
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
592
+ {
593
+ // get component
594
+ hr = WcaGetRecordString(hRec, tiarqComponent, &pwzData);
595
+ ExitOnFailure(hr, "Failed to get component");
596
+
597
+ // check if the component is our processor architecture
598
+ hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
599
+ ExitOnFailure(hr, "Failed to get component architecture.");
600
+
601
+ if (!fMatchingArchitecture)
602
+ {
603
+ continue; // not the same architecture, ignore
604
+ }
605
+
606
+ // create entry
607
+ pItm = (CPI_USER_IN_APPLICATION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_USER_IN_APPLICATION_ROLE));
608
+ if (!pItm)
609
+ ExitFunction1(hr = E_OUTOFMEMORY);
610
+
611
+ // get component install state
612
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
613
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
614
+
615
+ // get key
616
+ hr = WcaGetRecordString(hRec, tiarqUserInApplicationRole, &pwzData);
617
+ ExitOnFailure(hr, "Failed to get key");
618
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
619
+
620
+ // get application role
621
+ hr = WcaGetRecordString(hRec, tiarqApplicationRole, &pwzData);
622
+ ExitOnFailure(hr, "Failed to get application role");
623
+
624
+ hr = CpiApplicationRoleFindByKey(pAppRoleList, pwzData, &pItm->pApplicationRole);
625
+ if (S_FALSE == hr)
626
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
627
+ ExitOnFailure(hr, "Failed to find application role, key: %S", pwzData);
628
+
629
+ // get user domain
630
+ hr = WcaGetRecordFormattedString(hRec, tiarqDomain, &pwzDomain);
631
+ ExitOnFailure(hr, "Failed to get domain");
632
+
633
+ // get user name
634
+ hr = WcaGetRecordFormattedString(hRec, tiarqName, &pwzName);
635
+ ExitOnFailure(hr, "Failed to get name");
636
+
637
+ // build account name
638
+ hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount);
639
+ ExitOnFailure(hr, "Failed to build account name");
640
+
641
+ // set references & increment counters
642
+ if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
643
+ {
644
+ CpiApplicationRoleAddReferenceInstall(pItm->pApplicationRole);
645
+ pUsrInAppRoleList->iInstallCount++;
646
+ }
647
+ if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
648
+ {
649
+ CpiApplicationRoleAddReferenceUninstall(pItm->pApplicationRole);
650
+ pUsrInAppRoleList->iUninstallCount++;
651
+ }
652
+
653
+ // add entry
654
+ if (pUsrInAppRoleList->pFirst)
655
+ pItm->pNext = pUsrInAppRoleList->pFirst;
656
+ pUsrInAppRoleList->pFirst = pItm;
657
+ pItm = NULL;
658
+ }
659
+
660
+ if (E_NOMOREITEMS == hr)
661
+ hr = S_OK;
662
+
663
+LExit:
664
+ // clean up
665
+ if (pItm)
666
+ FreeUserInApplicationRole(pItm);
667
+
668
+ ReleaseStr(pwzData);
669
+ ReleaseStr(pwzDomain);
670
+ ReleaseStr(pwzName);
671
+
672
+ return hr;
673
+}
674
+
675
+static void FreeApplicationRole(
676
+ CPI_APPLICATION_ROLE* pItm
677
+ )
678
+{
679
+ if (pItm->pProperties)
680
+ CpiPropertiesFreeList(pItm->pProperties);
681
+
682
+ ReleaseObject(pItm->piUsersColl);
683
+
684
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
685
+}
686
+
687
+static void FreeUserInApplicationRole(
688
+ CPI_USER_IN_APPLICATION_ROLE* pItm
689
+ )
690
+{
691
+ ReleaseStr(pItm->pwzAccount);
692
+
693
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
694
+}
695
+
696
+//static HRESULT GetUsersCollForApplicationRole(
697
+// CPI_APPLICATION_ROLE* pAppRole,
698
+// ICatalogCollection** ppiUsersColl
699
+// )
700
+//{
701
+// HRESULT hr = S_OK;
702
+//
703
+// ICatalogCollection* piRoleColl = NULL;
704
+// ICatalogObject* piRoleObj = NULL;
705
+//
706
+// // if a previous attempt to locate the collection object failed
707
+// if (pAppRole->fObjectNotFound)
708
+// ExitFunction1(hr = S_FALSE);
709
+//
710
+// // get applications collection
711
+// if (!pAppRole->piUsersColl)
712
+// {
713
+// // get collection object for role
714
+// hr = FindObjectForApplicationRole(pAppRole, &piRoleObj);
715
+// ExitOnFailure(hr, "Failed to find collection object for role");
716
+//
717
+// if (S_FALSE == hr)
718
+// ExitFunction(); // exit with hr = S_FALSE
719
+//
720
+// // get users collection
721
+// hr = CpiGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInRole", &pAppRole->piUsersColl);
722
+// ExitOnFailure(hr, "Failed to get users in role collection");
723
+// }
724
+//
725
+// // return value
726
+// *ppiUsersColl = pAppRole->piUsersColl;
727
+// (*ppiUsersColl)->AddRef();
728
+//
729
+// hr = S_OK;
730
+//
731
+//LExit:
732
+// // clean up
733
+// ReleaseObject(piRoleColl);
734
+// ReleaseObject(piRoleObj);
735
+//
736
+// return hr;
737
+//}
738
+
739
+static HRESULT FindObjectForApplicationRole(
740
+ CPI_APPLICATION_ROLE* pItm,
741
+ ICatalogObject** ppiRoleObj
742
+ )
743
+{
744
+ HRESULT hr = S_OK;
745
+
746
+ ICatalogCollection* piRoleColl = NULL;
747
+
748
+ // get roles collection
749
+ hr = CpiGetRolesCollForApplication(pItm->pApplication, &piRoleColl);
750
+ ExitOnFailure(hr, "Failed to get collection");
751
+
752
+ if (S_FALSE == hr)
753
+ ExitFunction(); // exit with hr = S_FALSE
754
+
755
+ // find role object
756
+ hr = CpiFindCollectionObject(piRoleColl, NULL, pItm->wzName, ppiRoleObj);
757
+ ExitOnFailure(hr, "Failed to find object");
758
+
759
+ // exit with hr from CpiFindCollectionObject()
760
+
761
+LExit:
762
+ // clean up
763
+ ReleaseObject(piRoleColl);
764
+
765
+ return hr;
766
+}
767
+
768
+static HRESULT AddApplicationRoleToActionData(
769
+ CPI_APPLICATION_ROLE* pItm,
770
+ int iActionType,
771
+ int iActionCost,
772
+ LPWSTR* ppwzActionData
773
+ )
774
+{
775
+ HRESULT hr = S_OK;
776
+
777
+ // add action information to custom action data
778
+ hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
779
+ ExitOnFailure(hr, "Failed to add action type to custom action data");
780
+ hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
781
+ ExitOnFailure(hr, "Failed to add action cost to custom action data");
782
+
783
+ // add application role information to custom action data
784
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
785
+ ExitOnFailure(hr, "Failed to add application role key to custom action data");
786
+ hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData);
787
+ ExitOnFailure(hr, "Failed to add application role name to custom action data");
788
+
789
+ // add application information to custom action data
790
+ hr = WcaWriteStringToCaData(pItm->pApplication->wzID, ppwzActionData);
791
+ ExitOnFailure(hr, "Failed to add application id to custom action data");
792
+
793
+ // add partition information to custom action data
794
+ hr = WcaWriteStringToCaData(pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L"", ppwzActionData);
795
+ ExitOnFailure(hr, "Failed to add partition id to custom action data");
796
+
797
+ // add properties to custom action data
798
+ hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData);
799
+ ExitOnFailure(hr, "Failed to add properties to custom action data");
800
+
801
+ hr = S_OK;
802
+
803
+LExit:
804
+ return hr;
805
+}
806
+
807
+static HRESULT AddUserInApplicationRoleToActionData(
808
+ CPI_USER_IN_APPLICATION_ROLE* pItm,
809
+ int iActionType,
810
+ int iActionCost,
811
+ LPWSTR* ppwzActionData
812
+ )
813
+{
814
+ HRESULT hr = S_OK;
815
+
816
+ // add action information to custom action data
817
+ hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
818
+ ExitOnFailure(hr, "Failed to add action type to custom action data");
819
+ hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
820
+ ExitOnFailure(hr, "Failed to add action cost to custom action data");
821
+
822
+ // add application role information to custom action data
823
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
824
+ ExitOnFailure(hr, "Failed to add key to custom action data");
825
+ hr = WcaWriteStringToCaData(pItm->pApplicationRole->wzName, ppwzActionData);
826
+ ExitOnFailure(hr, "Failed to add role name to custom action data");
827
+ hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData);
828
+ ExitOnFailure(hr, "Failed to add user account to custom action data");
829
+
830
+ // add application information to custom action data
831
+ CPI_APPLICATION* pApplication = pItm->pApplicationRole->pApplication;
832
+ hr = WcaWriteStringToCaData(pApplication->wzID, ppwzActionData);
833
+ ExitOnFailure(hr, "Failed to add application id to custom action data");
834
+
835
+ // add partition information to custom action data
836
+ hr = WcaWriteStringToCaData(pApplication->pPartition ? pApplication->pPartition->wzID : L"", ppwzActionData);
837
+ ExitOnFailure(hr, "Failed to add partition id to custom action data");
838
+
839
+ hr = S_OK;
840
+
841
+LExit:
842
+ return hr;
843
+}
src/ca/cpapprolesched.h
new
+112
@@ -0,0 +1,112 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+struct CPI_APPLICATION_ROLE
6
+{
7
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
8
+ WCHAR wzName[MAX_DARWIN_COLUMN + 1];
9
+
10
+ int iPropertyCount;
11
+ CPI_PROPERTY* pProperties;
12
+
13
+ BOOL fHasComponent;
14
+ BOOL fReferencedForInstall;
15
+ BOOL fReferencedForUninstall;
16
+ BOOL fObjectNotFound;
17
+
18
+ INSTALLSTATE isInstalled, isAction;
19
+
20
+ CPI_APPLICATION* pApplication;
21
+
22
+ ICatalogCollection* piUsersColl;
23
+
24
+ CPI_APPLICATION_ROLE* pNext;
25
+};
26
+
27
+struct CPI_APPLICATION_ROLE_LIST
28
+{
29
+ CPI_APPLICATION_ROLE* pFirst;
30
+
31
+ int iInstallCount;
32
+ int iUninstallCount;
33
+};
34
+
35
+struct CPI_USER_IN_APPLICATION_ROLE
36
+{
37
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
38
+ LPWSTR pwzAccount;
39
+
40
+ INSTALLSTATE isInstalled, isAction;
41
+
42
+ CPI_APPLICATION_ROLE* pApplicationRole;
43
+
44
+ CPI_USER_IN_APPLICATION_ROLE* pNext;
45
+};
46
+
47
+struct CPI_USER_IN_APPLICATION_ROLE_LIST
48
+{
49
+ CPI_USER_IN_APPLICATION_ROLE* pFirst;
50
+
51
+ int iInstallCount;
52
+ int iUninstallCount;
53
+};
54
+
55
+
56
+// function prototypes
57
+
58
+void CpiApplicationRoleListFree(
59
+ CPI_APPLICATION_ROLE_LIST* pList
60
+ );
61
+HRESULT CpiApplicationRolesRead(
62
+ CPI_APPLICATION_LIST* pAppList,
63
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList
64
+ );
65
+HRESULT CpiApplicationRolesVerifyInstall(
66
+ CPI_APPLICATION_ROLE_LIST* pList
67
+ );
68
+HRESULT CpiApplicationRolesVerifyUninstall(
69
+ CPI_APPLICATION_ROLE_LIST* pList
70
+ );
71
+void CpiApplicationRoleAddReferenceInstall(
72
+ CPI_APPLICATION_ROLE* pItm
73
+ );
74
+void CpiApplicationRoleAddReferenceUninstall(
75
+ CPI_APPLICATION_ROLE* pItm
76
+ );
77
+HRESULT CpiApplicationRolesInstall(
78
+ CPI_APPLICATION_ROLE_LIST* pList,
79
+ int iRunMode,
80
+ LPWSTR* ppwzActionData,
81
+ int* piProgress
82
+ );
83
+HRESULT CpiApplicationRolesUninstall(
84
+ CPI_APPLICATION_ROLE_LIST* pList,
85
+ int iRunMode,
86
+ LPWSTR* ppwzActionData,
87
+ int* piProgress
88
+ );
89
+HRESULT CpiApplicationRoleFindByKey(
90
+ CPI_APPLICATION_ROLE_LIST* pList,
91
+ LPCWSTR pwzKey,
92
+ CPI_APPLICATION_ROLE** ppAppRole
93
+ );
94
+void CpiUserInApplicationRoleListFree(
95
+ CPI_USER_IN_APPLICATION_ROLE_LIST* pList
96
+ );
97
+HRESULT CpiUsersInApplicationRolesRead(
98
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
99
+ CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList
100
+ );
101
+HRESULT CpiUsersInApplicationRolesInstall(
102
+ CPI_USER_IN_APPLICATION_ROLE_LIST* pList,
103
+ int iRunMode,
104
+ LPWSTR* ppwzActionData,
105
+ int* piProgress
106
+ );
107
+HRESULT CpiUsersInApplicationRolesUninstall(
108
+ CPI_USER_IN_APPLICATION_ROLE_LIST* pList,
109
+ int iRunMode,
110
+ LPWSTR* ppwzActionData,
111
+ int* piProgress
112
+ );
src/ca/cpappsched.cpp
new
+752
@@ -0,0 +1,752 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// sql queries
7
+
8
+LPCWSTR vcsApplicationQuery =
9
+ L"SELECT `Application`, `Component_`, `Partition_`, `Id`, `Name` FROM `ComPlusApplication`";
10
+enum eApplicationQuery { aqApplication = 1, aqComponent, aqPartition, aqID, aqName };
11
+
12
+LPCWSTR vcsApplicationPropertyQuery =
13
+ L"SELECT `Name`, `Value` FROM `ComPlusApplicationProperty` WHERE `Application_` = ?";
14
+
15
+
16
+// property definitions
17
+
18
+CPI_PROPERTY_DEFINITION pdlApplicationProperties[] =
19
+{
20
+ {L"3GigSupportEnabled", cpptBoolean, 500},
21
+ {L"AccessChecksLevel", cpptInteger, 500},
22
+ {L"Activation", cpptInteger, 500},
23
+ {L"ApplicationAccessChecksEnabled", cpptBoolean, 500},
24
+ {L"ApplicationDirectory", cpptString, 501},
25
+ {L"Authentication", cpptInteger, 500},
26
+ {L"AuthenticationCapability", cpptInteger, 500},
27
+ {L"Changeable", cpptBoolean, 500},
28
+ {L"CommandLine", cpptString, 500},
29
+ {L"ConcurrentApps", cpptInteger, 501},
30
+ {L"CreatedBy", cpptString, 500},
31
+ {L"CRMEnabled", cpptBoolean, 500},
32
+ {L"CRMLogFile", cpptString, 500},
33
+ {L"Deleteable", cpptBoolean, 500},
34
+ {L"Description", cpptString, 500},
35
+ {L"DumpEnabled", cpptBoolean, 501},
36
+ {L"DumpOnException", cpptBoolean, 501},
37
+ {L"DumpOnFailfast", cpptBoolean, 501},
38
+ {L"DumpPath", cpptString, 501},
39
+ {L"EventsEnabled", cpptBoolean, 500},
40
+ {L"Identity", cpptString, 500},
41
+ {L"ImpersonationLevel", cpptInteger, 500},
42
+ {L"IsEnabled", cpptBoolean, 501},
43
+ {L"MaxDumpCount", cpptInteger, 501},
44
+ {L"Password", cpptString, 500},
45
+ {L"QCAuthenticateMsgs", cpptInteger, 501},
46
+ {L"QCListenerMaxThreads", cpptInteger, 501},
47
+ {L"QueueListenerEnabled", cpptBoolean, 500},
48
+ {L"QueuingEnabled", cpptBoolean, 500},
49
+ {L"RecycleActivationLimit", cpptInteger, 501},
50
+ {L"RecycleCallLimit", cpptInteger, 501},
51
+ {L"RecycleExpirationTimeout", cpptInteger, 501},
52
+ {L"RecycleLifetimeLimit", cpptInteger, 501},
53
+ {L"RecycleMemoryLimit", cpptInteger, 501},
54
+ {L"Replicable", cpptBoolean, 501},
55
+ {L"RunForever", cpptBoolean, 500},
56
+ {L"ShutdownAfter", cpptInteger, 500},
57
+ {L"SoapActivated", cpptBoolean, 502},
58
+ {L"SoapBaseUrl", cpptString, 502},
59
+ {L"SoapMailTo", cpptString, 502},
60
+ {L"SoapVRoot", cpptString, 502},
61
+ {L"SRPEnabled", cpptBoolean, 501},
62
+ {L"SRPTrustLevel", cpptInteger, 501},
63
+ {NULL, cpptNone, 0}
64
+};
65
+
66
+
67
+// prototypes for private helper functions
68
+
69
+static void FreeApplication(
70
+ CPI_APPLICATION* pItm
71
+ );
72
+static HRESULT FindObjectForApplication(
73
+ CPI_APPLICATION* pItm,
74
+ BOOL fFindId,
75
+ BOOL fFindName,
76
+ ICatalogObject** ppiAppObj
77
+ );
78
+static HRESULT AddApplicationToActionData(
79
+ CPI_APPLICATION* pItm,
80
+ int iActionType,
81
+ int iActionCost,
82
+ LPWSTR* ppwzActionData
83
+ );
84
+
85
+
86
+// function definitions
87
+
88
+void CpiApplicationListFree(
89
+ CPI_APPLICATION_LIST* pList
90
+ )
91
+{
92
+ CPI_APPLICATION* pItm = pList->pFirst;
93
+
94
+ while (pItm)
95
+ {
96
+ CPI_APPLICATION* pDelete = pItm;
97
+ pItm = pItm->pNext;
98
+ FreeApplication(pDelete);
99
+ }
100
+}
101
+
102
+HRESULT CpiApplicationsRead(
103
+ CPI_PARTITION_LIST* pPartList,
104
+ CPI_APPLICATION_LIST* pAppList
105
+ )
106
+{
107
+ HRESULT hr = S_OK;
108
+ UINT er = ERROR_SUCCESS;
109
+
110
+ int iVersionNT = 0;
111
+
112
+ PMSIHANDLE hView, hRec;
113
+
114
+ CPI_APPLICATION* pItm = NULL;
115
+ LPWSTR pwzData = NULL;
116
+ BOOL fMatchingArchitecture = FALSE;
117
+
118
+ // get NT version
119
+ hr = WcaGetIntProperty(L"VersionNT", &iVersionNT);
120
+ ExitOnFailure(hr, "Failed to get VersionNT property");
121
+
122
+ // loop through all applications
123
+ hr = WcaOpenExecuteView(vcsApplicationQuery, &hView);
124
+ ExitOnFailure(hr, "Failed to execute view on ComPlusApplication table");
125
+
126
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
127
+ {
128
+ // get component
129
+ hr = WcaGetRecordString(hRec, aqComponent, &pwzData);
130
+ ExitOnFailure(hr, "Failed to get component");
131
+
132
+ // check if the component is our processor architecture
133
+ if (pwzData && *pwzData)
134
+ {
135
+ hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
136
+ ExitOnFailure(hr, "Failed to get component architecture.");
137
+
138
+ if (!fMatchingArchitecture)
139
+ {
140
+ continue; // not the same architecture, ignore
141
+ }
142
+ }
143
+
144
+ // create entry
145
+ pItm = (CPI_APPLICATION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_APPLICATION));
146
+ if (!pItm)
147
+ ExitFunction1(hr = E_OUTOFMEMORY);
148
+
149
+ // get component install state
150
+ if (pwzData && *pwzData)
151
+ {
152
+ pItm->fHasComponent = TRUE;
153
+
154
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
155
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
156
+ }
157
+
158
+ // get key
159
+ hr = WcaGetRecordString(hRec, aqApplication, &pwzData);
160
+ ExitOnFailure(hr, "Failed to get key");
161
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
162
+
163
+ // get partition
164
+ if (502 <= iVersionNT)
165
+ {
166
+ hr = WcaGetRecordString(hRec, aqPartition, &pwzData);
167
+ ExitOnFailure(hr, "Failed to get partition");
168
+
169
+ if (pwzData && *pwzData)
170
+ {
171
+ hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition);
172
+ ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData);
173
+ }
174
+ }
175
+
176
+ // get id
177
+ hr = WcaGetRecordFormattedString(hRec, aqID, &pwzData);
178
+ ExitOnFailure(hr, "Failed to get id");
179
+
180
+ if (pwzData && *pwzData)
181
+ {
182
+ hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID));
183
+ ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData);
184
+ }
185
+
186
+ // get name
187
+ hr = WcaGetRecordFormattedString(hRec, aqName, &pwzData);
188
+ ExitOnFailure(hr, "Failed to get name");
189
+ StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
190
+
191
+ // if application is a locater, either an id or a name must be provided
192
+ if (!pItm->fHasComponent && !*pItm->wzID && !*pItm->wzName)
193
+ ExitOnFailure(hr = E_FAIL, "An application locater must have either an id or a name associated, key: %S", pItm->wzKey);
194
+
195
+ // if application is not a locater, an name must be provided
196
+ if (pItm->fHasComponent && !*pItm->wzName)
197
+ ExitOnFailure(hr = E_FAIL, "An application must have a name associated, key: %S", pItm->wzKey);
198
+
199
+ // get properties
200
+ if (CpiTableExists(cptComPlusApplicationProperty) && pItm->fHasComponent)
201
+ {
202
+ hr = CpiPropertiesRead(vcsApplicationPropertyQuery, pItm->wzKey, pdlApplicationProperties, &pItm->pProperties, &pItm->iPropertyCount);
203
+ ExitOnFailure(hr, "Failed to get properties");
204
+ }
205
+
206
+ // set references & increment counters
207
+ if (pItm->fHasComponent)
208
+ {
209
+ if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
210
+ {
211
+ if (pItm->pPartition)
212
+ CpiPartitionAddReferenceInstall(pItm->pPartition);
213
+ pAppList->iInstallCount++;
214
+ }
215
+ if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
216
+ {
217
+ if (pItm->pPartition)
218
+ CpiPartitionAddReferenceUninstall(pItm->pPartition);
219
+ pAppList->iUninstallCount++;
220
+ }
221
+ }
222
+
223
+ // add entry
224
+ if (pAppList->pFirst)
225
+ pItm->pNext = pAppList->pFirst;
226
+ pAppList->pFirst = pItm;
227
+ pItm = NULL;
228
+ }
229
+
230
+ if (E_NOMOREITEMS == hr)
231
+ hr = S_OK;
232
+
233
+LExit:
234
+ // clean up
235
+ if (pItm)
236
+ FreeApplication(pItm);
237
+
238
+ ReleaseStr(pwzData);
239
+
240
+ return hr;
241
+}
242
+
243
+HRESULT CpiApplicationsVerifyInstall(
244
+ CPI_APPLICATION_LIST* pList
245
+ )
246
+{
247
+ HRESULT hr = S_OK;
248
+ UINT er = ERROR_SUCCESS;
249
+
250
+ ICatalogObject* piAppObj = NULL;
251
+
252
+ for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
253
+ {
254
+ // referenced locaters or applications that are being installed
255
+ if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction)))
256
+ continue;
257
+
258
+ // if the application is referensed and is not a locater, it must be installed
259
+ if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction))
260
+ MessageExitOnFailure(hr = E_FAIL, msierrComPlusApplicationDependency, "An application is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey);
261
+
262
+ // application is supposed to exist
263
+ if (!pItm->fHasComponent || CpiIsInstalled(pItm->isInstalled))
264
+ {
265
+ // get collection object for application
266
+ hr = FindObjectForApplication(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piAppObj);
267
+ ExitOnFailure(hr, "Failed to find collection object for application");
268
+
269
+ // if the application was found
270
+ if (S_OK == hr)
271
+ {
272
+ // if we don't have an id, copy id from object
273
+ if (!*pItm->wzID)
274
+ {
275
+ hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID));
276
+ ExitOnFailure(hr, "Failed to get id");
277
+ }
278
+ }
279
+
280
+ // if the application was not found
281
+ else
282
+ {
283
+ // if the application is a locater, this is an error
284
+ if (!pItm->fHasComponent)
285
+ MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusApplicationNotFound, "An application required by this installation was not found, key: %S", pItm->wzKey);
286
+
287
+ // create a new id if one is missing
288
+ if (!*pItm->wzID)
289
+ {
290
+ hr = CpiCreateId(pItm->wzID, countof(pItm->wzID));
291
+ ExitOnFailure(hr, "Failed to create id");
292
+ }
293
+ }
294
+ }
295
+
296
+ // application is supposed to be created
297
+ else
298
+ {
299
+ // check for conflicts
300
+ do {
301
+ if (*pItm->wzID)
302
+ {
303
+ // find applications with conflicting id
304
+ hr = FindObjectForApplication(pItm, TRUE, FALSE, &piAppObj);
305
+ ExitOnFailure(hr, "Failed to find collection object for application");
306
+
307
+ if (S_FALSE == hr)
308
+ {
309
+ // find applications with conflicting name
310
+ hr = FindObjectForApplication(pItm, FALSE, TRUE, &piAppObj);
311
+ ExitOnFailure(hr, "Failed to find collection object for application");
312
+
313
+ if (S_OK == hr)
314
+ // "A application with a conflictiong name exists. retry cancel"
315
+ er = WcaErrorMessage(msierrComPlusApplicationNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0);
316
+ else
317
+ break; // no conflicting entry found, break loop
318
+ }
319
+ else
320
+ // "A application with a conflicting id exists. abort retry ignore"
321
+ er = WcaErrorMessage(msierrComPlusApplicationIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
322
+ }
323
+ else
324
+ {
325
+ // find applications with conflicting name
326
+ hr = FindObjectForApplication(pItm, FALSE, TRUE, &piAppObj);
327
+ ExitOnFailure(hr, "Failed to find collection object for application");
328
+
329
+ if (S_OK == hr)
330
+ // "A subscription with a conflictiong name exists. abort retry ignore"
331
+ er = WcaErrorMessage(msierrComPlusApplicationNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
332
+ else
333
+ break; // no conflicting entry found, break loop
334
+ }
335
+
336
+ switch (er)
337
+ {
338
+ case IDCANCEL:
339
+ case IDABORT:
340
+ ExitOnFailure(hr = E_FAIL, "An application with a conflictiong name or id exists, key: %S", pItm->wzKey);
341
+ break;
342
+ case IDRETRY:
343
+ break;
344
+ case IDIGNORE:
345
+ default:
346
+ // if we don't have an id, copy id from object
347
+ if (!*pItm->wzID)
348
+ {
349
+ hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID));
350
+ ExitOnFailure(hr, "Failed to get id");
351
+ }
352
+ hr = S_FALSE; // indicate that this is not a conflict
353
+ }
354
+ } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts
355
+
356
+ // create a new id if one is missing
357
+ if (!*pItm->wzID)
358
+ {
359
+ hr = CpiCreateId(pItm->wzID, countof(pItm->wzID));
360
+ ExitOnFailure(hr, "Failed to create id");
361
+ }
362
+ }
363
+
364
+ // clean up
365
+ ReleaseNullObject(piAppObj);
366
+ }
367
+
368
+ hr = S_OK;
369
+
370
+LExit:
371
+ // clean up
372
+ ReleaseObject(piAppObj);
373
+
374
+ return hr;
375
+}
376
+
377
+HRESULT CpiApplicationsVerifyUninstall(
378
+ CPI_APPLICATION_LIST* pList
379
+ )
380
+{
381
+ HRESULT hr = S_OK;
382
+ ICatalogObject* piAppObj = NULL;
383
+
384
+ for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
385
+ {
386
+ // referenced locaters or applications that are being installed
387
+ if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction)))
388
+ continue;
389
+
390
+ // get collection object for application
391
+ hr = FindObjectForApplication(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piAppObj);
392
+ ExitOnFailure(hr, "Failed to find collection object for application");
393
+
394
+ // if the application was found
395
+ if (S_OK == hr)
396
+ {
397
+ // if we don't have an id, copy id from object
398
+ if (!*pItm->wzID)
399
+ {
400
+ hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID));
401
+ ExitOnFailure(hr, "Failed to get id");
402
+ }
403
+ }
404
+
405
+ // if the application was not found
406
+ else
407
+ {
408
+ pItm->fObjectNotFound = TRUE;
409
+ if (pItm->fHasComponent)
410
+ pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall
411
+ }
412
+
413
+ // clean up
414
+ ReleaseNullObject(piAppObj);
415
+ }
416
+
417
+ hr = S_OK;
418
+
419
+LExit:
420
+ // clean up
421
+ ReleaseObject(piAppObj);
422
+
423
+ return hr;
424
+}
425
+
426
+void CpiApplicationAddReferenceInstall(
427
+ CPI_APPLICATION* pItm
428
+ )
429
+{
430
+ pItm->fReferencedForInstall = TRUE;
431
+ if (pItm->pPartition)
432
+ CpiPartitionAddReferenceInstall(pItm->pPartition);
433
+}
434
+
435
+void CpiApplicationAddReferenceUninstall(
436
+ CPI_APPLICATION* pItm
437
+ )
438
+{
439
+ pItm->fReferencedForUninstall = TRUE;
440
+ if (pItm->pPartition)
441
+ CpiPartitionAddReferenceUninstall(pItm->pPartition);
442
+}
443
+
444
+HRESULT CpiApplicationsInstall(
445
+ CPI_APPLICATION_LIST* pList,
446
+ int iRunMode,
447
+ LPWSTR* ppwzActionData,
448
+ int* piProgress
449
+ )
450
+{
451
+ HRESULT hr = S_OK;
452
+
453
+ int iActionType;
454
+
455
+ // add action text
456
+ hr = CpiAddActionTextToActionData(L"CreateComPlusApplications", ppwzActionData);
457
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
458
+
459
+ // add applicaton count to action data
460
+ hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
461
+ ExitOnFailure(hr, "Failed to add count to custom action data");
462
+
463
+ // add applications to custom action data
464
+ for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
465
+ {
466
+ // applications that are being installed only
467
+ if (!pItm->fHasComponent || !WcaIsInstalling(pItm->isInstalled, pItm->isAction))
468
+ continue;
469
+
470
+ // action type
471
+ if (rmRollback == iRunMode)
472
+ {
473
+ if (CpiIsInstalled(pItm->isInstalled))
474
+ iActionType = atNoOp;
475
+ else
476
+ iActionType = atRemove;
477
+ }
478
+ else
479
+ iActionType = atCreate;
480
+
481
+ // add to action data
482
+ hr = AddApplicationToActionData(pItm, iActionType, COST_APPLICATION_CREATE, ppwzActionData);
483
+ ExitOnFailure(hr, "Failed to add applicaton to custom action data, key: %S", pItm->wzKey);
484
+ }
485
+
486
+ // add progress tics
487
+ if (piProgress)
488
+ *piProgress += COST_APPLICATION_CREATE * pList->iInstallCount;
489
+
490
+ hr = S_OK;
491
+
492
+LExit:
493
+ return hr;
494
+}
495
+
496
+HRESULT CpiApplicationsUninstall(
497
+ CPI_APPLICATION_LIST* pList,
498
+ int iRunMode,
499
+ LPWSTR* ppwzActionData,
500
+ int* piProgress
501
+ )
502
+{
503
+ HRESULT hr = S_OK;
504
+
505
+ int iActionType;
506
+
507
+ // add action text
508
+ hr = CpiAddActionTextToActionData(L"RemoveComPlusApplications", ppwzActionData);
509
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
510
+
511
+ // add applicaton count to action data
512
+ hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
513
+ ExitOnFailure(hr, "Failed to add count to custom action data");
514
+
515
+ // add applications to custom action data
516
+ for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
517
+ {
518
+ // applications that are being uninstalled only
519
+ if (!pItm->fHasComponent || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
520
+ continue;
521
+
522
+ // action type
523
+ if (rmRollback == iRunMode)
524
+ iActionType = atCreate;
525
+ else
526
+ iActionType = atRemove;
527
+
528
+ // add to action data
529
+ hr = AddApplicationToActionData(pItm, iActionType, COST_APPLICATION_DELETE, ppwzActionData);
530
+ ExitOnFailure(hr, "Failed to add applicaton to custom action data, key: %S", pItm->wzKey);
531
+ }
532
+
533
+ // add progress tics
534
+ if (piProgress)
535
+ *piProgress += COST_APPLICATION_DELETE * pList->iUninstallCount;
536
+
537
+ hr = S_OK;
538
+
539
+LExit:
540
+ return hr;
541
+}
542
+
543
+HRESULT CpiApplicationFindByKey(
544
+ CPI_APPLICATION_LIST* pList,
545
+ LPCWSTR pwzKey,
546
+ CPI_APPLICATION** ppApp
547
+ )
548
+{
549
+ for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
550
+ {
551
+ if (0 == lstrcmpW(pItm->wzKey, pwzKey))
552
+ {
553
+ *ppApp = pItm;
554
+ return S_OK;
555
+ }
556
+ }
557
+
558
+ return S_FALSE;
559
+}
560
+
561
+HRESULT CpiGetRolesCollForApplication(
562
+ CPI_APPLICATION* pApp,
563
+ ICatalogCollection** ppiRolesColl
564
+ )
565
+{
566
+ HRESULT hr = S_OK;
567
+
568
+ ICatalogCollection* piAppColl = NULL;
569
+ ICatalogObject* piAppObj = NULL;
570
+
571
+ // if a previous attempt to locate the collection object failed
572
+ if (pApp->fObjectNotFound)
573
+ ExitFunction1(hr = S_FALSE);
574
+
575
+ // get applications collection
576
+ if (!pApp->piRolesColl)
577
+ {
578
+ // get applications collection
579
+ if (pApp->pPartition)
580
+ hr = CpiGetApplicationsCollForPartition(pApp->pPartition, &piAppColl);
581
+ else
582
+ hr = CpiGetApplicationsCollection(&piAppColl);
583
+ ExitOnFailure(hr, "Failed to get applications collection");
584
+
585
+ if (S_FALSE == hr)
586
+ ExitFunction(); // exit with hr = S_FALSE
587
+
588
+ // find application object
589
+ hr = CpiFindCollectionObject(piAppColl, pApp->wzID, *pApp->wzID ? NULL : pApp->wzName, &piAppObj);
590
+ ExitOnFailure(hr, "Failed to find application object");
591
+
592
+ if (S_FALSE == hr)
593
+ ExitFunction(); // exit with hr = S_FALSE
594
+
595
+ // get roles collection
596
+ hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Roles", &pApp->piRolesColl);
597
+ ExitOnFailure(hr, "Failed to get roles collection");
598
+ }
599
+
600
+ // return value
601
+ *ppiRolesColl = pApp->piRolesColl;
602
+ (*ppiRolesColl)->AddRef();
603
+
604
+ hr = S_OK;
605
+
606
+LExit:
607
+ // clean up
608
+ ReleaseObject(piAppColl);
609
+ ReleaseObject(piAppObj);
610
+
611
+ return hr;
612
+}
613
+
614
+HRESULT CpiGetComponentsCollForApplication(
615
+ CPI_APPLICATION* pApp,
616
+ ICatalogCollection** ppiCompsColl
617
+ )
618
+{
619
+ HRESULT hr = S_OK;
620
+
621
+ ICatalogCollection* piAppColl = NULL;
622
+ ICatalogObject* piAppObj = NULL;
623
+
624
+ // if a previous attempt to locate the collection object failed
625
+ if (pApp->fObjectNotFound)
626
+ ExitFunction1(hr = S_FALSE);
627
+
628
+ // get applications collection
629
+ if (!pApp->piCompsColl)
630
+ {
631
+ // get applications collection
632
+ if (pApp->pPartition)
633
+ hr = CpiGetApplicationsCollForPartition(pApp->pPartition, &piAppColl);
634
+ else
635
+ hr = CpiGetApplicationsCollection(&piAppColl);
636
+ ExitOnFailure(hr, "Failed to get applications collection");
637
+
638
+ if (S_FALSE == hr)
639
+ ExitFunction(); // exit with hr = S_FALSE
640
+
641
+ // find application object
642
+ hr = CpiFindCollectionObject(piAppColl, pApp->wzID, *pApp->wzID ? NULL : pApp->wzName, &piAppObj);
643
+ ExitOnFailure(hr, "Failed to find application object");
644
+
645
+ if (S_FALSE == hr)
646
+ ExitFunction(); // exit with hr = S_FALSE
647
+
648
+ // get roles collection
649
+ hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Components", &pApp->piCompsColl);
650
+ ExitOnFailure(hr, "Failed to get components collection");
651
+ }
652
+
653
+ // return value
654
+ *ppiCompsColl = pApp->piCompsColl;
655
+ (*ppiCompsColl)->AddRef();
656
+
657
+ hr = S_OK;
658
+
659
+LExit:
660
+ // clean up
661
+ ReleaseObject(piAppColl);
662
+ ReleaseObject(piAppObj);
663
+
664
+ return hr;
665
+}
666
+
667
+
668
+// helper function definitions
669
+
670
+static void FreeApplication(
671
+ CPI_APPLICATION* pItm
672
+ )
673
+{
674
+ if (pItm->pProperties)
675
+ CpiPropertiesFreeList(pItm->pProperties);
676
+
677
+ ReleaseObject(pItm->piRolesColl);
678
+ ReleaseObject(pItm->piCompsColl);
679
+
680
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
681
+}
682
+
683
+static HRESULT FindObjectForApplication(
684
+ CPI_APPLICATION* pItm,
685
+ BOOL fFindId,
686
+ BOOL fFindName,
687
+ ICatalogObject** ppiAppObj
688
+ )
689
+{
690
+ HRESULT hr = S_OK;
691
+
692
+ ICatalogCollection* piAppColl = NULL;
693
+
694
+ // get applications collection
695
+ if (pItm->pPartition)
696
+ hr = CpiGetApplicationsCollForPartition(pItm->pPartition, &piAppColl);
697
+ else
698
+ hr = CpiGetApplicationsCollection(&piAppColl);
699
+ ExitOnFailure(hr, "Failed to get applications collection");
700
+
701
+ if (S_FALSE == hr)
702
+ ExitFunction(); // exit with hr = S_FALSE
703
+
704
+ // find application object
705
+ hr = CpiFindCollectionObject(piAppColl, fFindId ? pItm->wzID : NULL, fFindName ? pItm->wzName : NULL, ppiAppObj);
706
+ ExitOnFailure(hr, "Failed to find application object");
707
+
708
+ // exit with hr from CpiFindCollectionObject()
709
+
710
+LExit:
711
+ // clean up
712
+ ReleaseObject(piAppColl);
713
+
714
+ return hr;
715
+}
716
+
717
+static HRESULT AddApplicationToActionData(
718
+ CPI_APPLICATION* pItm,
719
+ int iActionType,
720
+ int iActionCost,
721
+ LPWSTR* ppwzActionData
722
+ )
723
+{
724
+ HRESULT hr = S_OK;
725
+
726
+ // add action information to custom action data
727
+ hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
728
+ ExitOnFailure(hr, "Failed to add action type to custom action data");
729
+ hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
730
+ ExitOnFailure(hr, "Failed to add action cost to custom action data");
731
+
732
+ // add application information to custom action data
733
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
734
+ ExitOnFailure(hr, "Failed to add application key to custom action data");
735
+ hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData);
736
+ ExitOnFailure(hr, "Failed to add application id to custom action data");
737
+ hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData);
738
+ ExitOnFailure(hr, "Failed to add application name to custom action data");
739
+
740
+ // add partition information to custom action data
741
+ hr = WcaWriteStringToCaData(pItm->pPartition ? pItm->pPartition->wzID : L"", ppwzActionData);
742
+ ExitOnFailure(hr, "Failed to add partition id to custom action data");
743
+
744
+ // add properties to custom action data
745
+ hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData);
746
+ ExitOnFailure(hr, "Failed to add properties to custom action data");
747
+
748
+ hr = S_OK;
749
+
750
+LExit:
751
+ return hr;
752
+}
src/ca/cpappsched.h
new
+83
@@ -0,0 +1,83 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+struct CPI_APPLICATION
6
+{
7
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
8
+ WCHAR wzID[CPI_MAX_GUID + 1];
9
+ WCHAR wzName[MAX_DARWIN_COLUMN + 1];
10
+
11
+ int iPropertyCount;
12
+ CPI_PROPERTY* pProperties;
13
+
14
+ BOOL fHasComponent;
15
+ BOOL fReferencedForInstall;
16
+ BOOL fReferencedForUninstall;
17
+ BOOL fObjectNotFound;
18
+
19
+ INSTALLSTATE isInstalled, isAction;
20
+
21
+ CPI_PARTITION* pPartition;
22
+
23
+ ICatalogCollection* piRolesColl;
24
+ ICatalogCollection* piCompsColl;
25
+
26
+ CPI_APPLICATION* pNext;
27
+};
28
+
29
+struct CPI_APPLICATION_LIST
30
+{
31
+ CPI_APPLICATION* pFirst;
32
+
33
+ int iInstallCount;
34
+ int iUninstallCount;
35
+};
36
+
37
+
38
+// function prototypes
39
+
40
+void CpiApplicationListFree(
41
+ CPI_APPLICATION_LIST* pList
42
+ );
43
+HRESULT CpiApplicationsRead(
44
+ CPI_PARTITION_LIST* pPartList,
45
+ CPI_APPLICATION_LIST* pAppList
46
+ );
47
+HRESULT CpiApplicationsVerifyInstall(
48
+ CPI_APPLICATION_LIST* pList
49
+ );
50
+HRESULT CpiApplicationsVerifyUninstall(
51
+ CPI_APPLICATION_LIST* pList
52
+ );
53
+void CpiApplicationAddReferenceInstall(
54
+ CPI_APPLICATION* pItm
55
+ );
56
+void CpiApplicationAddReferenceUninstall(
57
+ CPI_APPLICATION* pItm
58
+ );
59
+HRESULT CpiApplicationsInstall(
60
+ CPI_APPLICATION_LIST* pList,
61
+ int iRunMode,
62
+ LPWSTR* ppwzActionData,
63
+ int* piProgress
64
+ );
65
+HRESULT CpiApplicationsUninstall(
66
+ CPI_APPLICATION_LIST* pList,
67
+ int iRunMode,
68
+ LPWSTR* ppwzActionData,
69
+ int* piProgress
70
+ );
71
+HRESULT CpiApplicationFindByKey(
72
+ CPI_APPLICATION_LIST* pList,
73
+ LPCWSTR pwzKey,
74
+ CPI_APPLICATION** ppApp
75
+ );
76
+HRESULT CpiGetRolesCollForApplication(
77
+ CPI_APPLICATION* pApp,
78
+ ICatalogCollection** ppiRolesColl
79
+ );
80
+HRESULT CpiGetComponentsCollForApplication(
81
+ CPI_APPLICATION* pApp,
82
+ ICatalogCollection** ppiCompsColl
83
+ );
src/ca/cpasmexec.cpp
new
+1888
@@ -0,0 +1,1888 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// GAC related declarations
7
+
8
+typedef struct _FUSION_INSTALL_REFERENCE_
9
+{
10
+ DWORD cbSize;
11
+ DWORD dwFlags;
12
+ GUID guidScheme;
13
+ LPCWSTR szIdentifier;
14
+ LPCWSTR szNonCannonicalData;
15
+} FUSION_INSTALL_REFERENCE;
16
+
17
+typedef struct _FUSION_INSTALL_REFERENCE_ *LPFUSION_INSTALL_REFERENCE;
18
+
19
+typedef const FUSION_INSTALL_REFERENCE *LPCFUSION_INSTALL_REFERENCE;
20
+
21
+typedef struct _ASSEMBLY_INFO
22
+{
23
+ ULONG cbAssemblyInfo;
24
+ DWORD dwAssemblyFlags;
25
+ ULARGE_INTEGER uliAssemblySizeInKB;
26
+ LPWSTR pszCurrentAssemblyPathBuf;
27
+ ULONG cchBuf;
28
+} ASSEMBLY_INFO;
29
+
30
+typedef interface IAssemblyCacheItem IAssemblyCacheItem;
31
+
32
+MIDL_INTERFACE("e707dcde-d1cd-11d2-bab9-00c04f8eceae")
33
+IAssemblyCache : public IUnknown
34
+{
35
+public:
36
+ virtual HRESULT STDMETHODCALLTYPE UninstallAssembly(
37
+ /* [in] */ DWORD dwFlags,
38
+ /* [in] */ LPCWSTR pszAssemblyName,
39
+ /* [in] */ LPCFUSION_INSTALL_REFERENCE pRefData,
40
+ /* [optional][out] */ ULONG *pulDisposition) = 0;
41
+
42
+ virtual HRESULT STDMETHODCALLTYPE QueryAssemblyInfo(
43
+ /* [in] */ DWORD dwFlags,
44
+ /* [in] */ LPCWSTR pszAssemblyName,
45
+ /* [out][in] */ ASSEMBLY_INFO *pAsmInfo) = 0;
46
+
47
+ virtual HRESULT STDMETHODCALLTYPE CreateAssemblyCacheItem(
48
+ /* [in] */ DWORD dwFlags,
49
+ /* [in] */ PVOID pvReserved,
50
+ /* [out] */ IAssemblyCacheItem **ppAsmItem,
51
+ /* [optional][in] */ LPCWSTR pszAssemblyName) = 0;
52
+
53
+ virtual HRESULT STDMETHODCALLTYPE CreateAssemblyScavenger(
54
+ /* [out] */ IUnknown **ppUnkReserved) = 0;
55
+
56
+ virtual HRESULT STDMETHODCALLTYPE InstallAssembly(
57
+ /* [in] */ DWORD dwFlags,
58
+ /* [in] */ LPCWSTR pszManifestFilePath,
59
+ /* [in] */ LPCFUSION_INSTALL_REFERENCE pRefData) = 0;
60
+};
61
+
62
+typedef HRESULT (__stdcall *LoadLibraryShimFunc)(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll);
63
+typedef HRESULT (__stdcall *CreateAssemblyCacheFunc)(IAssemblyCache **ppAsmCache, DWORD dwReserved);
64
+
65
+
66
+// RegistrationHelper related declarations
67
+
68
+static const GUID CLSID_RegistrationHelper =
69
+ { 0x89a86e7b, 0xc229, 0x4008, { 0x9b, 0xaa, 0x2f, 0x5c, 0x84, 0x11, 0xd7, 0xe0 } };
70
+
71
+enum eInstallationFlags {
72
+ ifConfigureComponentsOnly = 16,
73
+ ifFindOrCreateTargetApplication = 4,
74
+ ifExpectExistingTypeLib = 1
75
+};
76
+
77
+
78
+// private constants
79
+
80
+enum eAssemblyAttributes
81
+{
82
+ aaEventClass = (1 << 0),
83
+ aaDotNetAssembly = (1 << 1),
84
+ aaPathFromGAC = (1 << 2),
85
+ aaRunInCommit = (1 << 3)
86
+};
87
+
88
+
89
+// private structs
90
+
91
+struct CPI_ROLE_ASSIGNMENT
92
+{
93
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
94
+ WCHAR wzRoleName[MAX_DARWIN_COLUMN + 1];
95
+
96
+ CPI_ROLE_ASSIGNMENT* pNext;
97
+};
98
+
99
+struct CPI_METHOD
100
+{
101
+ WCHAR wzIndex[11 + 1];
102
+ WCHAR wzName[MAX_DARWIN_COLUMN + 1];
103
+
104
+ CPI_PROPERTY* pPropertyList;
105
+ CPI_ROLE_ASSIGNMENT* pRoleAssignmentList;
106
+
107
+ CPI_METHOD* pNext;
108
+};
109
+
110
+struct CPI_INTERFACE
111
+{
112
+ WCHAR wzIID[CPI_MAX_GUID + 1];
113
+
114
+ CPI_PROPERTY* pPropertyList;
115
+ CPI_ROLE_ASSIGNMENT* pRoleAssignmentList;
116
+ CPI_METHOD* pMethodList;
117
+
118
+ CPI_INTERFACE* pNext;
119
+};
120
+
121
+struct CPI_COMPONENT
122
+{
123
+ WCHAR wzCLSID[CPI_MAX_GUID + 1];
124
+
125
+ CPI_PROPERTY* pPropertyList;
126
+ CPI_ROLE_ASSIGNMENT* pRoleAssignmentList;
127
+ CPI_INTERFACE* pInterfaceList;
128
+
129
+ CPI_COMPONENT* pNext;
130
+};
131
+
132
+struct CPI_ASSEMBLY_ATTRIBUTES
133
+{
134
+ int iActionType;
135
+ int iActionCost;
136
+ LPWSTR pwzKey;
137
+ LPWSTR pwzAssemblyName;
138
+ LPWSTR pwzDllPath;
139
+ LPWSTR pwzTlbPath;
140
+ LPWSTR pwzPSDllPath;
141
+ LPWSTR pwzAppID;
142
+ LPWSTR pwzPartID;
143
+ int iAttributes;
144
+ CPI_COMPONENT* pCompList;
145
+};
146
+
147
+struct CPI_ROLE_ASSIGNMENTS_ATTRIBUTES
148
+{
149
+ int iActionType;
150
+ int iActionCost;
151
+ LPWSTR pwzKey;
152
+ LPWSTR pwzAppID;
153
+ LPWSTR pwzPartID;
154
+ int iRoleCount;
155
+ CPI_COMPONENT* pCompList;
156
+};
157
+
158
+
159
+// prototypes for private helper functions
160
+
161
+static HRESULT RegisterAssembly(
162
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
163
+ );
164
+static HRESULT UnregisterAssembly(
165
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
166
+ );
167
+static void InitAssemblyExec();
168
+static void UninitAssemblyExec();
169
+static HRESULT GetRegistrationHelper(
170
+ IDispatch** ppiRegHlp
171
+ );
172
+static HRESULT GetAssemblyCacheObject(
173
+ IAssemblyCache** ppAssemblyCache
174
+ );
175
+static HRESULT GetAssemblyPathFromGAC(
176
+ LPCWSTR pwzAssemblyName,
177
+ LPWSTR* ppwzAssemblyPath
178
+ );
179
+static HRESULT RegisterDotNetAssembly(
180
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
181
+ );
182
+static HRESULT RegisterNativeAssembly(
183
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
184
+ );
185
+static HRESULT UnregisterDotNetAssembly(
186
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
187
+ );
188
+static HRESULT RemoveComponents(
189
+ ICatalogCollection* piCompColl,
190
+ CPI_COMPONENT* pCompList
191
+ );
192
+static HRESULT ReadAssemblyAttributes(
193
+ LPWSTR* ppwzData,
194
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
195
+ );
196
+static void FreeAssemblyAttributes(
197
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
198
+ );
199
+static HRESULT ReadRoleAssignmentsAttributes(
200
+ LPWSTR* ppwzData,
201
+ CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs
202
+ );
203
+static void FreeRoleAssignmentsAttributes(
204
+ CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs
205
+ );
206
+static HRESULT ConfigureComponents(
207
+ LPCWSTR pwzPartID,
208
+ LPCWSTR pwzAppID,
209
+ CPI_COMPONENT* pCompList,
210
+ BOOL fCreate,
211
+ BOOL fProgress
212
+ );
213
+static HRESULT ConfigureInterfaces(
214
+ ICatalogCollection* piCompColl,
215
+ ICatalogObject* piCompObj,
216
+ CPI_INTERFACE* pIntfList,
217
+ BOOL fCreate
218
+ );
219
+static HRESULT ConfigureMethods(
220
+ ICatalogCollection* piIntfColl,
221
+ ICatalogObject* piIntfObj,
222
+ CPI_METHOD* pMethList,
223
+ BOOL fCreate
224
+ );
225
+static HRESULT ConfigureRoleAssignments(
226
+ LPCWSTR pwzCollName,
227
+ ICatalogCollection* piCompColl,
228
+ ICatalogObject* piCompObj,
229
+ CPI_ROLE_ASSIGNMENT* pRoleList,
230
+ BOOL fCreate
231
+ );
232
+static HRESULT ReadComponentList(
233
+ LPWSTR* ppwzData,
234
+ CPI_COMPONENT** ppCompList
235
+ );
236
+static HRESULT ReadInterfaceList(
237
+ LPWSTR* ppwzData,
238
+ CPI_INTERFACE** ppIntfList
239
+ );
240
+static HRESULT ReadMethodList(
241
+ LPWSTR* ppwzData,
242
+ CPI_METHOD** ppMethList
243
+ );
244
+static HRESULT ReadRoleAssignmentList(
245
+ LPWSTR* ppwzData,
246
+ CPI_ROLE_ASSIGNMENT** ppRoleList
247
+ );
248
+static void FreeComponentList(
249
+ CPI_COMPONENT* pList
250
+ );
251
+static void FreeInterfaceList(
252
+ CPI_INTERFACE* pList
253
+ );
254
+static void FreeMethodList(
255
+ CPI_METHOD* pList
256
+ );
257
+static void FreeRoleAssignmentList(
258
+ CPI_ROLE_ASSIGNMENT* pList
259
+ );
260
+
261
+
262
+// variables
263
+
264
+static IDispatch* gpiRegHlp;
265
+static IAssemblyCache* gpAssemblyCache;
266
+static HMODULE ghMscoree;
267
+static HMODULE ghFusion;
268
+
269
+
270
+// function definitions
271
+
272
+HRESULT CpiConfigureAssemblies(
273
+ LPWSTR* ppwzData,
274
+ HANDLE hRollbackFile
275
+ )
276
+{
277
+ HRESULT hr = S_OK;
278
+
279
+ CPI_ASSEMBLY_ATTRIBUTES attrs;
280
+ ::ZeroMemory(&attrs, sizeof(attrs));
281
+
282
+ // initialize
283
+ InitAssemblyExec();
284
+
285
+ // read action text
286
+ hr = CpiActionStartMessage(ppwzData, FALSE);
287
+ ExitOnFailure(hr, "Failed to send action start message");
288
+
289
+ // get count
290
+ int iCnt = 0;
291
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
292
+ ExitOnFailure(hr, "Failed to read count");
293
+
294
+ // write count to rollback file
295
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
296
+ ExitOnFailure(hr, "Failed to write count to rollback file");
297
+
298
+ for (int i = 0; i < iCnt; i++)
299
+ {
300
+ // read attributes from CustomActionData
301
+ hr = ReadAssemblyAttributes(ppwzData, &attrs);
302
+ ExitOnFailure(hr, "Failed to read assembly attributes");
303
+
304
+ // write key to rollback file
305
+ hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
306
+ ExitOnFailure(hr, "Failed to write key to rollback file");
307
+
308
+ // action
309
+ switch (attrs.iActionType)
310
+ {
311
+ case atCreate:
312
+ hr = RegisterAssembly(&attrs);
313
+ ExitOnFailure(hr, "Failed to register assembly, key: %S", attrs.pwzKey);
314
+ break;
315
+ case atRemove:
316
+ hr = UnregisterAssembly(&attrs);
317
+ ExitOnFailure(hr, "Failed to unregister assembly, key: %S", attrs.pwzKey);
318
+ break;
319
+ default:
320
+ hr = S_OK;
321
+ break;
322
+ }
323
+
324
+ if (S_FALSE == hr)
325
+ ExitFunction(); // aborted by user
326
+
327
+ // write completion status to rollback file
328
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
329
+ ExitOnFailure(hr, "Failed to write completion status to rollback file");
330
+
331
+ // progress
332
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
333
+ ExitOnFailure(hr, "Failed to update progress");
334
+ }
335
+
336
+ hr = S_OK;
337
+
338
+LExit:
339
+ // clean up
340
+ FreeAssemblyAttributes(&attrs);
341
+
342
+ // uninitialize
343
+ UninitAssemblyExec();
344
+
345
+ return hr;
346
+}
347
+
348
+HRESULT CpiRollbackConfigureAssemblies(
349
+ LPWSTR* ppwzData,
350
+ CPI_ROLLBACK_DATA* pRollbackDataList
351
+ )
352
+{
353
+ HRESULT hr = S_OK;
354
+
355
+ int iRollbackStatus;
356
+
357
+ CPI_ASSEMBLY_ATTRIBUTES attrs;
358
+ ::ZeroMemory(&attrs, sizeof(attrs));
359
+
360
+ // initialize
361
+ InitAssemblyExec();
362
+
363
+ // read action text
364
+ hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
365
+ ExitOnFailure(hr, "Failed to send action start message");
366
+
367
+ // get count
368
+ int iCnt = 0;
369
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
370
+ ExitOnFailure(hr, "Failed to read count");
371
+
372
+ for (int i = 0; i < iCnt; i++)
373
+ {
374
+ // read attributes from CustomActionData
375
+ hr = ReadAssemblyAttributes(ppwzData, &attrs);
376
+ ExitOnFailure(hr, "Failed to read assembly attributes");
377
+
378
+ // rollback status
379
+ hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
380
+
381
+ if (S_FALSE == hr)
382
+ continue; // not found, nothing to rollback
383
+
384
+ // action
385
+ switch (attrs.iActionType)
386
+ {
387
+ case atCreate:
388
+ hr = RegisterAssembly(&attrs);
389
+ if (FAILED(hr))
390
+ WcaLog(LOGMSG_STANDARD, "Failed to register assembly, hr: 0x%x, key: %S", hr, attrs.pwzKey);
391
+ break;
392
+ case atRemove:
393
+ hr = UnregisterAssembly(&attrs);
394
+ if (FAILED(hr))
395
+ WcaLog(LOGMSG_STANDARD, "Failed to unregister assembly, hr: 0x%x, key: %S", hr, attrs.pwzKey);
396
+ break;
397
+ }
398
+
399
+ // check rollback status
400
+ if (0 == iRollbackStatus)
401
+ continue; // operation did not complete, skip progress
402
+
403
+ // progress
404
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
405
+ ExitOnFailure(hr, "Failed to update progress");
406
+ }
407
+
408
+ hr = S_OK;
409
+
410
+LExit:
411
+ // clean up
412
+ FreeAssemblyAttributes(&attrs);
413
+
414
+ // uninitialize
415
+ UninitAssemblyExec();
416
+
417
+ return hr;
418
+}
419
+
420
+HRESULT CpiConfigureRoleAssignments(
421
+ LPWSTR* ppwzData,
422
+ HANDLE hRollbackFile
423
+ )
424
+{
425
+ HRESULT hr = S_OK;
426
+
427
+ CPI_ROLE_ASSIGNMENTS_ATTRIBUTES attrs;
428
+ ::ZeroMemory(&attrs, sizeof(attrs));
429
+
430
+ // read action text
431
+ hr = CpiActionStartMessage(ppwzData, FALSE);
432
+ ExitOnFailure(hr, "Failed to send action start message");
433
+
434
+ // get count
435
+ int iCnt = 0;
436
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
437
+ ExitOnFailure(hr, "Failed to read count");
438
+
439
+ // write count to rollback file
440
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
441
+ ExitOnFailure(hr, "Failed to write count to rollback file");
442
+
443
+ for (int i = 0; i < iCnt; i++)
444
+ {
445
+ // read attributes from CustomActionData
446
+ hr = ReadRoleAssignmentsAttributes(ppwzData, &attrs);
447
+ ExitOnFailure(hr, "Failed to read role assignments attributes");
448
+
449
+ // write key to rollback file
450
+ hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
451
+ ExitOnFailure(hr, "Failed to write key to rollback file");
452
+
453
+ // action
454
+ if (atNoOp != attrs.iActionType)
455
+ {
456
+ hr = ConfigureComponents(attrs.pwzPartID, attrs.pwzAppID, attrs.pCompList, atCreate == attrs.iActionType, TRUE);
457
+ ExitOnFailure(hr, "Failed to configure components");
458
+
459
+ if (S_FALSE == hr)
460
+ ExitFunction(); // aborted by user
461
+ }
462
+
463
+ // write completion status to rollback file
464
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
465
+ ExitOnFailure(hr, "Failed to write completion status to rollback file");
466
+
467
+ // progress
468
+ hr = WcaProgressMessage(attrs.iActionCost * attrs.iRoleCount, FALSE);
469
+ ExitOnFailure(hr, "Failed to update progress");
470
+ }
471
+
472
+ hr = S_OK;
473
+
474
+LExit:
475
+ // clean up
476
+ FreeRoleAssignmentsAttributes(&attrs);
477
+
478
+ return hr;
479
+}
480
+
481
+HRESULT CpiRollbackConfigureRoleAssignments(
482
+ LPWSTR* ppwzData,
483
+ CPI_ROLLBACK_DATA* pRollbackDataList
484
+ )
485
+{
486
+ HRESULT hr = S_OK;
487
+
488
+ int iRollbackStatus;
489
+
490
+ CPI_ROLE_ASSIGNMENTS_ATTRIBUTES attrs;
491
+ ::ZeroMemory(&attrs, sizeof(attrs));
492
+
493
+ // read action text
494
+ hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
495
+ ExitOnFailure(hr, "Failed to send action start message");
496
+
497
+ // get count
498
+ int iCnt = 0;
499
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
500
+ ExitOnFailure(hr, "Failed to read count");
501
+
502
+ for (int i = 0; i < iCnt; i++)
503
+ {
504
+ // read attributes from CustomActionData
505
+ hr = ReadRoleAssignmentsAttributes(ppwzData, &attrs);
506
+ ExitOnFailure(hr, "Failed to read role assignments attributes");
507
+
508
+ // rollback status
509
+ hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
510
+
511
+ if (S_FALSE == hr)
512
+ continue; // not found, nothing to rollback
513
+
514
+ // action
515
+ if (atNoOp != attrs.iActionType)
516
+ {
517
+ hr = ConfigureComponents(attrs.pwzPartID, attrs.pwzAppID, attrs.pCompList, atCreate == attrs.iActionType, TRUE);
518
+ ExitOnFailure(hr, "Failed to configure components");
519
+
520
+ if (S_FALSE == hr)
521
+ ExitFunction(); // aborted by user
522
+ }
523
+
524
+ // check rollback status
525
+ if (0 == iRollbackStatus)
526
+ continue; // operation did not complete, skip progress
527
+
528
+ // progress
529
+ hr = WcaProgressMessage(attrs.iActionCost * attrs.iRoleCount, FALSE);
530
+ ExitOnFailure(hr, "Failed to update progress");
531
+ }
532
+
533
+ hr = S_OK;
534
+
535
+LExit:
536
+ // clean up
537
+ FreeRoleAssignmentsAttributes(&attrs);
538
+
539
+ return hr;
540
+}
541
+
542
+
543
+// helper function definitions
544
+
545
+static HRESULT RegisterAssembly(
546
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
547
+ )
548
+{
549
+ HRESULT hr = S_OK;
550
+
551
+ // progress message
552
+ hr = CpiActionDataMessage(1, (pAttrs->iAttributes & aaPathFromGAC) ? pAttrs->pwzAssemblyName : pAttrs->pwzDllPath);
553
+ ExitOnFailure(hr, "Failed to send progress messages");
554
+
555
+ if (S_FALSE == hr)
556
+ ExitFunction(); // aborted by user
557
+
558
+ // log
559
+ WcaLog(LOGMSG_VERBOSE, "Registering assembly, key: %S", pAttrs->pwzKey);
560
+
561
+ // extract path from GAC
562
+ if (pAttrs->iAttributes & aaPathFromGAC)
563
+ {
564
+ hr = GetAssemblyPathFromGAC(pAttrs->pwzAssemblyName, &pAttrs->pwzDllPath);
565
+ if (S_FALSE == hr)
566
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
567
+ ExitOnFailure(hr, "Failed to get path for assembly from GAC");
568
+
569
+ // log
570
+ WcaLog(LOGMSG_VERBOSE, "Assembly path extracted from GAC, key: %S, path: '%S'", pAttrs->pwzKey, pAttrs->pwzDllPath);
571
+ }
572
+
573
+ // .net assembly
574
+ if (pAttrs->iAttributes & aaDotNetAssembly)
575
+ {
576
+ hr = RegisterDotNetAssembly(pAttrs);
577
+ ExitOnFailure(hr, "Failed to register .NET assembly");
578
+ }
579
+
580
+ // native assembly
581
+ else
582
+ {
583
+ hr = RegisterNativeAssembly(pAttrs);
584
+ ExitOnFailure(hr, "Failed to register native assembly");
585
+ }
586
+
587
+ // configure components
588
+ if (pAttrs->pCompList)
589
+ {
590
+ hr = ConfigureComponents(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pCompList, TRUE, FALSE);
591
+ ExitOnFailure(hr, "Failed to configure components");
592
+ }
593
+
594
+ hr = S_OK;
595
+
596
+LExit:
597
+ return hr;
598
+}
599
+
600
+static HRESULT UnregisterAssembly(
601
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
602
+ )
603
+{
604
+ HRESULT hr = S_OK;
605
+
606
+ long lChanges = 0;
607
+
608
+ ICatalogCollection* piColl = NULL;
609
+ ICatalogObject* piObj = NULL;
610
+
611
+ // progress message
612
+ hr = CpiActionDataMessage(1, (pAttrs->iAttributes & aaPathFromGAC) ? pAttrs->pwzAssemblyName : pAttrs->pwzDllPath);
613
+ ExitOnFailure(hr, "Failed to send progress messages");
614
+
615
+ if (S_FALSE == hr)
616
+ ExitFunction(); // aborted by user
617
+
618
+ // log
619
+ WcaLog(LOGMSG_VERBOSE, "Unregistering assembly, key: %S", pAttrs->pwzKey);
620
+
621
+ // extract path from GAC
622
+ if (pAttrs->iAttributes & aaPathFromGAC)
623
+ {
624
+ hr = GetAssemblyPathFromGAC(pAttrs->pwzAssemblyName, &pAttrs->pwzDllPath);
625
+ ExitOnFailure(hr, "Failed to get path for assembly from GAC");
626
+
627
+ if (S_FALSE == hr)
628
+ {
629
+ WcaLog(LOGMSG_VERBOSE, "Unable to locate assembly in GAC, assembly will not be unregistered from COM+, key: %S", pAttrs->pwzKey);
630
+ ExitFunction1(hr = S_OK);
631
+ }
632
+
633
+ // log
634
+ WcaLog(LOGMSG_VERBOSE, "Assembly path extracted from GAC, key: %S, path: '%S'", pAttrs->pwzKey, pAttrs->pwzDllPath);
635
+ }
636
+
637
+ // .NET assembly
638
+ if (pAttrs->iAttributes & aaDotNetAssembly)
639
+ {
640
+ if (pAttrs->pwzAppID && *pAttrs->pwzAppID)
641
+ {
642
+ // When unregistering a .net assembly using the RegistrationHelper class, and the application is
643
+ // left empty after all components in the assembly are removed, the RegistrationHelper class also
644
+ // attempts to remove the application for some reason. However, it does not handle the situation
645
+ // when the application has its deleteable property set to false, and will simply fail if this is
646
+ // the case. This is the reason we are clearing the deleatable property of the application here.
647
+ //
648
+ // TODO: handle rollbacks
649
+
650
+ // get applications collection
651
+ hr = CpiGetApplicationsCollection(pAttrs->pwzPartID, &piColl);
652
+ ExitOnFailure(hr, "Failed to get applications collection");
653
+
654
+ if (S_FALSE == hr)
655
+ {
656
+ // applications collection not found
657
+ WcaLog(LOGMSG_VERBOSE, "Unable to retrieve applications collection, nothing to delete, key: %S", pAttrs->pwzKey);
658
+ ExitFunction1(hr = S_OK);
659
+ }
660
+
661
+ // find application object
662
+ hr = CpiFindCollectionObjectByStringKey(piColl, pAttrs->pwzAppID, &piObj);
663
+ ExitOnFailure(hr, "Failed to find application object");
664
+
665
+ if (S_FALSE == hr)
666
+ {
667
+ // application not found
668
+ WcaLog(LOGMSG_VERBOSE, "Unable to find application object, nothing to delete, key: %S", pAttrs->pwzKey);
669
+ ExitFunction1(hr = S_OK);
670
+ }
671
+
672
+ // reset deleteable property
673
+ hr = CpiResetObjectProperty(piColl, piObj, L"Deleteable");
674
+ ExitOnFailure(hr, "Failed to reset deleteable property");
675
+ }
676
+
677
+ // unregister assembly
678
+ hr = UnregisterDotNetAssembly(pAttrs);
679
+ ExitOnFailure(hr, "Failed to unregister .NET assembly");
680
+ }
681
+
682
+ // native assembly
683
+ else
684
+ {
685
+ // get components collection
686
+ hr = CpiGetComponentsCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piColl);
687
+ ExitOnFailure(hr, "Failed to get components collection");
688
+
689
+ if (S_FALSE == hr)
690
+ {
691
+ // components collection not found
692
+ WcaLog(LOGMSG_VERBOSE, "Unable to retrieve components collection, nothing to delete, key: %S", pAttrs->pwzKey);
693
+ ExitFunction1(hr = S_OK);
694
+ }
695
+
696
+ // remove components
697
+ hr = RemoveComponents(piColl, pAttrs->pCompList);
698
+ ExitOnFailure(hr, "Failed to get remove components");
699
+
700
+ // save changes
701
+ hr = piColl->SaveChanges(&lChanges);
702
+ if (COMADMIN_E_OBJECTERRORS == hr)
703
+ CpiLogCatalogErrorInfo();
704
+ ExitOnFailure(hr, "Failed to save changes");
705
+ }
706
+
707
+ hr = S_OK;
708
+
709
+LExit:
710
+ // clean up
711
+ ReleaseObject(piColl);
712
+ ReleaseObject(piObj);
713
+
714
+ return hr;
715
+}
716
+
717
+static void InitAssemblyExec()
718
+{
719
+ gpiRegHlp = NULL;
720
+ gpAssemblyCache = NULL;
721
+ ghMscoree = NULL;
722
+ ghFusion = NULL;
723
+}
724
+
725
+static void UninitAssemblyExec()
726
+{
727
+ ReleaseObject(gpiRegHlp);
728
+ ReleaseObject(gpAssemblyCache);
729
+ if (ghFusion)
730
+ ::FreeLibrary(ghFusion);
731
+ if (ghMscoree)
732
+ ::FreeLibrary(ghMscoree);
733
+}
734
+
735
+static HRESULT GetRegistrationHelper(
736
+ IDispatch** ppiRegHlp
737
+ )
738
+{
739
+ HRESULT hr = S_OK;
740
+
741
+ if (!gpiRegHlp)
742
+ {
743
+ // create registration helper object
744
+ hr = ::CoCreateInstance(CLSID_RegistrationHelper, NULL, CLSCTX_ALL, IID_IDispatch, (void**)&gpiRegHlp);
745
+ ExitOnFailure(hr, "Failed to create registration helper object");
746
+ }
747
+
748
+ gpiRegHlp->AddRef();
749
+ *ppiRegHlp = gpiRegHlp;
750
+
751
+ hr = S_OK;
752
+
753
+LExit:
754
+ return hr;
755
+}
756
+
757
+static HRESULT GetAssemblyCacheObject(
758
+ IAssemblyCache** ppAssemblyCache
759
+ )
760
+{
761
+ HRESULT hr = S_OK;
762
+
763
+ if (!gpAssemblyCache)
764
+ {
765
+ // mscoree.dll
766
+ if (!ghMscoree)
767
+ {
768
+ // load mscoree.dll
769
+ ghMscoree = ::LoadLibraryW(L"mscoree.dll");
770
+ ExitOnNull(ghMscoree, hr, E_FAIL, "Failed to load mscoree.dll");
771
+ }
772
+
773
+ // fusion.dll
774
+ if (!ghFusion)
775
+ {
776
+ // get LoadLibraryShim function address
777
+ LoadLibraryShimFunc pfnLoadLibraryShim = (LoadLibraryShimFunc)::GetProcAddress(ghMscoree, "LoadLibraryShim");
778
+ ExitOnNull(pfnLoadLibraryShim, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for LoadLibraryShim() function");
779
+
780
+ // load fusion.dll
781
+ hr = pfnLoadLibraryShim(L"fusion.dll", NULL, NULL, &ghFusion);
782
+ ExitOnFailure(hr, "Failed to load fusion.dll");
783
+ }
784
+
785
+ // get CreateAssemblyCache function address
786
+ CreateAssemblyCacheFunc pfnCreateAssemblyCache = (CreateAssemblyCacheFunc)::GetProcAddress(ghFusion, "CreateAssemblyCache");
787
+ ExitOnNull(pfnCreateAssemblyCache, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for CreateAssemblyCache() function");
788
+
789
+ // create AssemblyCache object
790
+ hr = pfnCreateAssemblyCache(&gpAssemblyCache, 0);
791
+ ExitOnFailure(hr, "Failed to create AssemblyCache object");
792
+ }
793
+
794
+ gpAssemblyCache->AddRef();
795
+ *ppAssemblyCache = gpAssemblyCache;
796
+
797
+ hr = S_OK;
798
+
799
+LExit:
800
+ return hr;
801
+}
802
+
803
+static HRESULT GetAssemblyPathFromGAC(
804
+ LPCWSTR pwzAssemblyName,
805
+ LPWSTR* ppwzAssemblyPath
806
+ )
807
+{
808
+ HRESULT hr = S_OK;
809
+
810
+ IAssemblyCache* pAssemblyCache = NULL;
811
+
812
+ ASSEMBLY_INFO assemblyInfo;
813
+ WCHAR wzPathBuf[MAX_PATH];
814
+
815
+ ::ZeroMemory(&assemblyInfo, sizeof(ASSEMBLY_INFO));
816
+ ::ZeroMemory(wzPathBuf, countof(wzPathBuf));
817
+
818
+ // get AssemblyCache object
819
+ hr = GetAssemblyCacheObject(&pAssemblyCache);
820
+ ExitOnFailure(hr, "Failed to get AssemblyCache object");
821
+
822
+ // get assembly info
823
+ assemblyInfo.cbAssemblyInfo = sizeof(ASSEMBLY_INFO);
824
+ assemblyInfo.pszCurrentAssemblyPathBuf = wzPathBuf;
825
+ assemblyInfo.cchBuf = countof(wzPathBuf);
826
+
827
+ hr = pAssemblyCache->QueryAssemblyInfo(0, pwzAssemblyName, &assemblyInfo);
828
+ if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
829
+ ExitFunction1(hr = S_FALSE);
830
+ ExitOnFailure(hr, "Failed to get assembly info");
831
+
832
+ // copy assembly path
833
+ hr = StrAllocString(ppwzAssemblyPath, wzPathBuf, 0);
834
+ ExitOnFailure(hr, "Failed to copy assembly path");
835
+
836
+ hr = S_OK;
837
+
838
+LExit:
839
+ // clean up
840
+ ReleaseObject(pAssemblyCache);
841
+
842
+ return hr;
843
+}
844
+
845
+static HRESULT RegisterDotNetAssembly(
846
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
847
+ )
848
+{
849
+ HRESULT hr = S_OK;
850
+
851
+ IDispatch* piRegHlp = NULL;
852
+
853
+ DISPID dispid;
854
+ BSTR bstrMember = NULL;
855
+
856
+ long lInstallationFlags = 0;
857
+
858
+ VARIANTARG rgvarg[5];
859
+ DISPPARAMS dispparams;
860
+ EXCEPINFO excepInfo;
861
+
862
+ BSTR bstrPartName = NULL;
863
+ BSTR bstrAppName = NULL;
864
+ BSTR bstrDllPath = NULL;
865
+ BSTR bstrTlbPath = NULL;
866
+
867
+ ::ZeroMemory(rgvarg, sizeof(rgvarg));
868
+ ::ZeroMemory(&dispparams, sizeof(dispparams));
869
+ ::ZeroMemory(&excepInfo, sizeof(excepInfo));
870
+
871
+ bstrMember = ::SysAllocString(L"InstallAssembly_2");
872
+ ExitOnNull(bstrMember, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for method name");
873
+
874
+ // create BSTRs for parameters
875
+ if (pAttrs->pwzPartID && *pAttrs->pwzPartID)
876
+ {
877
+ bstrPartName = ::SysAllocString(pAttrs->pwzPartID);
878
+ ExitOnNull(bstrPartName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id");
879
+ }
880
+
881
+ if (pAttrs->pwzAppID && *pAttrs->pwzAppID)
882
+ {
883
+ bstrAppName = ::SysAllocString(pAttrs->pwzAppID);
884
+ ExitOnNull(bstrAppName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id");
885
+ }
886
+
887
+ bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath);
888
+ ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path");
889
+
890
+ if (pAttrs->pwzTlbPath && *pAttrs->pwzTlbPath)
891
+ {
892
+ bstrTlbPath = ::SysAllocString(pAttrs->pwzTlbPath);
893
+ ExitOnNull(bstrTlbPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path");
894
+ }
895
+
896
+ // get registration helper object
897
+ hr = GetRegistrationHelper(&piRegHlp);
898
+ ExitOnFailure(hr, "Failed to get registration helper object");
899
+
900
+ // get dispatch id of InstallAssembly() method
901
+ hr = piRegHlp->GetIDsOfNames(IID_NULL, &bstrMember, 1, LOCALE_USER_DEFAULT, &dispid);
902
+ ExitOnFailure(hr, "Failed to get dispatch id of InstallAssembly() method");
903
+
904
+ // set installation flags
905
+ lInstallationFlags = ifExpectExistingTypeLib;
906
+
907
+ if (!bstrAppName)
908
+ lInstallationFlags |= ifFindOrCreateTargetApplication;
909
+
910
+ // invoke InstallAssembly() method
911
+ rgvarg[0].vt = VT_I4;
912
+ rgvarg[0].lVal = lInstallationFlags;
913
+ rgvarg[1].vt = VT_BYREF|VT_BSTR;
914
+ rgvarg[1].pbstrVal = &bstrTlbPath;
915
+ rgvarg[2].vt = VT_BSTR;
916
+ rgvarg[2].bstrVal = bstrPartName;
917
+ rgvarg[3].vt = VT_BYREF|VT_BSTR;
918
+ rgvarg[3].pbstrVal = &bstrAppName;
919
+ rgvarg[4].vt = VT_BSTR;
920
+ rgvarg[4].bstrVal = bstrDllPath;
921
+ dispparams.rgvarg = rgvarg;
922
+ dispparams.cArgs = 5;
923
+ dispparams.cNamedArgs = 0;
924
+
925
+ hr = piRegHlp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, NULL, &excepInfo, NULL);
926
+ if (DISP_E_EXCEPTION == hr)
927
+ {
928
+ // log exception information
929
+ if (!excepInfo.pfnDeferredFillIn || (excepInfo.pfnDeferredFillIn && SUCCEEDED(excepInfo.pfnDeferredFillIn(&excepInfo))))
930
+ {
931
+ WcaLog(LOGMSG_STANDARD, "ExceptionInfo: Code='%hu', Source='%S', Description='%S', HelpFile='%S', HelpContext='%u'",
932
+ excepInfo.wCode, excepInfo.bstrSource,
933
+ excepInfo.bstrDescription ? excepInfo.bstrDescription : L"",
934
+ excepInfo.bstrHelpFile ? excepInfo.bstrHelpFile : L"",
935
+ excepInfo.dwHelpContext);
936
+ }
937
+ }
938
+ ExitOnFailure(hr, "Failed to invoke RegistrationHelper.InstallAssembly() method");
939
+
940
+ hr = S_OK;
941
+
942
+LExit:
943
+ // clean up
944
+ ReleaseObject(piRegHlp);
945
+
946
+ ReleaseBSTR(bstrMember);
947
+
948
+ ReleaseBSTR(excepInfo.bstrSource);
949
+ ReleaseBSTR(excepInfo.bstrDescription);
950
+ ReleaseBSTR(excepInfo.bstrHelpFile);
951
+
952
+ ReleaseBSTR(bstrPartName);
953
+ ReleaseBSTR(bstrAppName);
954
+ ReleaseBSTR(bstrDllPath);
955
+ ReleaseBSTR(bstrTlbPath);
956
+
957
+ return hr;
958
+}
959
+
960
+static HRESULT RegisterNativeAssembly(
961
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
962
+ )
963
+{
964
+ HRESULT hr = S_OK;
965
+
966
+ ICOMAdminCatalog* piCatalog = NULL;
967
+ ICOMAdminCatalog2* piCatalog2 = NULL;
968
+ BSTR bstrGlobPartID = NULL;
969
+
970
+ BSTR bstrPartID = NULL;
971
+ BSTR bstrAppID = NULL;
972
+ BSTR bstrDllPath = NULL;
973
+ BSTR bstrTlbPath = NULL;
974
+ BSTR bstrPSDllPath = NULL;
975
+
976
+ // create BSTRs for parameters
977
+ if (pAttrs->pwzPartID && *pAttrs->pwzPartID)
978
+ {
979
+ bstrPartID = ::SysAllocString(pAttrs->pwzPartID);
980
+ ExitOnNull(bstrPartID, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id");
981
+ }
982
+
983
+ bstrAppID = ::SysAllocString(pAttrs->pwzAppID);
984
+ ExitOnNull(bstrAppID, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id");
985
+
986
+ bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath);
987
+ ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path");
988
+
989
+ bstrTlbPath = ::SysAllocString(pAttrs->pwzTlbPath ? pAttrs->pwzTlbPath : L"");
990
+ ExitOnNull(bstrTlbPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path");
991
+
992
+ bstrPSDllPath = ::SysAllocString(pAttrs->pwzPSDllPath ? pAttrs->pwzPSDllPath : L"");
993
+ ExitOnNull(bstrPSDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path");
994
+
995
+ // get catalog
996
+ hr = CpiGetAdminCatalog(&piCatalog);
997
+ ExitOnFailure(hr, "Failed to get COM+ admin catalog");
998
+
999
+ // get ICOMAdminCatalog2 interface
1000
+ hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2);
1001
+
1002
+ // COM+ 1.5 or later
1003
+ if (E_NOINTERFACE != hr)
1004
+ {
1005
+ ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface");
1006
+
1007
+ // partition id
1008
+ if (!bstrPartID)
1009
+ {
1010
+ // get global partition id
1011
+ hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID);
1012
+ ExitOnFailure(hr, "Failed to get global partition id");
1013
+ }
1014
+
1015
+ // set current partition
1016
+ hr = piCatalog2->put_CurrentPartition(bstrPartID ? bstrPartID : bstrGlobPartID);
1017
+ ExitOnFailure(hr, "Failed to set current partition");
1018
+ }
1019
+
1020
+ // COM+ pre 1.5
1021
+ else
1022
+ {
1023
+ // this version of COM+ does not support partitions, make sure a partition was not specified
1024
+ if (bstrPartID)
1025
+ ExitOnFailure(hr = E_FAIL, "Partitions are not supported by this version of COM+");
1026
+ }
1027
+
1028
+ // install event classes
1029
+ if (pAttrs->iAttributes & aaEventClass)
1030
+ {
1031
+ hr = piCatalog->InstallEventClass(bstrAppID, bstrDllPath, bstrTlbPath, bstrPSDllPath);
1032
+ if (COMADMIN_E_OBJECTERRORS == hr)
1033
+ CpiLogCatalogErrorInfo();
1034
+ ExitOnFailure(hr, "Failed to install event classes");
1035
+ }
1036
+
1037
+ // install components
1038
+ else
1039
+ {
1040
+ hr = piCatalog->InstallComponent(bstrAppID, bstrDllPath, bstrTlbPath, bstrPSDllPath);
1041
+ if (COMADMIN_E_OBJECTERRORS == hr)
1042
+ CpiLogCatalogErrorInfo();
1043
+ ExitOnFailure(hr, "Failed to install components");
1044
+ }
1045
+
1046
+ hr = S_OK;
1047
+
1048
+LExit:
1049
+ // clean up
1050
+ ReleaseObject(piCatalog);
1051
+ ReleaseObject(piCatalog2);
1052
+ ReleaseBSTR(bstrGlobPartID);
1053
+
1054
+ ReleaseBSTR(bstrPartID);
1055
+ ReleaseBSTR(bstrAppID);
1056
+ ReleaseBSTR(bstrDllPath);
1057
+ ReleaseBSTR(bstrTlbPath);
1058
+ ReleaseBSTR(bstrPSDllPath);
1059
+
1060
+ return hr;
1061
+}
1062
+
1063
+static HRESULT UnregisterDotNetAssembly(
1064
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
1065
+ )
1066
+{
1067
+ HRESULT hr = S_OK;
1068
+
1069
+ IDispatch* piRegHlp = NULL;
1070
+
1071
+ DISPID dispid;
1072
+ BSTR bstrMember = NULL;
1073
+
1074
+ VARIANTARG rgvarg[3];
1075
+ DISPPARAMS dispparams;
1076
+ EXCEPINFO excepInfo;
1077
+
1078
+ BSTR bstrPartName = NULL;
1079
+ BSTR bstrAppName = NULL;
1080
+ BSTR bstrDllPath = NULL;
1081
+
1082
+ ::ZeroMemory(rgvarg, sizeof(rgvarg));
1083
+ ::ZeroMemory(&dispparams, sizeof(dispparams));
1084
+ ::ZeroMemory(&excepInfo, sizeof(excepInfo));
1085
+
1086
+ bstrMember = ::SysAllocString(L"UninstallAssembly_2");
1087
+ ExitOnNull(bstrMember, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for method name");
1088
+
1089
+ // create BSTRs for parameters
1090
+ if (pAttrs->pwzPartID && *pAttrs->pwzPartID)
1091
+ {
1092
+ bstrPartName = ::SysAllocString(pAttrs->pwzPartID);
1093
+ ExitOnNull(bstrPartName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id");
1094
+ }
1095
+
1096
+ bstrAppName = ::SysAllocString(pAttrs->pwzAppID);
1097
+ ExitOnNull(bstrAppName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id");
1098
+
1099
+ bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath);
1100
+ ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path");
1101
+
1102
+ // get registration helper object
1103
+ hr = GetRegistrationHelper(&piRegHlp);
1104
+ ExitOnFailure(hr, "Failed to get registration helper object");
1105
+
1106
+ // get dispatch id of UninstallAssembly() method
1107
+ hr = piRegHlp->GetIDsOfNames(IID_NULL, &bstrMember, 1, LOCALE_USER_DEFAULT, &dispid);
1108
+ ExitOnFailure(hr, "Failed to get dispatch id of UninstallAssembly() method");
1109
+
1110
+ // invoke UninstallAssembly() method
1111
+ rgvarg[0].vt = VT_BSTR;
1112
+ rgvarg[0].bstrVal = bstrPartName;
1113
+ rgvarg[1].vt = VT_BSTR;
1114
+ rgvarg[1].bstrVal = bstrAppName;
1115
+ rgvarg[2].vt = VT_BSTR;
1116
+ rgvarg[2].bstrVal = bstrDllPath;
1117
+ dispparams.rgvarg = rgvarg;
1118
+ dispparams.cArgs = 3;
1119
+ dispparams.cNamedArgs = 0;
1120
+
1121
+ hr = piRegHlp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, NULL, &excepInfo, NULL);
1122
+ if (DISP_E_EXCEPTION == hr)
1123
+ {
1124
+ // log exception information
1125
+ if (!excepInfo.pfnDeferredFillIn || (excepInfo.pfnDeferredFillIn && SUCCEEDED(excepInfo.pfnDeferredFillIn(&excepInfo))))
1126
+ {
1127
+ WcaLog(LOGMSG_STANDARD, "ExceptionInfo: Code='%hu', Source='%S', Description='%S', HelpFile='%S', HelpContext='%u'",
1128
+ excepInfo.wCode, excepInfo.bstrSource,
1129
+ excepInfo.bstrDescription ? excepInfo.bstrDescription : L"",
1130
+ excepInfo.bstrHelpFile ? excepInfo.bstrHelpFile : L"",
1131
+ excepInfo.dwHelpContext);
1132
+ }
1133
+ }
1134
+ ExitOnFailure(hr, "Failed to invoke RegistrationHelper.UninstallAssembly() method");
1135
+
1136
+ hr = S_OK;
1137
+
1138
+LExit:
1139
+ // clean up
1140
+ ReleaseObject(piRegHlp);
1141
+
1142
+ ReleaseBSTR(bstrMember);
1143
+
1144
+ ReleaseBSTR(excepInfo.bstrSource);
1145
+ ReleaseBSTR(excepInfo.bstrDescription);
1146
+ ReleaseBSTR(excepInfo.bstrHelpFile);
1147
+
1148
+ ReleaseBSTR(bstrPartName);
1149
+ ReleaseBSTR(bstrAppName);
1150
+ ReleaseBSTR(bstrDllPath);
1151
+
1152
+ return hr;
1153
+}
1154
+
1155
+static HRESULT RemoveComponents(
1156
+ ICatalogCollection* piCompColl,
1157
+ CPI_COMPONENT* pCompList
1158
+ )
1159
+{
1160
+ HRESULT hr = S_OK;
1161
+
1162
+ for (CPI_COMPONENT* pItm = pCompList; pItm; pItm = pItm->pNext)
1163
+ {
1164
+ // remove
1165
+ hr = CpiRemoveCollectionObject(piCompColl, pItm->wzCLSID, NULL, FALSE);
1166
+ ExitOnFailure(hr, "Failed to remove component");
1167
+
1168
+ if (S_FALSE == hr)
1169
+ WcaLog(LOGMSG_VERBOSE, "Component not found, nothing to delete, key: %S", pItm->wzCLSID);
1170
+ }
1171
+
1172
+ hr = S_OK;
1173
+
1174
+LExit:
1175
+ return hr;
1176
+}
1177
+
1178
+static HRESULT ReadAssemblyAttributes(
1179
+ LPWSTR* ppwzData,
1180
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
1181
+ )
1182
+{
1183
+ HRESULT hr = S_OK;
1184
+
1185
+ // read attributes
1186
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
1187
+ ExitOnFailure(hr, "Failed to read action type");
1188
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
1189
+ ExitOnFailure(hr, "Failed to read action cost");
1190
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
1191
+ ExitOnFailure(hr, "Failed to read key");
1192
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAssemblyName);
1193
+ ExitOnFailure(hr, "Failed to read assembly name");
1194
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzDllPath);
1195
+ ExitOnFailure(hr, "Failed to read dll path");
1196
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzTlbPath);
1197
+ ExitOnFailure(hr, "Failed to read tlb path");
1198
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPSDllPath);
1199
+ ExitOnFailure(hr, "Failed to read proxy-stub dll path");
1200
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iAttributes);
1201
+ ExitOnFailure(hr, "Failed to read attributes");
1202
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID);
1203
+ ExitOnFailure(hr, "Failed to read application id");
1204
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
1205
+ ExitOnFailure(hr, "Failed to read partition id");
1206
+
1207
+ // free existing component list
1208
+ if (pAttrs->pCompList)
1209
+ {
1210
+ FreeComponentList(pAttrs->pCompList);
1211
+ pAttrs->pCompList = NULL;
1212
+ }
1213
+
1214
+ // read components
1215
+ hr = ReadComponentList(ppwzData, &pAttrs->pCompList);
1216
+ ExitOnFailure(hr, "Failed to read components");
1217
+
1218
+ hr = S_OK;
1219
+
1220
+LExit:
1221
+ return hr;
1222
+}
1223
+
1224
+static void FreeAssemblyAttributes(
1225
+ CPI_ASSEMBLY_ATTRIBUTES* pAttrs
1226
+ )
1227
+{
1228
+ ReleaseStr(pAttrs->pwzKey);
1229
+ ReleaseStr(pAttrs->pwzAssemblyName);
1230
+ ReleaseStr(pAttrs->pwzDllPath);
1231
+ ReleaseStr(pAttrs->pwzTlbPath);
1232
+ ReleaseStr(pAttrs->pwzPSDllPath);
1233
+ ReleaseStr(pAttrs->pwzAppID);
1234
+ ReleaseStr(pAttrs->pwzPartID);
1235
+
1236
+ if (pAttrs->pCompList)
1237
+ FreeComponentList(pAttrs->pCompList);
1238
+}
1239
+
1240
+static HRESULT ReadRoleAssignmentsAttributes(
1241
+ LPWSTR* ppwzData,
1242
+ CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs
1243
+ )
1244
+{
1245
+ HRESULT hr = S_OK;
1246
+
1247
+ // read attributes
1248
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
1249
+ ExitOnFailure(hr, "Failed to read action type");
1250
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
1251
+ ExitOnFailure(hr, "Failed to read action cost");
1252
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
1253
+ ExitOnFailure(hr, "Failed to read key");
1254
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iRoleCount);
1255
+ ExitOnFailure(hr, "Failed to read role assignments count");
1256
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID);
1257
+ ExitOnFailure(hr, "Failed to read application id");
1258
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
1259
+ ExitOnFailure(hr, "Failed to read partition id");
1260
+
1261
+ // free existing component list
1262
+ if (pAttrs->pCompList)
1263
+ {
1264
+ FreeComponentList(pAttrs->pCompList);
1265
+ pAttrs->pCompList = NULL;
1266
+ }
1267
+
1268
+ // read components
1269
+ hr = ReadComponentList(ppwzData, &pAttrs->pCompList);
1270
+ ExitOnFailure(hr, "Failed to read components");
1271
+
1272
+ hr = S_OK;
1273
+
1274
+LExit:
1275
+ return hr;
1276
+}
1277
+
1278
+static void FreeRoleAssignmentsAttributes(
1279
+ CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs
1280
+ )
1281
+{
1282
+ ReleaseStr(pAttrs->pwzKey);
1283
+ ReleaseStr(pAttrs->pwzAppID);
1284
+ ReleaseStr(pAttrs->pwzPartID);
1285
+
1286
+ if (pAttrs->pCompList)
1287
+ FreeComponentList(pAttrs->pCompList);
1288
+}
1289
+
1290
+
1291
+static HRESULT ConfigureComponents(
1292
+ LPCWSTR pwzPartID,
1293
+ LPCWSTR pwzAppID,
1294
+ CPI_COMPONENT* pCompList,
1295
+ BOOL fCreate,
1296
+ BOOL fProgress
1297
+ )
1298
+{
1299
+ HRESULT hr = S_OK;
1300
+
1301
+ ICatalogCollection* piCompColl = NULL;
1302
+ ICatalogObject* piCompObj = NULL;
1303
+
1304
+ long lChanges = 0;
1305
+
1306
+ // get components collection
1307
+ hr = CpiGetComponentsCollection(pwzPartID, pwzAppID, &piCompColl);
1308
+ if (S_FALSE == hr)
1309
+ if (fCreate)
1310
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1311
+ else
1312
+ ExitFunction1(hr = S_OK);
1313
+ ExitOnFailure(hr, "Failed to get components collection");
1314
+
1315
+ // read components
1316
+ for (CPI_COMPONENT* pItm = pCompList; pItm; pItm = pItm->pNext)
1317
+ {
1318
+ // progress message
1319
+ if (fProgress)
1320
+ {
1321
+ hr = CpiActionDataMessage(1, pItm->wzCLSID);
1322
+ ExitOnFailure(hr, "Failed to send progress messages");
1323
+
1324
+ if (S_FALSE == hr)
1325
+ ExitFunction(); // aborted by user
1326
+ }
1327
+
1328
+ // find component
1329
+ hr = CpiFindCollectionObjectByStringKey(piCompColl, pItm->wzCLSID, &piCompObj);
1330
+ if (S_FALSE == hr)
1331
+ if (fCreate)
1332
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1333
+ else
1334
+ continue;
1335
+ ExitOnFailure(hr, "Failed to find component object");
1336
+
1337
+ // properties
1338
+ hr = CpiPutCollectionObjectValues(piCompObj, pItm->pPropertyList);
1339
+ ExitOnFailure(hr, "Failed to write properties");
1340
+
1341
+ // read roles
1342
+ if (pItm->pRoleAssignmentList)
1343
+ {
1344
+ hr = ConfigureRoleAssignments(L"RolesForComponent", piCompColl, piCompObj, pItm->pRoleAssignmentList, fCreate);
1345
+ ExitOnFailure(hr, "Failed to read roles");
1346
+ }
1347
+
1348
+ // read interfaces
1349
+ if (pItm->pInterfaceList)
1350
+ {
1351
+ hr = ConfigureInterfaces(piCompColl, piCompObj, pItm->pInterfaceList, fCreate);
1352
+ ExitOnFailure(hr, "Failed to read interfaces");
1353
+ }
1354
+
1355
+ // clean up
1356
+ ReleaseNullObject(piCompObj);
1357
+ }
1358
+
1359
+ // save changes
1360
+ hr = piCompColl->SaveChanges(&lChanges);
1361
+ if (COMADMIN_E_OBJECTERRORS == hr)
1362
+ CpiLogCatalogErrorInfo();
1363
+ ExitOnFailure(hr, "Failed to save changes");
1364
+
1365
+ hr = S_OK;
1366
+
1367
+LExit:
1368
+ // clean up
1369
+ ReleaseObject(piCompColl);
1370
+ ReleaseObject(piCompObj);
1371
+
1372
+ return hr;
1373
+}
1374
+
1375
+static HRESULT ConfigureInterfaces(
1376
+ ICatalogCollection* piCompColl,
1377
+ ICatalogObject* piCompObj,
1378
+ CPI_INTERFACE* pIntfList,
1379
+ BOOL fCreate
1380
+ )
1381
+{
1382
+ HRESULT hr = S_OK;
1383
+
1384
+ ICatalogCollection* piIntfColl = NULL;
1385
+ ICatalogObject* piIntfObj = NULL;
1386
+
1387
+ long lChanges = 0;
1388
+
1389
+ // get interfaces collection
1390
+ hr = CpiGetInterfacesCollection(piCompColl, piCompObj, &piIntfColl);
1391
+ if (S_FALSE == hr)
1392
+ if (fCreate)
1393
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1394
+ else
1395
+ ExitFunction1(hr = S_OK);
1396
+ ExitOnFailure(hr, "Failed to get interfaces collection");
1397
+
1398
+ // read interfaces
1399
+ for (CPI_INTERFACE* pItm = pIntfList; pItm; pItm = pItm->pNext)
1400
+ {
1401
+ // find interface
1402
+ hr = CpiFindCollectionObjectByStringKey(piIntfColl, pItm->wzIID, &piIntfObj);
1403
+ if (S_FALSE == hr)
1404
+ if (fCreate)
1405
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1406
+ else
1407
+ continue;
1408
+ ExitOnFailure(hr, "Failed to find interface object");
1409
+
1410
+ // properties
1411
+ hr = CpiPutCollectionObjectValues(piIntfObj, pItm->pPropertyList);
1412
+ ExitOnFailure(hr, "Failed to write properties");
1413
+
1414
+ // read roles
1415
+ if (pItm->pRoleAssignmentList)
1416
+ {
1417
+ hr = ConfigureRoleAssignments(L"RolesForInterface", piIntfColl, piIntfObj, pItm->pRoleAssignmentList, fCreate);
1418
+ ExitOnFailure(hr, "Failed to read roles");
1419
+ }
1420
+
1421
+ // read methods
1422
+ if (pItm->pMethodList)
1423
+ {
1424
+ hr = ConfigureMethods(piIntfColl, piIntfObj, pItm->pMethodList, fCreate);
1425
+ ExitOnFailure(hr, "Failed to read methods");
1426
+ }
1427
+
1428
+ // clean up
1429
+ ReleaseNullObject(piIntfObj);
1430
+ }
1431
+
1432
+ // save changes
1433
+ hr = piIntfColl->SaveChanges(&lChanges);
1434
+ if (COMADMIN_E_OBJECTERRORS == hr)
1435
+ CpiLogCatalogErrorInfo();
1436
+ ExitOnFailure(hr, "Failed to save changes");
1437
+
1438
+ hr = S_OK;
1439
+
1440
+LExit:
1441
+ // clean up
1442
+ ReleaseObject(piIntfColl);
1443
+ ReleaseObject(piIntfObj);
1444
+
1445
+ return hr;
1446
+}
1447
+
1448
+static HRESULT ConfigureMethods(
1449
+ ICatalogCollection* piIntfColl,
1450
+ ICatalogObject* piIntfObj,
1451
+ CPI_METHOD* pMethList,
1452
+ BOOL fCreate
1453
+ )
1454
+{
1455
+ HRESULT hr = S_OK;
1456
+
1457
+ ICatalogCollection* piMethColl = NULL;
1458
+ ICatalogObject* piMethObj = NULL;
1459
+
1460
+ long lChanges = 0;
1461
+
1462
+ // get methods collection
1463
+ hr = CpiGetMethodsCollection(piIntfColl, piIntfObj, &piMethColl);
1464
+ if (S_FALSE == hr)
1465
+ if (fCreate)
1466
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1467
+ else
1468
+ ExitFunction1(hr = S_OK);
1469
+ ExitOnFailure(hr, "Failed to get methods collection");
1470
+
1471
+ // read methods
1472
+ for (CPI_METHOD* pItm = pMethList; pItm; pItm = pItm->pNext)
1473
+ {
1474
+ // find method
1475
+ if (*pItm->wzIndex)
1476
+ hr = CpiFindCollectionObjectByIntegerKey(piMethColl, _wtol(pItm->wzIndex), &piMethObj);
1477
+ else
1478
+ hr = CpiFindCollectionObjectByName(piMethColl, pItm->wzName, &piMethObj);
1479
+
1480
+ if (S_FALSE == hr)
1481
+ if (fCreate)
1482
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1483
+ else
1484
+ continue;
1485
+ ExitOnFailure(hr, "Failed to find method object");
1486
+
1487
+ // properties
1488
+ hr = CpiPutCollectionObjectValues(piMethObj, pItm->pPropertyList);
1489
+ ExitOnFailure(hr, "Failed to write properties");
1490
+
1491
+ // read roles
1492
+ if (pItm->pRoleAssignmentList)
1493
+ {
1494
+ hr = ConfigureRoleAssignments(L"RolesForMethod", piMethColl, piMethObj, pItm->pRoleAssignmentList, fCreate);
1495
+ ExitOnFailure(hr, "Failed to read roles");
1496
+ }
1497
+
1498
+ // clean up
1499
+ ReleaseNullObject(piMethObj);
1500
+ }
1501
+
1502
+ // save changes
1503
+ hr = piMethColl->SaveChanges(&lChanges);
1504
+ if (COMADMIN_E_OBJECTERRORS == hr)
1505
+ CpiLogCatalogErrorInfo();
1506
+ ExitOnFailure(hr, "Failed to save changes");
1507
+
1508
+ hr = S_OK;
1509
+
1510
+LExit:
1511
+ // clean up
1512
+ ReleaseObject(piMethColl);
1513
+ ReleaseObject(piMethObj);
1514
+
1515
+ return hr;
1516
+}
1517
+
1518
+static HRESULT ConfigureRoleAssignments(
1519
+ LPCWSTR pwzCollName,
1520
+ ICatalogCollection* piCompColl,
1521
+ ICatalogObject* piCompObj,
1522
+ CPI_ROLE_ASSIGNMENT* pRoleList,
1523
+ BOOL fCreate
1524
+ )
1525
+{
1526
+ HRESULT hr = S_OK;
1527
+
1528
+ ICatalogCollection* piRoleColl = NULL;
1529
+ ICatalogObject* piRoleObj = NULL;
1530
+
1531
+ long lChanges = 0;
1532
+
1533
+ // get roles collection
1534
+ hr = CpiGetCatalogCollection(piCompColl, piCompObj, pwzCollName, &piRoleColl);
1535
+ if (S_FALSE == hr)
1536
+ if (fCreate)
1537
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1538
+ else
1539
+ ExitFunction1(hr = S_OK);
1540
+ ExitOnFailure(hr, "Failed to get role assignments collection");
1541
+
1542
+ // read roles
1543
+ for (CPI_ROLE_ASSIGNMENT* pItm = pRoleList; pItm; pItm = pItm->pNext)
1544
+ {
1545
+ if (fCreate)
1546
+ {
1547
+ // find existing role
1548
+ hr = CpiFindCollectionObjectByName(piRoleColl, pItm->wzRoleName, NULL);
1549
+ ExitOnFailure(hr, "Failed to find role, key: %S", pItm->wzKey);
1550
+
1551
+ if (S_OK == hr)
1552
+ continue; // role already exists
1553
+
1554
+ // add object
1555
+ hr = CpiAddCollectionObject(piRoleColl, &piRoleObj);
1556
+ ExitOnFailure(hr, "Failed to add role assignment to collection");
1557
+
1558
+ // role name
1559
+ hr = CpiPutCollectionObjectValue(piRoleObj, L"Name", pItm->wzRoleName);
1560
+ ExitOnFailure(hr, "Failed to set role name property, key: %S", pItm->wzKey);
1561
+
1562
+ // clean up
1563
+ ReleaseNullObject(piRoleObj);
1564
+ }
1565
+ else
1566
+ {
1567
+ // remove role
1568
+ hr = CpiRemoveCollectionObject(piRoleColl, NULL, pItm->wzRoleName, FALSE);
1569
+ ExitOnFailure(hr, "Failed to remove role, key: %S", pItm->wzKey);
1570
+ }
1571
+ }
1572
+
1573
+ // save changes
1574
+ hr = piRoleColl->SaveChanges(&lChanges);
1575
+ if (COMADMIN_E_OBJECTERRORS == hr)
1576
+ CpiLogCatalogErrorInfo();
1577
+ ExitOnFailure(hr, "Failed to save changes");
1578
+
1579
+ hr = S_OK;
1580
+
1581
+LExit:
1582
+ // clean up
1583
+ ReleaseObject(piRoleColl);
1584
+ ReleaseObject(piRoleObj);
1585
+
1586
+ return hr;
1587
+}
1588
+
1589
+static HRESULT ReadComponentList(
1590
+ LPWSTR* ppwzData,
1591
+ CPI_COMPONENT** ppCompList
1592
+ )
1593
+{
1594
+ HRESULT hr = S_OK;
1595
+
1596
+ LPWSTR pwzData = NULL;
1597
+
1598
+ CPI_COMPONENT* pItm = NULL;
1599
+
1600
+ int iCnt = 0;
1601
+
1602
+ // read count
1603
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
1604
+ ExitOnFailure(hr, "Failed to read count");
1605
+
1606
+ // read components
1607
+ for (int i = 0; i < iCnt; i++)
1608
+ {
1609
+ pItm = (CPI_COMPONENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_COMPONENT));
1610
+ if (!pItm)
1611
+ ExitFunction1(hr = E_OUTOFMEMORY);
1612
+
1613
+ // read clsid
1614
+ hr = WcaReadStringFromCaData(ppwzData, &pwzData);
1615
+ ExitOnFailure(hr, "Failed to read clsid");
1616
+ StringCchCopyW(pItm->wzCLSID, countof(pItm->wzCLSID), pwzData);
1617
+
1618
+ // read properties
1619
+ hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList);
1620
+ ExitOnFailure(hr, "Failed to read properties");
1621
+
1622
+ // read role assignments
1623
+ hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList);
1624
+ ExitOnFailure(hr, "Failed to read role assignments");
1625
+
1626
+ // read interfaces
1627
+ hr = ReadInterfaceList(ppwzData, &pItm->pInterfaceList);
1628
+ ExitOnFailure(hr, "Failed to read interfaces");
1629
+
1630
+ // add to list
1631
+ if (*ppCompList)
1632
+ pItm->pNext = *ppCompList;
1633
+ *ppCompList = pItm;
1634
+ pItm = NULL;
1635
+ }
1636
+
1637
+ hr = S_OK;
1638
+
1639
+LExit:
1640
+ // clean up
1641
+ ReleaseStr(pwzData);
1642
+
1643
+ if (pItm)
1644
+ FreeComponentList(pItm);
1645
+
1646
+ return hr;
1647
+}
1648
+
1649
+static HRESULT ReadInterfaceList(
1650
+ LPWSTR* ppwzData,
1651
+ CPI_INTERFACE** ppIntfList
1652
+ )
1653
+{
1654
+ HRESULT hr = S_OK;
1655
+
1656
+ LPWSTR pwzData = NULL;
1657
+
1658
+ CPI_INTERFACE* pItm = NULL;
1659
+
1660
+ int iCnt = 0;
1661
+
1662
+ // read count
1663
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
1664
+ ExitOnFailure(hr, "Failed to read count");
1665
+
1666
+ // read interfaces
1667
+ for (int i = 0; i < iCnt; i++)
1668
+ {
1669
+ pItm = (CPI_INTERFACE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_INTERFACE));
1670
+ if (!pItm)
1671
+ ExitFunction1(hr = E_OUTOFMEMORY);
1672
+
1673
+ // read iid
1674
+ hr = WcaReadStringFromCaData(ppwzData, &pwzData);
1675
+ ExitOnFailure(hr, "Failed to read iid");
1676
+ StringCchCopyW(pItm->wzIID, countof(pItm->wzIID), pwzData);
1677
+
1678
+ // read properties
1679
+ hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList);
1680
+ ExitOnFailure(hr, "Failed to read properties");
1681
+
1682
+ // read role assignments
1683
+ hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList);
1684
+ ExitOnFailure(hr, "Failed to read role assignments");
1685
+
1686
+ // read methods
1687
+ hr = ReadMethodList(ppwzData, &pItm->pMethodList);
1688
+ ExitOnFailure(hr, "Failed to read methods");
1689
+
1690
+ // add to list
1691
+ if (*ppIntfList)
1692
+ pItm->pNext = *ppIntfList;
1693
+ *ppIntfList = pItm;
1694
+ pItm = NULL;
1695
+ }
1696
+
1697
+ hr = S_OK;
1698
+
1699
+LExit:
1700
+ // clean up
1701
+ ReleaseStr(pwzData);
1702
+
1703
+ if (pItm)
1704
+ FreeInterfaceList(pItm);
1705
+
1706
+ return hr;
1707
+}
1708
+
1709
+static HRESULT ReadMethodList(
1710
+ LPWSTR* ppwzData,
1711
+ CPI_METHOD** ppMethList
1712
+ )
1713
+{
1714
+ HRESULT hr = S_OK;
1715
+
1716
+ LPWSTR pwzData = NULL;
1717
+
1718
+ CPI_METHOD* pItm = NULL;
1719
+
1720
+ int iCnt = 0;
1721
+
1722
+ // read count
1723
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
1724
+ ExitOnFailure(hr, "Failed to read count");
1725
+
1726
+ // read methods
1727
+ for (int i = 0; i < iCnt; i++)
1728
+ {
1729
+ pItm = (CPI_METHOD*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_METHOD));
1730
+ if (!pItm)
1731
+ ExitFunction1(hr = E_OUTOFMEMORY);
1732
+
1733
+ // read index
1734
+ hr = WcaReadStringFromCaData(ppwzData, &pwzData);
1735
+ ExitOnFailure(hr, "Failed to read index");
1736
+ StringCchCopyW(pItm->wzIndex, countof(pItm->wzIndex), pwzData);
1737
+
1738
+ // read name
1739
+ hr = WcaReadStringFromCaData(ppwzData, &pwzData);
1740
+ ExitOnFailure(hr, "Failed to read name");
1741
+ StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
1742
+
1743
+ // read properties
1744
+ hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList);
1745
+ ExitOnFailure(hr, "Failed to read properties");
1746
+
1747
+ // read role assignments
1748
+ hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList);
1749
+ ExitOnFailure(hr, "Failed to read role assignments");
1750
+
1751
+ // add to list
1752
+ if (*ppMethList)
1753
+ pItm->pNext = *ppMethList;
1754
+ *ppMethList = pItm;
1755
+ pItm = NULL;
1756
+ }
1757
+
1758
+ hr = S_OK;
1759
+
1760
+LExit:
1761
+ // clean up
1762
+ ReleaseStr(pwzData);
1763
+
1764
+ if (pItm)
1765
+ FreeMethodList(pItm);
1766
+
1767
+ return hr;
1768
+}
1769
+
1770
+static HRESULT ReadRoleAssignmentList(
1771
+ LPWSTR* ppwzData,
1772
+ CPI_ROLE_ASSIGNMENT** ppRoleList
1773
+ )
1774
+{
1775
+ HRESULT hr = S_OK;
1776
+
1777
+ LPWSTR pwzData = NULL;
1778
+
1779
+ CPI_ROLE_ASSIGNMENT* pItm = NULL;
1780
+
1781
+ int iCnt = 0;
1782
+
1783
+ // read role count
1784
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
1785
+ ExitOnFailure(hr, "Failed to read role assignments count");
1786
+
1787
+ // read roles
1788
+ for (int i = 0; i < iCnt; i++)
1789
+ {
1790
+ pItm = (CPI_ROLE_ASSIGNMENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLE_ASSIGNMENT));
1791
+ if (!pItm)
1792
+ ExitFunction1(hr = E_OUTOFMEMORY);
1793
+
1794
+ // read key
1795
+ hr = WcaReadStringFromCaData(ppwzData, &pwzData);
1796
+ ExitOnFailure(hr, "Failed to read key");
1797
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
1798
+
1799
+ // read role name
1800
+ hr = WcaReadStringFromCaData(ppwzData, &pwzData);
1801
+ ExitOnFailure(hr, "Failed to read role name");
1802
+ StringCchCopyW(pItm->wzRoleName, countof(pItm->wzRoleName), pwzData);
1803
+
1804
+ // add to list
1805
+ if (*ppRoleList)
1806
+ pItm->pNext = *ppRoleList;
1807
+ *ppRoleList = pItm;
1808
+ pItm = NULL;
1809
+ }
1810
+
1811
+ hr = S_OK;
1812
+
1813
+LExit:
1814
+ // clean up
1815
+ ReleaseStr(pwzData);
1816
+
1817
+ if (pItm)
1818
+ FreeRoleAssignmentList(pItm);
1819
+
1820
+ return hr;
1821
+}
1822
+
1823
+static void FreeComponentList(
1824
+ CPI_COMPONENT* pList
1825
+ )
1826
+{
1827
+ while (pList)
1828
+ {
1829
+ if (pList->pPropertyList)
1830
+ CpiFreePropertyList(pList->pPropertyList);
1831
+ if (pList->pRoleAssignmentList)
1832
+ FreeRoleAssignmentList(pList->pRoleAssignmentList);
1833
+ if (pList->pInterfaceList)
1834
+ FreeInterfaceList(pList->pInterfaceList);
1835
+
1836
+ CPI_COMPONENT* pDelete = pList;
1837
+ pList = pList->pNext;
1838
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
1839
+ }
1840
+}
1841
+
1842
+static void FreeInterfaceList(
1843
+ CPI_INTERFACE* pList
1844
+ )
1845
+{
1846
+ while (pList)
1847
+ {
1848
+ if (pList->pPropertyList)
1849
+ CpiFreePropertyList(pList->pPropertyList);
1850
+ if (pList->pRoleAssignmentList)
1851
+ FreeRoleAssignmentList(pList->pRoleAssignmentList);
1852
+ if (pList->pMethodList)
1853
+ FreeMethodList(pList->pMethodList);
1854
+
1855
+ CPI_INTERFACE* pDelete = pList;
1856
+ pList = pList->pNext;
1857
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
1858
+ }
1859
+}
1860
+
1861
+static void FreeMethodList(
1862
+ CPI_METHOD* pList
1863
+ )
1864
+{
1865
+ while (pList)
1866
+ {
1867
+ if (pList->pPropertyList)
1868
+ CpiFreePropertyList(pList->pPropertyList);
1869
+ if (pList->pRoleAssignmentList)
1870
+ FreeRoleAssignmentList(pList->pRoleAssignmentList);
1871
+
1872
+ CPI_METHOD* pDelete = pList;
1873
+ pList = pList->pNext;
1874
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
1875
+ }
1876
+}
1877
+
1878
+static void FreeRoleAssignmentList(
1879
+ CPI_ROLE_ASSIGNMENT* pList
1880
+ )
1881
+{
1882
+ while (pList)
1883
+ {
1884
+ CPI_ROLE_ASSIGNMENT* pDelete = pList;
1885
+ pList = pList->pNext;
1886
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
1887
+ }
1888
+}
src/ca/cpasmexec.h
new
+20
@@ -0,0 +1,20 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+HRESULT CpiConfigureAssemblies(
6
+ LPWSTR* ppwzData,
7
+ HANDLE hRollbackFile
8
+ );
9
+HRESULT CpiRollbackConfigureAssemblies(
10
+ LPWSTR* ppwzData,
11
+ CPI_ROLLBACK_DATA* pRollbackDataList
12
+ );
13
+HRESULT CpiConfigureRoleAssignments(
14
+ LPWSTR* ppwzData,
15
+ HANDLE hRollbackFile
16
+ );
17
+HRESULT CpiRollbackConfigureRoleAssignments(
18
+ LPWSTR* ppwzData,
19
+ CPI_ROLLBACK_DATA* pRollbackDataList
20
+ );
src/ca/cpasmsched.cpp
new
+2135
@@ -0,0 +1,2135 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// sql queries
7
+
8
+LPCWSTR vcsMsiAssemblyNameQuery =
9
+ L"SELECT `Name`, `Value` FROM `MsiAssemblyName` WHERE `Component_` = ?";
10
+enum eMsiAssemblyNameQuery { manqName = 1, manqValue };
11
+
12
+LPCWSTR vcsModuleQuery =
13
+ L"SELECT `ModuleID` FROM `ModuleSignature`";
14
+enum eModuleQuery { mqModule = 1 };
15
+
16
+LPCWSTR vcsAssemblyQuery =
17
+ L"SELECT `Assembly`, `Component_`, `Application_`, `AssemblyName`, `DllPath`, `TlbPath`, `PSDllPath`, `Attributes` FROM `ComPlusAssembly`";
18
+enum eAssemblyQuery { aqAssembly = 1, aqComponent, aqApplication, aqAssemblyName, aqDllPath, aqTlbPath, aqPSDllPath, aqAttributes };
19
+
20
+LPCWSTR vcsComponentQuery =
21
+ L"SELECT `ComPlusComponent`, `CLSID` FROM `ComPlusComponent` WHERE `Assembly_` = ?";
22
+enum eComponentQuery { cqComponent = 1, cqCLSID };
23
+
24
+LPCWSTR vcsComponentPropertyQuery =
25
+ L"SELECT `Name`, `Value` FROM `ComPlusComponentProperty` WHERE `ComPlusComponent_` = ?";
26
+
27
+LPCWSTR vcsInterfaceQuery =
28
+ L"SELECT `Interface`, `IID` FROM `ComPlusInterface` WHERE `ComPlusComponent_` = ?";
29
+enum eInterfaceQuery { iqInterface = 1, iqIID };
30
+
31
+LPCWSTR vcsInterfacePropertyQuery =
32
+ L"SELECT `Name`, `Value` FROM `ComPlusInterfaceProperty` WHERE `Interface_` = ?";
33
+
34
+LPCWSTR vcsMethodQuery =
35
+ L"SELECT `Method`, `Index`, `Name` FROM `ComPlusMethod` WHERE `Interface_` = ?";
36
+enum eMethodQuery { mqMethod = 1, mqIndex, mqName };
37
+
38
+LPCWSTR vcsMethodPropertyQuery =
39
+ L"SELECT `Name`, `Value` FROM `ComPlusMethodProperty` WHERE `Method_` = ?";
40
+
41
+LPCWSTR vcsRoleForComponentQuery =
42
+ L"SELECT `RoleForComponent`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForComponent` WHERE `ComPlusComponent_` = ?";
43
+LPCWSTR vcsRoleForInterfaceQuery =
44
+ L"SELECT `RoleForInterface`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForInterface` WHERE `Interface_` = ?";
45
+LPCWSTR vcsRoleForMethodQuery =
46
+ L"SELECT `RoleForMethod`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForMethod` WHERE `Method_` = ?";
47
+
48
+enum eRoleAssignmentQuery { raqKey = 1, raqApplicationRole, raqComponent };
49
+
50
+LPCWSTR vcsModuleComponentsQuery =
51
+ L"SELECT `Component`, `ModuleID` FROM `ModuleComponents`";
52
+LPCWSTR vcsModuleDependencyQuery =
53
+ L"SELECT `ModuleID`, `RequiredID` FROM `ModuleDependency`";
54
+LPCWSTR vcsAssemblyDependencyQuery =
55
+ L"SELECT `Assembly_`, `RequiredAssembly_` FROM `ComPlusAssemblyDependency`";
56
+
57
+enum eKeyPairQuery { kpqFirstKey = 1, kpqSecondKey };
58
+
59
+
60
+// private structs
61
+
62
+struct CPI_KEY_PAIR
63
+{
64
+ WCHAR wzFirstKey[MAX_DARWIN_KEY + 1];
65
+ WCHAR wzSecondKey[MAX_DARWIN_KEY + 1];
66
+
67
+ CPI_KEY_PAIR* pNext;
68
+};
69
+
70
+struct CPI_DEPENDENCY_CHAIN
71
+{
72
+ LPCWSTR pwzKey;
73
+
74
+ CPI_DEPENDENCY_CHAIN* pPrev;
75
+};
76
+
77
+struct CPI_MODULE
78
+{
79
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
80
+
81
+ CPI_MODULE* pPrev;
82
+ CPI_MODULE* pNext;
83
+};
84
+
85
+struct CPI_MODULE_LIST
86
+{
87
+ CPI_MODULE* pFirst;
88
+ CPI_MODULE* pLast;
89
+};
90
+
91
+
92
+// property definitions
93
+
94
+CPI_PROPERTY_DEFINITION pdlComponentProperties[] =
95
+{
96
+ {L"AllowInprocSubscribers", cpptBoolean, 500},
97
+ {L"ComponentAccessChecksEnabled", cpptBoolean, 500},
98
+ {L"ComponentTransactionTimeout", cpptInteger, 500},
99
+ {L"ComponentTransactionTimeoutEnabled", cpptBoolean, 500},
100
+ {L"COMTIIntrinsics", cpptBoolean, 500},
101
+ {L"ConstructionEnabled", cpptBoolean, 500},
102
+ {L"ConstructorString", cpptString, 500},
103
+ {L"CreationTimeout", cpptInteger, 500},
104
+ {L"Description", cpptString, 500},
105
+ {L"EventTrackingEnabled", cpptBoolean, 500},
106
+ {L"ExceptionClass", cpptString, 500},
107
+ {L"FireInParallel", cpptBoolean, 500},
108
+ {L"IISIntrinsics", cpptBoolean, 500},
109
+ {L"InitializesServerApplication", cpptBoolean, 500},
110
+ {L"IsEnabled", cpptBoolean, 501},
111
+ {L"IsPrivateComponent", cpptBoolean, 501},
112
+ {L"JustInTimeActivation", cpptBoolean, 500},
113
+ {L"LoadBalancingSupported", cpptBoolean, 500},
114
+ {L"MaxPoolSize", cpptInteger, 500},
115
+ {L"MinPoolSize", cpptInteger, 500},
116
+ {L"MultiInterfacePublisherFilterCLSID", cpptString, 500},
117
+ {L"MustRunInClientContext", cpptBoolean, 500},
118
+ {L"MustRunInDefaultContext", cpptBoolean, 501},
119
+ {L"ObjectPoolingEnabled", cpptBoolean, 500},
120
+ {L"PublisherID", cpptString, 500},
121
+ {L"SoapAssemblyName", cpptString, 502},
122
+ {L"SoapTypeName", cpptString, 502},
123
+ {L"Synchronization", cpptInteger, 500},
124
+ {L"Transaction", cpptInteger, 500},
125
+ {L"TxIsolationLevel", cpptInteger, 501},
126
+ {NULL, cpptNone, 0}
127
+};
128
+
129
+CPI_PROPERTY_DEFINITION pdlInterfaceProperties[] =
130
+{
131
+ {L"Description", cpptString, 500},
132
+ {L"QueuingEnabled", cpptBoolean, 500},
133
+ {NULL, cpptNone, 0}
134
+};
135
+
136
+CPI_PROPERTY_DEFINITION pdlMethodProperties[] =
137
+{
138
+ {L"AutoComplete", cpptBoolean, 500},
139
+ {L"Description", cpptString, 500},
140
+ {NULL, cpptNone, 0}
141
+};
142
+
143
+
144
+// prototypes for private helper functions
145
+
146
+static HRESULT GetAssemblyName(
147
+ LPCWSTR pwzComponent,
148
+ LPWSTR* ppwzAssemblyName
149
+ );
150
+static HRESULT KeyPairsRead(
151
+ LPCWSTR pwzQuery,
152
+ CPI_KEY_PAIR** ppKeyPairList
153
+ );
154
+static HRESULT ModulesRead(
155
+ CPI_MODULE_LIST* pModList
156
+ );
157
+static HRESULT AssembliesRead(
158
+ CPI_KEY_PAIR* pModCompList,
159
+ CPI_APPLICATION_LIST* pAppList,
160
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
161
+ CPI_ASSEMBLY_LIST* pAsmList
162
+ );
163
+static HRESULT ComponentsRead(
164
+ LPCWSTR pwzAsmKey,
165
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
166
+ CPI_ASSEMBLY* pAsm
167
+ );
168
+static HRESULT InterfacesRead(
169
+ LPCWSTR pwzCompKey,
170
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
171
+ CPI_ASSEMBLY* pAsm,
172
+ CPI_COMPONENT* pComp
173
+ );
174
+static HRESULT MethodsRead(
175
+ LPCWSTR pwzIntfKey,
176
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
177
+ CPI_ASSEMBLY* pAsm,
178
+ CPI_INTERFACE* pIntf
179
+ );
180
+static HRESULT RoleAssignmentsRead(
181
+ LPCWSTR pwzQuery,
182
+ LPCWSTR pwzKey,
183
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
184
+ CPI_ROLE_ASSIGNMENT** ppRoleList,
185
+ int* piInstallCount,
186
+ int* piUninstallCount
187
+ );
188
+static HRESULT TopSortModuleList(
189
+ CPI_KEY_PAIR* pDepList,
190
+ CPI_MODULE_LIST* pList
191
+ );
192
+static HRESULT SwapDependentModules(
193
+ CPI_DEPENDENCY_CHAIN* pdcPrev,
194
+ CPI_KEY_PAIR* pDepList,
195
+ CPI_MODULE_LIST* pList,
196
+ CPI_MODULE* pRoot,
197
+ CPI_MODULE* pItm
198
+ );
199
+static HRESULT ModuleFindByKey(
200
+ CPI_MODULE* pItm,
201
+ LPCWSTR pwzKey,
202
+ BOOL fReverse,
203
+ CPI_MODULE** ppItm
204
+ );
205
+static void SortAssemblyListByModule(
206
+ CPI_MODULE_LIST* pModList,
207
+ CPI_ASSEMBLY_LIST* pAsmList
208
+ );
209
+static HRESULT TopSortAssemblyList(
210
+ CPI_KEY_PAIR* pDepList,
211
+ CPI_ASSEMBLY_LIST* pList
212
+ );
213
+static HRESULT SwapDependentAssemblies(
214
+ CPI_DEPENDENCY_CHAIN* pdcPrev,
215
+ CPI_KEY_PAIR* pDepList,
216
+ CPI_ASSEMBLY_LIST* pList,
217
+ CPI_ASSEMBLY* pRoot,
218
+ CPI_ASSEMBLY* pItm
219
+ );
220
+static HRESULT AssemblyFindByKey(
221
+ CPI_ASSEMBLY* pItm,
222
+ LPCWSTR pwzKey,
223
+ BOOL fReverse,
224
+ CPI_ASSEMBLY** ppItm
225
+ );
226
+static HRESULT AddAssemblyToActionData(
227
+ CPI_ASSEMBLY* pItm,
228
+ BOOL fInstall,
229
+ int iActionType,
230
+ int iActionCost,
231
+ LPWSTR* ppwzActionData
232
+ );
233
+static HRESULT AddRoleAssignmentsToActionData(
234
+ CPI_ASSEMBLY* pItm,
235
+ BOOL fInstall,
236
+ int iActionType,
237
+ int iActionCost,
238
+ LPWSTR* ppwzActionData
239
+ );
240
+static HRESULT AddComponentToActionData(
241
+ CPI_COMPONENT* pItm,
242
+ BOOL fInstall,
243
+ BOOL fProps,
244
+ BOOL fRoles,
245
+ LPWSTR* ppwzActionData
246
+ );
247
+static HRESULT AddInterfaceToActionData(
248
+ CPI_INTERFACE* pItm,
249
+ BOOL fInstall,
250
+ BOOL fProps,
251
+ BOOL fRoles,
252
+ LPWSTR* ppwzActionData
253
+ );
254
+static HRESULT AddMethodToActionData(
255
+ CPI_METHOD* pItm,
256
+ BOOL fInstall,
257
+ BOOL fProps,
258
+ BOOL fRoles,
259
+ LPWSTR* ppwzActionData
260
+ );
261
+static HRESULT AddRolesToActionData(
262
+ int iRoleInstallCount,
263
+ int iRoleUninstallCount,
264
+ CPI_ROLE_ASSIGNMENT* pRoleList,
265
+ BOOL fInstall,
266
+ BOOL fRoles,
267
+ LPWSTR* ppwzActionData
268
+ );
269
+static HRESULT KeyPairFindByFirstKey(
270
+ CPI_KEY_PAIR* pList,
271
+ LPCWSTR pwzKey,
272
+ CPI_KEY_PAIR** ppItm
273
+ );
274
+static void AssemblyFree(
275
+ CPI_ASSEMBLY* pItm
276
+ );
277
+static void KeyPairsFreeList(
278
+ CPI_KEY_PAIR* pList
279
+ );
280
+void ModuleListFree(
281
+ CPI_MODULE_LIST* pList
282
+ );
283
+static void ModuleFree(
284
+ CPI_MODULE* pItm
285
+ );
286
+static void ComponentsFreeList(
287
+ CPI_COMPONENT* pList
288
+ );
289
+static void InterfacesFreeList(
290
+ CPI_INTERFACE* pList
291
+ );
292
+static void MethodsFreeList(
293
+ CPI_METHOD* pList
294
+ );
295
+static void RoleAssignmentsFreeList(
296
+ CPI_ROLE_ASSIGNMENT* pList
297
+ );
298
+
299
+
300
+// function definitions
301
+
302
+void CpiAssemblyListFree(
303
+ CPI_ASSEMBLY_LIST* pList
304
+ )
305
+{
306
+ CPI_ASSEMBLY* pItm = pList->pFirst;
307
+
308
+ while (pItm)
309
+ {
310
+ CPI_ASSEMBLY* pDelete = pItm;
311
+ pItm = pItm->pNext;
312
+ AssemblyFree(pDelete);
313
+ }
314
+}
315
+
316
+HRESULT CpiAssembliesRead(
317
+ CPI_APPLICATION_LIST* pAppList,
318
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
319
+ CPI_ASSEMBLY_LIST* pAsmList
320
+ )
321
+{
322
+ HRESULT hr = S_OK;
323
+ CPI_MODULE_LIST modList;
324
+ CPI_KEY_PAIR* pModCompList = NULL;
325
+ CPI_KEY_PAIR* pModDepList = NULL;
326
+ CPI_KEY_PAIR* pAsmDepList = NULL;
327
+
328
+ ::ZeroMemory(&modList, sizeof(CPI_MODULE_LIST));
329
+
330
+ BOOL fModuleSignatureTable = (S_OK == WcaTableExists(L"ModuleSignature"));
331
+ BOOL fModuleComponentsTable = (S_OK == WcaTableExists(L"ModuleComponents"));
332
+ BOOL fModuleDependencyTable = (S_OK == WcaTableExists(L"ModuleDependency"));
333
+
334
+ // read modules
335
+ if (fModuleSignatureTable)
336
+ {
337
+ hr = ModulesRead(&modList);
338
+ ExitOnFailure(hr, "Failed to read ModuleSignature table");
339
+ }
340
+
341
+ // read module components
342
+ if (fModuleComponentsTable)
343
+ {
344
+ hr = KeyPairsRead(vcsModuleComponentsQuery, &pModCompList);
345
+ ExitOnFailure(hr, "Failed to read ModuleComponents table");
346
+ }
347
+
348
+ // read module dependencies
349
+ if (fModuleDependencyTable)
350
+ {
351
+ hr = KeyPairsRead(vcsModuleDependencyQuery, &pModDepList);
352
+ ExitOnFailure(hr, "Failed to read ModuleDependency table");
353
+ }
354
+
355
+ // read assemblies
356
+ hr = AssembliesRead(pModCompList, pAppList, pAppRoleList, pAsmList);
357
+ ExitOnFailure(hr, "Failed to read ComPlusAssembly table");
358
+
359
+ // read assembly dependencies
360
+ if (CpiTableExists(cptComPlusAssemblyDependency))
361
+ {
362
+ hr = KeyPairsRead(vcsAssemblyDependencyQuery, &pAsmDepList);
363
+ ExitOnFailure(hr, "Failed to read ComPlusAssemblyDependency table");
364
+ }
365
+
366
+ // sort modules
367
+ if (modList.pFirst && pModDepList)
368
+ {
369
+ hr = TopSortModuleList(pModDepList, &modList);
370
+ ExitOnFailure(hr, "Failed to sort modules");
371
+ }
372
+
373
+ // sort assemblies by module
374
+ if (pAsmList->pFirst && modList.pFirst && pModDepList)
375
+ SortAssemblyListByModule(&modList, pAsmList);
376
+
377
+ // sort assemblies by dependency
378
+ if (pAsmList->pFirst && pAsmDepList)
379
+ {
380
+ hr = TopSortAssemblyList(pAsmDepList, pAsmList);
381
+ ExitOnFailure(hr, "Failed to sort assemblies");
382
+ }
383
+
384
+ hr = S_OK;
385
+
386
+LExit:
387
+ // clean up
388
+ ModuleListFree(&modList);
389
+ if (pModCompList)
390
+ KeyPairsFreeList(pModCompList);
391
+ if (pModDepList)
392
+ KeyPairsFreeList(pModDepList);
393
+ if (pAsmDepList)
394
+ KeyPairsFreeList(pAsmDepList);
395
+
396
+ return hr;
397
+}
398
+
399
+HRESULT CpiAssembliesVerifyInstall(
400
+ CPI_ASSEMBLY_LIST* pList
401
+ )
402
+{
403
+ HRESULT hr = S_OK;
404
+
405
+ for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
406
+ {
407
+ // assemblies that are being installed
408
+ if (!pItm->fReferencedForInstall && !pItm->iRoleAssignmentsInstallCount && !WcaIsInstalling(pItm->isInstalled, pItm->isAction))
409
+ continue;
410
+
411
+ // if the assembly is referensed, it must be installed
412
+ if ((pItm->fReferencedForInstall || pItm->iRoleAssignmentsInstallCount) && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction))
413
+ MessageExitOnFailure(hr = E_FAIL, msierrComPlusAssemblyDependency, "An assembly is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey);
414
+ }
415
+
416
+ hr = S_OK;
417
+
418
+LExit:
419
+ return hr;
420
+}
421
+
422
+HRESULT CpiAssembliesVerifyUninstall(
423
+ CPI_ASSEMBLY_LIST* pList
424
+ )
425
+{
426
+ HRESULT hr = S_OK;
427
+
428
+ for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
429
+ {
430
+ // assemblies that are being uninstalled
431
+ if (!pItm->fReferencedForUninstall && !pItm->iRoleAssignmentsUninstallCount && (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction) && !WcaIsReInstalling(pItm->isInstalled, pItm->isAction)))
432
+ continue;
433
+
434
+ // if the application is not present, there is no need to remove the components
435
+ if (pItm->pApplication && pItm->pApplication->fObjectNotFound)
436
+ {
437
+ pItm->fIgnore = TRUE;
438
+ pList->iUninstallCount--; // elements with the fIgnore flag set will not be scheduled for uninstall
439
+ pList->iRoleUninstallCount--;
440
+ }
441
+ }
442
+
443
+ hr = S_OK;
444
+
445
+//LExit:
446
+ return hr;
447
+}
448
+
449
+HRESULT CpiAssembliesInstall(
450
+ CPI_ASSEMBLY_LIST* pList,
451
+ int iRunMode,
452
+ LPWSTR* ppwzActionData,
453
+ int* piProgress
454
+ )
455
+{
456
+ HRESULT hr = S_OK;
457
+
458
+ int iActionType;
459
+ int iCount = 0;
460
+
461
+ // add action text
462
+ hr = CpiAddActionTextToActionData(L"RegisterComPlusAssemblies", ppwzActionData);
463
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
464
+
465
+ // assembly count
466
+ switch (iRunMode)
467
+ {
468
+ case rmDeferred:
469
+ iCount = pList->iInstallCount - pList->iCommitCount;
470
+ break;
471
+ case rmCommit:
472
+ iCount = pList->iCommitCount;
473
+ break;
474
+ case rmRollback:
475
+ iCount = pList->iInstallCount;
476
+ break;
477
+ }
478
+
479
+ // add assembly count to action data
480
+ hr = WcaWriteIntegerToCaData(iCount, ppwzActionData);
481
+ ExitOnFailure(hr, "Failed to add count to custom action data");
482
+
483
+ // add assemblies to custom action data in forward order
484
+ for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
485
+ {
486
+ // assemblies that are being installed, or contains roll assignments to install
487
+ if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction))
488
+ continue;
489
+
490
+ // assemblies that are being installed must be scheduled during the right type of action
491
+ BOOL fRunInCommit = 0 != (pItm->iAttributes & aaRunInCommit);
492
+ if (((rmCommit == iRunMode && !fRunInCommit) || (rmDeferred == iRunMode && fRunInCommit)))
493
+ continue;
494
+
495
+ // action type
496
+ if (rmRollback == iRunMode)
497
+ {
498
+ if (CpiIsInstalled(pItm->isInstalled))
499
+ iActionType = atNoOp;
500
+ else
501
+ iActionType = atRemove;
502
+ }
503
+ else
504
+ iActionType = atCreate;
505
+
506
+ // add to action data
507
+ hr = AddAssemblyToActionData(pItm, TRUE, iActionType, COST_ASSEMBLY_REGISTER, ppwzActionData);
508
+ ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey);
509
+ }
510
+
511
+ // add progress tics
512
+ if (piProgress)
513
+ *piProgress += COST_ASSEMBLY_REGISTER * iCount;
514
+
515
+ hr = S_OK;
516
+
517
+LExit:
518
+ return hr;
519
+}
520
+
521
+HRESULT CpiAssembliesUninstall(
522
+ CPI_ASSEMBLY_LIST* pList,
523
+ int iRunMode,
524
+ LPWSTR* ppwzActionData,
525
+ int* piProgress
526
+ )
527
+{
528
+ HRESULT hr = S_OK;
529
+
530
+ int iActionType;
531
+
532
+ // add action text
533
+ hr = CpiAddActionTextToActionData(L"UnregisterComPlusAssemblies", ppwzActionData);
534
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
535
+
536
+ // add assembly count to action data
537
+ hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
538
+ ExitOnFailure(hr, "Failed to add count to custom action data");
539
+
540
+ // add assemblies to custom action data in reverse order
541
+ for (CPI_ASSEMBLY* pItm = pList->pLast; pItm; pItm = pItm->pPrev)
542
+ {
543
+ // assemblies that are being uninstalled
544
+ if (pItm->fIgnore || (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction) && !WcaIsReInstalling(pItm->isInstalled, pItm->isAction)))
545
+ continue;
546
+
547
+ // action type
548
+ if (rmRollback == iRunMode)
549
+ iActionType = atCreate;
550
+ else
551
+ iActionType = atRemove;
552
+
553
+ // add to action data
554
+ hr = AddAssemblyToActionData(pItm, FALSE, iActionType, COST_ASSEMBLY_UNREGISTER, ppwzActionData);
555
+ ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey);
556
+ }
557
+
558
+ // add progress tics
559
+ if (piProgress)
560
+ *piProgress += COST_ASSEMBLY_UNREGISTER * pList->iUninstallCount;
561
+
562
+ hr = S_OK;
563
+
564
+LExit:
565
+ return hr;
566
+}
567
+
568
+HRESULT CpiRoleAssignmentsInstall(
569
+ CPI_ASSEMBLY_LIST* pList,
570
+ int iRunMode,
571
+ LPWSTR* ppwzActionData,
572
+ int* piProgress
573
+ )
574
+{
575
+ HRESULT hr = S_OK;
576
+
577
+ int iActionType;
578
+ int iCount = 0;
579
+
580
+ // add action text
581
+ hr = CpiAddActionTextToActionData(L"AddComPlusRoleAssignments", ppwzActionData);
582
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
583
+
584
+ // assembly count
585
+ switch (iRunMode)
586
+ {
587
+ case rmDeferred:
588
+ iCount = pList->iRoleInstallCount - pList->iRoleCommitCount;
589
+ break;
590
+ case rmCommit:
591
+ iCount = pList->iRoleCommitCount;
592
+ break;
593
+ case rmRollback:
594
+ iCount = pList->iRoleInstallCount;
595
+ break;
596
+ }
597
+
598
+ // add assembly count to action data
599
+ hr = WcaWriteIntegerToCaData(iCount, ppwzActionData);
600
+ ExitOnFailure(hr, "Failed to add count to custom action data");
601
+
602
+ // add assemblies to custom action data in forward order
603
+ for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
604
+ {
605
+ // assemblies that are being installed, or contains roll assignments to install
606
+ if (!pItm->iRoleAssignmentsInstallCount)
607
+ continue;
608
+
609
+ // assemblies that are being installed must be scheduled during the right type of action
610
+ BOOL fRunInCommit = 0 != (pItm->iAttributes & aaRunInCommit);
611
+ if (((rmCommit == iRunMode && !fRunInCommit) || (rmDeferred == iRunMode && fRunInCommit)))
612
+ continue;
613
+
614
+ // action type
615
+ if (rmRollback == iRunMode)
616
+ {
617
+ if (CpiIsInstalled(pItm->isInstalled))
618
+ iActionType = atNoOp;
619
+ else
620
+ iActionType = atRemove;
621
+ }
622
+ else
623
+ iActionType = atCreate;
624
+
625
+ // add to action data
626
+ hr = AddRoleAssignmentsToActionData(pItm, TRUE, iActionType, COST_ROLLASSIGNMENT_CREATE, ppwzActionData);
627
+ ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey);
628
+
629
+ // add progress tics
630
+ if (piProgress)
631
+ *piProgress += COST_ROLLASSIGNMENT_CREATE * pItm->iRoleAssignmentsInstallCount;
632
+ }
633
+
634
+ hr = S_OK;
635
+
636
+LExit:
637
+ return hr;
638
+}
639
+
640
+HRESULT CpiRoleAssignmentsUninstall(
641
+ CPI_ASSEMBLY_LIST* pList,
642
+ int iRunMode,
643
+ LPWSTR* ppwzActionData,
644
+ int* piProgress
645
+ )
646
+{
647
+ HRESULT hr = S_OK;
648
+
649
+ int iActionType;
650
+
651
+ // add action text
652
+ hr = CpiAddActionTextToActionData(L"RemoveComPlusRoleAssignments", ppwzActionData);
653
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
654
+
655
+ // add assembly count to action data
656
+ hr = WcaWriteIntegerToCaData(pList->iRoleUninstallCount, ppwzActionData);
657
+ ExitOnFailure(hr, "Failed to add count to custom action data");
658
+
659
+ // add assemblies to custom action data in reverse order
660
+ for (CPI_ASSEMBLY* pItm = pList->pLast; pItm; pItm = pItm->pPrev)
661
+ {
662
+ // assemblies that are being uninstalled
663
+ if (pItm->fIgnore || !pItm->iRoleAssignmentsUninstallCount)
664
+ continue;
665
+
666
+ // action type
667
+ if (rmRollback == iRunMode)
668
+ iActionType = atCreate;
669
+ else
670
+ iActionType = atRemove;
671
+
672
+ // add to action data
673
+ hr = AddRoleAssignmentsToActionData(pItm, FALSE, iActionType, COST_ROLLASSIGNMENT_DELETE, ppwzActionData);
674
+ ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey);
675
+
676
+ // add progress tics
677
+ if (piProgress)
678
+ *piProgress += COST_ROLLASSIGNMENT_DELETE * pItm->iRoleAssignmentsUninstallCount;
679
+ }
680
+
681
+ hr = S_OK;
682
+
683
+LExit:
684
+ return hr;
685
+}
686
+
687
+HRESULT CpiGetSubscriptionsCollForComponent(
688
+ CPI_ASSEMBLY* pAsm,
689
+ CPI_COMPONENT* pComp,
690
+ ICatalogCollection** ppiSubsColl
691
+ )
692
+{
693
+ HRESULT hr = S_OK;
694
+
695
+ ICatalogCollection* piCompColl = NULL;
696
+ ICatalogObject* piCompObj = NULL;
697
+
698
+ // get applications collection
699
+ if (!pComp->piSubsColl)
700
+ {
701
+ // get components collection for application
702
+ hr = CpiGetComponentsCollForApplication(pAsm->pApplication, &piCompColl);
703
+ ExitOnFailure(hr, "Failed to get components collection for application");
704
+
705
+ if (S_FALSE == hr)
706
+ ExitFunction(); // exit with hr = S_FALSE
707
+
708
+ // find component object
709
+ hr = CpiFindCollectionObject(piCompColl, pComp->wzCLSID, NULL, &piCompObj);
710
+ ExitOnFailure(hr, "Failed to find component object");
711
+
712
+ if (S_FALSE == hr)
713
+ ExitFunction(); // exit with hr = S_FALSE
714
+
715
+ // get roles collection
716
+ hr = CpiGetCatalogCollection(piCompColl, piCompObj, L"SubscriptionsForComponent", &pComp->piSubsColl);
717
+ ExitOnFailure(hr, "Failed to get subscriptions collection");
718
+ }
719
+
720
+ // return value
721
+ *ppiSubsColl = pComp->piSubsColl;
722
+ (*ppiSubsColl)->AddRef();
723
+
724
+ hr = S_OK;
725
+
726
+LExit:
727
+ // clean up
728
+ ReleaseObject(piCompColl);
729
+ ReleaseObject(piCompObj);
730
+
731
+ return hr;
732
+}
733
+
734
+
735
+// helper function definitions
736
+
737
+static HRESULT GetAssemblyName(
738
+ LPCWSTR pwzComponent,
739
+ LPWSTR* ppwzAssemblyName
740
+ )
741
+{
742
+ HRESULT hr = S_OK;
743
+
744
+ PMSIHANDLE hView, hRecKey, hRec;
745
+
746
+ LPWSTR pwzKey = NULL;
747
+
748
+ LPWSTR pwzName = NULL;
749
+ LPWSTR pwzVersion = NULL;
750
+ LPWSTR pwzCulture = NULL;
751
+ LPWSTR pwzPublicKeyToken = NULL;
752
+
753
+ // create parameter record
754
+ hRecKey = ::MsiCreateRecord(1);
755
+ ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record");
756
+ hr = WcaSetRecordString(hRecKey, 1, pwzComponent);
757
+ ExitOnFailure(hr, "Failed to set record string");
758
+
759
+ // open view
760
+ hr = WcaOpenView(vcsMsiAssemblyNameQuery, &hView);
761
+ ExitOnFailure(hr, "Failed to open view on MsiAssemblyName table");
762
+ hr = WcaExecuteView(hView, hRecKey);
763
+ ExitOnFailure(hr, "Failed to execute view on MsiAssemblyName table");
764
+
765
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
766
+ {
767
+ // read key
768
+ hr = WcaGetRecordString(hRec, manqName, &pwzKey);
769
+ ExitOnFailure(hr, "Failed to get name");
770
+
771
+ // read value
772
+ if (0 == lstrcmpiW(L"name", pwzKey))
773
+ hr = WcaGetRecordString(hRec, manqValue, &pwzName);
774
+ else if (0 == lstrcmpiW(L"version", pwzKey))
775
+ hr = WcaGetRecordString(hRec, manqValue, &pwzVersion);
776
+ else if (0 == lstrcmpiW(L"culture", pwzKey))
777
+ hr = WcaGetRecordString(hRec, manqValue, &pwzCulture);
778
+ else if (0 == lstrcmpiW(L"publicKeyToken", pwzKey))
779
+ hr = WcaGetRecordString(hRec, manqValue, &pwzPublicKeyToken);
780
+ else
781
+ {
782
+ WcaLog(LOGMSG_VERBOSE, "Unknown name in MsiAssemblyName table: %S, %S", pwzComponent, pwzKey);
783
+ hr = S_OK;
784
+ }
785
+
786
+ ExitOnFailure(hr, "Failed to get value");
787
+ }
788
+
789
+ if (E_NOMOREITEMS != hr)
790
+ ExitOnFailure(hr, "Failed to fetch record");
791
+
792
+ // verify
793
+ if (!(pwzName && *pwzName) || !(pwzVersion && *pwzVersion))
794
+ ExitOnFailure(hr = E_FAIL, "Incomplete assembly name");
795
+
796
+ // build name string
797
+ hr = StrAllocFormatted(ppwzAssemblyName, L"%s, Version=%s, Culture=%s, PublicKeyToken=%s",
798
+ pwzName, pwzVersion,
799
+ pwzCulture && *pwzCulture ? pwzCulture : L"Neutral",
800
+ pwzPublicKeyToken && *pwzPublicKeyToken ? pwzPublicKeyToken : L"null");
801
+ ExitOnFailure(hr, "Failed to build assembly name string");
802
+
803
+ hr = S_OK;
804
+
805
+LExit:
806
+ // clean up
807
+ ReleaseStr(pwzKey);
808
+ ReleaseStr(pwzName);
809
+ ReleaseStr(pwzVersion);
810
+ ReleaseStr(pwzCulture);
811
+ ReleaseStr(pwzPublicKeyToken);
812
+
813
+ return hr;
814
+}
815
+
816
+static HRESULT KeyPairsRead(
817
+ LPCWSTR pwzQuery,
818
+ CPI_KEY_PAIR** ppKeyPairList
819
+ )
820
+{
821
+ HRESULT hr = S_OK;
822
+
823
+ PMSIHANDLE hView, hRec;
824
+
825
+ CPI_KEY_PAIR* pItm = NULL;
826
+ LPWSTR pwzData = NULL;
827
+
828
+ // loop through all dependencies
829
+ hr = WcaOpenExecuteView(pwzQuery, &hView);
830
+ ExitOnFailure(hr, "Failed to execute view on table");
831
+
832
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
833
+ {
834
+ // create entry
835
+ pItm = (CPI_KEY_PAIR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_KEY_PAIR));
836
+ if (!pItm)
837
+ ExitFunction1(hr = E_OUTOFMEMORY);
838
+
839
+ // get key
840
+ hr = WcaGetRecordString(hRec, kpqFirstKey, &pwzData);
841
+ ExitOnFailure(hr, "Failed to get first key");
842
+ StringCchCopyW(pItm->wzFirstKey, countof(pItm->wzFirstKey), pwzData);
843
+
844
+ // get key
845
+ hr = WcaGetRecordString(hRec, kpqSecondKey, &pwzData);
846
+ ExitOnFailure(hr, "Failed to get second key");
847
+ StringCchCopyW(pItm->wzSecondKey, countof(pItm->wzSecondKey), pwzData);
848
+
849
+ // add entry
850
+ if (*ppKeyPairList)
851
+ pItm->pNext = *ppKeyPairList;
852
+ *ppKeyPairList = pItm;
853
+ pItm = NULL;
854
+ }
855
+
856
+ if (E_NOMOREITEMS == hr)
857
+ hr = S_OK;
858
+
859
+LExit:
860
+ // clean up
861
+ if (pItm)
862
+ KeyPairsFreeList(pItm);
863
+
864
+ ReleaseStr(pwzData);
865
+
866
+ return hr;
867
+}
868
+
869
+static HRESULT ModulesRead(
870
+ CPI_MODULE_LIST* pModList
871
+ )
872
+{
873
+ HRESULT hr = S_OK;
874
+
875
+ PMSIHANDLE hView, hRec;
876
+
877
+ CPI_MODULE* pItm = NULL;
878
+ LPWSTR pwzData = NULL;
879
+
880
+ // loop through all modules
881
+ hr = WcaOpenExecuteView(vcsModuleQuery, &hView);
882
+ ExitOnFailure(hr, "Failed to execute view on ModuleSignature table");
883
+
884
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
885
+ {
886
+ // create entry
887
+ pItm = (CPI_MODULE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_MODULE));
888
+ if (!pItm)
889
+ ExitFunction1(hr = E_OUTOFMEMORY);
890
+
891
+ // get key
892
+ hr = WcaGetRecordString(hRec, mqModule, &pwzData);
893
+ ExitOnFailure(hr, "Failed to get key");
894
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
895
+
896
+ // add entry
897
+ if (pModList->pLast)
898
+ {
899
+ pModList->pLast->pNext = pItm;
900
+ pItm->pPrev = pModList->pLast;
901
+ }
902
+ else
903
+ pModList->pFirst = pItm;
904
+ pModList->pLast = pItm;
905
+ pItm = NULL;
906
+ }
907
+
908
+ if (E_NOMOREITEMS == hr)
909
+ hr = S_OK;
910
+
911
+LExit:
912
+ // clean up
913
+ if (pItm)
914
+ ModuleFree(pItm);
915
+
916
+ ReleaseStr(pwzData);
917
+
918
+ return hr;
919
+}
920
+
921
+static HRESULT AssembliesRead(
922
+ CPI_KEY_PAIR* pModCompList,
923
+ CPI_APPLICATION_LIST* pAppList,
924
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
925
+ CPI_ASSEMBLY_LIST* pAsmList
926
+ )
927
+{
928
+ HRESULT hr = S_OK;
929
+ UINT er = ERROR_SUCCESS;
930
+
931
+ PMSIHANDLE hView, hRec;
932
+
933
+ CPI_ASSEMBLY* pItm = NULL;
934
+ CPI_KEY_PAIR* pModComp;
935
+ LPWSTR pwzData = NULL;
936
+ LPWSTR pwzComponent = NULL;
937
+ BOOL fMatchingArchitecture = FALSE;
938
+
939
+ // loop through all assemblies
940
+ hr = WcaOpenExecuteView(vcsAssemblyQuery, &hView);
941
+ ExitOnFailure(hr, "Failed to execute view on ComPlusAssembly table");
942
+
943
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
944
+ {
945
+ // get component
946
+ hr = WcaGetRecordString(hRec, aqComponent, &pwzComponent);
947
+ ExitOnFailure(hr, "Failed to get component");
948
+
949
+ // check if the component is our processor architecture
950
+ hr = CpiVerifyComponentArchitecure(pwzComponent, &fMatchingArchitecture);
951
+ ExitOnFailure(hr, "Failed to get component architecture.");
952
+
953
+ if (!fMatchingArchitecture)
954
+ {
955
+ continue; // not the same architecture, ignore
956
+ }
957
+
958
+ // create entry
959
+ pItm = (CPI_ASSEMBLY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ASSEMBLY));
960
+ if (!pItm)
961
+ ExitFunction1(hr = E_OUTOFMEMORY);
962
+
963
+ // get component install state
964
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &pItm->isInstalled, &pItm->isAction);
965
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
966
+
967
+ // get key
968
+ hr = WcaGetRecordString(hRec, aqAssembly, &pwzData);
969
+ ExitOnFailure(hr, "Failed to get key");
970
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
971
+
972
+ // get attributes
973
+ hr = WcaGetRecordInteger(hRec, aqAttributes, &pItm->iAttributes);
974
+ ExitOnFailure(hr, "Failed to get attributes");
975
+
976
+ // get assembly name
977
+ hr = WcaGetRecordFormattedString(hRec, aqAssemblyName, &pItm->pwzAssemblyName);
978
+ ExitOnFailure(hr, "Failed to get assembly name");
979
+
980
+ if (!*pItm->pwzAssemblyName && (pItm->iAttributes & aaPathFromGAC))
981
+ {
982
+ // get assembly name for component
983
+ hr = GetAssemblyName(pwzComponent, &pItm->pwzAssemblyName);
984
+ ExitOnFailure(hr, "Failed to get assembly name for component");
985
+ }
986
+
987
+ // get dll path
988
+ hr = WcaGetRecordFormattedString(hRec, aqDllPath, &pItm->pwzDllPath);
989
+ ExitOnFailure(hr, "Failed to get assembly dll path");
990
+
991
+ // get module
992
+ // TODO: if there is a very large number of components belonging to modules, this search might be slow
993
+ hr = KeyPairFindByFirstKey(pModCompList, pwzData, &pModComp);
994
+
995
+ if (S_OK == hr)
996
+ StringCchCopyW(pItm->wzModule, countof(pItm->wzModule), pModComp->wzSecondKey);
997
+
998
+ // get application
999
+ hr = WcaGetRecordString(hRec, aqApplication, &pwzData);
1000
+ ExitOnFailure(hr, "Failed to get application");
1001
+
1002
+ if (pwzData && *pwzData)
1003
+ {
1004
+ hr = CpiApplicationFindByKey(pAppList, pwzData, &pItm->pApplication);
1005
+ if (S_FALSE == hr)
1006
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1007
+ ExitOnFailure(hr, "Failed to find application, key: %S", pwzData);
1008
+ }
1009
+
1010
+ // get tlb path
1011
+ hr = WcaGetRecordFormattedString(hRec, aqTlbPath, &pItm->pwzTlbPath);
1012
+ ExitOnFailure(hr, "Failed to get assembly tlb path");
1013
+
1014
+ // get proxy-stub dll path
1015
+ hr = WcaGetRecordFormattedString(hRec, aqPSDllPath, &pItm->pwzPSDllPath);
1016
+ ExitOnFailure(hr, "Failed to get assembly proxy-stub DLL path");
1017
+
1018
+ // read components
1019
+ if (CpiTableExists(cptComPlusComponent))
1020
+ {
1021
+ hr = ComponentsRead(pItm->wzKey, pAppRoleList, pItm);
1022
+ ExitOnFailure(hr, "Failed to read components for assembly");
1023
+ }
1024
+
1025
+ // set references & increment counters
1026
+ if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
1027
+ {
1028
+ pAsmList->iInstallCount++;
1029
+ if (pItm->iAttributes & aaRunInCommit)
1030
+ pAsmList->iCommitCount++;
1031
+ }
1032
+ if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction) || WcaIsReInstalling(pItm->isInstalled, pItm->isAction))
1033
+ pAsmList->iUninstallCount++;
1034
+
1035
+ if (pItm->iRoleAssignmentsInstallCount)
1036
+ {
1037
+ pAsmList->iRoleInstallCount++;
1038
+ if (pItm->iAttributes & aaRunInCommit)
1039
+ pAsmList->iRoleCommitCount++;
1040
+ }
1041
+ if (pItm->iRoleAssignmentsUninstallCount)
1042
+ pAsmList->iRoleUninstallCount++;
1043
+
1044
+ if (pItm->pApplication)
1045
+ {
1046
+ if (pItm->iRoleAssignmentsInstallCount || WcaIsInstalling(pItm->isInstalled, pItm->isAction))
1047
+ CpiApplicationAddReferenceInstall(pItm->pApplication);
1048
+ if (pItm->iRoleAssignmentsUninstallCount || WcaIsUninstalling(pItm->isInstalled, pItm->isAction) || WcaIsReInstalling(pItm->isInstalled, pItm->isAction))
1049
+ CpiApplicationAddReferenceUninstall(pItm->pApplication);
1050
+ }
1051
+
1052
+ // add entry
1053
+ if (pAsmList->pLast)
1054
+ {
1055
+ pAsmList->pLast->pNext = pItm;
1056
+ pItm->pPrev = pAsmList->pLast;
1057
+ }
1058
+ else
1059
+ pAsmList->pFirst = pItm;
1060
+ pAsmList->pLast = pItm;
1061
+ pItm = NULL;
1062
+ }
1063
+
1064
+ if (E_NOMOREITEMS == hr)
1065
+ hr = S_OK;
1066
+
1067
+LExit:
1068
+ // clean up
1069
+ if (pItm)
1070
+ AssemblyFree(pItm);
1071
+
1072
+ ReleaseStr(pwzData);
1073
+ ReleaseStr(pwzComponent);
1074
+
1075
+ return hr;
1076
+}
1077
+
1078
+static HRESULT TopSortModuleList(
1079
+ CPI_KEY_PAIR* pDepList,
1080
+ CPI_MODULE_LIST* pList
1081
+ )
1082
+{
1083
+ HRESULT hr = S_OK;
1084
+
1085
+ // top sort list
1086
+ for (CPI_MODULE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
1087
+ {
1088
+ // append module
1089
+ hr = SwapDependentModules(NULL, pDepList, pList, pItm, pItm);
1090
+ ExitOnFailure(hr, "Failed to swap dependent modules");
1091
+ }
1092
+
1093
+ hr = S_OK;
1094
+
1095
+LExit:
1096
+ return hr;
1097
+}
1098
+
1099
+static HRESULT SwapDependentModules(
1100
+ CPI_DEPENDENCY_CHAIN* pdcPrev, // list containing the entire dependency chain
1101
+ CPI_KEY_PAIR* pDepList, // module dependency list
1102
+ CPI_MODULE_LIST* pList, // module list being sorted
1103
+ CPI_MODULE* pRoot, // first module in the chain
1104
+ CPI_MODULE* pItm // current module to test for dependencies
1105
+ )
1106
+{
1107
+ HRESULT hr = S_OK;
1108
+
1109
+ CPI_MODULE* pDepItm;
1110
+
1111
+ // find dependencies
1112
+ for (CPI_KEY_PAIR* pDep = pDepList; pDep; pDep = pDep->pNext)
1113
+ {
1114
+ if (0 == lstrcmpW(pItm->wzKey, pDep->wzFirstKey))
1115
+ {
1116
+ CPI_DEPENDENCY_CHAIN dcItm;
1117
+ dcItm.pwzKey = pItm->wzKey;
1118
+ dcItm.pPrev = pdcPrev;
1119
+
1120
+ // check for circular dependencies
1121
+ for (CPI_DEPENDENCY_CHAIN* pdcItm = &dcItm; pdcItm; pdcItm = pdcItm->pPrev)
1122
+ {
1123
+ if (0 == lstrcmpW(pdcItm->pwzKey, pDep->wzSecondKey))
1124
+ {
1125
+ // circular dependency found
1126
+ ExitOnFailure(hr = E_FAIL, "Circular module dependency found, key: %S", pDep->wzSecondKey);
1127
+ }
1128
+ }
1129
+
1130
+ // make sure the item is not already in the list
1131
+ hr = ModuleFindByKey(pRoot->pPrev, pDep->wzSecondKey, TRUE, &pDepItm); // find in reverse order
1132
+
1133
+ if (S_OK == hr)
1134
+ continue; // item found, move on
1135
+
1136
+ // find item in the list
1137
+ hr = ModuleFindByKey(pRoot->pNext, pDep->wzSecondKey, FALSE, &pDepItm); // find in forward order
1138
+
1139
+ if (S_FALSE == hr)
1140
+ {
1141
+ // not found
1142
+ ExitOnFailure(hr = E_FAIL, "Module dependency not found, key: %S", pDep->wzSecondKey);
1143
+ }
1144
+
1145
+ // if this item in turn has dependencies, they have to be swaped first
1146
+ hr = SwapDependentModules(&dcItm, pDepList, pList, pRoot, pDepItm);
1147
+ ExitOnFailure(hr, "Failed to swap dependent module");
1148
+
1149
+ // remove item from its current position
1150
+ pDepItm->pPrev->pNext = pDepItm->pNext; // pDepItm can never be the first item, no need to check pPrev
1151
+ if (pDepItm->pNext)
1152
+ pDepItm->pNext->pPrev = pDepItm->pPrev;
1153
+ else
1154
+ {
1155
+ pList->pLast = pDepItm->pPrev;
1156
+ pList->pLast->pNext = NULL;
1157
+ }
1158
+
1159
+ // insert before the current item
1160
+ if (pRoot->pPrev)
1161
+ pRoot->pPrev->pNext = pDepItm;
1162
+ else
1163
+ pList->pFirst = pDepItm;
1164
+ pDepItm->pPrev = pRoot->pPrev;
1165
+ pRoot->pPrev = pDepItm;
1166
+ pDepItm->pNext = pRoot;
1167
+ }
1168
+ }
1169
+
1170
+ hr = S_OK;
1171
+
1172
+LExit:
1173
+ return hr;
1174
+}
1175
+
1176
+static HRESULT ModuleFindByKey(
1177
+ CPI_MODULE* pItm,
1178
+ LPCWSTR pwzKey,
1179
+ BOOL fReverse,
1180
+ CPI_MODULE** ppItm
1181
+ )
1182
+{
1183
+ for (; pItm; pItm = fReverse ? pItm->pPrev : pItm->pNext)
1184
+ {
1185
+ if (0 == lstrcmpW(pItm->wzKey, pwzKey))
1186
+ {
1187
+ *ppItm = pItm;
1188
+ return S_OK;
1189
+ }
1190
+ }
1191
+
1192
+ return S_FALSE;
1193
+}
1194
+
1195
+static void SortAssemblyListByModule(
1196
+ CPI_MODULE_LIST* pModList,
1197
+ CPI_ASSEMBLY_LIST* pAsmList
1198
+ )
1199
+{
1200
+ CPI_ASSEMBLY* pMoved = NULL; // first moved item
1201
+
1202
+ // loop modules in reverse order
1203
+ for (CPI_MODULE* pMod = pModList->pLast; pMod; pMod = pMod->pPrev)
1204
+ {
1205
+ // loop assemblies in forward order, starting with the first unmoved item
1206
+ CPI_ASSEMBLY* pAsm = pMoved ? pMoved->pNext : pAsmList->pFirst;
1207
+ while (pAsm)
1208
+ {
1209
+ CPI_ASSEMBLY* pNext = pAsm->pNext;
1210
+
1211
+ // check if assembly belongs to the current module
1212
+ if (0 == lstrcmpW(pMod->wzKey, pAsm->wzModule))
1213
+ {
1214
+ // if the item is not already first in the list
1215
+ if (pAsm->pPrev)
1216
+ {
1217
+ // remove item from it's current position
1218
+ pAsm->pPrev->pNext = pAsm->pNext;
1219
+ if (pAsm->pNext)
1220
+ pAsm->pNext->pPrev = pAsm->pPrev;
1221
+ else
1222
+ pAsmList->pLast = pAsm->pPrev;
1223
+
1224
+ // insert item first in the list
1225
+ pAsmList->pFirst->pPrev = pAsm;
1226
+ pAsm->pNext = pAsmList->pFirst;
1227
+ pAsm->pPrev = NULL;
1228
+ pAsmList->pFirst = pAsm;
1229
+ }
1230
+
1231
+ // if we haven't moved any items yet, this is the first moved item
1232
+ if (!pMoved)
1233
+ pMoved = pAsm;
1234
+ }
1235
+
1236
+ pAsm = pNext;
1237
+ }
1238
+ }
1239
+}
1240
+
1241
+static HRESULT TopSortAssemblyList(
1242
+ CPI_KEY_PAIR* pDepList,
1243
+ CPI_ASSEMBLY_LIST* pList
1244
+ )
1245
+{
1246
+ HRESULT hr = S_OK;
1247
+
1248
+ // top sort list
1249
+ for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
1250
+ {
1251
+ // append module
1252
+ hr = SwapDependentAssemblies(NULL, pDepList, pList, pItm, pItm);
1253
+ ExitOnFailure(hr, "Failed to swap dependent assemblies");
1254
+ }
1255
+
1256
+ hr = S_OK;
1257
+
1258
+LExit:
1259
+ return hr;
1260
+}
1261
+
1262
+static HRESULT SwapDependentAssemblies(
1263
+ CPI_DEPENDENCY_CHAIN* pdcPrev, // list containing the entire dependency chain
1264
+ CPI_KEY_PAIR* pDepList, // assembly dependency list
1265
+ CPI_ASSEMBLY_LIST* pList, // assembly list being sorted
1266
+ CPI_ASSEMBLY* pRoot, // first assembly in the chain
1267
+ CPI_ASSEMBLY* pItm // current assembly to test for dependencies
1268
+ )
1269
+{
1270
+ HRESULT hr = S_OK;
1271
+
1272
+ CPI_ASSEMBLY* pDepItm;
1273
+
1274
+ // find dependencies
1275
+ for (CPI_KEY_PAIR* pDep = pDepList; pDep; pDep = pDep->pNext)
1276
+ {
1277
+ if (0 == lstrcmpW(pItm->wzKey, pDep->wzFirstKey))
1278
+ {
1279
+ CPI_DEPENDENCY_CHAIN dcItm;
1280
+ dcItm.pwzKey = pItm->wzKey;
1281
+ dcItm.pPrev = pdcPrev;
1282
+
1283
+ // check for circular dependencies
1284
+ for (CPI_DEPENDENCY_CHAIN* pdcItm = &dcItm; pdcItm; pdcItm = pdcItm->pPrev)
1285
+ {
1286
+ if (0 == lstrcmpW(pdcItm->pwzKey, pDep->wzSecondKey))
1287
+ {
1288
+ // circular dependency found
1289
+ ExitOnFailure(hr = E_FAIL, "Circular assembly dependency found, key: %S", pDep->wzSecondKey);
1290
+ }
1291
+ }
1292
+
1293
+ // make sure the item is not already in the list
1294
+ hr = AssemblyFindByKey(pRoot->pPrev, pDep->wzSecondKey, TRUE, &pDepItm); // find in reverse order
1295
+
1296
+ if (S_OK == hr)
1297
+ continue; // item found, move on
1298
+
1299
+ // find item in the list
1300
+ hr = AssemblyFindByKey(pRoot->pNext, pDep->wzSecondKey, FALSE, &pDepItm); // find in forward order
1301
+
1302
+ if (S_FALSE == hr)
1303
+ {
1304
+ // not found
1305
+ ExitOnFailure(hr = E_FAIL, "Assembly dependency not found, key: %S", pDep->wzSecondKey);
1306
+ }
1307
+
1308
+ // if the root item belongs to a module, this item must also belong to the same module
1309
+ if (*pItm->wzModule)
1310
+ {
1311
+ if (0 != lstrcmpW(pDepItm->wzModule, pItm->wzModule))
1312
+ ExitOnFailure(hr = E_FAIL, "An assembly dependency can only exist between two assemblies not belonging to modules, or belonging to the same module. assembly: %S, required assembly: %S", pItm->wzKey, pDepItm->wzKey);
1313
+ }
1314
+
1315
+ // if this item in turn has dependencies, they have to be swaped first
1316
+ hr = SwapDependentAssemblies(&dcItm, pDepList, pList, pRoot, pDepItm);
1317
+ ExitOnFailure(hr, "Failed to swap dependent assemblies");
1318
+
1319
+ // remove item from its current position
1320
+ pDepItm->pPrev->pNext = pDepItm->pNext; // pDepItm can never be the first item, no need to check pPrev
1321
+ if (pDepItm->pNext)
1322
+ pDepItm->pNext->pPrev = pDepItm->pPrev;
1323
+ else
1324
+ {
1325
+ pList->pLast = pDepItm->pPrev;
1326
+ pList->pLast->pNext = NULL;
1327
+ }
1328
+
1329
+ // insert before the current item
1330
+ if (pRoot->pPrev)
1331
+ pRoot->pPrev->pNext = pDepItm;
1332
+ else
1333
+ pList->pFirst = pDepItm;
1334
+ pDepItm->pPrev = pRoot->pPrev;
1335
+ pRoot->pPrev = pDepItm;
1336
+ pDepItm->pNext = pRoot;
1337
+ }
1338
+ }
1339
+
1340
+ hr = S_OK;
1341
+
1342
+LExit:
1343
+ return hr;
1344
+}
1345
+
1346
+static HRESULT AssemblyFindByKey(
1347
+ CPI_ASSEMBLY* pItm,
1348
+ LPCWSTR pwzKey,
1349
+ BOOL fReverse,
1350
+ CPI_ASSEMBLY** ppItm
1351
+ )
1352
+{
1353
+ for (; pItm; pItm = fReverse ? pItm->pPrev : pItm->pNext)
1354
+ {
1355
+ if (0 == lstrcmpW(pItm->wzKey, pwzKey))
1356
+ {
1357
+ *ppItm = pItm;
1358
+ return S_OK;
1359
+ }
1360
+ }
1361
+
1362
+ return S_FALSE;
1363
+}
1364
+
1365
+static HRESULT ComponentsRead(
1366
+ LPCWSTR pwzAsmKey,
1367
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
1368
+ CPI_ASSEMBLY* pAsm
1369
+ )
1370
+{
1371
+ HRESULT hr = S_OK;
1372
+ PMSIHANDLE hView;
1373
+ PMSIHANDLE hRec;
1374
+ PMSIHANDLE hRecKey;
1375
+ CPI_COMPONENT* pItm = NULL;
1376
+ LPWSTR pwzData = NULL;
1377
+
1378
+ // create parameter record
1379
+ hRecKey = ::MsiCreateRecord(1);
1380
+ ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record");
1381
+ hr = WcaSetRecordString(hRecKey, 1, pwzAsmKey);
1382
+ ExitOnFailure(hr, "Failed to set record string");
1383
+
1384
+ // open view
1385
+ hr = WcaOpenView(vcsComponentQuery, &hView);
1386
+ ExitOnFailure(hr, "Failed to open view on ComPlusComponent table");
1387
+ hr = WcaExecuteView(hView, hRecKey);
1388
+ ExitOnFailure(hr, "Failed to execute view on ComPlusComponent table");
1389
+
1390
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
1391
+ {
1392
+ // create entry
1393
+ pItm = (CPI_COMPONENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_COMPONENT));
1394
+ if (!pItm)
1395
+ ExitFunction1(hr = E_OUTOFMEMORY);
1396
+
1397
+ // get key
1398
+ hr = WcaGetRecordString(hRec, cqComponent, &pwzData);
1399
+ ExitOnFailure(hr, "Failed to get key");
1400
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
1401
+
1402
+ // get clsid
1403
+ hr = WcaGetRecordFormattedString(hRec, cqCLSID, &pwzData);
1404
+ ExitOnFailure(hr, "Failed to get clsid");
1405
+ StringCchCopyW(pItm->wzCLSID, countof(pItm->wzCLSID), pwzData);
1406
+
1407
+ // read properties
1408
+ if (CpiTableExists(cptComPlusComponentProperty))
1409
+ {
1410
+ hr = CpiPropertiesRead(vcsComponentPropertyQuery, pItm->wzKey, pdlComponentProperties, &pItm->pProperties, &pItm->iPropertyCount);
1411
+ ExitOnFailure(hr, "Failed to get component properties");
1412
+ }
1413
+
1414
+ // read roles
1415
+ if (CpiTableExists(cptComPlusRoleForComponent))
1416
+ {
1417
+ hr = RoleAssignmentsRead(vcsRoleForComponentQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount);
1418
+ ExitOnFailure(hr, "Failed to get roles for component");
1419
+ }
1420
+
1421
+ if (pItm->iRoleInstallCount)
1422
+ pAsm->iRoleAssignmentsInstallCount++;
1423
+ if (pItm->iRoleUninstallCount)
1424
+ pAsm->iRoleAssignmentsUninstallCount++;
1425
+
1426
+ // read interfaces
1427
+ if (CpiTableExists(cptComPlusInterface))
1428
+ {
1429
+ hr = InterfacesRead(pItm->wzKey, pAppRoleList, pAsm, pItm);
1430
+ ExitOnFailure(hr, "Failed to get interfaces for component");
1431
+ }
1432
+
1433
+ // add entry
1434
+ pAsm->iComponentCount++;
1435
+ if (pAsm->pComponents)
1436
+ pItm->pNext = pAsm->pComponents;
1437
+ pAsm->pComponents = pItm;
1438
+ pItm = NULL;
1439
+ }
1440
+
1441
+ if (E_NOMOREITEMS == hr)
1442
+ hr = S_OK;
1443
+
1444
+LExit:
1445
+ // clean up
1446
+ if (pItm)
1447
+ ComponentsFreeList(pItm);
1448
+
1449
+ ReleaseStr(pwzData);
1450
+
1451
+ return hr;
1452
+}
1453
+
1454
+static HRESULT InterfacesRead(
1455
+ LPCWSTR pwzCompKey,
1456
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
1457
+ CPI_ASSEMBLY* pAsm,
1458
+ CPI_COMPONENT* pComp
1459
+ )
1460
+{
1461
+ HRESULT hr = S_OK;
1462
+ PMSIHANDLE hView;
1463
+ PMSIHANDLE hRec;
1464
+ PMSIHANDLE hRecKey;
1465
+ CPI_INTERFACE* pItm = NULL;
1466
+ LPWSTR pwzData = NULL;
1467
+
1468
+ // create parameter record
1469
+ hRecKey = ::MsiCreateRecord(1);
1470
+ ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record");
1471
+ hr = WcaSetRecordString(hRecKey, 1, pwzCompKey);
1472
+ ExitOnFailure(hr, "Failed to set record string");
1473
+
1474
+ // open view
1475
+ hr = WcaOpenView(vcsInterfaceQuery, &hView);
1476
+ ExitOnFailure(hr, "Failed to open view on ComPlusInterface table");
1477
+ hr = WcaExecuteView(hView, hRecKey);
1478
+ ExitOnFailure(hr, "Failed to execute view on ComPlusInterface table");
1479
+
1480
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
1481
+ {
1482
+ // create entry
1483
+ pItm = (CPI_INTERFACE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_INTERFACE));
1484
+ if (!pItm)
1485
+ ExitFunction1(hr = E_OUTOFMEMORY);
1486
+
1487
+ // get key
1488
+ hr = WcaGetRecordString(hRec, iqInterface, &pwzData);
1489
+ ExitOnFailure(hr, "Failed to get key");
1490
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
1491
+
1492
+ // get iid
1493
+ hr = WcaGetRecordFormattedString(hRec, iqIID, &pwzData);
1494
+ ExitOnFailure(hr, "Failed to get iid");
1495
+ StringCchCopyW(pItm->wzIID, countof(pItm->wzIID), pwzData);
1496
+
1497
+ // read properties
1498
+ if (CpiTableExists(cptComPlusInterfaceProperty))
1499
+ {
1500
+ hr = CpiPropertiesRead(vcsInterfacePropertyQuery, pItm->wzKey, pdlInterfaceProperties, &pItm->pProperties, &pItm->iPropertyCount);
1501
+ ExitOnFailure(hr, "Failed to get interface properties");
1502
+ }
1503
+
1504
+ // read roles
1505
+ if (CpiTableExists(cptComPlusRoleForInterface))
1506
+ {
1507
+ hr = RoleAssignmentsRead(vcsRoleForInterfaceQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount);
1508
+ ExitOnFailure(hr, "Failed to get roles for interface");
1509
+ }
1510
+
1511
+ if (pItm->iRoleInstallCount)
1512
+ pAsm->iRoleAssignmentsInstallCount++;
1513
+ if (pItm->iRoleUninstallCount)
1514
+ pAsm->iRoleAssignmentsUninstallCount++;
1515
+
1516
+ // read methods
1517
+ if (CpiTableExists(cptComPlusMethod))
1518
+ {
1519
+ hr = MethodsRead(pItm->wzKey, pAppRoleList, pAsm, pItm);
1520
+ ExitOnFailure(hr, "Failed to get methods for interface");
1521
+ }
1522
+
1523
+ // add entry
1524
+ pComp->iInterfaceCount++;
1525
+ if (pComp->pInterfaces)
1526
+ pItm->pNext = pComp->pInterfaces;
1527
+ pComp->pInterfaces = pItm;
1528
+ pItm = NULL;
1529
+ }
1530
+
1531
+ if (E_NOMOREITEMS == hr)
1532
+ hr = S_OK;
1533
+
1534
+LExit:
1535
+ // clean up
1536
+ if (pItm)
1537
+ InterfacesFreeList(pItm);
1538
+
1539
+ ReleaseStr(pwzData);
1540
+
1541
+ return hr;
1542
+}
1543
+
1544
+static HRESULT MethodsRead(
1545
+ LPCWSTR pwzIntfKey,
1546
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
1547
+ CPI_ASSEMBLY* pAsm,
1548
+ CPI_INTERFACE* pIntf
1549
+ )
1550
+{
1551
+ HRESULT hr = S_OK;
1552
+ PMSIHANDLE hView, hRec, hRecKey;
1553
+ CPI_METHOD* pItm = NULL;
1554
+ LPWSTR pwzData = NULL;
1555
+
1556
+ // create parameter record
1557
+ hRecKey = ::MsiCreateRecord(1);
1558
+ ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record");
1559
+ hr = WcaSetRecordString(hRecKey, 1, pwzIntfKey);
1560
+ ExitOnFailure(hr, "Failed to set record string");
1561
+
1562
+ // open view
1563
+ hr = WcaOpenView(vcsMethodQuery, &hView);
1564
+ ExitOnFailure(hr, "Failed to open view on ComPlusMethod table");
1565
+ hr = WcaExecuteView(hView, hRecKey);
1566
+ ExitOnFailure(hr, "Failed to execute view on ComPlusMethod table");
1567
+
1568
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
1569
+ {
1570
+ // create entry
1571
+ pItm = (CPI_METHOD*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_METHOD));
1572
+ if (!pItm)
1573
+ ExitFunction1(hr = E_OUTOFMEMORY);
1574
+
1575
+ // get key
1576
+ hr = WcaGetRecordString(hRec, iqInterface, &pwzData);
1577
+ ExitOnFailure(hr, "Failed to get key");
1578
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
1579
+
1580
+ // get index
1581
+ hr = WcaGetRecordFormattedString(hRec, mqIndex, &pwzData);
1582
+ ExitOnFailure(hr, "Failed to get index");
1583
+ StringCchCopyW(pItm->wzIndex, countof(pItm->wzIndex), pwzData);
1584
+
1585
+ // get name
1586
+ hr = WcaGetRecordFormattedString(hRec, mqName, &pwzData);
1587
+ ExitOnFailure(hr, "Failed to get name");
1588
+ StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
1589
+
1590
+ // either an index or a name must be provided
1591
+ if (!*pItm->wzIndex && !*pItm->wzName)
1592
+ ExitOnFailure(hr = E_FAIL, "A method must have either an index or a name associated, key: %S", pItm->wzKey);
1593
+
1594
+ // read properties
1595
+ if (CpiTableExists(cptComPlusMethodProperty))
1596
+ {
1597
+ hr = CpiPropertiesRead(vcsMethodPropertyQuery, pItm->wzKey, pdlMethodProperties, &pItm->pProperties, &pItm->iPropertyCount);
1598
+ ExitOnFailure(hr, "Failed to get method properties");
1599
+ }
1600
+
1601
+ // read roles
1602
+ if (CpiTableExists(cptComPlusRoleForMethod))
1603
+ {
1604
+ hr = RoleAssignmentsRead(vcsRoleForMethodQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount);
1605
+ ExitOnFailure(hr, "Failed to get roles for method");
1606
+ }
1607
+
1608
+ if (pItm->iRoleInstallCount)
1609
+ pAsm->iRoleAssignmentsInstallCount++;
1610
+ if (pItm->iRoleUninstallCount)
1611
+ pAsm->iRoleAssignmentsUninstallCount++;
1612
+
1613
+ // add entry
1614
+ pIntf->iMethodCount++;
1615
+ if (pIntf->pMethods)
1616
+ pItm->pNext = pIntf->pMethods;
1617
+ pIntf->pMethods = pItm;
1618
+ pItm = NULL;
1619
+ }
1620
+
1621
+ if (E_NOMOREITEMS == hr)
1622
+ hr = S_OK;
1623
+
1624
+LExit:
1625
+ // clean up
1626
+ if (pItm)
1627
+ MethodsFreeList(pItm);
1628
+
1629
+ ReleaseStr(pwzData);
1630
+
1631
+ return hr;
1632
+}
1633
+
1634
+static HRESULT RoleAssignmentsRead(
1635
+ LPCWSTR pwzQuery,
1636
+ LPCWSTR pwzKey,
1637
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
1638
+ CPI_ROLE_ASSIGNMENT** ppRoleList,
1639
+ int* piInstallCount,
1640
+ int* piUninstallCount
1641
+ )
1642
+{
1643
+ HRESULT hr = S_OK;
1644
+ UINT er = ERROR_SUCCESS;
1645
+
1646
+ PMSIHANDLE hView, hRec, hRecKey;
1647
+
1648
+ CPI_ROLE_ASSIGNMENT* pItm = NULL;
1649
+ LPWSTR pwzData = NULL;
1650
+ BOOL fMatchingArchitecture = FALSE;
1651
+
1652
+ // create parameter record
1653
+ hRecKey = ::MsiCreateRecord(1);
1654
+ ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record");
1655
+ hr = WcaSetRecordString(hRecKey, 1, pwzKey);
1656
+ ExitOnFailure(hr, "Failed to set record string");
1657
+
1658
+ // open view
1659
+ hr = WcaOpenView(pwzQuery, &hView);
1660
+ ExitOnFailure(hr, "Failed to open view on role assignment table");
1661
+ hr = WcaExecuteView(hView, hRecKey);
1662
+ ExitOnFailure(hr, "Failed to execute view on role assignment table");
1663
+
1664
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
1665
+ {
1666
+ // get component
1667
+ hr = WcaGetRecordString(hRec, raqComponent, &pwzData);
1668
+ ExitOnFailure(hr, "Failed to get assembly component");
1669
+
1670
+ // check if the component is our processor architecture
1671
+ hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
1672
+ ExitOnFailure(hr, "Failed to get component architecture.");
1673
+
1674
+ if (!fMatchingArchitecture)
1675
+ {
1676
+ continue; // not the same architecture, ignore
1677
+ }
1678
+
1679
+ // create entry
1680
+ pItm = (CPI_ROLE_ASSIGNMENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLE_ASSIGNMENT));
1681
+ if (!pItm)
1682
+ ExitFunction1(hr = E_OUTOFMEMORY);
1683
+
1684
+ // get component install state
1685
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
1686
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
1687
+
1688
+ // get key
1689
+ hr = WcaGetRecordString(hRec, raqKey, &pwzData);
1690
+ ExitOnFailure(hr, "Failed to get key");
1691
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
1692
+
1693
+ // get application role
1694
+ hr = WcaGetRecordString(hRec, raqApplicationRole, &pwzData);
1695
+ ExitOnFailure(hr, "Failed to get application role");
1696
+
1697
+ hr = CpiApplicationRoleFindByKey(pAppRoleList, pwzData, &pItm->pApplicationRole);
1698
+ if (S_FALSE == hr)
1699
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
1700
+ ExitOnFailure(hr, "Failed to find application, key: %S", pwzData);
1701
+
1702
+ // set references & increment counters
1703
+ if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
1704
+ {
1705
+ CpiApplicationRoleAddReferenceInstall(pItm->pApplicationRole);
1706
+ ++*piInstallCount;
1707
+ }
1708
+ if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
1709
+ {
1710
+ CpiApplicationRoleAddReferenceUninstall(pItm->pApplicationRole);
1711
+ ++*piUninstallCount;
1712
+ }
1713
+
1714
+ // add entry
1715
+ if (*ppRoleList)
1716
+ pItm->pNext = *ppRoleList;
1717
+ *ppRoleList = pItm;
1718
+ pItm = NULL;
1719
+ }
1720
+
1721
+ if (E_NOMOREITEMS == hr)
1722
+ hr = S_OK;
1723
+
1724
+LExit:
1725
+ // clean up
1726
+ if (pItm)
1727
+ RoleAssignmentsFreeList(pItm);
1728
+
1729
+ ReleaseStr(pwzData);
1730
+
1731
+ return hr;
1732
+}
1733
+
1734
+static HRESULT AddAssemblyToActionData(
1735
+ CPI_ASSEMBLY* pItm,
1736
+ BOOL fInstall,
1737
+ int iActionType,
1738
+ int iActionCost,
1739
+ LPWSTR* ppwzActionData
1740
+ )
1741
+{
1742
+ HRESULT hr = S_OK;
1743
+
1744
+ // add action information to custom action data
1745
+ hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
1746
+ ExitOnFailure(hr, "Failed to add action type to custom action data");
1747
+ hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
1748
+ ExitOnFailure(hr, "Failed to add action cost to custom action data");
1749
+
1750
+ // add assembly information to custom action data
1751
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
1752
+ ExitOnFailure(hr, "Failed to add assembly key to custom action data");
1753
+ hr = WcaWriteStringToCaData(pItm->pwzAssemblyName, ppwzActionData);
1754
+ ExitOnFailure(hr, "Failed to add assembly name to custom action data");
1755
+ hr = WcaWriteStringToCaData(pItm->pwzDllPath, ppwzActionData);
1756
+ ExitOnFailure(hr, "Failed to add assembly dll path to custom action data");
1757
+ hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pwzTlbPath : L"", ppwzActionData);
1758
+ ExitOnFailure(hr, "Failed to add assembly tlb path to custom action data");
1759
+ hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pwzPSDllPath : L"", ppwzActionData);
1760
+ ExitOnFailure(hr, "Failed to add assembly proxy-stub dll path to custom action data");
1761
+ hr = WcaWriteIntegerToCaData(pItm->iAttributes, ppwzActionData);
1762
+ ExitOnFailure(hr, "Failed to add assembly attributes to custom action data");
1763
+
1764
+ // add application information to custom action data
1765
+ hr = WcaWriteStringToCaData(pItm->pApplication ? pItm->pApplication->wzID : L"", ppwzActionData);
1766
+ ExitOnFailure(hr, "Failed to add application id to custom action data");
1767
+
1768
+ // add partition information to custom action data
1769
+ LPCWSTR pwzPartID = pItm->pApplication && pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L"";
1770
+ hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData);
1771
+ ExitOnFailure(hr, "Failed to add partition id to custom action data");
1772
+
1773
+ // add components to custom action data
1774
+ //
1775
+ // components are needed acording to the following table:
1776
+ //
1777
+ // Native .NET
1778
+ // --------------------------------------------
1779
+ // NoOp | No | No
1780
+ // Create | Yes | Yes
1781
+ // Remove | Yes | No
1782
+ //
1783
+ int iCompCount = (atCreate == iActionType || (atRemove == iActionType && 0 == (pItm->iAttributes & aaDotNetAssembly))) ? pItm->iComponentCount : 0;
1784
+ hr = WcaWriteIntegerToCaData(iCompCount, ppwzActionData);
1785
+ ExitOnFailure(hr, "Failed to add component count to custom action data, key: %S", pItm->wzKey);
1786
+
1787
+ if (iCompCount)
1788
+ {
1789
+ for (CPI_COMPONENT* pComp = pItm->pComponents; pComp; pComp = pComp->pNext)
1790
+ {
1791
+ hr = AddComponentToActionData(pComp, fInstall, atCreate == iActionType, FALSE, ppwzActionData);
1792
+ ExitOnFailure(hr, "Failed to add component to custom action data, component: %S", pComp->wzKey);
1793
+ }
1794
+ }
1795
+
1796
+ hr = S_OK;
1797
+
1798
+LExit:
1799
+ return hr;
1800
+}
1801
+
1802
+static HRESULT AddRoleAssignmentsToActionData(
1803
+ CPI_ASSEMBLY* pItm,
1804
+ BOOL fInstall,
1805
+ int iActionType,
1806
+ int iActionCost,
1807
+ LPWSTR* ppwzActionData
1808
+ )
1809
+{
1810
+ HRESULT hr = S_OK;
1811
+
1812
+ // add action information to custom action data
1813
+ hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
1814
+ ExitOnFailure(hr, "Failed to add action type to custom action data");
1815
+ hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
1816
+ ExitOnFailure(hr, "Failed to add action cost to custom action data");
1817
+
1818
+ // add assembly information to custom action data
1819
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
1820
+ ExitOnFailure(hr, "Failed to add assembly key to custom action data");
1821
+ hr = WcaWriteIntegerToCaData(fInstall ? pItm->iRoleAssignmentsInstallCount : pItm->iRoleAssignmentsUninstallCount, ppwzActionData);
1822
+ ExitOnFailure(hr, "Failed to add role assignments count to custom action data");
1823
+
1824
+ // add application information to custom action data
1825
+ hr = WcaWriteStringToCaData(pItm->pApplication ? pItm->pApplication->wzID : L"", ppwzActionData);
1826
+ ExitOnFailure(hr, "Failed to add application id to custom action data");
1827
+
1828
+ // add partition information to custom action data
1829
+ LPCWSTR pwzPartID = pItm->pApplication && pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L"";
1830
+ hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData);
1831
+ ExitOnFailure(hr, "Failed to add partition id to custom action data");
1832
+
1833
+ // add components to custom action data
1834
+ hr = WcaWriteIntegerToCaData(pItm->iComponentCount, ppwzActionData);
1835
+ ExitOnFailure(hr, "Failed to add component count to custom action data");
1836
+
1837
+ for (CPI_COMPONENT* pComp = pItm->pComponents; pComp; pComp = pComp->pNext)
1838
+ {
1839
+ hr = AddComponentToActionData(pComp, fInstall, FALSE, TRUE, ppwzActionData);
1840
+ ExitOnFailure(hr, "Failed to add component to custom action data, component: %S", pComp->wzKey);
1841
+ }
1842
+
1843
+ hr = S_OK;
1844
+
1845
+LExit:
1846
+ return hr;
1847
+}
1848
+
1849
+static HRESULT AddComponentToActionData(
1850
+ CPI_COMPONENT* pItm,
1851
+ BOOL fInstall,
1852
+ BOOL fProps,
1853
+ BOOL fRoles,
1854
+ LPWSTR* ppwzActionData
1855
+ )
1856
+{
1857
+ HRESULT hr = S_OK;
1858
+
1859
+ // add component information to custom action data
1860
+ hr = WcaWriteStringToCaData(pItm->wzCLSID, ppwzActionData);
1861
+ ExitOnFailure(hr, "Failed to add component CLSID to custom action data");
1862
+
1863
+ // add properties to custom action data
1864
+ hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData);
1865
+ ExitOnFailure(hr, "Failed to add properties to custom action data");
1866
+
1867
+ // add roles to custom action data
1868
+ hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData);
1869
+ ExitOnFailure(hr, "Failed to add roles to custom action data");
1870
+
1871
+ // add interfaces to custom action data
1872
+ int iIntfCount = (fProps || fRoles) ? pItm->iInterfaceCount : 0;
1873
+ hr = WcaWriteIntegerToCaData(iIntfCount, ppwzActionData);
1874
+ ExitOnFailure(hr, "Failed to add interface count to custom action data");
1875
+
1876
+ if (iIntfCount)
1877
+ {
1878
+ for (CPI_INTERFACE* pIntf = pItm->pInterfaces; pIntf; pIntf = pIntf->pNext)
1879
+ {
1880
+ hr = AddInterfaceToActionData(pIntf, fInstall, fProps, fRoles, ppwzActionData);
1881
+ ExitOnFailure(hr, "Failed to add interface custom action data, interface: %S", pIntf->wzKey);
1882
+ }
1883
+ }
1884
+
1885
+ hr = S_OK;
1886
+
1887
+LExit:
1888
+ return hr;
1889
+}
1890
+
1891
+static HRESULT AddInterfaceToActionData(
1892
+ CPI_INTERFACE* pItm,
1893
+ BOOL fInstall,
1894
+ BOOL fProps,
1895
+ BOOL fRoles,
1896
+ LPWSTR* ppwzActionData
1897
+ )
1898
+{
1899
+ HRESULT hr = S_OK;
1900
+
1901
+ // add interface information to custom action data
1902
+ hr = WcaWriteStringToCaData(pItm->wzIID, ppwzActionData);
1903
+ ExitOnFailure(hr, "Failed to add interface IID to custom action data");
1904
+
1905
+ // add properties to custom action data
1906
+ hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData);
1907
+ ExitOnFailure(hr, "Failed to add properties to custom action data");
1908
+
1909
+ // add roles to custom action data
1910
+ hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData);
1911
+ ExitOnFailure(hr, "Failed to add roles to custom action data");
1912
+
1913
+ // add methods to custom action data
1914
+ hr = WcaWriteIntegerToCaData(pItm->iMethodCount, ppwzActionData);
1915
+ ExitOnFailure(hr, "Failed to add method count to custom action data");
1916
+
1917
+ for (CPI_METHOD* pMeth = pItm->pMethods; pMeth; pMeth = pMeth->pNext)
1918
+ {
1919
+ hr = AddMethodToActionData(pMeth, fInstall, fProps, fRoles, ppwzActionData);
1920
+ ExitOnFailure(hr, "Failed to add method custom action data, method: %S", pMeth->wzKey);
1921
+ }
1922
+
1923
+ hr = S_OK;
1924
+
1925
+LExit:
1926
+ return hr;
1927
+}
1928
+
1929
+static HRESULT AddMethodToActionData(
1930
+ CPI_METHOD* pItm,
1931
+ BOOL fInstall,
1932
+ BOOL fProps,
1933
+ BOOL fRoles,
1934
+ LPWSTR* ppwzActionData
1935
+ )
1936
+{
1937
+ HRESULT hr = S_OK;
1938
+
1939
+ // add interface information to custom action data
1940
+ hr = WcaWriteStringToCaData(pItm->wzIndex, ppwzActionData);
1941
+ ExitOnFailure(hr, "Failed to add method index to custom action data");
1942
+
1943
+ hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData);
1944
+ ExitOnFailure(hr, "Failed to add method name to custom action data");
1945
+
1946
+ // add properties to custom action data
1947
+ hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData);
1948
+ ExitOnFailure(hr, "Failed to add properties to custom action data");
1949
+
1950
+ // add roles to custom action data
1951
+ hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData);
1952
+ ExitOnFailure(hr, "Failed to add roles to custom action data");
1953
+
1954
+ hr = S_OK;
1955
+
1956
+LExit:
1957
+ return hr;
1958
+}
1959
+
1960
+static HRESULT AddRolesToActionData(
1961
+ int iRoleInstallCount,
1962
+ int iRoleUninstallCount,
1963
+ CPI_ROLE_ASSIGNMENT* pRoleList,
1964
+ BOOL fInstall,
1965
+ BOOL fRoles,
1966
+ LPWSTR* ppwzActionData
1967
+ )
1968
+{
1969
+ HRESULT hr = S_OK;
1970
+
1971
+ int iRoleCount = fRoles ? (fInstall ? iRoleInstallCount : iRoleUninstallCount) : 0;
1972
+ hr = WcaWriteIntegerToCaData(iRoleCount, ppwzActionData);
1973
+ ExitOnFailure(hr, "Failed to add role count to custom action data");
1974
+
1975
+ if (iRoleCount)
1976
+ {
1977
+ for (CPI_ROLE_ASSIGNMENT* pRole = pRoleList; pRole; pRole = pRole->pNext)
1978
+ {
1979
+ // make sure the install state matches the create flag
1980
+ if (fInstall ? !WcaIsInstalling(pRole->isInstalled, pRole->isAction) : !WcaIsUninstalling(pRole->isInstalled, pRole->isAction))
1981
+ continue;
1982
+
1983
+ hr = WcaWriteStringToCaData(pRole->pApplicationRole->wzKey, ppwzActionData);
1984
+ ExitOnFailure(hr, "Failed to add key to custom action data, role: %S", pRole->wzKey);
1985
+
1986
+ hr = WcaWriteStringToCaData(pRole->pApplicationRole->wzName, ppwzActionData);
1987
+ ExitOnFailure(hr, "Failed to add role name to custom action data, role: %S", pRole->wzKey);
1988
+ }
1989
+ }
1990
+
1991
+ hr = S_OK;
1992
+
1993
+LExit:
1994
+ return hr;
1995
+}
1996
+
1997
+static HRESULT KeyPairFindByFirstKey(
1998
+ CPI_KEY_PAIR* pList,
1999
+ LPCWSTR pwzKey,
2000
+ CPI_KEY_PAIR** ppItm
2001
+ )
2002
+{
2003
+ for (; pList; pList = pList->pNext)
2004
+ {
2005
+ if (0 == lstrcmpW(pList->wzFirstKey, pwzKey))
2006
+ {
2007
+ *ppItm = pList;
2008
+ return S_OK;
2009
+ }
2010
+ }
2011
+
2012
+ return S_FALSE;
2013
+}
2014
+
2015
+static void AssemblyFree(
2016
+ CPI_ASSEMBLY* pItm
2017
+ )
2018
+{
2019
+ ReleaseStr(pItm->pwzAssemblyName);
2020
+ ReleaseStr(pItm->pwzDllPath);
2021
+ ReleaseStr(pItm->pwzTlbPath);
2022
+ ReleaseStr(pItm->pwzPSDllPath);
2023
+
2024
+ if (pItm->pComponents)
2025
+ ComponentsFreeList(pItm->pComponents);
2026
+
2027
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
2028
+}
2029
+
2030
+static void KeyPairsFreeList(
2031
+ CPI_KEY_PAIR* pList
2032
+ )
2033
+{
2034
+ while (pList)
2035
+ {
2036
+ CPI_KEY_PAIR* pDelete = pList;
2037
+ pList = pList->pNext;
2038
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
2039
+ }
2040
+}
2041
+
2042
+void ModuleListFree(
2043
+ CPI_MODULE_LIST* pList
2044
+ )
2045
+{
2046
+ CPI_MODULE* pItm = pList->pFirst;
2047
+
2048
+ while (pItm)
2049
+ {
2050
+ CPI_MODULE* pDelete = pItm;
2051
+ pItm = pItm->pNext;
2052
+ ModuleFree(pDelete);
2053
+ }
2054
+}
2055
+
2056
+static void ModuleFree(
2057
+ CPI_MODULE* pItm
2058
+ )
2059
+{
2060
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
2061
+}
2062
+
2063
+static void ComponentsFreeList(
2064
+ CPI_COMPONENT* pList
2065
+ )
2066
+{
2067
+ while (pList)
2068
+ {
2069
+ if (pList->pProperties)
2070
+ CpiPropertiesFreeList(pList->pProperties);
2071
+
2072
+ if (pList->pRoles)
2073
+ RoleAssignmentsFreeList(pList->pRoles);
2074
+
2075
+ if (pList->pInterfaces)
2076
+ InterfacesFreeList(pList->pInterfaces);
2077
+
2078
+ ReleaseObject(pList->piSubsColl);
2079
+
2080
+ CPI_COMPONENT* pDelete = pList;
2081
+ pList = pList->pNext;
2082
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
2083
+ }
2084
+}
2085
+
2086
+static void InterfacesFreeList(
2087
+ CPI_INTERFACE* pList
2088
+ )
2089
+{
2090
+ while (pList)
2091
+ {
2092
+ if (pList->pProperties)
2093
+ CpiPropertiesFreeList(pList->pProperties);
2094
+
2095
+ if (pList->pRoles)
2096
+ RoleAssignmentsFreeList(pList->pRoles);
2097
+
2098
+ if (pList->pMethods)
2099
+ MethodsFreeList(pList->pMethods);
2100
+
2101
+ CPI_INTERFACE* pDelete = pList;
2102
+ pList = pList->pNext;
2103
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
2104
+ }
2105
+}
2106
+
2107
+static void MethodsFreeList(
2108
+ CPI_METHOD* pList
2109
+ )
2110
+{
2111
+ while (pList)
2112
+ {
2113
+ if (pList->pProperties)
2114
+ CpiPropertiesFreeList(pList->pProperties);
2115
+
2116
+ if (pList->pRoles)
2117
+ RoleAssignmentsFreeList(pList->pRoles);
2118
+
2119
+ CPI_METHOD* pDelete = pList;
2120
+ pList = pList->pNext;
2121
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
2122
+ }
2123
+}
2124
+
2125
+static void RoleAssignmentsFreeList(
2126
+ CPI_ROLE_ASSIGNMENT* pList
2127
+ )
2128
+{
2129
+ while (pList)
2130
+ {
2131
+ CPI_ROLE_ASSIGNMENT* pDelete = pList;
2132
+ pList = pList->pNext;
2133
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
2134
+ }
2135
+}
src/ca/cpasmsched.h
new
+168
@@ -0,0 +1,168 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+enum eAssemblyAttributes
6
+{
7
+ aaEventClass = (1 << 0),
8
+ aaDotNetAssembly = (1 << 1),
9
+ aaPathFromGAC = (1 << 2),
10
+ aaRunInCommit = (1 << 3)
11
+};
12
+
13
+
14
+// structs
15
+
16
+struct CPI_ROLE_ASSIGNMENT
17
+{
18
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
19
+
20
+ INSTALLSTATE isInstalled, isAction;
21
+
22
+ CPI_APPLICATION_ROLE* pApplicationRole;
23
+
24
+ CPI_ROLE_ASSIGNMENT* pNext;
25
+};
26
+
27
+struct CPI_METHOD
28
+{
29
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
30
+ WCHAR wzIndex[11 + 1];
31
+ WCHAR wzName[MAX_DARWIN_COLUMN + 1];
32
+
33
+ int iPropertyCount;
34
+ CPI_PROPERTY* pProperties;
35
+
36
+ int iRoleInstallCount;
37
+ int iRoleUninstallCount;
38
+ CPI_ROLE_ASSIGNMENT* pRoles;
39
+
40
+ CPI_METHOD* pNext;
41
+};
42
+
43
+struct CPI_INTERFACE
44
+{
45
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
46
+ WCHAR wzIID[CPI_MAX_GUID + 1];
47
+
48
+ int iPropertyCount;
49
+ CPI_PROPERTY* pProperties;
50
+
51
+ int iRoleInstallCount;
52
+ int iRoleUninstallCount;
53
+ CPI_ROLE_ASSIGNMENT* pRoles;
54
+
55
+ int iMethodCount;
56
+ CPI_METHOD* pMethods;
57
+
58
+ CPI_INTERFACE* pNext;
59
+};
60
+
61
+struct CPI_COMPONENT
62
+{
63
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
64
+ WCHAR wzCLSID[CPI_MAX_GUID + 1];
65
+
66
+ int iPropertyCount;
67
+ CPI_PROPERTY* pProperties;
68
+
69
+ int iRoleInstallCount;
70
+ int iRoleUninstallCount;
71
+ CPI_ROLE_ASSIGNMENT* pRoles;
72
+
73
+ int iInterfaceCount;
74
+ CPI_INTERFACE* pInterfaces;
75
+
76
+ ICatalogCollection* piSubsColl;
77
+
78
+ CPI_COMPONENT* pNext;
79
+};
80
+
81
+struct CPI_ASSEMBLY
82
+{
83
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
84
+ WCHAR wzModule[MAX_DARWIN_KEY + 1];
85
+ LPWSTR pwzAssemblyName;
86
+ LPWSTR pwzDllPath;
87
+ LPWSTR pwzTlbPath;
88
+ LPWSTR pwzPSDllPath;
89
+ int iAttributes;
90
+
91
+ int iComponentCount;
92
+ CPI_COMPONENT* pComponents;
93
+
94
+ BOOL fReferencedForInstall;
95
+ BOOL fReferencedForUninstall;
96
+ BOOL fIgnore;
97
+
98
+ int iRoleAssignmentsInstallCount;
99
+ int iRoleAssignmentsUninstallCount;
100
+
101
+ INSTALLSTATE isInstalled, isAction;
102
+
103
+ CPI_APPLICATION* pApplication;
104
+
105
+ CPI_ASSEMBLY* pPrev;
106
+ CPI_ASSEMBLY* pNext;
107
+};
108
+
109
+struct CPI_ASSEMBLY_LIST
110
+{
111
+ CPI_ASSEMBLY* pFirst;
112
+ CPI_ASSEMBLY* pLast;
113
+
114
+ int iInstallCount;
115
+ int iCommitCount;
116
+ int iUninstallCount;
117
+
118
+ int iRoleInstallCount;
119
+ int iRoleCommitCount;
120
+ int iRoleUninstallCount;
121
+};
122
+
123
+
124
+// function prototypes
125
+
126
+void CpiAssemblyListFree(
127
+ CPI_ASSEMBLY_LIST* pList
128
+ );
129
+HRESULT CpiAssembliesRead(
130
+ CPI_APPLICATION_LIST* pAppList,
131
+ CPI_APPLICATION_ROLE_LIST* pAppRoleList,
132
+ CPI_ASSEMBLY_LIST* pAsmList
133
+ );
134
+HRESULT CpiAssembliesVerifyInstall(
135
+ CPI_ASSEMBLY_LIST* pList
136
+ );
137
+HRESULT CpiAssembliesVerifyUninstall(
138
+ CPI_ASSEMBLY_LIST* pList
139
+ );
140
+HRESULT CpiAssembliesInstall(
141
+ CPI_ASSEMBLY_LIST* pList,
142
+ int iRunMode,
143
+ LPWSTR* ppwzActionData,
144
+ int* piProgress
145
+ );
146
+HRESULT CpiAssembliesUninstall(
147
+ CPI_ASSEMBLY_LIST* pList,
148
+ int iRunMode,
149
+ LPWSTR* ppwzActionData,
150
+ int* piProgress
151
+ );
152
+HRESULT CpiRoleAssignmentsInstall(
153
+ CPI_ASSEMBLY_LIST* pList,
154
+ int iRunMode,
155
+ LPWSTR* ppwzActionData,
156
+ int* piProgress
157
+ );
158
+HRESULT CpiRoleAssignmentsUninstall(
159
+ CPI_ASSEMBLY_LIST* pList,
160
+ int iRunMode,
161
+ LPWSTR* ppwzActionData,
162
+ int* piProgress
163
+ );
164
+HRESULT CpiGetSubscriptionsCollForComponent(
165
+ CPI_ASSEMBLY* pAsm,
166
+ CPI_COMPONENT* pComp,
167
+ ICatalogCollection** ppiSubsColl
168
+ );
src/ca/cpcost.h
new
+30
@@ -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
src/ca/cpexec.cpp
new
+704
@@ -0,0 +1,704 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+/********************************************************************
6
+ DllMain - standard entry point for all WiX CustomActions
7
+
8
+********************************************************************/
9
+extern "C" BOOL WINAPI DllMain(
10
+ IN HINSTANCE hInst,
11
+ IN ULONG ulReason,
12
+ IN LPVOID)
13
+{
14
+ switch(ulReason)
15
+ {
16
+ case DLL_PROCESS_ATTACH:
17
+ WcaGlobalInitialize(hInst);
18
+ break;
19
+
20
+ case DLL_PROCESS_DETACH:
21
+ WcaGlobalFinalize();
22
+ break;
23
+ }
24
+
25
+ return TRUE;
26
+}
27
+
28
+/********************************************************************
29
+ ComPlusPrepare - CUSTOM ACTION ENTRY POINT
30
+
31
+ Input: deferred CustomActionData - ComPlusPrepare
32
+********************************************************************/
33
+extern "C" UINT __stdcall ComPlusPrepare(MSIHANDLE hInstall)
34
+{
35
+ HRESULT hr = S_OK;
36
+ UINT er = ERROR_SUCCESS;
37
+
38
+ LPWSTR pwzCustomActionData = NULL;
39
+ LPWSTR pwzData = NULL;
40
+
41
+ HANDLE hRollbackFile = INVALID_HANDLE_VALUE;
42
+
43
+ // initialize
44
+ hr = WcaInitialize(hInstall, "ComPlusPrepare");
45
+ ExitOnFailure(hr, "Failed to initialize ComPlusPrepare");
46
+
47
+ // get custom action data
48
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
49
+ ExitOnFailure(hr, "Failed to get CustomActionData");
50
+ pwzData = pwzCustomActionData;
51
+
52
+ // create rollback file
53
+ hRollbackFile = ::CreateFileW(pwzData, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, NULL);
54
+ if (INVALID_HANDLE_VALUE == hRollbackFile)
55
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to create rollback file, name: %S", pwzData);
56
+
57
+ hr = S_OK;
58
+
59
+LExit:
60
+ // clean up
61
+ ReleaseStr(pwzCustomActionData);
62
+
63
+ if (INVALID_HANDLE_VALUE != hRollbackFile)
64
+ ::CloseHandle(hRollbackFile);
65
+
66
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
67
+ return WcaFinalize(er);
68
+}
69
+
70
+/********************************************************************
71
+ ComPlusCleanup - CUSTOM ACTION ENTRY POINT
72
+
73
+ Input: deferred CustomActionData - ComPlusCleanup
74
+********************************************************************/
75
+extern "C" UINT __stdcall ComPlusCleanup(MSIHANDLE hInstall)
76
+{
77
+ HRESULT hr = S_OK;
78
+ UINT er = ERROR_SUCCESS;
79
+
80
+ LPWSTR pwzCustomActionData = NULL;
81
+ LPWSTR pwzData = NULL;
82
+
83
+ // initialize
84
+ hr = WcaInitialize(hInstall, "ComPlusCleanup");
85
+ ExitOnFailure(hr, "Failed to initialize ComPlusCleanup");
86
+
87
+ // get custom action data
88
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
89
+ ExitOnFailure(hr, "Failed to get CustomActionData");
90
+ pwzData = pwzCustomActionData;
91
+
92
+ // delete rollback file
93
+ if (!::DeleteFileW(pwzData))
94
+ {
95
+ // error, but not a showstopper
96
+ hr = HRESULT_FROM_WIN32(::GetLastError());
97
+ WcaLog(LOGMSG_STANDARD, "Failed to delete rollback file, hr: 0x%x, name: %S", hr, pwzData);
98
+ }
99
+
100
+ hr = S_OK;
101
+
102
+LExit:
103
+ // clean up
104
+ ReleaseStr(pwzCustomActionData);
105
+
106
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
107
+ return WcaFinalize(er);
108
+}
109
+
110
+/********************************************************************
111
+ ComPlusInstallExecute - CUSTOM ACTION ENTRY POINT
112
+
113
+ Input: deferred CustomActionData - ComPlusInstallExecute
114
+********************************************************************/
115
+extern "C" UINT __stdcall ComPlusInstallExecute(MSIHANDLE hInstall)
116
+{
117
+ HRESULT hr = S_OK;
118
+ UINT er = ERROR_SUCCESS;
119
+
120
+ LPWSTR pwzCustomActionData = NULL;
121
+ LPWSTR pwzData = NULL;
122
+ LPWSTR pwzRollbackFileName = NULL;
123
+
124
+ HANDLE hRollbackFile = INVALID_HANDLE_VALUE;
125
+
126
+ BOOL fInitializedCom = FALSE;
127
+
128
+ // initialize
129
+ hr = WcaInitialize(hInstall, "ComPlusInstallExecute");
130
+ ExitOnFailure(hr, "Failed to initialize ComPlusInstallExecute");
131
+
132
+ hr = ::CoInitialize(NULL);
133
+ ExitOnFailure(hr, "Failed to initialize COM");
134
+ fInitializedCom = TRUE;
135
+
136
+ CpiInitialize();
137
+
138
+ // get custom action data
139
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
140
+ ExitOnFailure(hr, "Failed to get CustomActionData");
141
+ pwzData = pwzCustomActionData;
142
+
143
+ // open rollback file
144
+ hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName);
145
+ ExitOnFailure(hr, "Failed to read rollback file name");
146
+
147
+ hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
148
+ if (INVALID_HANDLE_VALUE == hRollbackFile)
149
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName);
150
+
151
+ // create partitions
152
+ hr = CpiConfigurePartitions(&pwzData, hRollbackFile);
153
+ ExitOnFailure(hr, "Failed to create partitions");
154
+ if (S_FALSE == hr) ExitFunction();
155
+
156
+ // create users in partition roles
157
+ hr = CpiConfigureUsersInPartitionRoles(&pwzData, hRollbackFile);
158
+ ExitOnFailure(hr, "Failed to create users in partition roles");
159
+ if (S_FALSE == hr) ExitFunction();
160
+
161
+ // create partition users
162
+ hr = CpiConfigurePartitionUsers(&pwzData, hRollbackFile);
163
+ ExitOnFailure(hr, "Failed to add partition users");
164
+ if (S_FALSE == hr) ExitFunction();
165
+
166
+ // create applications
167
+ hr = CpiConfigureApplications(&pwzData, hRollbackFile);
168
+ ExitOnFailure(hr, "Failed to create applications");
169
+ if (S_FALSE == hr) ExitFunction();
170
+
171
+ // create application roles
172
+ hr = CpiConfigureApplicationRoles(&pwzData, hRollbackFile);
173
+ ExitOnFailure(hr, "Failed to create application roles");
174
+ if (S_FALSE == hr) ExitFunction();
175
+
176
+ // create users in application roles
177
+ hr = CpiConfigureUsersInApplicationRoles(&pwzData, hRollbackFile);
178
+ ExitOnFailure(hr, "Failed to create users in application roles");
179
+ if (S_FALSE == hr) ExitFunction();
180
+
181
+ // register assemblies
182
+ hr = CpiConfigureAssemblies(&pwzData, hRollbackFile);
183
+ ExitOnFailure(hr, "Failed to register assemblies");
184
+ if (S_FALSE == hr) ExitFunction();
185
+
186
+ // create role assignments
187
+ hr = CpiConfigureRoleAssignments(&pwzData, hRollbackFile);
188
+ ExitOnFailure(hr, "Failed to create role assignments");
189
+ if (S_FALSE == hr) ExitFunction();
190
+
191
+ // create subscriptions
192
+ hr = CpiConfigureSubscriptions(&pwzData, hRollbackFile);
193
+ ExitOnFailure(hr, "Failed to create subscriptions");
194
+ if (S_FALSE == hr) ExitFunction();
195
+
196
+ hr = S_OK;
197
+
198
+LExit:
199
+ // clean up
200
+ ReleaseStr(pwzCustomActionData);
201
+ ReleaseStr(pwzRollbackFileName);
202
+
203
+ if (INVALID_HANDLE_VALUE != hRollbackFile)
204
+ ::CloseHandle(hRollbackFile);
205
+
206
+ // unitialize
207
+ CpiFinalize();
208
+
209
+ if (fInitializedCom)
210
+ ::CoUninitialize();
211
+
212
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
213
+ return WcaFinalize(er);
214
+}
215
+
216
+/********************************************************************
217
+ ComPlusInstallExecuteCommit - CUSTOM ACTION ENTRY POINT
218
+
219
+ Input: deferred CustomActionData - ComPlusInstallExecuteCommit
220
+********************************************************************/
221
+extern "C" UINT __stdcall ComPlusInstallExecuteCommit(MSIHANDLE hInstall)
222
+{
223
+ HRESULT hr = S_OK;
224
+ UINT er = ERROR_SUCCESS;
225
+
226
+ LPWSTR pwzCustomActionData = NULL;
227
+ LPWSTR pwzData = NULL;
228
+ LPWSTR pwzRollbackFileName = NULL;
229
+
230
+ HANDLE hRollbackFile = INVALID_HANDLE_VALUE;
231
+
232
+ BOOL fInitializedCom = FALSE;
233
+
234
+ // initialize
235
+ hr = WcaInitialize(hInstall, "ComPlusInstallExecuteCommit");
236
+ ExitOnFailure(hr, "Failed to initialize ComPlusInstallExecuteCommit");
237
+
238
+ hr = ::CoInitialize(NULL);
239
+ ExitOnFailure(hr, "Failed to initialize COM");
240
+ fInitializedCom = TRUE;
241
+
242
+ CpiInitialize();
243
+
244
+ // get custom action data
245
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
246
+ ExitOnFailure(hr, "Failed to get CustomActionData");
247
+ pwzData = pwzCustomActionData;
248
+
249
+ // open rollback file
250
+ hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName);
251
+ ExitOnFailure(hr, "Failed to read rollback file name");
252
+
253
+ hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
254
+ if (INVALID_HANDLE_VALUE == hRollbackFile)
255
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName);
256
+
257
+ if (INVALID_SET_FILE_POINTER == ::SetFilePointer(hRollbackFile, 0, NULL, FILE_END))
258
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to set file pointer");
259
+
260
+ // register assemblies
261
+ hr = CpiConfigureAssemblies(&pwzData, hRollbackFile);
262
+ ExitOnFailure(hr, "Failed to register assemblies");
263
+ if (S_FALSE == hr) ExitFunction();
264
+
265
+ // create role assignments
266
+ hr = CpiConfigureRoleAssignments(&pwzData, hRollbackFile);
267
+ ExitOnFailure(hr, "Failed to create role assignments");
268
+ if (S_FALSE == hr) ExitFunction();
269
+
270
+ // create subscriptions
271
+ hr = CpiConfigureSubscriptions(&pwzData, hRollbackFile);
272
+ ExitOnFailure(hr, "Failed to create subscriptions");
273
+ if (S_FALSE == hr) ExitFunction();
274
+
275
+ hr = S_OK;
276
+
277
+LExit:
278
+ // clean up
279
+ ReleaseStr(pwzCustomActionData);
280
+
281
+ if (INVALID_HANDLE_VALUE != hRollbackFile)
282
+ ::CloseHandle(hRollbackFile);
283
+
284
+ // unitialize
285
+ CpiFinalize();
286
+
287
+ if (fInitializedCom)
288
+ ::CoUninitialize();
289
+
290
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
291
+ return WcaFinalize(er);
292
+}
293
+
294
+/********************************************************************
295
+ ComPlusRollbackInstallExecute - CUSTOM ACTION ENTRY POINT
296
+
297
+ Input: deferred CustomActionData - ComPlusRollbackInstallExecute
298
+********************************************************************/
299
+extern "C" UINT __stdcall ComPlusRollbackInstallExecute(MSIHANDLE hInstall)
300
+{
301
+ HRESULT hr = S_OK;
302
+ UINT er = ERROR_SUCCESS;
303
+
304
+ LPWSTR pwzCustomActionData = NULL;
305
+ LPWSTR pwzData = NULL;
306
+ LPWSTR pwzRollbackFileName = NULL;
307
+
308
+ HANDLE hRollbackFile = INVALID_HANDLE_VALUE;
309
+
310
+ CPI_ROLLBACK_DATA* prdPartitions = NULL;
311
+ CPI_ROLLBACK_DATA* prdUsersInPartitionRoles = NULL;
312
+ CPI_ROLLBACK_DATA* prdPartitionUsers = NULL;
313
+ CPI_ROLLBACK_DATA* prdApplications = NULL;
314
+ CPI_ROLLBACK_DATA* prdApplicationRoles = NULL;
315
+ CPI_ROLLBACK_DATA* prdUsersApplicationRoles = NULL;
316
+ CPI_ROLLBACK_DATA* prdAssemblies = NULL;
317
+ CPI_ROLLBACK_DATA* prdRoleAssignments = NULL;
318
+ CPI_ROLLBACK_DATA* prdSubscriptions = NULL;
319
+
320
+ BOOL fInitializedCom = FALSE;
321
+
322
+ // initialize
323
+ hr = WcaInitialize(hInstall, "ComPlusRollbackInstallExecute");
324
+ ExitOnFailure(hr, "Failed to initialize ComPlusRollbackInstallExecute");
325
+
326
+ hr = ::CoInitialize(NULL);
327
+ ExitOnFailure(hr, "Failed to initialize COM");
328
+ fInitializedCom = TRUE;
329
+
330
+ CpiInitialize();
331
+
332
+ // get custom action data
333
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
334
+ ExitOnFailure(hr, "Failed to get CustomActionData");
335
+ pwzData = pwzCustomActionData;
336
+
337
+ // open rollback file
338
+ hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName);
339
+ ExitOnFailure(hr, "Failed to read rollback file name");
340
+
341
+ hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
342
+ if (INVALID_HANDLE_VALUE == hRollbackFile)
343
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName);
344
+
345
+ // read rollback data (execute)
346
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitions);
347
+ ExitOnFailure(hr, "Failed to read partitions rollback data");
348
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersInPartitionRoles);
349
+ ExitOnFailure(hr, "Failed to read users in partition roles rollback data");
350
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitionUsers);
351
+ ExitOnFailure(hr, "Failed to read partition users rollback data");
352
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdApplications);
353
+ ExitOnFailure(hr, "Failed to read applications rollback data");
354
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdApplicationRoles);
355
+ ExitOnFailure(hr, "Failed to read application roles rollback data");
356
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersApplicationRoles);
357
+ ExitOnFailure(hr, "Failed to read users in application roles rollback data");
358
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdAssemblies);
359
+ ExitOnFailure(hr, "Failed to read assemblies rollback data");
360
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdRoleAssignments);
361
+ ExitOnFailure(hr, "Failed to read role assignments rollback data");
362
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdSubscriptions);
363
+ ExitOnFailure(hr, "Failed to read subscription rollback data");
364
+
365
+ // read rollback data (commit)
366
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdAssemblies);
367
+ ExitOnFailure(hr, "Failed to read assemblies rollback data (commit)");
368
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdRoleAssignments);
369
+ ExitOnFailure(hr, "Failed to read role assignments rollback data");
370
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdSubscriptions);
371
+ ExitOnFailure(hr, "Failed to read subscription rollback data (commit)");
372
+
373
+ ::CloseHandle(hRollbackFile);
374
+ hRollbackFile = INVALID_HANDLE_VALUE;
375
+
376
+ // rollback create subscriptions
377
+ hr = CpiRollbackConfigureSubscriptions(&pwzData, prdSubscriptions);
378
+ ExitOnFailure(hr, "Failed to rollback create subscriptions");
379
+
380
+ // rollback create role assignments
381
+ hr = CpiRollbackConfigureRoleAssignments(&pwzData, prdRoleAssignments);
382
+ ExitOnFailure(hr, "Failed to rollback create role assignments");
383
+
384
+ // rollback register assemblies
385
+ hr = CpiRollbackConfigureAssemblies(&pwzData, prdAssemblies);
386
+ ExitOnFailure(hr, "Failed to rollback register assemblies");
387
+
388
+ // rollback create users in application roles
389
+ hr = CpiRollbackConfigureUsersInApplicationRoles(&pwzData, prdUsersApplicationRoles);
390
+ ExitOnFailure(hr, "Failed to rollback create users in application roles");
391
+
392
+ // rollback create application roles
393
+ hr = CpiRollbackConfigureApplicationRoles(&pwzData, prdApplicationRoles);
394
+ ExitOnFailure(hr, "Failed to rollback create application roles");
395
+
396
+ // rollback create applications
397
+ hr = CpiRollbackConfigureApplications(&pwzData, prdApplications);
398
+ ExitOnFailure(hr, "Failed to rollback create applications");
399
+
400
+ // rollback create partition users
401
+ hr = CpiRollbackConfigurePartitionUsers(&pwzData, prdPartitionUsers);
402
+ ExitOnFailure(hr, "Failed to rollback create partition users");
403
+
404
+ // rollback create users in partition roles
405
+ hr = CpiRollbackConfigureUsersInPartitionRoles(&pwzData, prdUsersInPartitionRoles);
406
+ ExitOnFailure(hr, "Failed to rollback create users in partition roles");
407
+
408
+ // rollback create partitions
409
+ hr = CpiRollbackConfigurePartitions(&pwzData, prdPartitions);
410
+ ExitOnFailure(hr, "Failed to rollback create partitions");
411
+
412
+ hr = S_OK;
413
+
414
+LExit:
415
+ // clean up
416
+ ReleaseStr(pwzCustomActionData);
417
+ ReleaseStr(pwzRollbackFileName);
418
+
419
+ if (INVALID_HANDLE_VALUE != hRollbackFile)
420
+ ::CloseHandle(hRollbackFile);
421
+
422
+ if (prdPartitions)
423
+ CpiFreeRollbackDataList(prdPartitions);
424
+ if (prdUsersInPartitionRoles)
425
+ CpiFreeRollbackDataList(prdUsersInPartitionRoles);
426
+ if (prdPartitionUsers)
427
+ CpiFreeRollbackDataList(prdPartitionUsers);
428
+ if (prdApplications)
429
+ CpiFreeRollbackDataList(prdApplications);
430
+ if (prdApplicationRoles)
431
+ CpiFreeRollbackDataList(prdApplicationRoles);
432
+ if (prdUsersApplicationRoles)
433
+ CpiFreeRollbackDataList(prdUsersApplicationRoles);
434
+ if (prdAssemblies)
435
+ CpiFreeRollbackDataList(prdAssemblies);
436
+ if (prdRoleAssignments)
437
+ CpiFreeRollbackDataList(prdRoleAssignments);
438
+ if (prdSubscriptions)
439
+ CpiFreeRollbackDataList(prdSubscriptions);
440
+
441
+ // unitialize
442
+ CpiFinalize();
443
+
444
+ if (fInitializedCom)
445
+ ::CoUninitialize();
446
+
447
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
448
+ return WcaFinalize(er);
449
+}
450
+
451
+/********************************************************************
452
+ ComPlusUninstallExecute - CUSTOM ACTION ENTRY POINT
453
+
454
+ Input: deferred CustomActionData - ComPlusUninstallExecute
455
+********************************************************************/
456
+extern "C" UINT __stdcall ComPlusUninstallExecute(MSIHANDLE hInstall)
457
+{
458
+ HRESULT hr = S_OK;
459
+ UINT er = ERROR_SUCCESS;
460
+
461
+ LPWSTR pwzCustomActionData = NULL;
462
+ LPWSTR pwzData = NULL;
463
+ LPWSTR pwzRollbackFileName = NULL;
464
+
465
+ HANDLE hRollbackFile = INVALID_HANDLE_VALUE;
466
+
467
+ BOOL fInitializedCom = FALSE;
468
+
469
+ // initialize
470
+ hr = WcaInitialize(hInstall, "ComPlusUninstallExecute");
471
+ ExitOnFailure(hr, "Failed to initialize ComPlusUninstallExecute");
472
+
473
+ hr = ::CoInitialize(NULL);
474
+ ExitOnFailure(hr, "Failed to initialize COM");
475
+ fInitializedCom = TRUE;
476
+
477
+ CpiInitialize();
478
+
479
+ // get custom action data
480
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
481
+ ExitOnFailure(hr, "Failed to get CustomActionData");
482
+ pwzData = pwzCustomActionData;
483
+
484
+ // open rollback file
485
+ hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName);
486
+ ExitOnFailure(hr, "Failed to read rollback file name");
487
+
488
+ hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
489
+ if (INVALID_HANDLE_VALUE == hRollbackFile)
490
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName);
491
+
492
+ // delete subscriptions
493
+ hr = CpiConfigureSubscriptions(&pwzData, hRollbackFile);
494
+ ExitOnFailure(hr, "Failed to delete subscriptions");
495
+ if (S_FALSE == hr) ExitFunction();
496
+
497
+ // delete role assignments
498
+ hr = CpiConfigureRoleAssignments(&pwzData, hRollbackFile);
499
+ ExitOnFailure(hr, "Failed to delete role assignments");
500
+ if (S_FALSE == hr) ExitFunction();
501
+
502
+ // unregister assemblies
503
+ hr = CpiConfigureAssemblies(&pwzData, hRollbackFile);
504
+ ExitOnFailure(hr, "Failed to unregister assemblies");
505
+ if (S_FALSE == hr) ExitFunction();
506
+
507
+ // remove users in application roles
508
+ hr = CpiConfigureUsersInApplicationRoles(&pwzData, hRollbackFile);
509
+ ExitOnFailure(hr, "Failed to delete users in application roles");
510
+ if (S_FALSE == hr) ExitFunction();
511
+
512
+ // remove application roles
513
+ hr = CpiConfigureApplicationRoles(&pwzData, hRollbackFile);
514
+ ExitOnFailure(hr, "Failed to delete application roles");
515
+ if (S_FALSE == hr) ExitFunction();
516
+
517
+ // remove applications
518
+ hr = CpiConfigureApplications(&pwzData, hRollbackFile);
519
+ ExitOnFailure(hr, "Failed to remove applications");
520
+ if (S_FALSE == hr) ExitFunction();
521
+
522
+ // remove partition users
523
+ hr = CpiConfigurePartitionUsers(&pwzData, hRollbackFile);
524
+ ExitOnFailure(hr, "Failed to remove partition users");
525
+ if (S_FALSE == hr) ExitFunction();
526
+
527
+ // remove users in partition roles
528
+ hr = CpiConfigureUsersInPartitionRoles(&pwzData, hRollbackFile);
529
+ ExitOnFailure(hr, "Failed to delete users in partition roles");
530
+ if (S_FALSE == hr) ExitFunction();
531
+
532
+ // remove partitions
533
+ hr = CpiConfigurePartitions(&pwzData, hRollbackFile);
534
+ ExitOnFailure(hr, "Failed to delete partitions");
535
+ if (S_FALSE == hr) ExitFunction();
536
+
537
+ hr = S_OK;
538
+
539
+LExit:
540
+ // clean up
541
+ ReleaseStr(pwzCustomActionData);
542
+ ReleaseStr(pwzRollbackFileName);
543
+
544
+ if (INVALID_HANDLE_VALUE != hRollbackFile)
545
+ ::CloseHandle(hRollbackFile);
546
+
547
+ // unitialize
548
+ CpiFinalize();
549
+
550
+ if (fInitializedCom)
551
+ ::CoUninitialize();
552
+
553
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
554
+ return WcaFinalize(er);
555
+}
556
+
557
+/********************************************************************
558
+ ComPlusRollbackUninstallExecute - CUSTOM ACTION ENTRY POINT
559
+
560
+ Input: deferred CustomActionData - ComPlusRollbackUninstallExecute
561
+********************************************************************/
562
+extern "C" UINT __stdcall ComPlusRollbackUninstallExecute(MSIHANDLE hInstall)
563
+{
564
+ HRESULT hr = S_OK;
565
+ UINT er = ERROR_SUCCESS;
566
+
567
+ LPWSTR pwzCustomActionData = NULL;
568
+ LPWSTR pwzData = NULL;
569
+ LPWSTR pwzRollbackFileName = NULL;
570
+
571
+ HANDLE hRollbackFile = INVALID_HANDLE_VALUE;
572
+
573
+ CPI_ROLLBACK_DATA* prdPartitions = NULL;
574
+ CPI_ROLLBACK_DATA* prdUsersInPartitionRoles = NULL;
575
+ CPI_ROLLBACK_DATA* prdPartitionUsers = NULL;
576
+ CPI_ROLLBACK_DATA* prdApplications = NULL;
577
+ CPI_ROLLBACK_DATA* prdApplicationRoles = NULL;
578
+ CPI_ROLLBACK_DATA* prdUsersApplicationRoles = NULL;
579
+ CPI_ROLLBACK_DATA* prdAssemblies = NULL;
580
+ CPI_ROLLBACK_DATA* prdRoleAssignments = NULL;
581
+ CPI_ROLLBACK_DATA* prdSubscriptions = NULL;
582
+
583
+ BOOL fInitializedCom = FALSE;
584
+
585
+ // initialize
586
+ hr = WcaInitialize(hInstall, "ComPlusRollbackUninstallExecute");
587
+ ExitOnFailure(hr, "Failed to initialize ComPlusRollbackUninstallExecute");
588
+
589
+ hr = ::CoInitialize(NULL);
590
+ ExitOnFailure(hr, "Failed to initialize COM");
591
+ fInitializedCom = TRUE;
592
+
593
+ CpiInitialize();
594
+
595
+ // get custom action data
596
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
597
+ ExitOnFailure(hr, "Failed to get CustomActionData");
598
+ pwzData = pwzCustomActionData;
599
+
600
+ // open rollback file
601
+ hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName);
602
+ ExitOnFailure(hr, "Failed to read rollback file name");
603
+
604
+ hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
605
+ if (INVALID_HANDLE_VALUE == hRollbackFile)
606
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName);
607
+
608
+ // read rollback data
609
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdSubscriptions);
610
+ ExitOnFailure(hr, "Failed to read subscription rollback data");
611
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdRoleAssignments);
612
+ ExitOnFailure(hr, "Failed to read role assignments rollback data");
613
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdAssemblies);
614
+ ExitOnFailure(hr, "Failed to read assemblies rollback data");
615
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersApplicationRoles);
616
+ ExitOnFailure(hr, "Failed to read users in application roles rollback data");
617
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdApplicationRoles);
618
+ ExitOnFailure(hr, "Failed to read application roles rollback data");
619
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdApplications);
620
+ ExitOnFailure(hr, "Failed to read applications rollback data");
621
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitionUsers);
622
+ ExitOnFailure(hr, "Failed to read partition users rollback data");
623
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersInPartitionRoles);
624
+ ExitOnFailure(hr, "Failed to read users in partition roles rollback data");
625
+ hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitions);
626
+ ExitOnFailure(hr, "Failed to read partitions rollback data");
627
+
628
+ ::CloseHandle(hRollbackFile);
629
+ hRollbackFile = INVALID_HANDLE_VALUE;
630
+
631
+ // rollback remove partitions
632
+ hr = CpiRollbackConfigurePartitions(&pwzData, prdPartitions);
633
+ ExitOnFailure(hr, "Failed to rollback delete partitions");
634
+
635
+ // rollback remove users in partition roles
636
+ hr = CpiRollbackConfigureUsersInPartitionRoles(&pwzData, prdUsersInPartitionRoles);
637
+ ExitOnFailure(hr, "Failed to rollback delete users in partition roles");
638
+
639
+ // rollback remove partition users
640
+ hr = CpiRollbackConfigurePartitionUsers(&pwzData, prdPartitionUsers);
641
+ ExitOnFailure(hr, "Failed to rollback delete partition users");
642
+
643
+ // rollback remove applications
644
+ hr = CpiRollbackConfigureApplications(&pwzData, prdApplications);
645
+ ExitOnFailure(hr, "Failed to rollback delete applications");
646
+
647
+ // rollback remove application roles
648
+ hr = CpiRollbackConfigureApplicationRoles(&pwzData, prdApplicationRoles);
649
+ ExitOnFailure(hr, "Failed to rollback delete application roles");
650
+
651
+ // rollback remove users in application roles
652
+ hr = CpiRollbackConfigureUsersInApplicationRoles(&pwzData, prdUsersApplicationRoles);
653
+ ExitOnFailure(hr, "Failed to rollback delete users in application roles");
654
+
655
+ // rollback unregister assemblies
656
+ hr = CpiRollbackConfigureAssemblies(&pwzData, prdAssemblies);
657
+ ExitOnFailure(hr, "Failed to rollback unregister assemblies");
658
+
659
+ // rollback delete role assignments
660
+ hr = CpiRollbackConfigureRoleAssignments(&pwzData, prdAssemblies);
661
+ ExitOnFailure(hr, "Failed to rollback delete role assignments");
662
+
663
+ // rollback delete subscriptions
664
+ hr = CpiRollbackConfigureSubscriptions(&pwzData, prdSubscriptions);
665
+ ExitOnFailure(hr, "Failed to rollback delete subscriptions");
666
+
667
+ hr = S_OK;
668
+
669
+LExit:
670
+ // clean up
671
+ ReleaseStr(pwzCustomActionData);
672
+ ReleaseStr(pwzRollbackFileName);
673
+
674
+ if (INVALID_HANDLE_VALUE != hRollbackFile)
675
+ ::CloseHandle(hRollbackFile);
676
+
677
+ if (prdPartitions)
678
+ CpiFreeRollbackDataList(prdPartitions);
679
+ if (prdUsersInPartitionRoles)
680
+ CpiFreeRollbackDataList(prdUsersInPartitionRoles);
681
+ if (prdPartitionUsers)
682
+ CpiFreeRollbackDataList(prdPartitionUsers);
683
+ if (prdApplications)
684
+ CpiFreeRollbackDataList(prdApplications);
685
+ if (prdApplicationRoles)
686
+ CpiFreeRollbackDataList(prdApplicationRoles);
687
+ if (prdUsersApplicationRoles)
688
+ CpiFreeRollbackDataList(prdUsersApplicationRoles);
689
+ if (prdAssemblies)
690
+ CpiFreeRollbackDataList(prdAssemblies);
691
+ if (prdRoleAssignments)
692
+ CpiFreeRollbackDataList(prdRoleAssignments);
693
+ if (prdSubscriptions)
694
+ CpiFreeRollbackDataList(prdSubscriptions);
695
+
696
+ // unitialize
697
+ CpiFinalize();
698
+
699
+ if (fInitializedCom)
700
+ ::CoUninitialize();
701
+
702
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
703
+ return WcaFinalize(er);
704
+}
src/ca/cpexec.def
new
+11
@@ -0,0 +1,11 @@
1
+; Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+
4
+EXPORTS
5
+ ComPlusPrepare
6
+ ComPlusCleanup
7
+ ComPlusInstallExecute
8
+ ComPlusInstallExecuteCommit
9
+ ComPlusRollbackInstallExecute
10
+ ComPlusUninstallExecute
11
+ ComPlusRollbackUninstallExecute
src/ca/cppartexec.cpp
new
+690
@@ -0,0 +1,690 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// private structs
7
+
8
+struct CPI_PARTITION_ATTRIBUTES
9
+{
10
+ int iActionType;
11
+ int iActionCost;
12
+ LPWSTR pwzKey;
13
+ LPWSTR pwzID;
14
+ LPWSTR pwzName;
15
+ CPI_PROPERTY* pPropList;
16
+};
17
+
18
+struct CPI_PARTITION_USER_ATTRIBUTES
19
+{
20
+ int iActionType;
21
+ int iActionCost;
22
+ LPWSTR pwzKey;
23
+ LPWSTR pwzAccount;
24
+ LPWSTR pwzPartID;
25
+};
26
+
27
+
28
+// prototypes for private helper functions
29
+
30
+static HRESULT ReadPartitionAttributes(
31
+ LPWSTR* ppwzData,
32
+ CPI_PARTITION_ATTRIBUTES* pAttrs
33
+ );
34
+static void FreePartitionAttributes(
35
+ CPI_PARTITION_ATTRIBUTES* pAttrs
36
+ );
37
+static HRESULT CreatePartition(
38
+ CPI_PARTITION_ATTRIBUTES* pAttrs
39
+ );
40
+static HRESULT RemovePartition(
41
+ CPI_PARTITION_ATTRIBUTES* pAttrs
42
+ );
43
+static HRESULT ReadPartitionUserAttributes(
44
+ LPWSTR* ppwzData,
45
+ CPI_PARTITION_USER_ATTRIBUTES* pAttrs
46
+ );
47
+static void FreePartitionUserAttributes(
48
+ CPI_PARTITION_USER_ATTRIBUTES* pAttrs
49
+ );
50
+static HRESULT CreatePartitionUser(
51
+ CPI_PARTITION_USER_ATTRIBUTES* pAttrs
52
+ );
53
+static HRESULT RemovePartitionUser(
54
+ CPI_PARTITION_USER_ATTRIBUTES* pAttrs
55
+ );
56
+
57
+
58
+// function definitions
59
+
60
+HRESULT CpiConfigurePartitions(
61
+ LPWSTR* ppwzData,
62
+ HANDLE hRollbackFile
63
+ )
64
+{
65
+ HRESULT hr = S_OK;
66
+
67
+ CPI_PARTITION_ATTRIBUTES attrs;
68
+ ::ZeroMemory(&attrs, sizeof(attrs));
69
+
70
+ // read action text
71
+ hr = CpiActionStartMessage(ppwzData, FALSE);
72
+ ExitOnFailure(hr, "Failed to send action start message");
73
+
74
+ // ger partition count
75
+ int iCnt = 0;
76
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
77
+ ExitOnFailure(hr, "Failed to read count");
78
+
79
+ // write count to rollback file
80
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
81
+ ExitOnFailure(hr, "Failed to write count to rollback file");
82
+
83
+ for (int i = 0; i < iCnt; i++)
84
+ {
85
+ // read partition attributes from CustomActionData
86
+ hr = ReadPartitionAttributes(ppwzData, &attrs);
87
+ ExitOnFailure(hr, "Failed to read attributes");
88
+
89
+ // progress message
90
+ hr = CpiActionDataMessage(1, attrs.pwzName);
91
+ ExitOnFailure(hr, "Failed to send progress messages");
92
+
93
+ if (S_FALSE == hr)
94
+ ExitFunction();
95
+
96
+ // write key to rollback file
97
+ hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
98
+ ExitOnFailure(hr, "Failed to write key to rollback file");
99
+
100
+ // action
101
+ switch (attrs.iActionType)
102
+ {
103
+ case atCreate:
104
+ hr = CreatePartition(&attrs);
105
+ ExitOnFailure(hr, "Failed to create partition, key: %S", attrs.pwzKey);
106
+ break;
107
+ case atRemove:
108
+ hr = RemovePartition(&attrs);
109
+ ExitOnFailure(hr, "Failed to remove partition, key: %S", attrs.pwzKey);
110
+ break;
111
+ }
112
+
113
+ // write completion status to rollback file
114
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
115
+ ExitOnFailure(hr, "Failed to write completion status to rollback file");
116
+
117
+ // progress
118
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
119
+ ExitOnFailure(hr, "Failed to update progress");
120
+ }
121
+
122
+ hr = S_OK;
123
+
124
+LExit:
125
+ // clean up
126
+ FreePartitionAttributes(&attrs);
127
+
128
+ return hr;
129
+}
130
+
131
+HRESULT CpiRollbackConfigurePartitions(
132
+ LPWSTR* ppwzData,
133
+ CPI_ROLLBACK_DATA* pRollbackDataList
134
+ )
135
+{
136
+ HRESULT hr = S_OK;
137
+
138
+ int iRollbackStatus;
139
+
140
+ CPI_PARTITION_ATTRIBUTES attrs;
141
+ ::ZeroMemory(&attrs, sizeof(attrs));
142
+
143
+ // read action text
144
+ hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
145
+ ExitOnFailure(hr, "Failed to send action start message");
146
+
147
+ // get count
148
+ int iCnt = 0;
149
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
150
+ ExitOnFailure(hr, "Failed to read count");
151
+
152
+ for (int i = 0; i < iCnt; i++)
153
+ {
154
+ // read partition attributes from CustomActionData
155
+ hr = ReadPartitionAttributes(ppwzData, &attrs);
156
+ ExitOnFailure(hr, "Failed to read attributes");
157
+
158
+ // rollback status
159
+ hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
160
+
161
+ if (S_FALSE == hr)
162
+ continue; // not found, nothing to rollback
163
+
164
+ // progress message
165
+ hr = CpiActionDataMessage(1, attrs.pwzName);
166
+ ExitOnFailure(hr, "Failed to send progress messages");
167
+
168
+ if (S_FALSE == hr)
169
+ ExitFunction();
170
+
171
+ // action
172
+ switch (attrs.iActionType)
173
+ {
174
+ case atCreate:
175
+ hr = CreatePartition(&attrs);
176
+ if (FAILED(hr))
177
+ WcaLog(LOGMSG_STANDARD, "Failed to create partition, hr: 0x%x, key: %S", hr, attrs.pwzKey);
178
+ break;
179
+ case atRemove:
180
+ hr = RemovePartition(&attrs);
181
+ if (FAILED(hr))
182
+ WcaLog(LOGMSG_STANDARD, "Failed to remove partition, hr: 0x%x, key: %S", hr, attrs.pwzKey);
183
+ break;
184
+ }
185
+
186
+ // check rollback status
187
+ if (0 == iRollbackStatus)
188
+ continue; // operation did not complete, skip progress
189
+
190
+ // progress
191
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
192
+ ExitOnFailure(hr, "Failed to update progress");
193
+ }
194
+
195
+ hr = S_OK;
196
+
197
+LExit:
198
+ // clean up
199
+ FreePartitionAttributes(&attrs);
200
+
201
+ return hr;
202
+}
203
+
204
+HRESULT CpiConfigurePartitionUsers(
205
+ LPWSTR* ppwzData,
206
+ HANDLE hRollbackFile
207
+ )
208
+{
209
+ HRESULT hr = S_OK;
210
+
211
+ CPI_PARTITION_USER_ATTRIBUTES attrs;
212
+ ::ZeroMemory(&attrs, sizeof(attrs));
213
+
214
+ // read action text
215
+ hr = CpiActionStartMessage(ppwzData, FALSE);
216
+ ExitOnFailure(hr, "Failed to send action start message");
217
+
218
+ // ger partition count
219
+ int iCnt = 0;
220
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
221
+ ExitOnFailure(hr, "Failed to read count");
222
+
223
+ // write count to rollback file
224
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
225
+ ExitOnFailure(hr, "Failed to write count to rollback file");
226
+
227
+ for (int i = 0; i < iCnt; i++)
228
+ {
229
+ // read partition attributes from CustomActionData
230
+ hr = ReadPartitionUserAttributes(ppwzData, &attrs);
231
+ ExitOnFailure(hr, "Failed to read attributes");
232
+
233
+ // progress message
234
+ hr = CpiActionDataMessage(1, attrs.pwzAccount);
235
+ ExitOnFailure(hr, "Failed to send progress messages");
236
+
237
+ if (S_FALSE == hr)
238
+ ExitFunction();
239
+
240
+ // write key to rollback file
241
+ hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
242
+ ExitOnFailure(hr, "Failed to write key to rollback file");
243
+
244
+ // action
245
+ switch (attrs.iActionType)
246
+ {
247
+ case atCreate:
248
+ hr = CreatePartitionUser(&attrs);
249
+ ExitOnFailure(hr, "Failed to create partition user, key: %S", attrs.pwzKey);
250
+ break;
251
+ case atRemove:
252
+ hr = RemovePartitionUser(&attrs);
253
+ ExitOnFailure(hr, "Failed to remove partition user, key: %S", attrs.pwzKey);
254
+ break;
255
+ }
256
+
257
+ // write completion status to rollback file
258
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
259
+ ExitOnFailure(hr, "Failed to write completion status to rollback file");
260
+
261
+ // progress
262
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
263
+ ExitOnFailure(hr, "Failed to update progress");
264
+ }
265
+
266
+ hr = S_OK;
267
+
268
+LExit:
269
+ // clean up
270
+ FreePartitionUserAttributes(&attrs);
271
+
272
+ return hr;
273
+}
274
+
275
+HRESULT CpiRollbackConfigurePartitionUsers(
276
+ LPWSTR* ppwzData,
277
+ CPI_ROLLBACK_DATA* pRollbackDataList
278
+ )
279
+{
280
+ HRESULT hr = S_OK;
281
+
282
+ int iRollbackStatus;
283
+
284
+ CPI_PARTITION_USER_ATTRIBUTES attrs;
285
+ ::ZeroMemory(&attrs, sizeof(attrs));
286
+
287
+ // read action text
288
+ hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
289
+ ExitOnFailure(hr, "Failed to send action start message");
290
+
291
+ // get count
292
+ int iCnt = 0;
293
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
294
+ ExitOnFailure(hr, "Failed to read count");
295
+
296
+ for (int i = 0; i < iCnt; i++)
297
+ {
298
+ // read partition attributes from CustomActionData
299
+ hr = ReadPartitionUserAttributes(ppwzData, &attrs);
300
+ ExitOnFailure(hr, "Failed to read attributes");
301
+
302
+ // rollback status
303
+ hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
304
+
305
+ if (S_FALSE == hr)
306
+ continue; // not found, nothing to rollback
307
+
308
+ // progress message
309
+ hr = CpiActionDataMessage(1, attrs.pwzAccount);
310
+ ExitOnFailure(hr, "Failed to send progress messages");
311
+
312
+ if (S_FALSE == hr)
313
+ ExitFunction();
314
+
315
+ // action
316
+ switch (attrs.iActionType)
317
+ {
318
+ case atCreate:
319
+ hr = CreatePartitionUser(&attrs);
320
+ ExitOnFailure(hr, "Failed to create partition user, key: %S", attrs.pwzKey);
321
+ break;
322
+ case atRemove:
323
+ hr = RemovePartitionUser(&attrs);
324
+ ExitOnFailure(hr, "Failed to remove partition user, key: %S", attrs.pwzKey);
325
+ break;
326
+ }
327
+
328
+ // check rollback status
329
+ if (0 == iRollbackStatus)
330
+ continue; // operation did not complete, skip progress
331
+
332
+ // progress
333
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
334
+ ExitOnFailure(hr, "Failed to update progress");
335
+ }
336
+
337
+ hr = S_OK;
338
+
339
+LExit:
340
+ // clean up
341
+ FreePartitionUserAttributes(&attrs);
342
+
343
+ return hr;
344
+}
345
+
346
+
347
+// helper function definitions
348
+
349
+static HRESULT ReadPartitionAttributes(
350
+ LPWSTR* ppwzData,
351
+ CPI_PARTITION_ATTRIBUTES* pAttrs
352
+ )
353
+{
354
+ HRESULT hr = S_OK;
355
+
356
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
357
+ ExitOnFailure(hr, "Failed to read action type");
358
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
359
+ ExitOnFailure(hr, "Failed to read action cost");
360
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
361
+ ExitOnFailure(hr, "Failed to read key");
362
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzID);
363
+ ExitOnFailure(hr, "Failed to read id");
364
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName);
365
+ ExitOnFailure(hr, "Failed to read name");
366
+ hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList);
367
+ ExitOnFailure(hr, "Failed to read properties");
368
+
369
+ hr = S_OK;
370
+
371
+LExit:
372
+ return hr;
373
+}
374
+
375
+static void FreePartitionAttributes(
376
+ CPI_PARTITION_ATTRIBUTES* pAttrs
377
+ )
378
+{
379
+ ReleaseStr(pAttrs->pwzKey);
380
+ ReleaseStr(pAttrs->pwzID);
381
+ ReleaseStr(pAttrs->pwzName);
382
+
383
+ if (pAttrs->pPropList)
384
+ CpiFreePropertyList(pAttrs->pPropList);
385
+}
386
+
387
+static HRESULT CreatePartition(
388
+ CPI_PARTITION_ATTRIBUTES* pAttrs
389
+ )
390
+{
391
+ HRESULT hr = S_OK;
392
+
393
+ ICatalogCollection* piPartColl = NULL;
394
+ ICatalogObject* piPartObj = NULL;
395
+
396
+ long lChanges = 0;
397
+
398
+ // log
399
+ WcaLog(LOGMSG_VERBOSE, "Creating partition, key: %S", pAttrs->pwzKey);
400
+
401
+ // get partitions collection
402
+ hr = CpiGetPartitionsCollection(&piPartColl);
403
+ ExitOnFailure(hr, "Failed to get partitions collection");
404
+
405
+ // check if partition exists
406
+ hr = CpiFindCollectionObjectByStringKey(piPartColl, pAttrs->pwzID, &piPartObj);
407
+ ExitOnFailure(hr, "Failed to find partition");
408
+
409
+ if (S_FALSE == hr)
410
+ {
411
+ // create partition
412
+ hr = CpiAddCollectionObject(piPartColl, &piPartObj);
413
+ ExitOnFailure(hr, "Failed to add partition to collection");
414
+
415
+ hr = CpiPutCollectionObjectValue(piPartObj, L"ID", pAttrs->pwzID);
416
+ ExitOnFailure(hr, "Failed to set partition id property");
417
+
418
+ hr = CpiPutCollectionObjectValue(piPartObj, L"Name", pAttrs->pwzName);
419
+ ExitOnFailure(hr, "Failed to set partition name property");
420
+ }
421
+
422
+ // properties
423
+ hr = CpiPutCollectionObjectValues(piPartObj, pAttrs->pPropList);
424
+ ExitOnFailure(hr, "Failed to write properties");
425
+
426
+ // save changes
427
+ hr = piPartColl->SaveChanges(&lChanges);
428
+ if (COMADMIN_E_OBJECTERRORS == hr)
429
+ CpiLogCatalogErrorInfo();
430
+ ExitOnFailure(hr, "Failed to save changes");
431
+
432
+ // log
433
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
434
+
435
+ hr = S_OK;
436
+
437
+LExit:
438
+ // clean up
439
+ ReleaseObject(piPartColl);
440
+ ReleaseObject(piPartObj);
441
+
442
+ return hr;
443
+}
444
+
445
+static HRESULT RemovePartition(
446
+ CPI_PARTITION_ATTRIBUTES* pAttrs
447
+ )
448
+{
449
+ HRESULT hr = S_OK;
450
+
451
+ ICatalogCollection* piPartColl = NULL;
452
+
453
+ long lChanges = 0;
454
+
455
+ // log
456
+ WcaLog(LOGMSG_VERBOSE, "Removing partition, key: %S", pAttrs->pwzKey);
457
+
458
+ // get partitions collection
459
+ hr = CpiGetPartitionsCollection(&piPartColl);
460
+ ExitOnFailure(hr, "Failed to get partitions collection");
461
+
462
+ // remove
463
+ hr = CpiRemoveCollectionObject(piPartColl, pAttrs->pwzID, NULL, TRUE);
464
+ ExitOnFailure(hr, "Failed to remove partition");
465
+
466
+ if (S_FALSE == hr)
467
+ {
468
+ // partition not found
469
+ WcaLog(LOGMSG_VERBOSE, "Partition not found, nothing to delete, key: %S", pAttrs->pwzKey);
470
+ ExitFunction1(hr = S_OK);
471
+ }
472
+
473
+ // save changes
474
+ hr = piPartColl->SaveChanges(&lChanges);
475
+ if (COMADMIN_E_OBJECTERRORS == hr)
476
+ CpiLogCatalogErrorInfo();
477
+ ExitOnFailure(hr, "Failed to save changes");
478
+
479
+ // log
480
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
481
+
482
+ hr = S_OK;
483
+
484
+LExit:
485
+ // clean up
486
+ ReleaseObject(piPartColl);
487
+
488
+ return hr;
489
+}
490
+
491
+static HRESULT ReadPartitionUserAttributes(
492
+ LPWSTR* ppwzData,
493
+ CPI_PARTITION_USER_ATTRIBUTES* pAttrs
494
+ )
495
+{
496
+ HRESULT hr = S_OK;
497
+
498
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
499
+ ExitOnFailure(hr, "Failed to read action type");
500
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
501
+ ExitOnFailure(hr, "Failed to read action cost");
502
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
503
+ ExitOnFailure(hr, "Failed to read key");
504
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount);
505
+ ExitOnFailure(hr, "Failed to read account name");
506
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
507
+ ExitOnFailure(hr, "Failed to read partition id");
508
+
509
+ hr = S_OK;
510
+
511
+LExit:
512
+ return hr;
513
+}
514
+
515
+static void FreePartitionUserAttributes(
516
+ CPI_PARTITION_USER_ATTRIBUTES* pAttrs
517
+ )
518
+{
519
+ ReleaseStr(pAttrs->pwzKey);
520
+ ReleaseStr(pAttrs->pwzAccount);
521
+ ReleaseStr(pAttrs->pwzPartID);
522
+}
523
+
524
+static HRESULT CreatePartitionUser(
525
+ CPI_PARTITION_USER_ATTRIBUTES* pAttrs
526
+ )
527
+{
528
+ HRESULT hr = S_OK;
529
+ UINT er = ERROR_SUCCESS;
530
+
531
+ ICatalogCollection* piUserColl = NULL;
532
+ ICatalogObject* piUserObj = NULL;
533
+
534
+ PSID pSid = NULL;
535
+ long lChanges = 0;
536
+
537
+ // log
538
+ WcaLog(LOGMSG_VERBOSE, "Setting default partition for user, key: %S", pAttrs->pwzKey);
539
+
540
+ // get partition users collection
541
+ hr = CpiGetPartitionUsersCollection(&piUserColl);
542
+ ExitOnFailure(hr, "Failed to get partition users collection");
543
+
544
+ // get SID for account
545
+ do {
546
+ er = ERROR_SUCCESS;
547
+ hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid);
548
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
549
+ {
550
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount);
551
+ er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
552
+ switch (er)
553
+ {
554
+ case IDABORT:
555
+ ExitFunction(); // exit with error code from CpiAccountNameToSid()
556
+ case IDRETRY:
557
+ break;
558
+ case IDIGNORE:
559
+ default:
560
+ ExitFunction1(hr = S_OK);
561
+ }
562
+ }
563
+ else
564
+ ExitOnFailure(hr, "Failed to get SID for account");
565
+ } while (IDRETRY == er);
566
+
567
+ // remove any existing entry
568
+ hr = CpiRemoveUserCollectionObject(piUserColl, pSid);
569
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr)
570
+ {
571
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr);
572
+ hr = S_FALSE;
573
+ }
574
+ else
575
+ ExitOnFailure(hr, "Failed to remove user");
576
+
577
+ if (S_OK == hr)
578
+ WcaLog(LOGMSG_VERBOSE, "Existing default partition for user was removed, key: %S", pAttrs->pwzKey);
579
+
580
+ // add partition user
581
+ hr = CpiAddCollectionObject(piUserColl, &piUserObj);
582
+ ExitOnFailure(hr, "Failed to add partition to collection");
583
+
584
+ hr = CpiPutCollectionObjectValue(piUserObj, L"AccountName", pAttrs->pwzAccount);
585
+ ExitOnFailure(hr, "Failed to set account name property");
586
+
587
+ hr = CpiPutCollectionObjectValue(piUserObj, L"DefaultPartitionID", pAttrs->pwzPartID);
588
+ ExitOnFailure(hr, "Failed to set default partition id property");
589
+
590
+ // save changes
591
+ hr = piUserColl->SaveChanges(&lChanges);
592
+ if (COMADMIN_E_OBJECTERRORS == hr)
593
+ CpiLogCatalogErrorInfo();
594
+ ExitOnFailure(hr, "Failed to save changes");
595
+
596
+ // log
597
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
598
+
599
+ hr = S_OK;
600
+
601
+LExit:
602
+ // clean up
603
+ ReleaseObject(piUserColl);
604
+ ReleaseObject(piUserObj);
605
+
606
+ if (pSid)
607
+ ::HeapFree(::GetProcessHeap(), 0, pSid);
608
+
609
+ return hr;
610
+}
611
+
612
+static HRESULT RemovePartitionUser(
613
+ CPI_PARTITION_USER_ATTRIBUTES* pAttrs
614
+ )
615
+{
616
+ HRESULT hr = S_OK;
617
+ UINT er = ERROR_SUCCESS;
618
+
619
+ ICatalogCollection* piUserColl = NULL;
620
+
621
+ PSID pSid = NULL;
622
+ long lChanges = 0;
623
+
624
+ // log
625
+ WcaLog(LOGMSG_VERBOSE, "Removing default partition for user, key: %S", pAttrs->pwzKey);
626
+
627
+ // get partition users collection
628
+ hr = CpiGetPartitionUsersCollection(&piUserColl);
629
+ ExitOnFailure(hr, "Failed to get partition users collection");
630
+
631
+ // get SID for account
632
+ do {
633
+ er = ERROR_SUCCESS;
634
+ hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid);
635
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
636
+ {
637
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount);
638
+ er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
639
+ switch (er)
640
+ {
641
+ case IDABORT:
642
+ ExitFunction(); // exit with error code from CpiAccountNameToSid()
643
+ case IDRETRY:
644
+ break;
645
+ case IDIGNORE:
646
+ default:
647
+ ExitFunction1(hr = S_OK);
648
+ }
649
+ }
650
+ else
651
+ ExitOnFailure(hr, "Failed to get SID for account");
652
+ } while (IDRETRY == er);
653
+
654
+ // remove
655
+ hr = CpiRemoveUserCollectionObject(piUserColl, pSid);
656
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr)
657
+ {
658
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr);
659
+ hr = S_FALSE;
660
+ }
661
+ else
662
+ ExitOnFailure(hr, "Failed to remove user");
663
+
664
+ if (S_FALSE == hr)
665
+ {
666
+ // user not found
667
+ WcaLog(LOGMSG_VERBOSE, "Default partition for user not found, nothing to delete, key: %S", pAttrs->pwzKey);
668
+ ExitFunction1(hr = S_OK);
669
+ }
670
+
671
+ // save changes
672
+ hr = piUserColl->SaveChanges(&lChanges);
673
+ if (COMADMIN_E_OBJECTERRORS == hr)
674
+ CpiLogCatalogErrorInfo();
675
+ ExitOnFailure(hr, "Failed to save changes");
676
+
677
+ // log
678
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
679
+
680
+ hr = S_OK;
681
+
682
+LExit:
683
+ // clean up
684
+ ReleaseObject(piUserColl);
685
+
686
+ if (pSid)
687
+ ::HeapFree(::GetProcessHeap(), 0, pSid);
688
+
689
+ return hr;
690
+}
src/ca/cppartexec.h
new
+20
@@ -0,0 +1,20 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+HRESULT CpiConfigurePartitions(
6
+ LPWSTR* ppwzData,
7
+ HANDLE hRollbackFile
8
+ );
9
+HRESULT CpiRollbackConfigurePartitions(
10
+ LPWSTR* ppwzData,
11
+ CPI_ROLLBACK_DATA* pRollbackDataList
12
+ );
13
+HRESULT CpiConfigurePartitionUsers(
14
+ LPWSTR* ppwzData,
15
+ HANDLE hRollbackFile
16
+ );
17
+HRESULT CpiRollbackConfigurePartitionUsers(
18
+ LPWSTR* ppwzData,
19
+ CPI_ROLLBACK_DATA* pRollbackDataList
20
+ );
src/ca/cppartroleexec.cpp
new
+397
@@ -0,0 +1,397 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// private structs
7
+
8
+struct CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES
9
+{
10
+ int iActionType;
11
+ int iActionCost;
12
+ LPWSTR pwzKey;
13
+ LPWSTR pwzRoleName;
14
+ LPWSTR pwzAccount;
15
+ LPWSTR pwzPartID;
16
+};
17
+
18
+
19
+// prototypes for private helper functions
20
+
21
+static HRESULT ReadUserInPartitionRoleAttributes(
22
+ LPWSTR* ppwzData,
23
+ CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
24
+ );
25
+static void FreeUserInPartitionRoleAttributes(
26
+ CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
27
+ );
28
+static HRESULT CreateUserInPartitionRole(
29
+ CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
30
+ );
31
+static HRESULT RemoveUserInPartitionRole(
32
+ CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
33
+ );
34
+
35
+
36
+// function definitions
37
+
38
+HRESULT CpiConfigureUsersInPartitionRoles(
39
+ LPWSTR* ppwzData,
40
+ HANDLE hRollbackFile
41
+ )
42
+{
43
+ HRESULT hr = S_OK;
44
+
45
+ CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES attrs;
46
+ ::ZeroMemory(&attrs, sizeof(attrs));
47
+
48
+ // read action text
49
+ hr = CpiActionStartMessage(ppwzData, FALSE);
50
+ ExitOnFailure(hr, "Failed to send action start message");
51
+
52
+ // ger count
53
+ int iCnt = 0;
54
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
55
+ ExitOnFailure(hr, "Failed to read count");
56
+
57
+ // write count to rollback file
58
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
59
+ ExitOnFailure(hr, "Failed to write count to rollback file");
60
+
61
+ for (int i = 0; i < iCnt; i++)
62
+ {
63
+ // read attributes from CustomActionData
64
+ hr = ReadUserInPartitionRoleAttributes(ppwzData, &attrs);
65
+ ExitOnFailure(hr, "Failed to read attributes");
66
+
67
+ // progress message
68
+ hr = CpiActionDataMessage(1, attrs.pwzRoleName);
69
+ ExitOnFailure(hr, "Failed to send progress messages");
70
+
71
+ if (S_FALSE == hr)
72
+ ExitFunction();
73
+
74
+ // write key to rollback file
75
+ hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
76
+ ExitOnFailure(hr, "Failed to write key to rollback file");
77
+
78
+ // action
79
+ switch (attrs.iActionType)
80
+ {
81
+ case atCreate:
82
+ hr = CreateUserInPartitionRole(&attrs);
83
+ ExitOnFailure(hr, "Failed to add user to partition role, key: %S", attrs.pwzKey);
84
+ break;
85
+ case atRemove:
86
+ hr = RemoveUserInPartitionRole(&attrs);
87
+ ExitOnFailure(hr, "Failed to remove user from partition role, key: %S", attrs.pwzKey);
88
+ break;
89
+ }
90
+
91
+ // write completion status to rollback file
92
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
93
+ ExitOnFailure(hr, "Failed to write completion status to rollback file");
94
+
95
+ // progress
96
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
97
+ ExitOnFailure(hr, "Failed to update progress");
98
+ }
99
+
100
+ hr = S_OK;
101
+
102
+LExit:
103
+ // clean up
104
+ FreeUserInPartitionRoleAttributes(&attrs);
105
+
106
+ return hr;
107
+}
108
+
109
+HRESULT CpiRollbackConfigureUsersInPartitionRoles(
110
+ LPWSTR* ppwzData,
111
+ CPI_ROLLBACK_DATA* pRollbackDataList
112
+ )
113
+{
114
+ HRESULT hr = S_OK;
115
+
116
+ int iRollbackStatus;
117
+
118
+ CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES attrs;
119
+ ::ZeroMemory(&attrs, sizeof(attrs));
120
+
121
+ // read action text
122
+ hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
123
+ ExitOnFailure(hr, "Failed to send action start message");
124
+
125
+ // get count
126
+ int iCnt = 0;
127
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
128
+ ExitOnFailure(hr, "Failed to read count");
129
+
130
+ for (int i = 0; i < iCnt; i++)
131
+ {
132
+ // read attributes from CustomActionData
133
+ hr = ReadUserInPartitionRoleAttributes(ppwzData, &attrs);
134
+ ExitOnFailure(hr, "Failed to read attributes");
135
+
136
+ // rollback status
137
+ hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
138
+
139
+ if (S_FALSE == hr)
140
+ continue; // not found, nothing to rollback
141
+
142
+ // progress message
143
+ hr = CpiActionDataMessage(1, attrs.pwzRoleName);
144
+ ExitOnFailure(hr, "Failed to send progress messages");
145
+
146
+ if (S_FALSE == hr)
147
+ ExitFunction();
148
+
149
+ // action
150
+ switch (attrs.iActionType)
151
+ {
152
+ case atCreate:
153
+ hr = CreateUserInPartitionRole(&attrs);
154
+ if (FAILED(hr))
155
+ WcaLog(LOGMSG_STANDARD, "Failed to add user to partition role, hr: 0x%x, key: %S", hr, attrs.pwzKey);
156
+ break;
157
+ case atRemove:
158
+ hr = RemoveUserInPartitionRole(&attrs);
159
+ if (FAILED(hr))
160
+ WcaLog(LOGMSG_STANDARD, "Failed to remove user from partition role, hr: 0x%x, key: %S", hr, attrs.pwzKey);
161
+ break;
162
+ }
163
+
164
+ // check rollback status
165
+ if (0 == iRollbackStatus)
166
+ continue; // operation did not complete, skip progress
167
+
168
+ // progress
169
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
170
+ ExitOnFailure(hr, "Failed to update progress");
171
+ }
172
+
173
+ hr = S_OK;
174
+
175
+LExit:
176
+ // clean up
177
+ FreeUserInPartitionRoleAttributes(&attrs);
178
+
179
+ return hr;
180
+}
181
+
182
+
183
+// helper function definitions
184
+
185
+static HRESULT ReadUserInPartitionRoleAttributes(
186
+ LPWSTR* ppwzData,
187
+ CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
188
+ )
189
+{
190
+ HRESULT hr = S_OK;
191
+
192
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
193
+ ExitOnFailure(hr, "Failed to read action type");
194
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
195
+ ExitOnFailure(hr, "Failed to read action cost");
196
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
197
+ ExitOnFailure(hr, "Failed to read key");
198
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzRoleName);
199
+ ExitOnFailure(hr, "Failed to read role name");
200
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount);
201
+ ExitOnFailure(hr, "Failed to read account name");
202
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
203
+ ExitOnFailure(hr, "Failed to read partition id");
204
+
205
+ hr = S_OK;
206
+
207
+LExit:
208
+ return hr;
209
+}
210
+
211
+static void FreeUserInPartitionRoleAttributes(
212
+ CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
213
+ )
214
+{
215
+ ReleaseStr(pAttrs->pwzKey);
216
+ ReleaseStr(pAttrs->pwzRoleName);
217
+ ReleaseStr(pAttrs->pwzAccount);
218
+ ReleaseStr(pAttrs->pwzPartID);
219
+}
220
+
221
+static HRESULT CreateUserInPartitionRole(
222
+ CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
223
+ )
224
+{
225
+ HRESULT hr = S_OK;
226
+ UINT er = ERROR_SUCCESS;
227
+
228
+ ICatalogCollection* piUsrInRoleColl = NULL;
229
+ ICatalogObject* piUsrInRoleObj = NULL;
230
+
231
+ PSID pSid = NULL;
232
+ long lChanges = 0;
233
+
234
+ // log
235
+ WcaLog(LOGMSG_VERBOSE, "Adding user to partition role, key: %S", pAttrs->pwzKey);
236
+
237
+ // get users in partition role collection
238
+ hr = CpiGetUsersInPartitionRoleCollection(pAttrs->pwzPartID, pAttrs->pwzRoleName, &piUsrInRoleColl);
239
+ if (S_FALSE == hr)
240
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
241
+ ExitOnFailure(hr, "Failed to get users in partition role collection");
242
+
243
+ // get SID for account
244
+ do {
245
+ er = ERROR_SUCCESS;
246
+ hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid);
247
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
248
+ {
249
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount);
250
+ er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
251
+ switch (er)
252
+ {
253
+ case IDABORT:
254
+ ExitFunction(); // exit with error code from CpiAccountNameToSid()
255
+ case IDRETRY:
256
+ break;
257
+ case IDIGNORE:
258
+ default:
259
+ ExitFunction1(hr = S_OK);
260
+ }
261
+ }
262
+ else
263
+ ExitOnFailure(hr, "Failed to get SID for account");
264
+ } while (IDRETRY == er);
265
+
266
+ // find any existing entry
267
+ hr = CpiFindUserCollectionObject(piUsrInRoleColl, pSid, NULL);
268
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr)
269
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr);
270
+ else
271
+ ExitOnFailure(hr, "Failed to find user in partition role");
272
+
273
+ if (S_OK == hr)
274
+ {
275
+ WcaLog(LOGMSG_VERBOSE, "User already assigned to partition role, key: %S", pAttrs->pwzKey);
276
+ ExitFunction(); // exit with hr = S_OK
277
+ }
278
+
279
+ // convert SID back to account name
280
+ hr = CpiSidToAccountName(pSid, &pAttrs->pwzAccount);
281
+ ExitOnFailure(hr, "Failed to convert SID to account name");
282
+
283
+ // add user
284
+ hr = CpiAddCollectionObject(piUsrInRoleColl, &piUsrInRoleObj);
285
+ ExitOnFailure(hr, "Failed to add user in role to collection");
286
+
287
+ hr = CpiPutCollectionObjectValue(piUsrInRoleObj, L"User", pAttrs->pwzAccount);
288
+ ExitOnFailure(hr, "Failed to set role name property");
289
+
290
+ // save changes
291
+ hr = piUsrInRoleColl->SaveChanges(&lChanges);
292
+ if (COMADMIN_E_OBJECTERRORS == hr)
293
+ CpiLogCatalogErrorInfo();
294
+ ExitOnFailure(hr, "Failed to save changes");
295
+
296
+ // log
297
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
298
+
299
+ hr = S_OK;
300
+
301
+LExit:
302
+ // clean up
303
+ ReleaseObject(piUsrInRoleColl);
304
+ ReleaseObject(piUsrInRoleObj);
305
+
306
+ if (pSid)
307
+ ::HeapFree(::GetProcessHeap(), 0, pSid);
308
+
309
+ return hr;
310
+}
311
+
312
+static HRESULT RemoveUserInPartitionRole(
313
+ CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs
314
+ )
315
+{
316
+ HRESULT hr = S_OK;
317
+ UINT er = ERROR_SUCCESS;
318
+
319
+ ICatalogCollection* piUsrInRoleColl = NULL;
320
+
321
+ PSID pSid = NULL;
322
+ long lChanges = 0;
323
+
324
+ // log
325
+ WcaLog(LOGMSG_VERBOSE, "Removing user from partition role, key: %S", pAttrs->pwzKey);
326
+
327
+ // get users in partition role collection
328
+ hr = CpiGetUsersInPartitionRoleCollection(pAttrs->pwzPartID, pAttrs->pwzRoleName, &piUsrInRoleColl);
329
+ ExitOnFailure(hr, "Failed to get users in partition role collection");
330
+
331
+ if (S_FALSE == hr)
332
+ {
333
+ // users in role collection not found
334
+ WcaLog(LOGMSG_VERBOSE, "Unable to retrieve users in partition role collection, nothing to delete, key: %S", pAttrs->pwzKey);
335
+ ExitFunction1(hr = S_OK);
336
+ }
337
+
338
+ // get SID for account
339
+ do {
340
+ er = ERROR_SUCCESS;
341
+ hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid);
342
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
343
+ {
344
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount);
345
+ er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
346
+ switch (er)
347
+ {
348
+ case IDABORT:
349
+ ExitFunction(); // exit with error code from CpiAccountNameToSid()
350
+ case IDRETRY:
351
+ break;
352
+ case IDIGNORE:
353
+ default:
354
+ ExitFunction1(hr = S_OK);
355
+ }
356
+ }
357
+ else
358
+ ExitOnFailure(hr, "Failed to get SID for account");
359
+ } while (IDRETRY == er);
360
+
361
+ // remove
362
+ hr = CpiRemoveUserCollectionObject(piUsrInRoleColl, pSid);
363
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr)
364
+ {
365
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr);
366
+ hr = S_FALSE;
367
+ }
368
+ else
369
+ ExitOnFailure(hr, "Failed to remove user");
370
+
371
+ if (S_FALSE == hr)
372
+ {
373
+ // role not found
374
+ WcaLog(LOGMSG_VERBOSE, "User not found for partition role, nothing to delete, key: %S", pAttrs->pwzKey);
375
+ ExitFunction1(hr = S_OK);
376
+ }
377
+
378
+ // save changes
379
+ hr = piUsrInRoleColl->SaveChanges(&lChanges);
380
+ if (COMADMIN_E_OBJECTERRORS == hr)
381
+ CpiLogCatalogErrorInfo();
382
+ ExitOnFailure(hr, "Failed to save changes");
383
+
384
+ // log
385
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
386
+
387
+ hr = S_OK;
388
+
389
+LExit:
390
+ // clean up
391
+ ReleaseObject(piUsrInRoleColl);
392
+
393
+ if (pSid)
394
+ ::HeapFree(::GetProcessHeap(), 0, pSid);
395
+
396
+ return hr;
397
+}
src/ca/cppartroleexec.h
new
+12
@@ -0,0 +1,12 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+HRESULT CpiConfigureUsersInPartitionRoles(
6
+ LPWSTR* ppwzData,
7
+ HANDLE hRollbackFile
8
+ );
9
+HRESULT CpiRollbackConfigureUsersInPartitionRoles(
10
+ LPWSTR* ppwzData,
11
+ CPI_ROLLBACK_DATA* pRollbackDataList
12
+ );
src/ca/cppartrolesched.cpp
new
+421
@@ -0,0 +1,421 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// sql queries
7
+
8
+LPCWSTR vcsPartitionRoleQuery =
9
+ L"SELECT `PartitionRole`, `Partition_`, `Component_`, `Name` FROM `ComPlusPartitionRole`";
10
+enum ePartitionRoleQuery { prqPartitionRole = 1, prqPartition, prqComponent, prqName };
11
+
12
+LPCWSTR vcsUserInPartitionRoleQuery =
13
+ L"SELECT `UserInPartitionRole`, `PartitionRole_`, `ComPlusUserInPartitionRole`.`Component_`, `Domain`, `Name` FROM `ComPlusUserInPartitionRole`, `User` WHERE `User_` = `User`";
14
+LPCWSTR vcsGroupInPartitionRoleQuery =
15
+ L"SELECT `GroupInPartitionRole`, `PartitionRole_`, `ComPlusGroupInPartitionRole`.`Component_`, `Domain`, `Name` FROM `ComPlusGroupInPartitionRole`, `Group` WHERE `Group_` = `Group`";
16
+enum eTrusteeInPartitionRoleQuery { tiprqUserInPartitionRole = 1, tiprqPartitionRole, tiprqComponent, tiprqDomain, tiprqName };
17
+
18
+
19
+// prototypes for private helper functions
20
+
21
+static HRESULT TrusteesInPartitionRolesRead(
22
+ LPCWSTR pwzQuery,
23
+ CPI_PARTITION_ROLE_LIST* pPartRoleList,
24
+ CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList
25
+ );
26
+static void FreePartitionRole(
27
+ CPI_PARTITION_ROLE* pItm
28
+ );
29
+static void FreeUserInPartitionRole(
30
+ CPI_USER_IN_PARTITION_ROLE* pItm
31
+ );
32
+static HRESULT AddUserInPartitionRoleToActionData(
33
+ CPI_USER_IN_PARTITION_ROLE* pItm,
34
+ int iActionType,
35
+ int iActionCost,
36
+ LPWSTR* ppwzActionData
37
+ );
38
+
39
+
40
+// function definitions
41
+
42
+void CpiPartitionRoleListFree(
43
+ CPI_PARTITION_ROLE_LIST* pList
44
+ )
45
+{
46
+ CPI_PARTITION_ROLE* pItm = pList->pFirst;
47
+
48
+ while (pItm)
49
+ {
50
+ CPI_PARTITION_ROLE* pDelete = pItm;
51
+ pItm = pItm->pNext;
52
+ FreePartitionRole(pDelete);
53
+ }
54
+}
55
+
56
+HRESULT CpiPartitionRolesRead(
57
+ CPI_PARTITION_LIST* pPartList,
58
+ CPI_PARTITION_ROLE_LIST* pPartRoleList
59
+ )
60
+{
61
+ HRESULT hr = S_OK;
62
+ PMSIHANDLE hView, hRec;
63
+ CPI_PARTITION_ROLE* pItm = NULL;
64
+ LPWSTR pwzData = NULL;
65
+
66
+ // loop through all application roles
67
+ hr = WcaOpenExecuteView(vcsPartitionRoleQuery, &hView);
68
+ ExitOnFailure(hr, "Failed to execute view on ComPlusPartitionRole table");
69
+
70
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
71
+ {
72
+ // create entry
73
+ pItm = (CPI_PARTITION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION_ROLE));
74
+ if (!pItm)
75
+ ExitFunction1(hr = E_OUTOFMEMORY);
76
+
77
+ // get key
78
+ hr = WcaGetRecordString(hRec, prqPartitionRole, &pwzData);
79
+ ExitOnFailure(hr, "Failed to get key");
80
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
81
+
82
+ // get partition
83
+ hr = WcaGetRecordString(hRec, prqPartition, &pwzData);
84
+ ExitOnFailure(hr, "Failed to get application");
85
+
86
+ hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition);
87
+ if (S_FALSE == hr)
88
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
89
+ ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData);
90
+
91
+ // get name
92
+ hr = WcaGetRecordFormattedString(hRec, prqName, &pwzData);
93
+ ExitOnFailure(hr, "Failed to get name");
94
+ StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
95
+
96
+ // add entry
97
+ if (pPartRoleList->pFirst)
98
+ pItm->pNext = pPartRoleList->pFirst;
99
+ pPartRoleList->pFirst = pItm;
100
+ pItm = NULL;
101
+ }
102
+
103
+ if (E_NOMOREITEMS == hr)
104
+ hr = S_OK;
105
+
106
+LExit:
107
+ // clean up
108
+ if (pItm)
109
+ FreePartitionRole(pItm);
110
+
111
+ ReleaseStr(pwzData);
112
+
113
+ return hr;
114
+}
115
+
116
+HRESULT CpiPartitionRoleFindByKey(
117
+ CPI_PARTITION_ROLE_LIST* pList,
118
+ LPCWSTR pwzKey,
119
+ CPI_PARTITION_ROLE** ppPartRole
120
+ )
121
+{
122
+ for (CPI_PARTITION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
123
+ {
124
+ if (0 == lstrcmpW(pItm->wzKey, pwzKey))
125
+ {
126
+ *ppPartRole = pItm;
127
+ return S_OK;
128
+ }
129
+ }
130
+
131
+ return E_FAIL;
132
+}
133
+
134
+void CpiUserInPartitionRoleListFree(
135
+ CPI_USER_IN_PARTITION_ROLE_LIST* pList
136
+ )
137
+{
138
+ CPI_USER_IN_PARTITION_ROLE* pItm = pList->pFirst;
139
+
140
+ while (pItm)
141
+ {
142
+ CPI_USER_IN_PARTITION_ROLE* pDelete = pItm;
143
+ pItm = pItm->pNext;
144
+ FreeUserInPartitionRole(pDelete);
145
+ }
146
+}
147
+
148
+HRESULT CpiUsersInPartitionRolesRead(
149
+ CPI_PARTITION_ROLE_LIST* pPartRoleList,
150
+ CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList
151
+ )
152
+{
153
+ HRESULT hr = S_OK;
154
+
155
+ // read users in partition roles
156
+ if (CpiTableExists(cptComPlusUserInPartitionRole))
157
+ {
158
+ hr = TrusteesInPartitionRolesRead(vcsUserInPartitionRoleQuery, pPartRoleList, pUsrInPartRoleList);
159
+ ExitOnFailure(hr, "Failed to read users in partition roles");
160
+ }
161
+
162
+ // read groups in partition roles
163
+ if (CpiTableExists(cptComPlusGroupInPartitionRole))
164
+ {
165
+ hr = TrusteesInPartitionRolesRead(vcsGroupInPartitionRoleQuery, pPartRoleList, pUsrInPartRoleList);
166
+ ExitOnFailure(hr, "Failed to read groups in partition roles");
167
+ }
168
+
169
+ hr = S_OK;
170
+
171
+LExit:
172
+ return hr;
173
+}
174
+
175
+HRESULT CpiUsersInPartitionRolesInstall(
176
+ CPI_USER_IN_PARTITION_ROLE_LIST* pList,
177
+ int iRunMode,
178
+ LPWSTR* ppwzActionData,
179
+ int* piProgress
180
+ )
181
+{
182
+ HRESULT hr = S_OK;
183
+
184
+ int iActionType;
185
+
186
+ // add action text
187
+ hr = CpiAddActionTextToActionData(L"AddUsersToComPlusPartitionRoles", ppwzActionData);
188
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
189
+
190
+ // add count to action data
191
+ hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
192
+ ExitOnFailure(hr, "Failed to add count to custom action data");
193
+
194
+ // add roles to custom action data
195
+ for (CPI_USER_IN_PARTITION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
196
+ {
197
+ // roles that are being installed only
198
+ if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction))
199
+ continue;
200
+
201
+ // action type
202
+ if (rmRollback == iRunMode)
203
+ {
204
+ if (CpiIsInstalled(pItm->isInstalled))
205
+ iActionType = atNoOp;
206
+ else
207
+ iActionType = atRemove;
208
+ }
209
+ else
210
+ iActionType = atCreate;
211
+
212
+ // add to action data
213
+ hr = AddUserInPartitionRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_CREATE, ppwzActionData);
214
+ ExitOnFailure(hr, "Failed to add user in partition role to custom action data, key: %S", pItm->wzKey);
215
+ }
216
+
217
+ // add progress tics
218
+ if (piProgress)
219
+ *piProgress += COST_USER_IN_APPLICATION_ROLE_CREATE * pList->iInstallCount;
220
+
221
+ hr = S_OK;
222
+
223
+LExit:
224
+ return hr;
225
+}
226
+
227
+HRESULT CpiUsersInPartitionRolesUninstall(
228
+ CPI_USER_IN_PARTITION_ROLE_LIST* pList,
229
+ int iRunMode,
230
+ LPWSTR* ppwzActionData,
231
+ int* piProgress
232
+ )
233
+{
234
+ HRESULT hr = S_OK;
235
+
236
+ int iActionType;
237
+
238
+ // add action text
239
+ hr = CpiAddActionTextToActionData(L"RemoveUsersFromComPlusPartRoles", ppwzActionData);
240
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
241
+
242
+ // add count to action data
243
+ hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
244
+ ExitOnFailure(hr, "Failed to add count to custom action data");
245
+
246
+ // add roles to custom action data
247
+ for (CPI_USER_IN_PARTITION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
248
+ {
249
+ // roles that are being uninstalled only
250
+ if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
251
+ continue;
252
+
253
+ // action type
254
+ if (rmRollback == iRunMode)
255
+ iActionType = atCreate;
256
+ else
257
+ iActionType = atRemove;
258
+
259
+ // add to action data
260
+ hr = AddUserInPartitionRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_DELETE, ppwzActionData);
261
+ ExitOnFailure(hr, "Failed to add user in partition role to custom action data, key: %S", pItm->wzKey);
262
+ }
263
+
264
+ // add progress tics
265
+ if (piProgress)
266
+ *piProgress += COST_USER_IN_APPLICATION_ROLE_DELETE * pList->iUninstallCount;
267
+
268
+ hr = S_OK;
269
+
270
+LExit:
271
+ return hr;
272
+}
273
+
274
+
275
+// helper function definitions
276
+
277
+static HRESULT TrusteesInPartitionRolesRead(
278
+ LPCWSTR pwzQuery,
279
+ CPI_PARTITION_ROLE_LIST* pPartRoleList,
280
+ CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList
281
+ )
282
+{
283
+ HRESULT hr = S_OK;
284
+ UINT er = ERROR_SUCCESS;
285
+
286
+ PMSIHANDLE hView, hRec;
287
+
288
+ CPI_USER_IN_PARTITION_ROLE* pItm = NULL;
289
+ LPWSTR pwzData = NULL;
290
+ LPWSTR pwzDomain = NULL;
291
+ LPWSTR pwzName = NULL;
292
+ BOOL fMatchingArchitecture = FALSE;
293
+
294
+ // loop through all application roles
295
+ hr = WcaOpenExecuteView(pwzQuery, &hView);
296
+ ExitOnFailure(hr, "Failed to execute view on table");
297
+
298
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
299
+ {
300
+ // get component
301
+ hr = WcaGetRecordString(hRec, tiprqComponent, &pwzData);
302
+ ExitOnFailure(hr, "Failed to get component");
303
+
304
+ // check if the component is our processor architecture
305
+ hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
306
+ ExitOnFailure(hr, "Failed to get component architecture.");
307
+
308
+ if (!fMatchingArchitecture)
309
+ {
310
+ continue; // not the same architecture, ignore
311
+ }
312
+
313
+ // create entry
314
+ pItm = (CPI_USER_IN_PARTITION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_USER_IN_PARTITION_ROLE));
315
+ if (!pItm)
316
+ ExitFunction1(hr = E_OUTOFMEMORY);
317
+
318
+ // get component install state
319
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
320
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
321
+
322
+ // get key
323
+ hr = WcaGetRecordString(hRec, tiprqUserInPartitionRole, &pwzData);
324
+ ExitOnFailure(hr, "Failed to get key");
325
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
326
+
327
+ // get partition role
328
+ hr = WcaGetRecordString(hRec, tiprqPartitionRole, &pwzData);
329
+ ExitOnFailure(hr, "Failed to get partition role");
330
+
331
+ hr = CpiPartitionRoleFindByKey(pPartRoleList, pwzData, &pItm->pPartitionRole);
332
+ ExitOnFailure(hr, "Failed to find partition role, key: %S", pwzData);
333
+
334
+ // get user domain
335
+ hr = WcaGetRecordFormattedString(hRec, tiprqDomain, &pwzDomain);
336
+ ExitOnFailure(hr, "Failed to get domain");
337
+
338
+ // get user name
339
+ hr = WcaGetRecordFormattedString(hRec, tiprqName, &pwzName);
340
+ ExitOnFailure(hr, "Failed to get name");
341
+
342
+ // build account name
343
+ hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount);
344
+ ExitOnFailure(hr, "Failed to build account name");
345
+
346
+ // increment counters
347
+ if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
348
+ pUsrInPartRoleList->iInstallCount++;
349
+ if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
350
+ pUsrInPartRoleList->iUninstallCount++;
351
+
352
+ // add entry
353
+ if (pUsrInPartRoleList->pFirst)
354
+ pItm->pNext = pUsrInPartRoleList->pFirst;
355
+ pUsrInPartRoleList->pFirst = pItm;
356
+ pItm = NULL;
357
+ }
358
+
359
+ if (E_NOMOREITEMS == hr)
360
+ hr = S_OK;
361
+
362
+LExit:
363
+ // clean up
364
+ if (pItm)
365
+ FreeUserInPartitionRole(pItm);
366
+
367
+ ReleaseStr(pwzData);
368
+ ReleaseStr(pwzDomain);
369
+ ReleaseStr(pwzName);
370
+
371
+ return hr;
372
+}
373
+
374
+static void FreePartitionRole(
375
+ CPI_PARTITION_ROLE* pItm
376
+ )
377
+{
378
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
379
+}
380
+
381
+static void FreeUserInPartitionRole(
382
+ CPI_USER_IN_PARTITION_ROLE* pItm
383
+ )
384
+{
385
+ ReleaseStr(pItm->pwzAccount);
386
+
387
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
388
+}
389
+
390
+static HRESULT AddUserInPartitionRoleToActionData(
391
+ CPI_USER_IN_PARTITION_ROLE* pItm,
392
+ int iActionType,
393
+ int iActionCost,
394
+ LPWSTR* ppwzActionData
395
+ )
396
+{
397
+ HRESULT hr = S_OK;
398
+
399
+ // add action information to custom action data
400
+ hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
401
+ ExitOnFailure(hr, "Failed to add action type to custom action data");
402
+ hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
403
+ ExitOnFailure(hr, "Failed to add action cost to custom action data");
404
+
405
+ // add application role information to custom action data
406
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
407
+ ExitOnFailure(hr, "Failed to add key to custom action data");
408
+ hr = WcaWriteStringToCaData(pItm->pPartitionRole->wzName, ppwzActionData);
409
+ ExitOnFailure(hr, "Failed to add role name to custom action data");
410
+ hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData);
411
+ ExitOnFailure(hr, "Failed to add user account to custom action data");
412
+
413
+ // add partition information to custom action data
414
+ hr = WcaWriteStringToCaData(pItm->pPartitionRole->pPartition->wzID, ppwzActionData);
415
+ ExitOnFailure(hr, "Failed to add partition id to custom action data");
416
+
417
+ hr = S_OK;
418
+
419
+LExit:
420
+ return hr;
421
+}
src/ca/cppartrolesched.h
new
+76
@@ -0,0 +1,76 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+struct CPI_PARTITION_ROLE
6
+{
7
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
8
+ WCHAR wzName[MAX_DARWIN_COLUMN + 1];
9
+
10
+ CPI_PARTITION* pPartition;
11
+
12
+ ICatalogCollection* piUsersColl;
13
+
14
+ CPI_PARTITION_ROLE* pNext;
15
+};
16
+
17
+struct CPI_PARTITION_ROLE_LIST
18
+{
19
+ CPI_PARTITION_ROLE* pFirst;
20
+};
21
+
22
+struct CPI_USER_IN_PARTITION_ROLE
23
+{
24
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
25
+ LPWSTR pwzAccount;
26
+
27
+ INSTALLSTATE isInstalled, isAction;
28
+
29
+ CPI_PARTITION_ROLE* pPartitionRole;
30
+
31
+ CPI_USER_IN_PARTITION_ROLE* pNext;
32
+};
33
+
34
+struct CPI_USER_IN_PARTITION_ROLE_LIST
35
+{
36
+ CPI_USER_IN_PARTITION_ROLE* pFirst;
37
+
38
+ int iInstallCount;
39
+ int iUninstallCount;
40
+};
41
+
42
+
43
+// function prototypes
44
+
45
+void CpiPartitionRoleListFree(
46
+ CPI_PARTITION_ROLE_LIST* pList
47
+ );
48
+HRESULT CpiPartitionRolesRead(
49
+ CPI_PARTITION_LIST* pPartList,
50
+ CPI_PARTITION_ROLE_LIST* pPartRoleList
51
+ );
52
+HRESULT CpiPartitionRoleFindByKey(
53
+ CPI_PARTITION_ROLE_LIST* pList,
54
+ LPCWSTR pwzKey,
55
+ CPI_PARTITION_ROLE** ppPartRole
56
+ );
57
+
58
+void CpiUserInPartitionRoleListFree(
59
+ CPI_USER_IN_PARTITION_ROLE_LIST* pList
60
+ );
61
+HRESULT CpiUsersInPartitionRolesRead(
62
+ CPI_PARTITION_ROLE_LIST* pPartRoleList,
63
+ CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList
64
+ );
65
+HRESULT CpiUsersInPartitionRolesInstall(
66
+ CPI_USER_IN_PARTITION_ROLE_LIST* pList,
67
+ int iRunMode,
68
+ LPWSTR* ppwzActionData,
69
+ int* piProgress
70
+ );
71
+HRESULT CpiUsersInPartitionRolesUninstall(
72
+ CPI_USER_IN_PARTITION_ROLE_LIST* pList,
73
+ int iRunMode,
74
+ LPWSTR* ppwzActionData,
75
+ int* piProgress
76
+ );
src/ca/cppartsched.cpp
new
+912
@@ -0,0 +1,912 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// sql queries
7
+
8
+LPCWSTR vcsPartitionQuery =
9
+ L"SELECT `Partition`, `Component_`, `Id`, `Name` FROM `ComPlusPartition`";
10
+enum ePartitionQuery { pqPartition = 1, pqComponent, pqID, pqName };
11
+
12
+LPCWSTR vcsPartitionPropertyQuery =
13
+ L"SELECT `Name`, `Value` FROM `ComPlusPartitionProperty` WHERE `Partition_` = ?";
14
+
15
+LPCWSTR vcsPartitionUserQuery =
16
+ L"SELECT `PartitionUser`, `Partition_`, `ComPlusPartitionUser`.`Component_`, `Domain`, `Name` FROM `ComPlusPartitionUser`, `User` WHERE `User_` = `User`";
17
+enum ePartitionUserQuery { puqPartitionUser = 1, puqPartition, puqComponent, puqDomain, puqName };
18
+
19
+
20
+// property definitions
21
+
22
+CPI_PROPERTY_DEFINITION pdlPartitionProperties[] =
23
+{
24
+ {L"Changeable", cpptBoolean, 502},
25
+ {L"Deleteable", cpptBoolean, 502},
26
+ {L"Description", cpptString, 502},
27
+ {NULL, cpptNone, 0}
28
+};
29
+
30
+
31
+// prototypes for private helper functions
32
+
33
+static void FreePartition(
34
+ CPI_PARTITION* pItm
35
+ );
36
+static void FreePartitionUser(
37
+ CPI_PARTITION_USER* pItm
38
+ );
39
+static HRESULT AddPartitionToActionData(
40
+ CPI_PARTITION* pItm,
41
+ int iActionType,
42
+ int iActionCost,
43
+ LPWSTR* ppwzActionData
44
+ );
45
+static HRESULT AddPartitionUserToActionData(
46
+ CPI_PARTITION_USER* pItm,
47
+ int iActionType,
48
+ int iActionCost,
49
+ LPWSTR* ppwzActionData
50
+ );
51
+
52
+
53
+// function definitions
54
+
55
+void CpiPartitionListFree(
56
+ CPI_PARTITION_LIST* pList
57
+ )
58
+{
59
+ CPI_PARTITION* pItm = pList->pFirst;
60
+
61
+ while (pItm)
62
+ {
63
+ CPI_PARTITION* pDelete = pItm;
64
+ pItm = pItm->pNext;
65
+ FreePartition(pDelete);
66
+ }
67
+}
68
+
69
+HRESULT CpiPartitionsRead(
70
+ CPI_PARTITION_LIST* pPartList
71
+ )
72
+{
73
+ HRESULT hr = S_OK;
74
+ UINT er = ERROR_SUCCESS;
75
+
76
+ PMSIHANDLE hView, hRec;
77
+
78
+ CPI_PARTITION* pItm = NULL;
79
+ LPWSTR pwzData = NULL;
80
+ BOOL fMatchingArchitecture = FALSE;
81
+
82
+ // loop through all partitions
83
+ hr = WcaOpenExecuteView(vcsPartitionQuery, &hView);
84
+ ExitOnFailure(hr, "Failed to execute view on ComPlusPartition table");
85
+
86
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
87
+ {
88
+ // get component
89
+ hr = WcaGetRecordString(hRec, pqComponent, &pwzData);
90
+ ExitOnFailure(hr, "Failed to get component");
91
+
92
+ // check if the component is our processor architecture
93
+ if (pwzData && *pwzData)
94
+ {
95
+ hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
96
+ ExitOnFailure(hr, "Failed to get component architecture.");
97
+
98
+ if (!fMatchingArchitecture)
99
+ {
100
+ continue; // not the same architecture, ignore
101
+ }
102
+ }
103
+
104
+ // create entry
105
+ pItm = (CPI_PARTITION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION));
106
+ if (!pItm)
107
+ ExitFunction1(hr = E_OUTOFMEMORY);
108
+
109
+ // get component install state
110
+ if (pwzData && *pwzData)
111
+ {
112
+ pItm->fHasComponent = TRUE;
113
+
114
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
115
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
116
+ }
117
+
118
+ // get key
119
+ hr = WcaGetRecordString(hRec, pqPartition, &pwzData);
120
+ ExitOnFailure(hr, "Failed to get key");
121
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
122
+
123
+ // get id
124
+ hr = WcaGetRecordFormattedString(hRec, pqID, &pwzData);
125
+ ExitOnFailure(hr, "Failed to get id");
126
+
127
+ if (pwzData && *pwzData)
128
+ {
129
+ hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID));
130
+ ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData);
131
+ }
132
+
133
+ // get name
134
+ hr = WcaGetRecordFormattedString(hRec, pqName, &pwzData);
135
+ ExitOnFailure(hr, "Failed to get name");
136
+ StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
137
+
138
+ // if partition is a locater, either an id or a name must be provided
139
+ if (!pItm->fHasComponent && !*pItm->wzID && !*pItm->wzName)
140
+ ExitOnFailure(hr = E_FAIL, "A partition locater must have either an id or a name associated, key: %S", pItm->wzKey);
141
+
142
+ // if partition is not a locater, an name must be provided
143
+ if (pItm->fHasComponent && !*pItm->wzName)
144
+ ExitOnFailure(hr = E_FAIL, "A partition must have a name associated, key: %S", pItm->wzKey);
145
+
146
+ // get properties
147
+ if (CpiTableExists(cptComPlusPartitionProperty) && pItm->fHasComponent)
148
+ {
149
+ hr = CpiPropertiesRead(vcsPartitionPropertyQuery, pItm->wzKey, pdlPartitionProperties, &pItm->pProperties, &pItm->iPropertyCount);
150
+ ExitOnFailure(hr, "Failed to get properties");
151
+ }
152
+
153
+ // increment counters
154
+ if (pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction))
155
+ pPartList->iInstallCount++;
156
+ if (pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
157
+ pPartList->iUninstallCount++;
158
+
159
+ // add entry
160
+ if (pPartList->pFirst)
161
+ pItm->pNext = pPartList->pFirst;
162
+ pPartList->pFirst = pItm;
163
+ pItm = NULL;
164
+ }
165
+
166
+ if (E_NOMOREITEMS == hr)
167
+ hr = S_OK;
168
+
169
+LExit:
170
+ // clean up
171
+ if (pItm)
172
+ FreePartition(pItm);
173
+
174
+ ReleaseStr(pwzData);
175
+
176
+ return hr;
177
+}
178
+
179
+HRESULT CpiPartitionsVerifyInstall(
180
+ CPI_PARTITION_LIST* pList
181
+ )
182
+{
183
+ HRESULT hr = S_OK;
184
+ UINT er = ERROR_SUCCESS;
185
+
186
+ ICatalogCollection* piPartColl = NULL;
187
+ ICatalogObject* piPartObj = NULL;
188
+
189
+ for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
190
+ {
191
+ // referenced locaters or partitions that are being installed
192
+ if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction)))
193
+ continue;
194
+
195
+ // if the partition is referensed and is not a locater, it must be installed
196
+ if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction))
197
+ MessageExitOnFailure(hr = E_FAIL, msierrComPlusPartitionDependency, "A partition is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey);
198
+
199
+ // get partitions collection
200
+ if (!piPartColl)
201
+ {
202
+ hr = CpiGetPartitionsCollection(&piPartColl);
203
+ ExitOnFailure(hr, "Failed to get partitions collection");
204
+ }
205
+
206
+ // partition is supposed to exist
207
+ if (!pItm->fHasComponent || CpiIsInstalled(pItm->isInstalled))
208
+ {
209
+ // get collection object for partition
210
+ hr = CpiFindCollectionObject(piPartColl, pItm->wzID, *pItm->wzID ? NULL : pItm->wzName, &piPartObj);
211
+ ExitOnFailure(hr, "Failed to find collection object for partition");
212
+
213
+ // if the partition was found
214
+ if (S_OK == hr)
215
+ {
216
+ // if we don't have an id, copy id from object
217
+ if (!*pItm->wzID)
218
+ {
219
+ hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID));
220
+ ExitOnFailure(hr, "Failed to get id");
221
+ }
222
+ }
223
+
224
+ // if the partition was not found
225
+ else
226
+ {
227
+ // if the application is a locater, this is an error
228
+ if (!pItm->fHasComponent)
229
+ MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusPartitionNotFound, "A partition required by this installation was not found, key: %S", pItm->wzKey);
230
+
231
+ // create a new id if one is missing
232
+ if (!*pItm->wzID)
233
+ {
234
+ hr = CpiCreateId(pItm->wzID, countof(pItm->wzID));
235
+ ExitOnFailure(hr, "Failed to create id");
236
+ }
237
+ }
238
+ }
239
+
240
+ // partition is supposed to be created
241
+ else
242
+ {
243
+ // check for conflicts
244
+ do {
245
+ if (*pItm->wzID)
246
+ {
247
+ // find partitions with conflicting id
248
+ hr = CpiFindCollectionObject(piPartColl, pItm->wzID, NULL, &piPartObj);
249
+ ExitOnFailure(hr, "Failed to find collection object for partition");
250
+
251
+ if (S_FALSE == hr)
252
+ {
253
+ // find partitions with conflicting name
254
+ hr = CpiFindCollectionObject(piPartColl, NULL, pItm->wzName, &piPartObj);
255
+ ExitOnFailure(hr, "Failed to find collection object for partition");
256
+
257
+ if (S_OK == hr)
258
+ // "A partition with a conflictiong name exists. retry cancel"
259
+ er = WcaErrorMessage(msierrComPlusPartitionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0);
260
+ else
261
+ break; // no conflicting entry found, break loop
262
+ }
263
+ else
264
+ // "A partition with a conflicting id exists. abort retry ignore"
265
+ er = WcaErrorMessage(msierrComPlusPartitionIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
266
+ }
267
+ else
268
+ {
269
+ // find partitions with conflicting name
270
+ hr = CpiFindCollectionObject(piPartColl, NULL, pItm->wzName, &piPartObj);
271
+ ExitOnFailure(hr, "Failed to find collection object for partition");
272
+
273
+ if (S_OK == hr)
274
+ // "A partition with a conflictiong name exists. abort retry ignore"
275
+ er = WcaErrorMessage(msierrComPlusPartitionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
276
+ else
277
+ break; // no conflicting entry found, break loop
278
+ }
279
+
280
+ switch (er)
281
+ {
282
+ case IDCANCEL:
283
+ case IDABORT:
284
+ ExitOnFailure(hr = E_FAIL, "A partition with a conflictiong name or id exists, key: %S", pItm->wzKey);
285
+ break;
286
+ case IDRETRY:
287
+ break;
288
+ case IDIGNORE:
289
+ default:
290
+ // if we don't have an id, copy id from object
291
+ if (!*pItm->wzID)
292
+ {
293
+ hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID));
294
+ ExitOnFailure(hr, "Failed to get id");
295
+ }
296
+ hr = S_FALSE; // indicate that this is not a conflict
297
+ }
298
+ } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts
299
+
300
+ // create a new id if one is missing
301
+ if (!*pItm->wzID)
302
+ {
303
+ hr = CpiCreateId(pItm->wzID, countof(pItm->wzID));
304
+ ExitOnFailure(hr, "Failed to create id");
305
+ }
306
+ }
307
+
308
+ // clean up
309
+ ReleaseNullObject(piPartObj);
310
+ }
311
+
312
+ hr = S_OK;
313
+
314
+LExit:
315
+ // clean up
316
+ ReleaseObject(piPartColl);
317
+ ReleaseObject(piPartObj);
318
+
319
+ return hr;
320
+}
321
+
322
+HRESULT CpiPartitionsVerifyUninstall(
323
+ CPI_PARTITION_LIST* pList
324
+ )
325
+{
326
+ HRESULT hr = S_OK;
327
+ ICatalogCollection* piPartColl = NULL;
328
+ ICatalogObject* piPartObj = NULL;
329
+
330
+ for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
331
+ {
332
+ // referenced locaters or partitions that are being uninstalled
333
+ if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction)))
334
+ continue;
335
+
336
+ // get partitions collection
337
+ if (!piPartColl)
338
+ {
339
+ hr = CpiGetPartitionsCollection(&piPartColl);
340
+ ExitOnFailure(hr, "Failed to get partitions collection");
341
+ }
342
+
343
+ // get collection object for partition
344
+ hr = CpiFindCollectionObject(piPartColl, pItm->wzID, *pItm->wzID ? NULL : pItm->wzName, &piPartObj);
345
+ ExitOnFailure(hr, "Failed to find collection object for partition");
346
+
347
+ // if the partition was found
348
+ if (S_OK == hr)
349
+ {
350
+ // if we don't have an id, copy id from object
351
+ if (!*pItm->wzID)
352
+ {
353
+ hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID));
354
+ ExitOnFailure(hr, "Failed to get id");
355
+ }
356
+ }
357
+
358
+ // if the partition was not found
359
+ else
360
+ {
361
+ pItm->fObjectNotFound = TRUE;
362
+ if (pItm->fHasComponent)
363
+ pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall
364
+ }
365
+
366
+ // clean up
367
+ ReleaseNullObject(piPartObj);
368
+ }
369
+
370
+ hr = S_OK;
371
+
372
+LExit:
373
+ // clean up
374
+ ReleaseObject(piPartColl);
375
+ ReleaseObject(piPartObj);
376
+
377
+ return hr;
378
+}
379
+
380
+void CpiPartitionAddReferenceInstall(
381
+ CPI_PARTITION* pItm
382
+ )
383
+{
384
+ pItm->fReferencedForInstall = TRUE;
385
+}
386
+
387
+void CpiPartitionAddReferenceUninstall(
388
+ CPI_PARTITION* pItm
389
+ )
390
+{
391
+ pItm->fReferencedForUninstall = TRUE;
392
+}
393
+
394
+HRESULT CpiPartitionsInstall(
395
+ CPI_PARTITION_LIST* pList,
396
+ int iRunMode,
397
+ LPWSTR* ppwzActionData,
398
+ int* piProgress
399
+ )
400
+{
401
+ HRESULT hr = S_OK;
402
+
403
+ int iActionType;
404
+
405
+ // add action text
406
+ hr = CpiAddActionTextToActionData(L"CreateComPlusPartitions", ppwzActionData);
407
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
408
+
409
+ // add partition count to action data
410
+ hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
411
+ ExitOnFailure(hr, "Failed to add count to custom action data");
412
+
413
+ // add applications to custom action data
414
+ for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
415
+ {
416
+ // partitions that are being installed only
417
+ if (!pItm->fHasComponent || !WcaIsInstalling(pItm->isInstalled, pItm->isAction))
418
+ continue;
419
+
420
+ // action type
421
+ if (rmRollback == iRunMode)
422
+ {
423
+ if (CpiIsInstalled(pItm->isInstalled))
424
+ iActionType = atNoOp;
425
+ else
426
+ iActionType = atRemove;
427
+ }
428
+ else
429
+ iActionType = atCreate;
430
+
431
+ // add to action data
432
+ hr = AddPartitionToActionData(pItm, iActionType, COST_PARTITION_CREATE, ppwzActionData);
433
+ ExitOnFailure(hr, "Failed to add partition to custom action data, key: %S", pItm->wzKey);
434
+ }
435
+
436
+ // add progress tics
437
+ if (piProgress)
438
+ *piProgress += COST_PARTITION_CREATE * pList->iInstallCount;
439
+
440
+ hr = S_OK;
441
+
442
+LExit:
443
+ return hr;
444
+}
445
+
446
+HRESULT CpiPartitionsUninstall(
447
+ CPI_PARTITION_LIST* pList,
448
+ int iRunMode,
449
+ LPWSTR* ppwzActionData,
450
+ int* piProgress
451
+ )
452
+{
453
+ HRESULT hr = S_OK;
454
+
455
+ int iActionType;
456
+
457
+ // add action text
458
+ hr = CpiAddActionTextToActionData(L"RemoveComPlusPartitions", ppwzActionData);
459
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
460
+
461
+ // add partition count to action data
462
+ hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
463
+ ExitOnFailure(hr, "Failed to add count to custom action data");
464
+
465
+ // add partitions to custom action data
466
+ for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
467
+ {
468
+ // partitions that are being uninstalled only
469
+ if (!pItm->fHasComponent || pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
470
+ continue;
471
+
472
+ // action type
473
+ if (rmRollback == iRunMode)
474
+ iActionType = atCreate;
475
+ else
476
+ iActionType = atRemove;
477
+
478
+ // add to action data
479
+ hr = AddPartitionToActionData(pItm, iActionType, COST_PARTITION_DELETE, ppwzActionData);
480
+ ExitOnFailure(hr, "Failed to add partition to custom action data, key:", pItm->wzKey);
481
+ }
482
+
483
+ // add progress tics
484
+ if (piProgress)
485
+ *piProgress += COST_PARTITION_DELETE * pList->iUninstallCount;
486
+
487
+ hr = S_OK;
488
+
489
+LExit:
490
+ return hr;
491
+}
492
+
493
+HRESULT CpiPartitionFindByKey(
494
+ CPI_PARTITION_LIST* pList,
495
+ LPCWSTR wzKey,
496
+ CPI_PARTITION** ppItm
497
+ )
498
+{
499
+ for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
500
+ {
501
+ if (0 == lstrcmpW(pItm->wzKey, wzKey))
502
+ {
503
+ *ppItm = pItm;
504
+ return S_OK;
505
+ }
506
+ }
507
+
508
+ return S_FALSE;
509
+}
510
+
511
+HRESULT CpiGetApplicationsCollForPartition(
512
+ CPI_PARTITION* pPart,
513
+ ICatalogCollection** ppiAppColl
514
+ )
515
+{
516
+ HRESULT hr = S_OK;
517
+
518
+ ICatalogCollection* piPartColl = NULL;
519
+ ICatalogObject* piPartObj = NULL;
520
+
521
+ // if a previous attempt to locate the collection object failed
522
+ if (pPart->fObjectNotFound)
523
+ ExitFunction1(hr = S_FALSE);
524
+
525
+ // get applications collection
526
+ if (!pPart->piApplicationsColl)
527
+ {
528
+ // get partitions collection from catalog
529
+ hr = CpiGetPartitionsCollection(&piPartColl);
530
+ ExitOnFailure(hr, "Failed to get partitions collection");
531
+
532
+ // find application object
533
+ hr = CpiFindCollectionObject(piPartColl, pPart->wzID, *pPart->wzID ? NULL : pPart->wzName, &piPartObj);
534
+ ExitOnFailure(hr, "Failed to find partition object");
535
+
536
+ if (S_FALSE == hr)
537
+ {
538
+ pPart->fObjectNotFound = TRUE;
539
+ ExitFunction(); // exit with hr = S_FALSE
540
+ }
541
+
542
+ // get roles collection
543
+ hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"Applications", &pPart->piApplicationsColl);
544
+ ExitOnFailure(hr, "Failed to get applications collection");
545
+ }
546
+
547
+ // return value
548
+ *ppiAppColl = pPart->piApplicationsColl;
549
+ (*ppiAppColl)->AddRef();
550
+
551
+ hr = S_OK;
552
+
553
+LExit:
554
+ // clean up
555
+ ReleaseObject(piPartColl);
556
+ ReleaseObject(piPartObj);
557
+
558
+ return hr;
559
+}
560
+
561
+HRESULT CpiGetRolesCollForPartition(
562
+ CPI_PARTITION* pPart,
563
+ ICatalogCollection** ppiRolesColl
564
+ )
565
+{
566
+ HRESULT hr = S_OK;
567
+
568
+ ICatalogCollection* piPartColl = NULL;
569
+ ICatalogObject* piPartObj = NULL;
570
+
571
+ // if a previous attempt to locate the collection object failed
572
+ if (pPart->fObjectNotFound)
573
+ ExitFunction1(hr = S_FALSE);
574
+
575
+ // get applications collection
576
+ if (!pPart->piRolesColl)
577
+ {
578
+ // get partitions collection from catalog
579
+ hr = CpiGetPartitionsCollection(&piPartColl);
580
+ ExitOnFailure(hr, "Failed to get partitions collection");
581
+
582
+ // find partition object
583
+ hr = CpiFindCollectionObject(piPartColl, pPart->wzID, *pPart->wzID ? NULL : pPart->wzName, &piPartObj);
584
+ ExitOnFailure(hr, "Failed to find partition object");
585
+
586
+ if (S_FALSE == hr)
587
+ ExitFunction(); // exit with hr = S_FALSE
588
+
589
+ // get roles collection
590
+ hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"RolesForPartition", &pPart->piRolesColl);
591
+ ExitOnFailure(hr, "Failed to get roles collection");
592
+ }
593
+
594
+ // return value
595
+ *ppiRolesColl = pPart->piRolesColl;
596
+ (*ppiRolesColl)->AddRef();
597
+
598
+ hr = S_OK;
599
+
600
+LExit:
601
+ // clean up
602
+ ReleaseObject(piPartColl);
603
+ ReleaseObject(piPartObj);
604
+
605
+ return hr;
606
+}
607
+
608
+void CpiPartitionUserListFree(
609
+ CPI_PARTITION_USER_LIST* pList
610
+ )
611
+{
612
+ CPI_PARTITION_USER* pItm = pList->pFirst;
613
+
614
+ while (pItm)
615
+ {
616
+ CPI_PARTITION_USER* pDelete = pItm;
617
+ pItm = pItm->pNext;
618
+ FreePartitionUser(pDelete);
619
+ }
620
+}
621
+
622
+HRESULT CpiPartitionUsersRead(
623
+ CPI_PARTITION_LIST* pPartList,
624
+ CPI_PARTITION_USER_LIST* pPartUsrList
625
+ )
626
+{
627
+ HRESULT hr = S_OK;
628
+ UINT er = ERROR_SUCCESS;
629
+
630
+ PMSIHANDLE hView, hRec;
631
+
632
+ CPI_PARTITION_USER* pItm = NULL;
633
+ LPWSTR pwzData = NULL;
634
+ LPWSTR pwzDomain = NULL;
635
+ LPWSTR pwzName = NULL;
636
+ BOOL fMatchingArchitecture = FALSE;
637
+
638
+ // loop through all partition users
639
+ hr = WcaOpenExecuteView(vcsPartitionUserQuery, &hView);
640
+ ExitOnFailure(hr, "Failed to execute view on ComPlusPartitionUser table");
641
+
642
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
643
+ {
644
+ // get component
645
+ hr = WcaGetRecordString(hRec, puqComponent, &pwzData);
646
+ ExitOnFailure(hr, "Failed to get component");
647
+
648
+ // check if the component is our processor architecture
649
+ hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
650
+ ExitOnFailure(hr, "Failed to get component architecture.");
651
+
652
+ if (!fMatchingArchitecture)
653
+ {
654
+ continue; // not the same architecture, ignore
655
+ }
656
+
657
+ // create entry
658
+ pItm = (CPI_PARTITION_USER*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION_USER));
659
+ if (!pItm)
660
+ ExitFunction1(hr = E_OUTOFMEMORY);
661
+
662
+ // get component install state
663
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
664
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
665
+
666
+ // get key
667
+ hr = WcaGetRecordString(hRec, puqPartitionUser, &pwzData);
668
+ ExitOnFailure(hr, "Failed to get key");
669
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
670
+
671
+ // get partition
672
+ hr = WcaGetRecordString(hRec, puqPartition, &pwzData);
673
+ ExitOnFailure(hr, "Failed to get partition");
674
+
675
+ hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition);
676
+ if (S_FALSE == hr)
677
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
678
+ ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData);
679
+
680
+ // get user domain
681
+ hr = WcaGetRecordFormattedString(hRec, puqDomain, &pwzDomain);
682
+ ExitOnFailure(hr, "Failed to get user domain");
683
+
684
+ // get user name
685
+ hr = WcaGetRecordFormattedString(hRec, puqName, &pwzName);
686
+ ExitOnFailure(hr, "Failed to get user name");
687
+
688
+ // build account name
689
+ hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount);
690
+ ExitOnFailure(hr, "Failed to build account name");
691
+
692
+ // set references & increment counters
693
+ if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
694
+ {
695
+ pItm->pPartition->fReferencedForInstall = TRUE;
696
+ pPartUsrList->iInstallCount++;
697
+ }
698
+ if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
699
+ {
700
+ pItm->pPartition->fReferencedForUninstall = TRUE;
701
+ pPartUsrList->iUninstallCount++;
702
+ }
703
+
704
+ // add entry
705
+ if (pPartUsrList->pFirst)
706
+ pItm->pNext = pPartUsrList->pFirst;
707
+ pPartUsrList->pFirst = pItm;
708
+ pItm = NULL;
709
+ }
710
+
711
+ if (E_NOMOREITEMS == hr)
712
+ hr = S_OK;
713
+
714
+LExit:
715
+ // clean up
716
+ if (pItm)
717
+ FreePartitionUser(pItm);
718
+
719
+ ReleaseStr(pwzData);
720
+ ReleaseStr(pwzDomain);
721
+ ReleaseStr(pwzName);
722
+
723
+ return hr;
724
+}
725
+
726
+HRESULT CpiPartitionUsersInstall(
727
+ CPI_PARTITION_USER_LIST* pList,
728
+ int iRunMode,
729
+ LPWSTR* ppwzActionData,
730
+ int* piProgress
731
+ )
732
+{
733
+ HRESULT hr = S_OK;
734
+
735
+ int iActionType;
736
+
737
+ // add action text
738
+ hr = CpiAddActionTextToActionData(L"AddComPlusPartitionUsers", ppwzActionData);
739
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
740
+
741
+ // add partition count to action data
742
+ hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
743
+ ExitOnFailure(hr, "Failed to add count to custom action data");
744
+
745
+ // add applications to custom action data
746
+ for (CPI_PARTITION_USER* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
747
+ {
748
+ // partitions that are being installed only
749
+ if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction))
750
+ continue;
751
+
752
+ // action type
753
+ if (rmRollback == iRunMode)
754
+ {
755
+ if (CpiIsInstalled(pItm->isInstalled))
756
+ iActionType = atNoOp;
757
+ else
758
+ iActionType = atRemove;
759
+ }
760
+ else
761
+ iActionType = atCreate;
762
+
763
+ // add to action data
764
+ hr = AddPartitionUserToActionData(pItm, iActionType, COST_PARTITION_USER_CREATE, ppwzActionData);
765
+ ExitOnFailure(hr, "Failed to add partition user to custom action data, key: %S", pItm->wzKey);
766
+ }
767
+
768
+ // add progress tics
769
+ if (piProgress)
770
+ *piProgress += COST_PARTITION_USER_CREATE * pList->iInstallCount;
771
+
772
+ hr = S_OK;
773
+
774
+LExit:
775
+ return hr;
776
+}
777
+
778
+HRESULT CpiPartitionUsersUninstall(
779
+ CPI_PARTITION_USER_LIST* pList,
780
+ int iRunMode,
781
+ LPWSTR* ppwzActionData,
782
+ int* piProgress
783
+ )
784
+{
785
+ HRESULT hr = S_OK;
786
+
787
+ int iActionType;
788
+
789
+ // add action text
790
+ hr = CpiAddActionTextToActionData(L"RemoveComPlusPartitionUsers", ppwzActionData);
791
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
792
+
793
+ // add partition count to action data
794
+ hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
795
+ ExitOnFailure(hr, "Failed to add count to custom action data");
796
+
797
+ // add partitions to custom action data
798
+ for (CPI_PARTITION_USER* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
799
+ {
800
+ // partitions that are being uninstalled only
801
+ if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
802
+ continue;
803
+
804
+ // action type
805
+ if (rmRollback == iRunMode)
806
+ iActionType = atCreate;
807
+ else
808
+ iActionType = atRemove;
809
+
810
+ // add to action data
811
+ hr = AddPartitionUserToActionData(pItm, iActionType, COST_PARTITION_USER_DELETE, ppwzActionData);
812
+ ExitOnFailure(hr, "Failed to add partition user to custom action data, key: %S", pItm->wzKey);
813
+ }
814
+
815
+ // add progress tics
816
+ if (piProgress)
817
+ *piProgress += COST_PARTITION_USER_DELETE * pList->iUninstallCount;
818
+
819
+ hr = S_OK;
820
+
821
+LExit:
822
+ return hr;
823
+}
824
+
825
+
826
+// helper function definitions
827
+
828
+static void FreePartition(
829
+ CPI_PARTITION* pItm
830
+ )
831
+{
832
+ if (pItm->pProperties)
833
+ CpiPropertiesFreeList(pItm->pProperties);
834
+
835
+ ReleaseObject(pItm->piApplicationsColl);
836
+ ReleaseObject(pItm->piRolesColl);
837
+
838
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
839
+}
840
+
841
+static void FreePartitionUser(
842
+ CPI_PARTITION_USER* pItm
843
+ )
844
+{
845
+ ReleaseStr(pItm->pwzAccount);
846
+
847
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
848
+}
849
+
850
+static HRESULT AddPartitionToActionData(
851
+ CPI_PARTITION* pItm,
852
+ int iActionType,
853
+ int iActionCost,
854
+ LPWSTR* ppwzActionData
855
+ )
856
+{
857
+ HRESULT hr = S_OK;
858
+
859
+ // add action information to custom action data
860
+ hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
861
+ ExitOnFailure(hr, "Failed to add action type to custom action data");
862
+ hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
863
+ ExitOnFailure(hr, "Failed to add action cost to custom action data");
864
+
865
+ // add partition information to custom action data
866
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
867
+ ExitOnFailure(hr, "Failed to add partition key to custom action data");
868
+ hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData);
869
+ ExitOnFailure(hr, "Failed to add partition id to custom action data");
870
+ hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData);
871
+ ExitOnFailure(hr, "Failed to add partition name to custom action data");
872
+
873
+ // add properties to custom action data
874
+ hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData);
875
+ ExitOnFailure(hr, "Failed to add properties to custom action data");
876
+
877
+ hr = S_OK;
878
+
879
+LExit:
880
+ return hr;
881
+}
882
+
883
+static HRESULT AddPartitionUserToActionData(
884
+ CPI_PARTITION_USER* pItm,
885
+ int iActionType,
886
+ int iActionCost,
887
+ LPWSTR* ppwzActionData
888
+ )
889
+{
890
+ HRESULT hr = S_OK;
891
+
892
+ // add action information to custom action data
893
+ hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
894
+ ExitOnFailure(hr, "Failed to add action type to custom action data");
895
+ hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
896
+ ExitOnFailure(hr, "Failed to add action cost to custom action data");
897
+
898
+ // add partition user information to custom action data
899
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
900
+ ExitOnFailure(hr, "Failed to add partition user key to custom action data");
901
+ hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData);
902
+ ExitOnFailure(hr, "Failed to add user account to custom action data");
903
+
904
+ // add partition information to custom action data
905
+ hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pPartition->wzID : L"", ppwzActionData);
906
+ ExitOnFailure(hr, "Failed to add partition id to custom action data");
907
+
908
+ hr = S_OK;
909
+
910
+LExit:
911
+ return hr;
912
+}
src/ca/cppartsched.h
new
+125
@@ -0,0 +1,125 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+struct CPI_PARTITION
6
+{
7
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
8
+ WCHAR wzID[CPI_MAX_GUID + 1];
9
+ WCHAR wzName[MAX_DARWIN_COLUMN + 1];
10
+
11
+ int iPropertyCount;
12
+ CPI_PROPERTY* pProperties;
13
+
14
+ BOOL fHasComponent;
15
+ BOOL fReferencedForInstall;
16
+ BOOL fReferencedForUninstall;
17
+ BOOL fObjectNotFound;
18
+
19
+ INSTALLSTATE isInstalled, isAction;
20
+
21
+ ICatalogCollection* piApplicationsColl;
22
+ ICatalogCollection* piRolesColl;
23
+
24
+ CPI_PARTITION* pNext;
25
+};
26
+
27
+struct CPI_PARTITION_LIST
28
+{
29
+ CPI_PARTITION* pFirst;
30
+
31
+ int iInstallCount;
32
+ int iUninstallCount;
33
+};
34
+
35
+struct CPI_PARTITION_USER
36
+{
37
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
38
+ LPWSTR pwzAccount;
39
+
40
+ BOOL fNoFind;
41
+
42
+ INSTALLSTATE isInstalled, isAction;
43
+
44
+ CPI_PARTITION* pPartition;
45
+
46
+ CPI_PARTITION_USER* pNext;
47
+};
48
+
49
+struct CPI_PARTITION_USER_LIST
50
+{
51
+ CPI_PARTITION_USER* pFirst;
52
+
53
+ int iInstallCount;
54
+ int iUninstallCount;
55
+};
56
+
57
+
58
+// function prototypes
59
+
60
+void CpiPartitionListFree(
61
+ CPI_PARTITION_LIST* pList
62
+ );
63
+HRESULT CpiPartitionsRead(
64
+ CPI_PARTITION_LIST* pPartList
65
+ );
66
+HRESULT CpiPartitionsVerifyInstall(
67
+ CPI_PARTITION_LIST* pList
68
+ );
69
+HRESULT CpiPartitionsVerifyUninstall(
70
+ CPI_PARTITION_LIST* pList
71
+ );
72
+void CpiPartitionAddReferenceInstall(
73
+ CPI_PARTITION* pItm
74
+ );
75
+void CpiPartitionAddReferenceUninstall(
76
+ CPI_PARTITION* pItm
77
+ );
78
+HRESULT CpiPartitionsInstall(
79
+ CPI_PARTITION_LIST* pList,
80
+ int iRunMode,
81
+ LPWSTR* ppwzActionData,
82
+ int* piProgress
83
+ );
84
+HRESULT CpiPartitionsUninstall(
85
+ CPI_PARTITION_LIST* pList,
86
+ int iRunMode,
87
+ LPWSTR* ppwzActionData,
88
+ int* piProgress
89
+ );
90
+HRESULT CpiPartitionFindByKey(
91
+ CPI_PARTITION_LIST* pList,
92
+ LPCWSTR wzKey,
93
+ CPI_PARTITION** ppItm
94
+ );
95
+HRESULT CpiGetApplicationsCollForPartition(
96
+ CPI_PARTITION* pPart,
97
+ ICatalogCollection** ppiAppColl
98
+ );
99
+HRESULT CpiGetPartitionUsersCollection(
100
+ CPI_PARTITION* pPart,
101
+ ICatalogCollection** ppiPartUsrColl
102
+ );
103
+HRESULT CpiGetRolesCollForPartition(
104
+ CPI_PARTITION* pPart,
105
+ ICatalogCollection** ppiRolesColl
106
+ );
107
+void CpiPartitionUserListFree(
108
+ CPI_PARTITION_USER_LIST* pList
109
+ );
110
+HRESULT CpiPartitionUsersRead(
111
+ CPI_PARTITION_LIST* pPartList,
112
+ CPI_PARTITION_USER_LIST* pPartUsrList
113
+ );
114
+HRESULT CpiPartitionUsersInstall(
115
+ CPI_PARTITION_USER_LIST* pList,
116
+ int iRunMode,
117
+ LPWSTR* ppwzActionData,
118
+ int* piProgress
119
+ );
120
+HRESULT CpiPartitionUsersUninstall(
121
+ CPI_PARTITION_USER_LIST* pList,
122
+ int iRunMode,
123
+ LPWSTR* ppwzActionData,
124
+ int* piProgress
125
+ );
src/ca/cpsched.cpp
new
+590
@@ -0,0 +1,590 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+#ifdef _WIN64
7
+#define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare_64"
8
+#define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare_64"
9
+#define CP_COMPLUSROLLBACKINSTALLEXECUTE L"ComPlusRollbackInstallExecute_64"
10
+#define CP_COMPLUSINSTALLEXECUTE L"ComPlusInstallExecute_64"
11
+#define CP_COMPLUSINSTALLEXECUTECOMMIT L"ComPlusInstallExecuteCommit_64"
12
+#define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit_64"
13
+#define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare_64"
14
+#define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare_64"
15
+#define CP_COMPLUSROLLBACKUNINSTALLEXECUTE L"ComPlusRollbackUninstallExecute_64"
16
+#define CP_COMPLUSUNINSTALLEXECUTE L"ComPlusUninstallExecute_64"
17
+#define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit_64"
18
+#else
19
+#define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare"
20
+#define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare"
21
+#define CP_COMPLUSROLLBACKINSTALLEXECUTE L"ComPlusRollbackInstallExecute"
22
+#define CP_COMPLUSINSTALLEXECUTE L"ComPlusInstallExecute"
23
+#define CP_COMPLUSINSTALLEXECUTECOMMIT L"ComPlusInstallExecuteCommit"
24
+#define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit"
25
+#define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare"
26
+#define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare"
27
+#define CP_COMPLUSROLLBACKUNINSTALLEXECUTE L"ComPlusRollbackUninstallExecute"
28
+#define CP_COMPLUSUNINSTALLEXECUTE L"ComPlusUninstallExecute"
29
+#define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit"
30
+#endif
31
+
32
+
33
+/********************************************************************
34
+ DllMain - standard entry point for all WiX CustomActions
35
+
36
+********************************************************************/
37
+extern "C" BOOL WINAPI DllMain(
38
+ IN HINSTANCE hInst,
39
+ IN ULONG ulReason,
40
+ IN LPVOID)
41
+{
42
+ switch(ulReason)
43
+ {
44
+ case DLL_PROCESS_ATTACH:
45
+ WcaGlobalInitialize(hInst);
46
+ break;
47
+
48
+ case DLL_PROCESS_DETACH:
49
+ WcaGlobalFinalize();
50
+ break;
51
+ }
52
+
53
+ return TRUE;
54
+}
55
+
56
+/********************************************************************
57
+ ConfigureComPlusInstall - CUSTOM ACTION ENTRY POINT for installing COM+ components
58
+
59
+********************************************************************/
60
+extern "C" UINT __stdcall ConfigureComPlusInstall(MSIHANDLE hInstall)
61
+{
62
+ HRESULT hr = S_OK;
63
+ UINT er = ERROR_SUCCESS;
64
+
65
+ BOOL fInitializedCom = FALSE;
66
+
67
+ ICOMAdminCatalog* piCatalog = NULL;
68
+
69
+ CPI_PARTITION_LIST partList;
70
+ CPI_PARTITION_ROLE_LIST partRoleList;
71
+ CPI_USER_IN_PARTITION_ROLE_LIST usrInPartRoleList;
72
+ CPI_PARTITION_USER_LIST partUsrList;
73
+ CPI_APPLICATION_LIST appList;
74
+ CPI_APPLICATION_ROLE_LIST appRoleList;
75
+ CPI_USER_IN_APPLICATION_ROLE_LIST usrInAppRoleList;
76
+ CPI_ASSEMBLY_LIST asmList;
77
+ CPI_SUBSCRIPTION_LIST subList;
78
+
79
+ LPWSTR pwzRollbackFileName = NULL;
80
+ LPWSTR pwzActionData = NULL;
81
+ LPWSTR pwzRollbackActionData = NULL;
82
+ LPWSTR pwzCommitActionData = NULL;
83
+
84
+ int iVersionNT = 0;
85
+ int iProgress = 0;
86
+ int iCommitProgress = 0;
87
+
88
+ ::ZeroMemory(&partList, sizeof(CPI_PARTITION_LIST));
89
+ ::ZeroMemory(&partRoleList, sizeof(CPI_PARTITION_ROLE_LIST));
90
+ ::ZeroMemory(&usrInPartRoleList, sizeof(CPI_USER_IN_PARTITION_ROLE_LIST));
91
+ ::ZeroMemory(&partUsrList, sizeof(CPI_PARTITION_USER_LIST));
92
+ ::ZeroMemory(&appList, sizeof(CPI_APPLICATION_LIST));
93
+ ::ZeroMemory(&appRoleList, sizeof(CPI_APPLICATION_ROLE_LIST));
94
+ ::ZeroMemory(&usrInAppRoleList, sizeof(CPI_USER_IN_APPLICATION_ROLE_LIST));
95
+ ::ZeroMemory(&asmList, sizeof(CPI_ASSEMBLY_LIST));
96
+ ::ZeroMemory(&subList, sizeof(CPI_SUBSCRIPTION_LIST));
97
+
98
+ // initialize
99
+ hr = WcaInitialize(hInstall, "ConfigureComPlusInstall");
100
+ ExitOnFailure(hr, "Failed to initialize");
101
+
102
+ hr = ::CoInitialize(NULL);
103
+ ExitOnFailure(hr, "Failed to initialize COM");
104
+ fInitializedCom = TRUE;
105
+
106
+ CpiInitialize();
107
+
108
+ // check for the prerequsite tables
109
+ if (!CpiTableExists(cptComPlusPartition) && !CpiTableExists(cptComPlusApplication) && !CpiTableExists(cptComPlusAssembly))
110
+ {
111
+ WcaLog(LOGMSG_VERBOSE, "skipping install COM+ CustomAction, no ComPlusPartition, ComPlusApplication or ComPlusAssembly table present");
112
+ ExitFunction1(hr = S_FALSE);
113
+ }
114
+
115
+ // make sure we can access the COM+ admin catalog
116
+ do {
117
+ hr = CpiGetAdminCatalog(&piCatalog);
118
+ if (FAILED(hr))
119
+ {
120
+ WcaLog(LOGMSG_STANDARD, "Failed to get COM+ admin catalog");
121
+ er = WcaErrorMessage(msierrComPlusCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
122
+ switch (er)
123
+ {
124
+ case IDABORT:
125
+ ExitFunction(); // exit with hr from CpiGetAdminCatalog() to kick off a rollback
126
+ case IDRETRY:
127
+ hr = S_FALSE;
128
+ break;
129
+ case IDIGNORE:
130
+ default:
131
+ ExitFunction1(hr = S_OK); // pretend everything is okay and bail
132
+ }
133
+ }
134
+ } while (S_FALSE == hr);
135
+
136
+ // get NT version
137
+ hr = WcaGetIntProperty(L"VersionNT", &iVersionNT);
138
+ ExitOnFailure(hr, "Failed to get VersionNT property");
139
+
140
+ // read elements
141
+ if (502 <= iVersionNT && CpiTableExists(cptComPlusPartition))
142
+ {
143
+ hr = CpiPartitionsRead(&partList);
144
+ MessageExitOnFailure(hr, msierrComPlusPartitionReadFailed, "Failed to read ComPlusPartitions table");
145
+ }
146
+
147
+ if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionRole))
148
+ {
149
+ hr = CpiPartitionRolesRead(&partList, &partRoleList);
150
+ MessageExitOnFailure(hr, msierrComPlusPartitionRoleReadFailed, "Failed to read ComPlusPartitionRole table");
151
+ }
152
+
153
+ if (502 <= iVersionNT && (CpiTableExists(cptComPlusUserInPartitionRole) || CpiTableExists(cptComPlusGroupInPartitionRole)))
154
+ {
155
+ hr = CpiUsersInPartitionRolesRead(&partRoleList, &usrInPartRoleList);
156
+ MessageExitOnFailure(hr, msierrComPlusUserInPartitionRoleReadFailed, "Failed to read ComPlusUserInPartitionRole table");
157
+ }
158
+
159
+ if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionUser))
160
+ {
161
+ hr = CpiPartitionUsersRead(&partList, &partUsrList);
162
+ MessageExitOnFailure(hr, msierrComPlusPartitionUserReadFailed, "Failed to read ComPlusPartitionUser table");
163
+ }
164
+
165
+ if (CpiTableExists(cptComPlusApplication))
166
+ {
167
+ hr = CpiApplicationsRead(&partList, &appList);
168
+ MessageExitOnFailure(hr, msierrComPlusApplicationReadFailed, "Failed to read ComPlusApplication table");
169
+ }
170
+
171
+ if (CpiTableExists(cptComPlusApplicationRole))
172
+ {
173
+ hr = CpiApplicationRolesRead(&appList, &appRoleList);
174
+ MessageExitOnFailure(hr, msierrComPlusApplicationRoleReadFailed, "Failed to read ComPlusApplicationRole table");
175
+ }
176
+
177
+ if (CpiTableExists(cptComPlusUserInApplicationRole) || CpiTableExists(cptComPlusGroupInApplicationRole))
178
+ {
179
+ hr = CpiUsersInApplicationRolesRead(&appRoleList, &usrInAppRoleList);
180
+ MessageExitOnFailure(hr, msierrComPlusUserInApplicationRoleReadFailed, "Failed to read ComPlusUserInApplicationRole table");
181
+ }
182
+
183
+ if (CpiTableExists(cptComPlusAssembly))
184
+ {
185
+ hr = CpiAssembliesRead(&appList, &appRoleList, &asmList);
186
+ MessageExitOnFailure(hr, msierrComPlusAssembliesReadFailed, "Failed to read ComPlusAssembly table");
187
+ }
188
+
189
+ if (CpiTableExists(cptComPlusSubscription))
190
+ {
191
+ hr = CpiSubscriptionsRead(&asmList, &subList);
192
+ MessageExitOnFailure(hr, msierrComPlusSubscriptionReadFailed, "Failed to read ComPlusSubscription table");
193
+ }
194
+
195
+ // verify elements
196
+ hr = CpiPartitionsVerifyInstall(&partList);
197
+ ExitOnFailure(hr, "Failed to verify partitions");
198
+
199
+ hr = CpiApplicationsVerifyInstall(&appList);
200
+ ExitOnFailure(hr, "Failed to verify applications");
201
+
202
+ hr = CpiApplicationRolesVerifyInstall(&appRoleList);
203
+ ExitOnFailure(hr, "Failed to verify application roles");
204
+
205
+ hr = CpiAssembliesVerifyInstall(&asmList);
206
+ ExitOnFailure(hr, "Failed to verify assemblies");
207
+
208
+ if (subList.iInstallCount)
209
+ {
210
+ hr = CpiSubscriptionsVerifyInstall(&subList);
211
+ ExitOnFailure(hr, "Failed to verify subscriptions");
212
+ }
213
+
214
+ // schedule
215
+ if (partList.iInstallCount || appList.iInstallCount || usrInAppRoleList.iInstallCount ||
216
+ appRoleList.iInstallCount || asmList.iInstallCount || asmList.iRoleInstallCount || subList.iInstallCount)
217
+ {
218
+ // create rollback file name
219
+ hr = CpiGetTempFileName(&pwzRollbackFileName);
220
+ ExitOnFailure(hr, "Failed to get rollback file name");
221
+
222
+ // schedule rollback prepare custom action
223
+ hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKINSTALLPREPARE, pwzRollbackFileName, 0);
224
+ ExitOnFailure(hr, "Failed to schedule ComPlusRollbackInstallPrepare");
225
+
226
+ // schedule prepare custom action
227
+ hr = WcaDoDeferredAction(CP_COMPLUSINSTALLPREPARE, pwzRollbackFileName, 0);
228
+ ExitOnFailure(hr, "Failed to schedule ComPlusInstallPrepare");
229
+
230
+ // schedule rollback custom action
231
+ hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzRollbackActionData);
232
+ ExitOnFailure(hr, "Failed to add rollback file name to rollback custom action data");
233
+
234
+ hr = CpiSubscriptionsInstall(&subList, rmRollback, &pwzRollbackActionData, NULL);
235
+ ExitOnFailure(hr, "Failed to install subscriptions");
236
+ hr = CpiRoleAssignmentsInstall(&asmList, rmRollback, &pwzRollbackActionData, NULL);
237
+ ExitOnFailure(hr, "Failed to install assemblies");
238
+ hr = CpiAssembliesInstall(&asmList, rmRollback, &pwzRollbackActionData, NULL);
239
+ ExitOnFailure(hr, "Failed to install assemblies");
240
+ hr = CpiUsersInApplicationRolesInstall(&usrInAppRoleList, rmRollback, &pwzRollbackActionData, NULL);
241
+ ExitOnFailure(hr, "Failed to install users in application roles");
242
+ hr = CpiApplicationRolesInstall(&appRoleList, rmRollback, &pwzRollbackActionData, NULL);
243
+ ExitOnFailure(hr, "Failed to install application roles");
244
+ hr = CpiApplicationsInstall(&appList, rmRollback, &pwzRollbackActionData, NULL);
245
+ ExitOnFailure(hr, "Failed to install applications");
246
+ hr = CpiPartitionUsersInstall(&partUsrList, rmRollback, &pwzRollbackActionData, NULL);
247
+ ExitOnFailure(hr, "Failed to install partition users");
248
+ hr = CpiUsersInPartitionRolesInstall(&usrInPartRoleList, rmRollback, &pwzRollbackActionData, NULL);
249
+ ExitOnFailure(hr, "Failed to install users in partition roles");
250
+ hr = CpiPartitionsInstall(&partList, rmRollback, &pwzRollbackActionData, NULL);
251
+ ExitOnFailure(hr, "Failed to install partitions");
252
+
253
+ hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKINSTALLEXECUTE, pwzRollbackActionData, 0);
254
+ ExitOnFailure(hr, "Failed to schedule ComPlusRollbackInstallExecute");
255
+
256
+ // schedule install custom action
257
+ hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzActionData);
258
+ ExitOnFailure(hr, "Failed to add rollback file name to custom action data");
259
+
260
+ hr = CpiPartitionsInstall(&partList, rmDeferred, &pwzActionData, &iProgress);
261
+ ExitOnFailure(hr, "Failed to install partitions");
262
+ hr = CpiUsersInPartitionRolesInstall(&usrInPartRoleList, rmDeferred, &pwzActionData, &iProgress);
263
+ ExitOnFailure(hr, "Failed to install users in partition roles");
264
+ hr = CpiPartitionUsersInstall(&partUsrList, rmDeferred, &pwzActionData, &iProgress);
265
+ ExitOnFailure(hr, "Failed to install partition users");
266
+ hr = CpiApplicationsInstall(&appList, rmDeferred, &pwzActionData, &iProgress);
267
+ ExitOnFailure(hr, "Failed to install applications");
268
+ hr = CpiApplicationRolesInstall(&appRoleList, rmDeferred, &pwzActionData, &iProgress);
269
+ ExitOnFailure(hr, "Failed to install application roles");
270
+ hr = CpiUsersInApplicationRolesInstall(&usrInAppRoleList, rmDeferred, &pwzActionData, &iProgress);
271
+ ExitOnFailure(hr, "Failed to install users in application roles");
272
+ hr = CpiAssembliesInstall(&asmList, rmDeferred, &pwzActionData, &iProgress);
273
+ ExitOnFailure(hr, "Failed to install assemblies");
274
+ hr = CpiRoleAssignmentsInstall(&asmList, rmDeferred, &pwzActionData, &iProgress);
275
+ ExitOnFailure(hr, "Failed to install assemblies");
276
+ hr = CpiSubscriptionsInstall(&subList, rmDeferred, &pwzActionData, &iProgress);
277
+ ExitOnFailure(hr, "Failed to install subscriptions");
278
+
279
+ hr = WcaDoDeferredAction(CP_COMPLUSINSTALLEXECUTE, pwzActionData, iProgress);
280
+ ExitOnFailure(hr, "Failed to schedule ComPlusInstallExecute");
281
+
282
+ // schedule install commit custom action
283
+ hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzCommitActionData);
284
+ ExitOnFailure(hr, "Failed to add rollback file name to commit custom action data");
285
+
286
+ hr = CpiAssembliesInstall(&asmList, rmCommit, &pwzCommitActionData, &iCommitProgress);
287
+ ExitOnFailure(hr, "Failed to install assemblies");
288
+ hr = CpiRoleAssignmentsInstall(&asmList, rmCommit, &pwzCommitActionData, &iCommitProgress);
289
+ ExitOnFailure(hr, "Failed to install assemblies");
290
+ hr = CpiSubscriptionsInstall(&subList, rmCommit, &pwzCommitActionData, &iCommitProgress);
291
+ ExitOnFailure(hr, "Failed to install subscriptions");
292
+
293
+ hr = WcaDoDeferredAction(CP_COMPLUSINSTALLEXECUTECOMMIT, pwzCommitActionData, iCommitProgress);
294
+ ExitOnFailure(hr, "Failed to schedule ComPlusInstallExecuteCommit");
295
+
296
+ // schedule commit custom action
297
+ hr = WcaDoDeferredAction(CP_COMPLUSINSTALLCOMMIT, pwzRollbackFileName, 0);
298
+ ExitOnFailure(hr, "Failed to schedule ComPlusInstallCommit");
299
+ }
300
+
301
+ hr = S_OK;
302
+
303
+LExit:
304
+ // clean up
305
+ ReleaseObject(piCatalog);
306
+
307
+ ReleaseStr(pwzRollbackFileName);
308
+ ReleaseStr(pwzActionData);
309
+ ReleaseStr(pwzRollbackActionData);
310
+ ReleaseStr(pwzCommitActionData);
311
+
312
+ CpiPartitionListFree(&partList);
313
+ CpiPartitionRoleListFree(&partRoleList);
314
+ CpiUserInPartitionRoleListFree(&usrInPartRoleList);
315
+ CpiPartitionUserListFree(&partUsrList);
316
+ CpiApplicationListFree(&appList);
317
+ CpiApplicationRoleListFree(&appRoleList);
318
+ CpiUserInApplicationRoleListFree(&usrInAppRoleList);
319
+ CpiAssemblyListFree(&asmList);
320
+ CpiSubscriptionListFree(&subList);
321
+
322
+ // unitialize
323
+ CpiFinalize();
324
+
325
+ if (fInitializedCom)
326
+ ::CoUninitialize();
327
+
328
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
329
+ return WcaFinalize(er);
330
+}
331
+
332
+
333
+/********************************************************************
334
+ ConfigureComPlusUninstall - CUSTOM ACTION ENTRY POINT for uninstalling COM+ components
335
+
336
+********************************************************************/
337
+extern "C" UINT __stdcall ConfigureComPlusUninstall(MSIHANDLE hInstall)
338
+{
339
+ HRESULT hr = S_OK;
340
+ UINT er = ERROR_SUCCESS;
341
+
342
+ BOOL fInitializedCom = FALSE;
343
+
344
+ ICOMAdminCatalog* piCatalog = NULL;
345
+
346
+ CPI_PARTITION_LIST partList;
347
+ CPI_PARTITION_ROLE_LIST partRoleList;
348
+ CPI_USER_IN_PARTITION_ROLE_LIST usrInPartRoleList;
349
+ CPI_PARTITION_USER_LIST partUsrList;
350
+ CPI_APPLICATION_LIST appList;
351
+ CPI_APPLICATION_ROLE_LIST appRoleList;
352
+ CPI_USER_IN_APPLICATION_ROLE_LIST usrInAppRoleList;
353
+ CPI_ASSEMBLY_LIST asmList;
354
+ CPI_SUBSCRIPTION_LIST subList;
355
+
356
+ LPWSTR pwzRollbackFileName = NULL;
357
+ LPWSTR pwzActionData = NULL;
358
+ LPWSTR pwzRollbackActionData = NULL;
359
+
360
+ int iVersionNT = 0;
361
+ int iProgress = 0;
362
+
363
+ ::ZeroMemory(&partList, sizeof(CPI_PARTITION_LIST));
364
+ ::ZeroMemory(&partRoleList, sizeof(CPI_PARTITION_ROLE_LIST));
365
+ ::ZeroMemory(&usrInPartRoleList, sizeof(CPI_USER_IN_PARTITION_ROLE_LIST));
366
+ ::ZeroMemory(&partUsrList, sizeof(CPI_PARTITION_USER_LIST));
367
+ ::ZeroMemory(&appList, sizeof(CPI_APPLICATION_LIST));
368
+ ::ZeroMemory(&appRoleList, sizeof(CPI_APPLICATION_ROLE_LIST));
369
+ ::ZeroMemory(&usrInAppRoleList, sizeof(CPI_USER_IN_APPLICATION_ROLE_LIST));
370
+ ::ZeroMemory(&asmList, sizeof(CPI_ASSEMBLY_LIST));
371
+ ::ZeroMemory(&subList, sizeof(CPI_SUBSCRIPTION_LIST));
372
+
373
+ // initialize
374
+ hr = WcaInitialize(hInstall, "ConfigureComPlusUninstall");
375
+ ExitOnFailure(hr, "Failed to initialize");
376
+
377
+ hr = ::CoInitialize(NULL);
378
+ ExitOnFailure(hr, "Failed to initialize COM");
379
+ fInitializedCom = TRUE;
380
+
381
+ CpiInitialize();
382
+
383
+ // check for the prerequsite tables
384
+ if (!CpiTableExists(cptComPlusPartition) && !CpiTableExists(cptComPlusApplication) && !CpiTableExists(cptComPlusAssembly))
385
+ {
386
+ WcaLog(LOGMSG_VERBOSE, "skipping uninstall COM+ CustomAction, no ComPlusPartition, ComPlusApplication or ComPlusAssembly table present");
387
+ ExitFunction1(hr = S_FALSE);
388
+ }
389
+
390
+ // make sure we can access the COM+ admin catalog
391
+ do {
392
+ hr = CpiGetAdminCatalog(&piCatalog);
393
+ if (FAILED(hr))
394
+ {
395
+ WcaLog(LOGMSG_STANDARD, "Failed to get COM+ admin catalog");
396
+ er = WcaErrorMessage(msierrComPlusCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
397
+ switch (er)
398
+ {
399
+ case IDABORT:
400
+ ExitFunction(); // exit with hr from CpiGetAdminCatalog() to kick off a rollback
401
+ case IDRETRY:
402
+ hr = S_FALSE;
403
+ break;
404
+ case IDIGNORE:
405
+ default:
406
+ ExitFunction1(hr = S_OK); // pretend everything is okay and bail
407
+ }
408
+ }
409
+ } while (S_FALSE == hr);
410
+
411
+ // get NT version
412
+ hr = WcaGetIntProperty(L"VersionNT", &iVersionNT);
413
+ ExitOnFailure(hr, "Failed to get VersionNT property");
414
+
415
+ // read elements
416
+ if (502 <= iVersionNT && CpiTableExists(cptComPlusPartition))
417
+ {
418
+ hr = CpiPartitionsRead(&partList);
419
+ MessageExitOnFailure(hr, msierrComPlusPartitionReadFailed, "Failed to read ComPlusPartitions table");
420
+ }
421
+
422
+ if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionRole))
423
+ {
424
+ hr = CpiPartitionRolesRead(&partList, &partRoleList);
425
+ MessageExitOnFailure(hr, msierrComPlusPartitionRoleReadFailed, "Failed to read ComPlusPartitionRole table");
426
+ }
427
+
428
+ if (502 <= iVersionNT && (CpiTableExists(cptComPlusUserInPartitionRole) || CpiTableExists(cptComPlusGroupInPartitionRole)))
429
+ {
430
+ hr = CpiUsersInPartitionRolesRead(&partRoleList, &usrInPartRoleList);
431
+ MessageExitOnFailure(hr, msierrComPlusUserInPartitionRoleReadFailed, "Failed to read ComPlusUserInPartitionRole table");
432
+ }
433
+
434
+ if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionUser))
435
+ {
436
+ hr = CpiPartitionUsersRead(&partList, &partUsrList);
437
+ MessageExitOnFailure(hr, msierrComPlusPartitionUserReadFailed, "Failed to read ComPlusPartitionUser table");
438
+ }
439
+
440
+ if (CpiTableExists(cptComPlusApplication))
441
+ {
442
+ hr = CpiApplicationsRead(&partList, &appList);
443
+ MessageExitOnFailure(hr, msierrComPlusApplicationReadFailed, "Failed to read ComPlusApplication table");
444
+ }
445
+
446
+ if (CpiTableExists(cptComPlusApplicationRole))
447
+ {
448
+ hr = CpiApplicationRolesRead(&appList, &appRoleList);
449
+ MessageExitOnFailure(hr, msierrComPlusApplicationRoleReadFailed, "Failed to read ComPlusApplicationRole table");
450
+ }
451
+
452
+ if (CpiTableExists(cptComPlusUserInApplicationRole) || CpiTableExists(cptComPlusGroupInApplicationRole))
453
+ {
454
+ hr = CpiUsersInApplicationRolesRead(&appRoleList, &usrInAppRoleList);
455
+ MessageExitOnFailure(hr, msierrComPlusUserInApplicationRoleReadFailed, "Failed to read ComPlusUserInApplicationRole table");
456
+ }
457
+
458
+ if (CpiTableExists(cptComPlusAssembly))
459
+ {
460
+ hr = CpiAssembliesRead(&appList, &appRoleList, &asmList);
461
+ MessageExitOnFailure(hr, msierrComPlusAssembliesReadFailed, "Failed to read ComPlusAssembly table");
462
+ }
463
+
464
+ if (CpiTableExists(cptComPlusSubscription))
465
+ {
466
+ hr = CpiSubscriptionsRead(&asmList, &subList);
467
+ MessageExitOnFailure(hr, msierrComPlusSubscriptionReadFailed, "Failed to read ComPlusSubscription table");
468
+ }
469
+
470
+ // verify elements
471
+ hr = CpiPartitionsVerifyUninstall(&partList);
472
+ ExitOnFailure(hr, "Failed to verify partitions");
473
+
474
+ hr = CpiApplicationsVerifyUninstall(&appList);
475
+ ExitOnFailure(hr, "Failed to verify applications");
476
+
477
+ hr = CpiApplicationRolesVerifyUninstall(&appRoleList);
478
+ ExitOnFailure(hr, "Failed to verify application roles");
479
+
480
+ hr = CpiAssembliesVerifyUninstall(&asmList);
481
+ ExitOnFailure(hr, "Failed to verify assemblies");
482
+
483
+ if (subList.iUninstallCount)
484
+ {
485
+ hr = CpiSubscriptionsVerifyUninstall(&subList);
486
+ ExitOnFailure(hr, "Failed to verify subscriptions");
487
+ }
488
+
489
+ // schedule
490
+ if (partList.iUninstallCount || appList.iUninstallCount || appRoleList.iUninstallCount ||
491
+ usrInAppRoleList.iUninstallCount || asmList.iUninstallCount || asmList.iRoleUninstallCount || subList.iUninstallCount)
492
+ {
493
+ // create rollback file name
494
+ hr = CpiGetTempFileName(&pwzRollbackFileName);
495
+ ExitOnFailure(hr, "Failed to get rollback file name");
496
+
497
+ // schedule rollback prepare custom action
498
+ hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKINSTALLPREPARE, pwzRollbackFileName, 0);
499
+ ExitOnFailure(hr, "Failed to schedule ComPlusRollbackInstallPrepare");
500
+
501
+ // schedule prepare custom action
502
+ hr = WcaDoDeferredAction(CP_COMPLUSINSTALLPREPARE, pwzRollbackFileName, 0);
503
+ ExitOnFailure(hr, "Failed to schedule ComPlusInstallPrepare");
504
+
505
+ // schedule rollback custom action
506
+ hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzRollbackActionData);
507
+ ExitOnFailure(hr, "Failed to add rollback file name to rollback custom action data");
508
+
509
+ hr = CpiPartitionsUninstall(&partList, rmRollback, &pwzRollbackActionData, NULL);
510
+ ExitOnFailure(hr, "Failed to uninstall partitions");
511
+ hr = CpiUsersInPartitionRolesUninstall(&usrInPartRoleList, rmRollback, &pwzRollbackActionData, NULL);
512
+ ExitOnFailure(hr, "Failed to uninstall users in partition roles");
513
+ hr = CpiPartitionUsersUninstall(&partUsrList, rmRollback, &pwzRollbackActionData, NULL);
514
+ ExitOnFailure(hr, "Failed to uninstall partition users");
515
+ hr = CpiApplicationsUninstall(&appList, rmRollback, &pwzRollbackActionData, NULL);
516
+ ExitOnFailure(hr, "Failed to uninstall applications");
517
+ hr = CpiApplicationRolesUninstall(&appRoleList, rmRollback, &pwzRollbackActionData, NULL);
518
+ ExitOnFailure(hr, "Failed to uninstall application roles");
519
+ hr = CpiUsersInApplicationRolesUninstall(&usrInAppRoleList, rmRollback, &pwzRollbackActionData, NULL);
520
+ ExitOnFailure(hr, "Failed to uninstall users in application roles");
521
+ hr = CpiAssembliesUninstall(&asmList, rmRollback, &pwzRollbackActionData, NULL);
522
+ ExitOnFailure(hr, "Failed to uninstall assemblies");
523
+ hr = CpiRoleAssignmentsUninstall(&asmList, rmRollback, &pwzRollbackActionData, NULL);
524
+ ExitOnFailure(hr, "Failed to uninstall assemblies");
525
+ hr = CpiSubscriptionsUninstall(&subList, rmRollback, &pwzRollbackActionData, NULL);
526
+ ExitOnFailure(hr, "Failed to uninstall subscriptions");
527
+
528
+ hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKUNINSTALLEXECUTE, pwzRollbackActionData, 0);
529
+ ExitOnFailure(hr, "Failed to schedule ComPlusRollbackUninstallExecute");
530
+
531
+ // schedule install custom action
532
+ hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzActionData);
533
+ ExitOnFailure(hr, "Failed to add rollback file name to custom action data");
534
+
535
+ hr = CpiSubscriptionsUninstall(&subList, rmDeferred, &pwzActionData, &iProgress);
536
+ ExitOnFailure(hr, "Failed to uninstall subscriptions");
537
+ hr = CpiRoleAssignmentsUninstall(&asmList, rmDeferred, &pwzActionData, &iProgress);
538
+ ExitOnFailure(hr, "Failed to uninstall assemblies");
539
+ hr = CpiAssembliesUninstall(&asmList, rmDeferred, &pwzActionData, &iProgress);
540
+ ExitOnFailure(hr, "Failed to uninstall assemblies");
541
+ hr = CpiUsersInApplicationRolesUninstall(&usrInAppRoleList, rmDeferred, &pwzActionData, &iProgress);
542
+ ExitOnFailure(hr, "Failed to uninstall users in application roles");
543
+ hr = CpiApplicationRolesUninstall(&appRoleList, rmDeferred, &pwzActionData, &iProgress);
544
+ ExitOnFailure(hr, "Failed to uninstall application roles");
545
+ hr = CpiApplicationsUninstall(&appList, rmDeferred, &pwzActionData, &iProgress);
546
+ ExitOnFailure(hr, "Failed to uninstall applications");
547
+ hr = CpiPartitionUsersUninstall(&partUsrList, rmDeferred, &pwzActionData, &iProgress);
548
+ ExitOnFailure(hr, "Failed to uninstall partition users");
549
+ hr = CpiUsersInPartitionRolesUninstall(&usrInPartRoleList, rmDeferred, &pwzActionData, &iProgress);
550
+ ExitOnFailure(hr, "Failed to uninstall users in partition roles");
551
+ hr = CpiPartitionsUninstall(&partList, rmDeferred, &pwzActionData, &iProgress);
552
+ ExitOnFailure(hr, "Failed to uninstall partitions");
553
+
554
+ hr = WcaDoDeferredAction(CP_COMPLUSUNINSTALLEXECUTE, pwzActionData, iProgress);
555
+ ExitOnFailure(hr, "Failed to schedule ComPlusUninstallExecute");
556
+
557
+ // schedule commit custom action
558
+ hr = WcaDoDeferredAction(CP_COMPLUSINSTALLCOMMIT, pwzRollbackFileName, 0);
559
+ ExitOnFailure(hr, "Failed to schedule ComPlusInstallCommit");
560
+ }
561
+
562
+ hr = S_OK;
563
+
564
+LExit:
565
+ // clean up
566
+ ReleaseObject(piCatalog);
567
+
568
+ ReleaseStr(pwzRollbackFileName);
569
+ ReleaseStr(pwzActionData);
570
+ ReleaseStr(pwzRollbackActionData);
571
+
572
+ CpiPartitionListFree(&partList);
573
+ CpiPartitionRoleListFree(&partRoleList);
574
+ CpiUserInPartitionRoleListFree(&usrInPartRoleList);
575
+ CpiPartitionUserListFree(&partUsrList);
576
+ CpiApplicationListFree(&appList);
577
+ CpiApplicationRoleListFree(&appRoleList);
578
+ CpiUserInApplicationRoleListFree(&usrInAppRoleList);
579
+ CpiAssemblyListFree(&asmList);
580
+ CpiSubscriptionListFree(&subList);
581
+
582
+ // unitialize
583
+ CpiFinalize();
584
+
585
+ if (fInitializedCom)
586
+ ::CoUninitialize();
587
+
588
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
589
+ return WcaFinalize(er);
590
+}
src/ca/cpsubsexec.cpp
new
+411
@@ -0,0 +1,411 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// private structs
7
+
8
+struct CPI_SUBSCRIPTION_ATTRIBUTES
9
+{
10
+ int iActionType;
11
+ int iActionCost;
12
+ LPWSTR pwzKey;
13
+ LPWSTR pwzID;
14
+ LPWSTR pwzName;
15
+ LPWSTR pwzEventCLSID;
16
+ LPWSTR pwzPublisherID;
17
+ LPWSTR pwzCompCLSID;
18
+ LPWSTR pwzAppID;
19
+ LPWSTR pwzPartID;
20
+ CPI_PROPERTY* pPropList;
21
+};
22
+
23
+
24
+// prototypes for private helper functions
25
+
26
+static HRESULT ReadSubscriptionAttributes(
27
+ LPWSTR* ppwzData,
28
+ CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
29
+ );
30
+static void FreeSubscriptionAttributes(
31
+ CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
32
+ );
33
+static HRESULT CreateSubscription(
34
+ CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
35
+ );
36
+static HRESULT RemoveSubscription(
37
+ CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
38
+ );
39
+
40
+
41
+// function definitions
42
+
43
+HRESULT CpiConfigureSubscriptions(
44
+ LPWSTR* ppwzData,
45
+ HANDLE hRollbackFile
46
+ )
47
+{
48
+ HRESULT hr = S_OK;
49
+
50
+ CPI_SUBSCRIPTION_ATTRIBUTES attrs;
51
+ ::ZeroMemory(&attrs, sizeof(attrs));
52
+
53
+ // read action text
54
+ hr = CpiActionStartMessage(ppwzData, FALSE);
55
+ ExitOnFailure(hr, "Failed to send action start message");
56
+
57
+ // ger count
58
+ int iCnt = 0;
59
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
60
+ ExitOnFailure(hr, "Failed to read count");
61
+
62
+ // write count to rollback file
63
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt);
64
+ ExitOnFailure(hr, "Failed to write count to rollback file");
65
+
66
+ for (int i = 0; i < iCnt; i++)
67
+ {
68
+ // read attributes from CustomActionData
69
+ hr = ReadSubscriptionAttributes(ppwzData, &attrs);
70
+ ExitOnFailure(hr, "Failed to read attributes");
71
+
72
+ // progress message
73
+ hr = CpiActionDataMessage(1, attrs.pwzName);
74
+ ExitOnFailure(hr, "Failed to send progress messages");
75
+
76
+ if (S_FALSE == hr)
77
+ ExitFunction();
78
+
79
+ // write key to rollback file
80
+ hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey);
81
+ ExitOnFailure(hr, "Failed to write key to rollback file");
82
+
83
+ // action
84
+ switch (attrs.iActionType)
85
+ {
86
+ case atCreate:
87
+ hr = CreateSubscription(&attrs);
88
+ ExitOnFailure(hr, "Failed to create subscription, key: %S", attrs.pwzKey);
89
+ break;
90
+ case atRemove:
91
+ hr = RemoveSubscription(&attrs);
92
+ ExitOnFailure(hr, "Failed to remove subscription, key: %S", attrs.pwzKey);
93
+ break;
94
+ }
95
+
96
+ // write completion status to rollback file
97
+ hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1);
98
+ ExitOnFailure(hr, "Failed to write completion status to rollback file");
99
+
100
+ // progress
101
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
102
+ ExitOnFailure(hr, "Failed to update progress");
103
+ }
104
+
105
+ hr = S_OK;
106
+
107
+LExit:
108
+ // clean up
109
+ FreeSubscriptionAttributes(&attrs);
110
+
111
+ return hr;
112
+}
113
+
114
+HRESULT CpiRollbackConfigureSubscriptions(
115
+ LPWSTR* ppwzData,
116
+ CPI_ROLLBACK_DATA* pRollbackDataList
117
+ )
118
+{
119
+ HRESULT hr = S_OK;
120
+
121
+ int iRollbackStatus;
122
+
123
+ CPI_SUBSCRIPTION_ATTRIBUTES attrs;
124
+ ::ZeroMemory(&attrs, sizeof(attrs));
125
+
126
+ // read action text
127
+ hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList);
128
+ ExitOnFailure(hr, "Failed to send action start message");
129
+
130
+ // ger count
131
+ int iCnt = 0;
132
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
133
+ ExitOnFailure(hr, "Failed to read count");
134
+
135
+ for (int i = 0; i < iCnt; i++)
136
+ {
137
+ // read attributes from CustomActionData
138
+ hr = ReadSubscriptionAttributes(ppwzData, &attrs);
139
+ ExitOnFailure(hr, "Failed to read attributes");
140
+
141
+ // rollback status
142
+ hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus);
143
+
144
+ if (S_FALSE == hr)
145
+ continue; // not found, nothing to rollback
146
+
147
+ // progress message
148
+ hr = CpiActionDataMessage(1, attrs.pwzName);
149
+ ExitOnFailure(hr, "Failed to send progress messages");
150
+
151
+ if (S_FALSE == hr)
152
+ ExitFunction();
153
+
154
+ // action
155
+ switch (attrs.iActionType)
156
+ {
157
+ case atCreate:
158
+ hr = CreateSubscription(&attrs);
159
+ if (FAILED(hr))
160
+ WcaLog(LOGMSG_STANDARD, "Failed to create subscription, hr: 0x%x, key: %S", hr, attrs.pwzKey);
161
+ break;
162
+ case atRemove:
163
+ hr = RemoveSubscription(&attrs);
164
+ if (FAILED(hr))
165
+ WcaLog(LOGMSG_STANDARD, "Failed to remove subscription, hr: 0x%x, key: %S", hr, attrs.pwzKey);
166
+ break;
167
+ }
168
+
169
+ // check rollback status
170
+ if (0 == iRollbackStatus)
171
+ continue; // operation did not complete, skip progress
172
+
173
+ // progress
174
+ hr = WcaProgressMessage(attrs.iActionCost, FALSE);
175
+ ExitOnFailure(hr, "Failed to update progress");
176
+ }
177
+
178
+ hr = S_OK;
179
+
180
+LExit:
181
+ // clean up
182
+ FreeSubscriptionAttributes(&attrs);
183
+
184
+ return hr;
185
+}
186
+
187
+
188
+// helper function definitions
189
+
190
+static HRESULT ReadSubscriptionAttributes(
191
+ LPWSTR* ppwzData,
192
+ CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
193
+ )
194
+{
195
+ HRESULT hr = S_OK;
196
+
197
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType);
198
+ ExitOnFailure(hr, "Failed to read action type");
199
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost);
200
+ ExitOnFailure(hr, "Failed to read action cost");
201
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
202
+ ExitOnFailure(hr, "Failed to read key");
203
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzID);
204
+ ExitOnFailure(hr, "Failed to read id");
205
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName);
206
+ ExitOnFailure(hr, "Failed to read name");
207
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzEventCLSID);
208
+ ExitOnFailure(hr, "Failed to read event clsid");
209
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPublisherID);
210
+ ExitOnFailure(hr, "Failed to read publisher id");
211
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzCompCLSID);
212
+ ExitOnFailure(hr, "Failed to read component clsid");
213
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID);
214
+ ExitOnFailure(hr, "Failed to read application id");
215
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID);
216
+ ExitOnFailure(hr, "Failed to read partition id");
217
+
218
+ hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList);
219
+ ExitOnFailure(hr, "Failed to read properties");
220
+
221
+ hr = S_OK;
222
+
223
+LExit:
224
+ return hr;
225
+}
226
+
227
+static void FreeSubscriptionAttributes(
228
+ CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
229
+ )
230
+{
231
+ ReleaseStr(pAttrs->pwzKey);
232
+ ReleaseStr(pAttrs->pwzID);
233
+ ReleaseStr(pAttrs->pwzName);
234
+ ReleaseStr(pAttrs->pwzEventCLSID);
235
+ ReleaseStr(pAttrs->pwzPublisherID);
236
+ ReleaseStr(pAttrs->pwzCompCLSID);
237
+ ReleaseStr(pAttrs->pwzAppID);
238
+ ReleaseStr(pAttrs->pwzPartID);
239
+
240
+ if (pAttrs->pPropList)
241
+ CpiFreePropertyList(pAttrs->pPropList);
242
+}
243
+
244
+static HRESULT CreateSubscription(
245
+ CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
246
+ )
247
+{
248
+ HRESULT hr = S_OK;
249
+ UINT er = ERROR_SUCCESS;
250
+
251
+ ICatalogCollection* piSubsColl = NULL;
252
+ ICatalogObject* piSubsObj = NULL;
253
+
254
+ PSID pSid = NULL;
255
+ long lChanges = 0;
256
+
257
+ // log
258
+ WcaLog(LOGMSG_VERBOSE, "Creating subscription, key: %S", pAttrs->pwzKey);
259
+
260
+ // get subscriptions collection
261
+ hr = CpiGetSubscriptionsCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzCompCLSID, &piSubsColl);
262
+ if (S_FALSE == hr)
263
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
264
+ ExitOnFailure(hr, "Failed to get subscriptions collection");
265
+
266
+ // check if subscription exists
267
+ hr = CpiFindCollectionObjectByStringKey(piSubsColl, pAttrs->pwzID, &piSubsObj);
268
+ ExitOnFailure(hr, "Failed to find subscription");
269
+
270
+ if (S_FALSE == hr)
271
+ {
272
+ // create subscription
273
+ hr = CpiAddCollectionObject(piSubsColl, &piSubsObj);
274
+ ExitOnFailure(hr, "Failed to add subscription to collection");
275
+
276
+ hr = CpiPutCollectionObjectValue(piSubsObj, L"ID", pAttrs->pwzID);
277
+ ExitOnFailure(hr, "Failed to set subscription id property");
278
+
279
+ hr = CpiPutCollectionObjectValue(piSubsObj, L"Name", pAttrs->pwzName);
280
+ ExitOnFailure(hr, "Failed to set subscription name property");
281
+
282
+ if (pAttrs->pwzEventCLSID && *pAttrs->pwzEventCLSID)
283
+ {
284
+ hr = CpiPutCollectionObjectValue(piSubsObj, L"EventCLSID", pAttrs->pwzEventCLSID);
285
+ ExitOnFailure(hr, "Failed to set role event clsid property");
286
+ }
287
+
288
+ if (pAttrs->pwzPublisherID && *pAttrs->pwzPublisherID)
289
+ {
290
+ hr = CpiPutCollectionObjectValue(piSubsObj, L"PublisherID", pAttrs->pwzPublisherID);
291
+ ExitOnFailure(hr, "Failed to set role publisher id property");
292
+ }
293
+ }
294
+
295
+ // properties
296
+ for (CPI_PROPERTY* pItm = pAttrs->pPropList; pItm; pItm = pItm->pNext)
297
+ {
298
+ // UserName property
299
+ if (0 == lstrcmpW(pItm->wzName, L"UserName"))
300
+ {
301
+ // get SID for account
302
+ do {
303
+ er = ERROR_SUCCESS;
304
+ hr = CpiAccountNameToSid(pItm->pwzValue, &pSid);
305
+ if (!::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK))
306
+ {
307
+ if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr)
308
+ {
309
+ WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pItm->pwzValue);
310
+ er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
311
+ switch (er)
312
+ {
313
+ case IDABORT:
314
+ ExitFunction(); // exit with error code from CpiAccountNameToSid()
315
+ case IDRETRY:
316
+ break;
317
+ case IDIGNORE:
318
+ default:
319
+ hr = S_FALSE;
320
+ }
321
+ }
322
+ else
323
+ ExitOnFailure(hr, "Failed to get SID for account, account: '%S'", pItm->pwzValue);
324
+ }
325
+ else if (FAILED(hr))
326
+ {
327
+ WcaLog(LOGMSG_STANDARD, "Failed to get SID for account, hr: 0x%x, account: '%S'", hr, pItm->pwzValue);
328
+ hr = S_FALSE;
329
+ }
330
+ } while (IDRETRY == er);
331
+
332
+ if (S_FALSE == hr)
333
+ continue;
334
+
335
+ // convert SID back to account name
336
+ hr = CpiSidToAccountName(pSid, &pItm->pwzValue);
337
+ ExitOnFailure(hr, "Failed to convert SID to account name");
338
+ }
339
+
340
+ // set property
341
+ hr = CpiPutCollectionObjectValue(piSubsObj, pItm->wzName, pItm->pwzValue);
342
+ ExitOnFailure(hr, "Failed to set object property value, name: %S", pItm->wzName);
343
+ }
344
+
345
+ // save changes
346
+ hr = piSubsColl->SaveChanges(&lChanges);
347
+ if (COMADMIN_E_OBJECTERRORS == hr)
348
+ CpiLogCatalogErrorInfo();
349
+ ExitOnFailure(hr, "Failed to save changes");
350
+
351
+ // log
352
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
353
+
354
+ hr = S_OK;
355
+
356
+LExit:
357
+ // clean up
358
+ ReleaseObject(piSubsColl);
359
+ ReleaseObject(piSubsObj);
360
+
361
+ if (pSid)
362
+ ::HeapFree(::GetProcessHeap(), 0, pSid);
363
+
364
+ return hr;
365
+}
366
+
367
+static HRESULT RemoveSubscription(
368
+ CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs
369
+ )
370
+{
371
+ HRESULT hr = S_OK;
372
+
373
+ ICatalogCollection* piSubsColl = NULL;
374
+
375
+ long lChanges = 0;
376
+
377
+ // log
378
+ WcaLog(LOGMSG_VERBOSE, "Removing subscription, key: %S", pAttrs->pwzKey);
379
+
380
+ // get subscriptions collection
381
+ hr = CpiGetSubscriptionsCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzCompCLSID, &piSubsColl);
382
+ ExitOnFailure(hr, "Failed to get subscriptions collection");
383
+
384
+ if (S_FALSE == hr)
385
+ {
386
+ // subscription not found
387
+ WcaLog(LOGMSG_VERBOSE, "Unable to retrieve subscriptions collection, nothing to delete, key: %S", pAttrs->pwzKey);
388
+ ExitFunction1(hr = S_OK);
389
+ }
390
+
391
+ // remove
392
+ hr = CpiRemoveCollectionObject(piSubsColl, pAttrs->pwzID, NULL, FALSE);
393
+ ExitOnFailure(hr, "Failed to remove subscriptions");
394
+
395
+ // save changes
396
+ hr = piSubsColl->SaveChanges(&lChanges);
397
+ if (COMADMIN_E_OBJECTERRORS == hr)
398
+ CpiLogCatalogErrorInfo();
399
+ ExitOnFailure(hr, "Failed to save changes");
400
+
401
+ // log
402
+ WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey);
403
+
404
+ hr = S_OK;
405
+
406
+LExit:
407
+ // clean up
408
+ ReleaseObject(piSubsColl);
409
+
410
+ return hr;
411
+}
src/ca/cpsubsexec.h
new
+12
@@ -0,0 +1,12 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+HRESULT CpiConfigureSubscriptions(
6
+ LPWSTR* ppwzData,
7
+ HANDLE hRollbackFile
8
+ );
9
+HRESULT CpiRollbackConfigureSubscriptions(
10
+ LPWSTR* ppwzData,
11
+ CPI_ROLLBACK_DATA* pRollbackDataList
12
+ );
src/ca/cpsubssched.cpp
new
+606
@@ -0,0 +1,606 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// sql queries
7
+
8
+LPCWSTR vcsSubscriptionQuery =
9
+ L"SELECT `Subscription`, `ComPlusComponent_`, `Component_`, `Id`, `Name`, `EventCLSID`, `PublisherID` FROM `ComPlusSubscription`";
10
+enum eSubscriptionQuery { sqSubscription = 1, sqComPlusComponent, sqComponent, sqID, sqName, sqEventCLSID, sqPublisherID };
11
+
12
+LPCWSTR vcsSubscriptionPropertyQuery =
13
+ L"SELECT `Name`, `Value` FROM `ComPlusSubscriptionProperty` WHERE `Subscription_` = ?";
14
+
15
+
16
+// property definitions
17
+
18
+CPI_PROPERTY_DEFINITION pdlSubscriptionProperties[] =
19
+{
20
+ {L"Description", cpptString, 500},
21
+ {L"Enabled", cpptBoolean, 500},
22
+ {L"EventClassPartitionID", cpptString, 502},
23
+ {L"FilterCriteria", cpptString, 500},
24
+ {L"InterfaceID", cpptString, 500},
25
+ {L"MachineName", cpptString, 500},
26
+ {L"MethodName", cpptString, 500},
27
+ {L"PerUser", cpptBoolean, 500},
28
+ {L"Queued", cpptBoolean, 500},
29
+ {L"SubscriberMoniker", cpptString, 500},
30
+ {L"UserName", cpptUser, 500},
31
+ {NULL, cpptNone, 0}
32
+};
33
+
34
+
35
+// prototypes for private helper functions
36
+
37
+static void FreeSubscription(
38
+ CPI_SUBSCRIPTION* pItm
39
+ );
40
+static HRESULT FindObjectForSubscription(
41
+ CPI_SUBSCRIPTION* pItm,
42
+ BOOL fFindId,
43
+ BOOL fFindName,
44
+ ICatalogObject** ppiSubsObj
45
+ );
46
+static HRESULT AddSubscriptionToActionData(
47
+ CPI_SUBSCRIPTION* pItm,
48
+ int iActionType,
49
+ int iActionCost,
50
+ LPWSTR* ppwzActionData
51
+ );
52
+static HRESULT ComponentFindByKey(
53
+ CPI_ASSEMBLY_LIST* pAsmList,
54
+ LPCWSTR pwzKey,
55
+ CPI_ASSEMBLY** ppAsmItm,
56
+ CPI_COMPONENT** ppCompItm
57
+ );
58
+
59
+
60
+// function definitions
61
+
62
+void CpiSubscriptionListFree(
63
+ CPI_SUBSCRIPTION_LIST* pList
64
+ )
65
+{
66
+ CPI_SUBSCRIPTION* pItm = pList->pFirst;
67
+
68
+ while (pItm)
69
+ {
70
+ CPI_SUBSCRIPTION* pDelete = pItm;
71
+ pItm = pItm->pNext;
72
+ FreeSubscription(pDelete);
73
+ }
74
+}
75
+
76
+HRESULT CpiSubscriptionsRead(
77
+ CPI_ASSEMBLY_LIST* pAsmList,
78
+ CPI_SUBSCRIPTION_LIST* pSubList
79
+ )
80
+{
81
+ HRESULT hr = S_OK;
82
+ UINT er = ERROR_SUCCESS;
83
+
84
+ PMSIHANDLE hView, hRec;
85
+
86
+ CPI_SUBSCRIPTION* pItm = NULL;
87
+ LPWSTR pwzData = NULL;
88
+ BOOL fMatchingArchitecture = FALSE;
89
+
90
+ // loop through all applications
91
+ hr = WcaOpenExecuteView(vcsSubscriptionQuery, &hView);
92
+ ExitOnFailure(hr, "Failed to execute view on ComPlusSubscription table");
93
+
94
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
95
+ {
96
+ // get component
97
+ hr = WcaGetRecordString(hRec, sqComponent, &pwzData);
98
+ ExitOnFailure(hr, "Failed to get component");
99
+
100
+ // check if the component is our processor architecture
101
+ hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture);
102
+ ExitOnFailure(hr, "Failed to get component architecture.");
103
+
104
+ if (!fMatchingArchitecture)
105
+ {
106
+ continue; // not the same architecture, ignore
107
+ }
108
+
109
+ // create entry
110
+ pItm = (CPI_SUBSCRIPTION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_SUBSCRIPTION));
111
+ if (!pItm)
112
+ ExitFunction1(hr = E_OUTOFMEMORY);
113
+
114
+ // get component install state
115
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
116
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
117
+
118
+ // get key
119
+ hr = WcaGetRecordString(hRec, sqSubscription, &pwzData);
120
+ ExitOnFailure(hr, "Failed to get key");
121
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
122
+
123
+ // get com+ component
124
+ hr = WcaGetRecordString(hRec, sqComPlusComponent, &pwzData);
125
+ ExitOnFailure(hr, "Failed to get COM+ component");
126
+
127
+ hr = ComponentFindByKey(pAsmList, pwzData, &pItm->pAssembly, &pItm->pComponent);
128
+
129
+ if (S_FALSE == hr)
130
+ {
131
+ // component not found
132
+ ExitOnFailure(hr = E_FAIL, "Failed to find component, key: %S", pwzData);
133
+ }
134
+
135
+ // get id
136
+ hr = WcaGetRecordFormattedString(hRec, sqID, &pwzData);
137
+ ExitOnFailure(hr, "Failed to get id");
138
+
139
+ if (pwzData && *pwzData)
140
+ {
141
+ hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID));
142
+ ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData);
143
+ }
144
+
145
+ // get name
146
+ hr = WcaGetRecordFormattedString(hRec, sqName, &pwzData);
147
+ ExitOnFailure(hr, "Failed to get name");
148
+ StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
149
+
150
+ // get event clsid
151
+ hr = WcaGetRecordFormattedString(hRec, sqEventCLSID, &pwzData);
152
+ ExitOnFailure(hr, "Failed to get event clsid");
153
+ StringCchCopyW(pItm->wzEventCLSID, countof(pItm->wzEventCLSID), pwzData);
154
+
155
+ // get publisher id
156
+ hr = WcaGetRecordFormattedString(hRec, sqPublisherID, &pwzData);
157
+ ExitOnFailure(hr, "Failed to get publisher id");
158
+ StringCchCopyW(pItm->wzPublisherID, countof(pItm->wzPublisherID), pwzData);
159
+
160
+ // get properties
161
+ if (CpiTableExists(cptComPlusSubscriptionProperty))
162
+ {
163
+ hr = CpiPropertiesRead(vcsSubscriptionPropertyQuery, pItm->wzKey, pdlSubscriptionProperties, &pItm->pProperties, &pItm->iPropertyCount);
164
+ ExitOnFailure(hr, "Failed to get subscription properties");
165
+ }
166
+
167
+ // set references & increment counters
168
+ if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
169
+ {
170
+ CpiApplicationAddReferenceInstall(pItm->pAssembly->pApplication);
171
+ pItm->pAssembly->fReferencedForInstall = TRUE;
172
+ pSubList->iInstallCount++;
173
+ if (pItm->pAssembly->iAttributes & aaRunInCommit)
174
+ pSubList->iCommitCount++;
175
+ }
176
+ if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
177
+ {
178
+ CpiApplicationAddReferenceUninstall(pItm->pAssembly->pApplication);
179
+ pItm->pAssembly->fReferencedForUninstall = TRUE;
180
+ pSubList->iUninstallCount++;
181
+ }
182
+
183
+ // add entry
184
+ if (pSubList->pFirst)
185
+ pItm->pNext = pSubList->pFirst;
186
+ pSubList->pFirst = pItm;
187
+ pItm = NULL;
188
+ }
189
+
190
+ if (E_NOMOREITEMS == hr)
191
+ hr = S_OK;
192
+
193
+LExit:
194
+ // clean up
195
+ if (pItm)
196
+ FreeSubscription(pItm);
197
+
198
+ ReleaseStr(pwzData);
199
+
200
+ return hr;
201
+}
202
+
203
+HRESULT CpiSubscriptionsVerifyInstall(
204
+ CPI_SUBSCRIPTION_LIST* pList
205
+ )
206
+{
207
+ HRESULT hr = S_OK;
208
+ UINT er = ERROR_SUCCESS;
209
+
210
+ ICatalogObject* piSubsObj = NULL;
211
+
212
+ for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
213
+ {
214
+ // subscriptions that are being installed
215
+ if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction))
216
+ continue;
217
+
218
+ // subscription is supposed to exist
219
+ if (CpiIsInstalled(pItm->isInstalled))
220
+ {
221
+ // if we don't have an id
222
+ if (!*pItm->wzID)
223
+ {
224
+ // find subscriptions with conflicting name
225
+ hr = FindObjectForSubscription(pItm, FALSE, TRUE, &piSubsObj);
226
+ ExitOnFailure(hr, "Failed to find collection object for subscription");
227
+
228
+ // if the subscription was found
229
+ if (S_OK == hr)
230
+ {
231
+ // get id from subscription object
232
+ hr = CpiGetKeyForObject(piSubsObj, pItm->wzID, countof(pItm->wzID));
233
+ ExitOnFailure(hr, "Failed to get id");
234
+ }
235
+
236
+ // if the subscription was not found
237
+ else
238
+ {
239
+ // create a new id
240
+ hr = CpiCreateId(pItm->wzID, countof(pItm->wzID));
241
+ ExitOnFailure(hr, "Failed to create id");
242
+ }
243
+ }
244
+ }
245
+
246
+ // subscription is supposed to be created
247
+ else
248
+ {
249
+ // check for conflicts
250
+ do {
251
+ if (*pItm->wzID)
252
+ {
253
+ // find subscriptions with conflicting id
254
+ hr = FindObjectForSubscription(pItm, TRUE, FALSE, &piSubsObj);
255
+ ExitOnFailure(hr, "Failed to find collection object for subscription");
256
+
257
+ if (S_FALSE == hr)
258
+ {
259
+ // find subscriptions with conflicting name
260
+ hr = FindObjectForSubscription(pItm, FALSE, TRUE, &piSubsObj);
261
+ ExitOnFailure(hr, "Failed to find collection object for subscription");
262
+
263
+ if (S_OK == hr)
264
+ // "A subscription with a conflictiong name exists. retry cancel"
265
+ er = WcaErrorMessage(msierrComPlusSubscriptionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0);
266
+ else
267
+ break; // no conflicting entry found, break loop
268
+ }
269
+ else
270
+ // "A subscription with a conflicting id exists. abort retry ignore"
271
+ er = WcaErrorMessage(msierrComPlusSubscriptionIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
272
+ }
273
+ else
274
+ {
275
+ // find subscriptions with conflicting name
276
+ hr = FindObjectForSubscription(pItm, FALSE, TRUE, &piSubsObj);
277
+ ExitOnFailure(hr, "Failed to find collection object for subscription");
278
+
279
+ if (S_OK == hr)
280
+ // "A subscription with a conflictiong name exists. abort retry ignore"
281
+ er = WcaErrorMessage(msierrComPlusSubscriptionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
282
+ else
283
+ break; // no conflicting entry found, break loop
284
+ }
285
+
286
+ switch (er)
287
+ {
288
+ case IDCANCEL:
289
+ case IDABORT:
290
+ ExitOnFailure(hr = E_FAIL, "A subscription with a conflictiong name or id exists, key: %S", pItm->wzKey);
291
+ break;
292
+ case IDRETRY:
293
+ break;
294
+ case IDIGNORE:
295
+ default:
296
+ // if we don't have an id, copy id from object
297
+ if (!*pItm->wzID)
298
+ {
299
+ hr = CpiGetKeyForObject(piSubsObj, pItm->wzID, countof(pItm->wzID));
300
+ ExitOnFailure(hr, "Failed to get id");
301
+ }
302
+ hr = S_FALSE; // indicate that this is not a conflict
303
+ }
304
+ } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts
305
+
306
+ // create a new id if one is missing
307
+ if (!*pItm->wzID)
308
+ {
309
+ hr = CpiCreateId(pItm->wzID, countof(pItm->wzID));
310
+ ExitOnFailure(hr, "Failed to create id");
311
+ }
312
+ }
313
+
314
+ // clean up
315
+ ReleaseNullObject(piSubsObj);
316
+ }
317
+
318
+ hr = S_OK;
319
+
320
+LExit:
321
+ // clean up
322
+ ReleaseObject(piSubsObj);
323
+
324
+ return hr;
325
+}
326
+
327
+HRESULT CpiSubscriptionsVerifyUninstall(
328
+ CPI_SUBSCRIPTION_LIST* pList
329
+ )
330
+{
331
+ HRESULT hr = S_OK;
332
+ ICatalogObject* piSubsObj = NULL;
333
+
334
+ for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
335
+ {
336
+ // subscriptions that are being installed
337
+ if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
338
+ continue;
339
+
340
+ // find subscriptions with conflicting name
341
+ hr = FindObjectForSubscription(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piSubsObj);
342
+ ExitOnFailure(hr, "Failed to find collection object for subscription");
343
+
344
+ // if the subscription was found
345
+ if (S_OK == hr)
346
+ {
347
+ // if we don't have an id, copy id from object
348
+ if (!*pItm->wzID)
349
+ {
350
+ hr = CpiGetKeyForObject(piSubsObj, pItm->wzID, countof(pItm->wzID));
351
+ ExitOnFailure(hr, "Failed to get id");
352
+ }
353
+ }
354
+
355
+ // if the subscription was not found
356
+ else
357
+ {
358
+ pItm->fObjectNotFound = TRUE;
359
+ pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall
360
+ }
361
+
362
+ // clean up
363
+ ReleaseNullObject(piSubsObj);
364
+ }
365
+
366
+ hr = S_OK;
367
+
368
+LExit:
369
+ // clean up
370
+ ReleaseObject(piSubsObj);
371
+
372
+ return hr;
373
+}
374
+
375
+HRESULT CpiSubscriptionsInstall(
376
+ CPI_SUBSCRIPTION_LIST* pList,
377
+ int iRunMode,
378
+ LPWSTR* ppwzActionData,
379
+ int* piProgress
380
+ )
381
+{
382
+ HRESULT hr = S_OK;
383
+
384
+ int iActionType;
385
+ int iCount = 0;
386
+
387
+ // add action text
388
+ hr = CpiAddActionTextToActionData(L"CreateSubscrComPlusComponents", ppwzActionData);
389
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
390
+
391
+ // subscription count
392
+ switch (iRunMode)
393
+ {
394
+ case rmDeferred:
395
+ iCount = pList->iInstallCount - pList->iCommitCount;
396
+ break;
397
+ case rmCommit:
398
+ iCount = pList->iCommitCount;
399
+ break;
400
+ case rmRollback:
401
+ iCount = pList->iInstallCount;
402
+ break;
403
+ }
404
+
405
+ // add subscription count to action data
406
+ hr = WcaWriteIntegerToCaData(iCount, ppwzActionData);
407
+ ExitOnFailure(hr, "Failed to add count to custom action data");
408
+
409
+ // add assemblies to custom action data in forward order
410
+ for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
411
+ {
412
+ // roles that are being installed only
413
+ if ((rmCommit == iRunMode && !(pItm->pAssembly->iAttributes & aaRunInCommit)) ||
414
+ (rmDeferred == iRunMode && (pItm->pAssembly->iAttributes & aaRunInCommit)) ||
415
+ !WcaIsInstalling(pItm->isInstalled, pItm->isAction))
416
+ continue;
417
+
418
+ // action type
419
+ if (rmRollback == iRunMode)
420
+ {
421
+ if (CpiIsInstalled(pItm->isInstalled))
422
+ iActionType = atNoOp;
423
+ else
424
+ iActionType = atRemove;
425
+ }
426
+ else
427
+ iActionType = atCreate;
428
+
429
+ // add to action data
430
+ hr = AddSubscriptionToActionData(pItm, iActionType, COST_SUBSCRIPTION_CREATE, ppwzActionData);
431
+ ExitOnFailure(hr, "Failed to add subscription to custom action data, key: %S", pItm->wzKey);
432
+ }
433
+
434
+ // add progress tics
435
+ if (piProgress)
436
+ *piProgress += COST_SUBSCRIPTION_CREATE * pList->iInstallCount;
437
+
438
+ hr = S_OK;
439
+
440
+LExit:
441
+ return hr;
442
+}
443
+
444
+HRESULT CpiSubscriptionsUninstall(
445
+ CPI_SUBSCRIPTION_LIST* pList,
446
+ int iRunMode,
447
+ LPWSTR* ppwzActionData,
448
+ int* piProgress
449
+ )
450
+{
451
+ HRESULT hr = S_OK;
452
+
453
+ int iActionType;
454
+
455
+ // add action text
456
+ hr = CpiAddActionTextToActionData(L"RemoveSubscrComPlusComponents", ppwzActionData);
457
+ ExitOnFailure(hr, "Failed to add action text to custom action data");
458
+
459
+ // add subscription count to action data
460
+ hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
461
+ ExitOnFailure(hr, "Failed to add count to custom action data");
462
+
463
+ // add assemblies to custom action data in reverse order
464
+ for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
465
+ {
466
+ // roles that are being uninstalled only
467
+ if (pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
468
+ continue;
469
+
470
+ // action type
471
+ if (rmRollback == iRunMode)
472
+ iActionType = atCreate;
473
+ else
474
+ iActionType = atRemove;
475
+
476
+ // add to action data
477
+ hr = AddSubscriptionToActionData(pItm, iActionType, COST_SUBSCRIPTION_DELETE, ppwzActionData);
478
+ ExitOnFailure(hr, "Failed to add subscription to custom action data, key: %S", pItm->wzKey);
479
+ }
480
+
481
+ // add progress tics
482
+ if (piProgress)
483
+ *piProgress += COST_SUBSCRIPTION_DELETE * pList->iUninstallCount;
484
+
485
+ hr = S_OK;
486
+
487
+LExit:
488
+ return hr;
489
+}
490
+
491
+
492
+// helper function definitions
493
+
494
+static void FreeSubscription(
495
+ CPI_SUBSCRIPTION* pItm
496
+ )
497
+{
498
+ if (pItm->pProperties)
499
+ CpiPropertiesFreeList(pItm->pProperties);
500
+
501
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
502
+}
503
+
504
+static HRESULT FindObjectForSubscription(
505
+ CPI_SUBSCRIPTION* pItm,
506
+ BOOL fFindId,
507
+ BOOL fFindName,
508
+ ICatalogObject** ppiSubsObj
509
+ )
510
+{
511
+ HRESULT hr = S_OK;
512
+
513
+ ICatalogCollection* piSubsColl = NULL;
514
+
515
+ // get applications collection
516
+ hr = CpiGetSubscriptionsCollForComponent(pItm->pAssembly, pItm->pComponent, &piSubsColl);
517
+ ExitOnFailure(hr, "Failed to get collection");
518
+
519
+ if (S_FALSE == hr)
520
+ ExitFunction(); // exit with hr = S_FALSE
521
+
522
+ // find application object
523
+ hr = CpiFindCollectionObject(piSubsColl, fFindId ? pItm->wzID : NULL, fFindName ? pItm->wzName : NULL, ppiSubsObj);
524
+ ExitOnFailure(hr, "Failed to find object");
525
+
526
+ // exit with hr from CpiFindCollectionObject()
527
+
528
+LExit:
529
+ // clean up
530
+ ReleaseObject(piSubsColl);
531
+
532
+ return hr;
533
+}
534
+
535
+static HRESULT AddSubscriptionToActionData(
536
+ CPI_SUBSCRIPTION* pItm,
537
+ int iActionType,
538
+ int iActionCost,
539
+ LPWSTR* ppwzActionData
540
+ )
541
+{
542
+ HRESULT hr = S_OK;
543
+
544
+ // add action information to custom action data
545
+ hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData);
546
+ ExitOnFailure(hr, "Failed to add action type to custom action data");
547
+ hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData);
548
+ ExitOnFailure(hr, "Failed to add action cost to custom action data");
549
+
550
+ // add application role information to custom action data
551
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
552
+ ExitOnFailure(hr, "Failed to add subscription key to custom action data");
553
+ hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData);
554
+ ExitOnFailure(hr, "Failed to add subscription id to custom action data");
555
+ hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData);
556
+ ExitOnFailure(hr, "Failed to add subscription name to custom action data");
557
+ hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->wzEventCLSID : L"", ppwzActionData);
558
+ ExitOnFailure(hr, "Failed to add assembly tlb path to custom action data");
559
+ hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->wzPublisherID : L"", ppwzActionData);
560
+ ExitOnFailure(hr, "Failed to add assembly proxy-stub dll path to custom action data");
561
+
562
+ // add component information to custom action data
563
+ hr = WcaWriteStringToCaData(pItm->pComponent->wzCLSID, ppwzActionData);
564
+ ExitOnFailure(hr, "Failed to add application id to custom action data");
565
+
566
+ // add application information to custom action data
567
+ hr = WcaWriteStringToCaData(pItm->pAssembly->pApplication->wzID, ppwzActionData);
568
+ ExitOnFailure(hr, "Failed to add application id to custom action data");
569
+
570
+ // add partition information to custom action data
571
+ LPCWSTR pwzPartID = pItm->pAssembly->pApplication->pPartition ? pItm->pAssembly->pApplication->pPartition->wzID : L"";
572
+ hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData);
573
+ ExitOnFailure(hr, "Failed to add partition id to custom action data");
574
+
575
+ // add properties to custom action data
576
+ hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData);
577
+ ExitOnFailure(hr, "Failed to add properties to custom action data");
578
+
579
+ hr = S_OK;
580
+
581
+LExit:
582
+ return hr;
583
+}
584
+
585
+static HRESULT ComponentFindByKey(
586
+ CPI_ASSEMBLY_LIST* pAsmList,
587
+ LPCWSTR pwzKey,
588
+ CPI_ASSEMBLY** ppAsmItm,
589
+ CPI_COMPONENT** ppCompItm
590
+ )
591
+{
592
+ for (CPI_ASSEMBLY* pAsmItm = pAsmList->pFirst; pAsmItm; pAsmItm = pAsmItm->pNext)
593
+ {
594
+ for (CPI_COMPONENT* pCompItm = pAsmItm->pComponents; pCompItm; pCompItm = pCompItm->pNext)
595
+ {
596
+ if (0 == lstrcmpW(pCompItm->wzKey, pwzKey))
597
+ {
598
+ *ppAsmItm = pAsmItm;
599
+ *ppCompItm = pCompItm;
600
+ return S_OK;
601
+ }
602
+ }
603
+ }
604
+
605
+ return S_FALSE;
606
+}
src/ca/cpsubssched.h
new
+62
@@ -0,0 +1,62 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+struct CPI_SUBSCRIPTION
6
+{
7
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
8
+ WCHAR wzID[CPI_MAX_GUID + 1];
9
+ WCHAR wzName[MAX_DARWIN_COLUMN + 1];
10
+ WCHAR wzEventCLSID[CPI_MAX_GUID + 1];
11
+ WCHAR wzPublisherID[CPI_MAX_GUID + 1];
12
+
13
+ BOOL fObjectNotFound;
14
+
15
+ int iPropertyCount;
16
+ CPI_PROPERTY* pProperties;
17
+
18
+ INSTALLSTATE isInstalled, isAction;
19
+
20
+ CPI_ASSEMBLY* pAssembly;
21
+ CPI_COMPONENT* pComponent;
22
+
23
+ CPI_SUBSCRIPTION* pNext;
24
+};
25
+
26
+struct CPI_SUBSCRIPTION_LIST
27
+{
28
+ CPI_SUBSCRIPTION* pFirst;
29
+
30
+ int iInstallCount;
31
+ int iCommitCount;
32
+ int iUninstallCount;
33
+};
34
+
35
+
36
+// function prototypes
37
+
38
+void CpiSubscriptionListFree(
39
+ CPI_SUBSCRIPTION_LIST* pList
40
+ );
41
+HRESULT CpiSubscriptionsRead(
42
+ CPI_ASSEMBLY_LIST* pAsmList,
43
+ CPI_SUBSCRIPTION_LIST* pSubList
44
+ );
45
+HRESULT CpiSubscriptionsVerifyInstall(
46
+ CPI_SUBSCRIPTION_LIST* pList
47
+ );
48
+HRESULT CpiSubscriptionsVerifyUninstall(
49
+ CPI_SUBSCRIPTION_LIST* pList
50
+ );
51
+HRESULT CpiSubscriptionsInstall(
52
+ CPI_SUBSCRIPTION_LIST* pList,
53
+ int iRunMode,
54
+ LPWSTR* ppwzActionData,
55
+ int* piProgress
56
+ );
57
+HRESULT CpiSubscriptionsUninstall(
58
+ CPI_SUBSCRIPTION_LIST* pList,
59
+ int iRunMode,
60
+ LPWSTR* ppwzActionData,
61
+ int* piProgress
62
+ );
src/ca/cputilexec.cpp
new
+1881
@@ -0,0 +1,1881 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// private structs
7
+
8
+struct CPI_WELLKNOWN_SID
9
+{
10
+ LPCWSTR pwzName;
11
+ SID_IDENTIFIER_AUTHORITY iaIdentifierAuthority;
12
+ BYTE nSubAuthorityCount;
13
+ DWORD dwSubAuthority[8];
14
+};
15
+
16
+
17
+// well known SIDs
18
+
19
+CPI_WELLKNOWN_SID wsWellKnownSids[] = {
20
+ {L"\\Everyone", SECURITY_WORLD_SID_AUTHORITY, 1, {SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0}},
21
+ {L"\\Administrators", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0}},
22
+ {L"\\LocalSystem", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0}},
23
+ {L"\\LocalService", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}},
24
+ {L"\\NetworkService", SECURITY_NT_AUTHORITY, 1, {SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}},
25
+ {L"\\AuthenticatedUser", SECURITY_NT_AUTHORITY, 1, {SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0}},
26
+ {L"\\Guests", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS, 0, 0, 0, 0, 0, 0}},
27
+ {L"\\Users", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0}},
28
+ {L"\\CREATOR OWNER", SECURITY_NT_AUTHORITY, 1, {SECURITY_CREATOR_OWNER_RID, 0, 0, 0, 0, 0, 0, 0}},
29
+ {NULL, SECURITY_NULL_SID_AUTHORITY, 0, {0, 0, 0, 0, 0, 0, 0, 0}}
30
+};
31
+
32
+
33
+// prototypes for private helper functions
34
+
35
+static HRESULT FindUserCollectionObjectIndex(
36
+ ICatalogCollection* piColl,
37
+ PSID pSid,
38
+ int* pi
39
+ );
40
+static HRESULT CreateSidFromDomainRidPair(
41
+ PSID pDomainSid,
42
+ DWORD dwRid,
43
+ PSID* ppSid
44
+ );
45
+static HRESULT InitLsaUnicodeString(
46
+ PLSA_UNICODE_STRING plusStr,
47
+ LPCWSTR pwzStr,
48
+ DWORD dwLen
49
+ );
50
+static void FreeLsaUnicodeString(
51
+ PLSA_UNICODE_STRING plusStr
52
+ );
53
+static HRESULT WriteFileAll(
54
+ HANDLE hFile,
55
+ PBYTE pbBuffer,
56
+ DWORD dwBufferLength
57
+ );
58
+static HRESULT ReadFileAll(
59
+ HANDLE hFile,
60
+ PBYTE pbBuffer,
61
+ DWORD dwBufferLength
62
+ );
63
+
64
+
65
+// variables
66
+
67
+static ICOMAdminCatalog* gpiCatalog;
68
+
69
+
70
+// function definitions
71
+
72
+void CpiInitialize()
73
+{
74
+ // collections
75
+ gpiCatalog = NULL;
76
+}
77
+
78
+void CpiFinalize()
79
+{
80
+ // collections
81
+ ReleaseObject(gpiCatalog);
82
+}
83
+
84
+HRESULT CpiActionStartMessage(
85
+ LPWSTR* ppwzActionData,
86
+ BOOL fSuppress
87
+ )
88
+{
89
+ HRESULT hr = S_OK;
90
+ UINT er = ERROR_SUCCESS;
91
+
92
+ PMSIHANDLE hRec;
93
+
94
+ LPWSTR pwzData = NULL;
95
+
96
+ // create record
97
+ hRec = ::MsiCreateRecord(3);
98
+ ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record");
99
+
100
+ // action name
101
+ hr = WcaReadStringFromCaData(ppwzActionData, &pwzData);
102
+ ExitOnFailure(hr, "Failed to action name");
103
+
104
+ er = ::MsiRecordSetStringW(hRec, 1, pwzData);
105
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set action name");
106
+
107
+ // description
108
+ hr = WcaReadStringFromCaData(ppwzActionData, &pwzData);
109
+ ExitOnFailure(hr, "Failed to description");
110
+
111
+ er = ::MsiRecordSetStringW(hRec, 2, pwzData);
112
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set description");
113
+
114
+ // template
115
+ hr = WcaReadStringFromCaData(ppwzActionData, &pwzData);
116
+ ExitOnFailure(hr, "Failed to template");
117
+
118
+ er = ::MsiRecordSetStringW(hRec, 3, pwzData);
119
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set template");
120
+
121
+ // message
122
+ if (!fSuppress)
123
+ {
124
+ er = WcaProcessMessage(INSTALLMESSAGE_ACTIONSTART, hRec);
125
+ if (0 == er || IDOK == er || IDYES == er)
126
+ {
127
+ hr = S_OK;
128
+ }
129
+ else if (IDABORT == er || IDCANCEL == er)
130
+ {
131
+ WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit
132
+ hr = S_FALSE;
133
+ }
134
+ else
135
+ hr = E_UNEXPECTED;
136
+ }
137
+
138
+LExit:
139
+ // clean up
140
+ ReleaseStr(pwzData);
141
+
142
+ return hr;
143
+}
144
+
145
+HRESULT CpiActionDataMessage(
146
+ DWORD cArgs,
147
+ ...
148
+ )
149
+{
150
+ HRESULT hr = S_OK;
151
+ UINT er = ERROR_SUCCESS;
152
+
153
+ PMSIHANDLE hRec;
154
+ va_list args;
155
+
156
+ // record
157
+ hRec = ::MsiCreateRecord(cArgs);
158
+ ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record");
159
+
160
+ va_start(args, cArgs);
161
+ for (DWORD i = 1; i <= cArgs; i++)
162
+ {
163
+ LPCWSTR pwzArg = va_arg(args, WCHAR*);
164
+ if (pwzArg && *pwzArg)
165
+ {
166
+ er = ::MsiRecordSetStringW(hRec, i, pwzArg);
167
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set record field string");
168
+ }
169
+ }
170
+ va_end(args);
171
+
172
+ // message
173
+ er = WcaProcessMessage(INSTALLMESSAGE_ACTIONDATA, hRec);
174
+ if (0 == er || IDOK == er || IDYES == er)
175
+ {
176
+ hr = S_OK;
177
+ }
178
+ else if (IDABORT == er || IDCANCEL == er)
179
+ {
180
+ WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit
181
+ hr = S_FALSE;
182
+ }
183
+ else
184
+ hr = E_UNEXPECTED;
185
+
186
+LExit:
187
+ return hr;
188
+}
189
+
190
+HRESULT CpiGetAdminCatalog(
191
+ ICOMAdminCatalog** ppiCatalog
192
+ )
193
+{
194
+ HRESULT hr = S_OK;
195
+
196
+ if (!gpiCatalog)
197
+ {
198
+ // get collection
199
+ hr = ::CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_ALL, IID_ICOMAdminCatalog, (void**)&gpiCatalog);
200
+ ExitOnFailure(hr, "Failed to create COM+ admin catalog object");
201
+ }
202
+
203
+ // return value
204
+ gpiCatalog->AddRef();
205
+ *ppiCatalog = gpiCatalog;
206
+
207
+ hr = S_OK;
208
+
209
+LExit:
210
+ return hr;
211
+}
212
+
213
+HRESULT CpiLogCatalogErrorInfo()
214
+{
215
+ HRESULT hr = S_OK;
216
+
217
+ ICOMAdminCatalog* piCatalog = NULL;
218
+ ICatalogCollection* piErrColl = NULL;
219
+ IDispatch* piDisp = NULL;
220
+ ICatalogObject* piObj = NULL;
221
+
222
+ LPWSTR pwzName = NULL;
223
+ LPWSTR pwzErrorCode = NULL;
224
+ LPWSTR pwzMajorRef = NULL;
225
+ LPWSTR pwzMinorRef = NULL;
226
+
227
+ // get catalog
228
+ hr = CpiGetAdminCatalog(&piCatalog);
229
+ ExitOnFailure(hr, "Failed to get COM+ admin catalog");
230
+
231
+ // get error info collection
232
+ hr = CpiGetCatalogCollection(L"ErrorInfo", &piErrColl);
233
+ ExitOnFailure(hr, "Failed to get error info collection");
234
+
235
+ // loop objects
236
+ long lCnt;
237
+ hr = piErrColl->get_Count(&lCnt);
238
+ ExitOnFailure(hr, "Failed to get to number of items in collection");
239
+
240
+ for (long i = 0; i < lCnt; i++)
241
+ {
242
+ // get ICatalogObject interface
243
+ hr = piErrColl->get_Item(i, &piDisp);
244
+ ExitOnFailure(hr, "Failed to get item from partitions collection");
245
+
246
+ hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
247
+ ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
248
+
249
+ // get properties
250
+ hr = CpiGetCollectionObjectValue(piObj, L"Name", &pwzName);
251
+ ExitOnFailure(hr, "Failed to get name");
252
+ hr = CpiGetCollectionObjectValue(piObj, L"ErrorCode", &pwzErrorCode);
253
+ ExitOnFailure(hr, "Failed to get error code");
254
+ hr = CpiGetCollectionObjectValue(piObj, L"MajorRef", &pwzMajorRef);
255
+ ExitOnFailure(hr, "Failed to get major ref");
256
+ hr = CpiGetCollectionObjectValue(piObj, L"MinorRef", &pwzMinorRef);
257
+ ExitOnFailure(hr, "Failed to get minor ref");
258
+
259
+ // write to log
260
+ WcaLog(LOGMSG_STANDARD, "ErrorInfo: Name='%S', ErrorCode='%S', MajorRef='%S', MinorRef='%S'",
261
+ pwzName, pwzErrorCode, pwzMajorRef, pwzMinorRef);
262
+
263
+ // clean up
264
+ ReleaseNullObject(piDisp);
265
+ ReleaseNullObject(piObj);
266
+ }
267
+
268
+ hr = S_OK;
269
+
270
+LExit:
271
+ // clean up
272
+ ReleaseObject(piCatalog);
273
+ ReleaseObject(piErrColl);
274
+ ReleaseObject(piDisp);
275
+ ReleaseObject(piObj);
276
+
277
+ ReleaseStr(pwzName);
278
+ ReleaseStr(pwzErrorCode);
279
+ ReleaseStr(pwzMajorRef);
280
+ ReleaseStr(pwzMinorRef);
281
+
282
+ return hr;
283
+}
284
+
285
+HRESULT CpiGetCatalogCollection(
286
+ LPCWSTR pwzName,
287
+ ICatalogCollection** ppiColl
288
+ )
289
+{
290
+ HRESULT hr = S_OK;
291
+
292
+ ICOMAdminCatalog* piCatalog = NULL;
293
+ IDispatch* piDisp = NULL;
294
+
295
+ BSTR bstrName = NULL;
296
+
297
+ // copy name string
298
+ bstrName = ::SysAllocString(pwzName);
299
+ ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name");
300
+
301
+ // get catalog
302
+ hr = CpiGetAdminCatalog(&piCatalog);
303
+ ExitOnFailure(hr, "Failed to get COM+ admin catalog");
304
+
305
+ // get collecton from catalog
306
+ hr = piCatalog->GetCollection(bstrName, &piDisp);
307
+ ExitOnFailure(hr, "Failed to get collection");
308
+
309
+ hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl);
310
+ ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface");
311
+
312
+ // populate collection
313
+ hr = (*ppiColl)->Populate();
314
+ if (COMADMIN_E_OBJECTERRORS == hr)
315
+ CpiLogCatalogErrorInfo();
316
+ ExitOnFailure(hr, "Failed to populate collection");
317
+
318
+ hr = S_OK;
319
+
320
+LExit:
321
+ // clean up
322
+ ReleaseObject(piCatalog);
323
+ ReleaseObject(piDisp);
324
+ ReleaseBSTR(bstrName);
325
+
326
+ return hr;
327
+}
328
+
329
+HRESULT CpiGetCatalogCollection(
330
+ ICatalogCollection* piColl,
331
+ ICatalogObject* piObj,
332
+ LPCWSTR pwzName,
333
+ ICatalogCollection** ppiColl
334
+ )
335
+{
336
+ HRESULT hr = S_OK;
337
+
338
+ ICOMAdminCatalog* piCatalog = NULL;
339
+ IDispatch* piDisp = NULL;
340
+
341
+ BSTR bstrName = NULL;
342
+
343
+ VARIANT vtKey;
344
+ ::VariantInit(&vtKey);
345
+
346
+ // copy name string
347
+ bstrName = ::SysAllocString(pwzName);
348
+ ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name");
349
+
350
+ // get catalog
351
+ hr = CpiGetAdminCatalog(&piCatalog);
352
+ ExitOnFailure(hr, "Failed to get COM+ admin catalog");
353
+
354
+ // get key
355
+ hr = piObj->get_Key(&vtKey);
356
+ ExitOnFailure(hr, "Failed to get object key");
357
+
358
+ // get collecton from catalog
359
+ hr = piColl->GetCollection(bstrName, vtKey, &piDisp);
360
+ ExitOnFailure(hr, "Failed to get collection");
361
+
362
+ hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl);
363
+ ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface");
364
+
365
+ // populate collection
366
+ hr = (*ppiColl)->Populate();
367
+ if (COMADMIN_E_OBJECTERRORS == hr)
368
+ CpiLogCatalogErrorInfo();
369
+ ExitOnFailure(hr, "Failed to populate collection");
370
+
371
+ hr = S_OK;
372
+
373
+LExit:
374
+ // clean up
375
+ ReleaseObject(piCatalog);
376
+ ReleaseObject(piDisp);
377
+ ReleaseBSTR(bstrName);
378
+ ::VariantClear(&vtKey);
379
+
380
+ return hr;
381
+}
382
+
383
+HRESULT CpiAddCollectionObject(
384
+ ICatalogCollection* piColl,
385
+ ICatalogObject** ppiObj
386
+ )
387
+{
388
+ HRESULT hr = S_OK;
389
+
390
+ IDispatch* piDisp = NULL;
391
+
392
+ hr = piColl->Add(&piDisp);
393
+ ExitOnFailure(hr, "Failed to add object to collection");
394
+
395
+ hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)ppiObj);
396
+ ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
397
+
398
+ hr = S_OK;
399
+
400
+LExit:
401
+ // clean up
402
+ ReleaseObject(piDisp);
403
+
404
+ return hr;
405
+}
406
+
407
+HRESULT CpiPutCollectionObjectValue(
408
+ ICatalogObject* piObj,
409
+ LPCWSTR pwzPropName,
410
+ LPCWSTR pwzValue
411
+ )
412
+{
413
+ HRESULT hr = S_OK;
414
+
415
+ BSTR bstrPropName = NULL;
416
+
417
+ VARIANT vtVal;
418
+ ::VariantInit(&vtVal);
419
+
420
+ // allocate property name string
421
+ bstrPropName = ::SysAllocString(pwzPropName);
422
+ ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate property name string");
423
+
424
+ // prepare value variant
425
+ vtVal.vt = VT_BSTR;
426
+ vtVal.bstrVal = ::SysAllocString(pwzValue);
427
+ ExitOnNull(vtVal.bstrVal, hr, E_OUTOFMEMORY, "Failed to allocate property value string");
428
+
429
+ // put value
430
+ hr = piObj->put_Value(bstrPropName, vtVal);
431
+ ExitOnFailure(hr, "Failed to put property value");
432
+
433
+ hr = S_OK;
434
+
435
+LExit:
436
+ // clean up
437
+ ReleaseBSTR(bstrPropName);
438
+ ::VariantClear(&vtVal);
439
+
440
+ return hr;
441
+}
442
+
443
+HRESULT CpiPutCollectionObjectValues(
444
+ ICatalogObject* piObj,
445
+ CPI_PROPERTY* pPropList
446
+ )
447
+{
448
+ HRESULT hr = S_OK;
449
+
450
+ for (CPI_PROPERTY* pItm = pPropList; pItm; pItm = pItm->pNext)
451
+ {
452
+ // set property
453
+ hr = CpiPutCollectionObjectValue(piObj, pItm->wzName, pItm->pwzValue);
454
+ ExitOnFailure(hr, "Failed to set object property value, name: %S", pItm->wzName);
455
+ }
456
+
457
+ hr = S_OK;
458
+
459
+LExit:
460
+ return hr;
461
+}
462
+
463
+HRESULT CpiGetCollectionObjectValue(
464
+ ICatalogObject* piObj,
465
+ LPCWSTR szPropName,
466
+ LPWSTR* ppwzValue
467
+ )
468
+{
469
+ HRESULT hr = S_OK;
470
+
471
+ BSTR bstrPropName = NULL;
472
+
473
+ VARIANT vtVal;
474
+ ::VariantInit(&vtVal);
475
+
476
+ // allocate property name string
477
+ bstrPropName = ::SysAllocString(szPropName);
478
+ ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate property name string");
479
+
480
+ // get value
481
+ hr = piObj->get_Value(bstrPropName, &vtVal);
482
+ ExitOnFailure(hr, "Failed to get property value");
483
+
484
+ hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
485
+ ExitOnFailure(hr, "Failed to change variant type");
486
+
487
+ hr = StrAllocString(ppwzValue, vtVal.bstrVal, ::SysStringLen(vtVal.bstrVal));
488
+ ExitOnFailure(hr, "Failed to allocate memory for value string");
489
+
490
+ hr = S_OK;
491
+
492
+LExit:
493
+ // clean up
494
+ ReleaseBSTR(bstrPropName);
495
+ ::VariantClear(&vtVal);
496
+
497
+ return hr;
498
+}
499
+
500
+HRESULT CpiResetObjectProperty(
501
+ ICatalogCollection* piColl,
502
+ ICatalogObject* piObj,
503
+ LPCWSTR pwzPropName
504
+ )
505
+{
506
+ HRESULT hr = S_OK;
507
+
508
+ BSTR bstrPropName = NULL;
509
+
510
+ long lChanges = 0;
511
+
512
+ VARIANT vtVal;
513
+ ::VariantInit(&vtVal);
514
+
515
+ // allocate property name string
516
+ bstrPropName = ::SysAllocString(pwzPropName);
517
+ ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate deleteable property name string");
518
+
519
+ // get value
520
+ hr = piObj->get_Value(bstrPropName, &vtVal);
521
+ ExitOnFailure(hr, "Failed to get deleteable property value");
522
+
523
+ hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BOOL);
524
+ ExitOnFailure(hr, "Failed to change variant type");
525
+
526
+ // if the deleteable property is set
527
+ if (VARIANT_FALSE == vtVal.boolVal)
528
+ {
529
+ // clear property
530
+ vtVal.boolVal = VARIANT_TRUE;
531
+
532
+ hr = piObj->put_Value(bstrPropName, vtVal);
533
+ ExitOnFailure(hr, "Failed to get property value");
534
+
535
+ // save changes
536
+ hr = piColl->SaveChanges(&lChanges);
537
+ if (COMADMIN_E_OBJECTERRORS == hr)
538
+ CpiLogCatalogErrorInfo();
539
+ ExitOnFailure(hr, "Failed to save changes");
540
+ }
541
+
542
+ hr = S_OK;
543
+
544
+LExit:
545
+ // clean up
546
+ ReleaseBSTR(bstrPropName);
547
+ ::VariantClear(&vtVal);
548
+
549
+ return hr;
550
+}
551
+
552
+HRESULT CpiRemoveCollectionObject(
553
+ ICatalogCollection* piColl,
554
+ LPCWSTR pwzID,
555
+ LPCWSTR pwzName,
556
+ BOOL fResetDeleteable
557
+ )
558
+{
559
+ HRESULT hr = S_OK;
560
+
561
+ IDispatch* piDisp = NULL;
562
+ ICatalogObject* piObj = NULL;
563
+
564
+ BOOL fMatch = FALSE;
565
+
566
+ VARIANT vtVal;
567
+ ::VariantInit(&vtVal);
568
+
569
+ long lCnt;
570
+ hr = piColl->get_Count(&lCnt);
571
+ ExitOnFailure(hr, "Failed to get to number of items in collection");
572
+
573
+ for (long i = 0; i < lCnt; i++)
574
+ {
575
+ // get ICatalogObject interface
576
+ hr = piColl->get_Item(i, &piDisp);
577
+ ExitOnFailure(hr, "Failed to get object from collection");
578
+
579
+ hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
580
+ ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
581
+
582
+ // compare id
583
+ if (pwzID && *pwzID)
584
+ {
585
+ hr = piObj->get_Key(&vtVal);
586
+ ExitOnFailure(hr, "Failed to get key");
587
+
588
+ hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
589
+ ExitOnFailure(hr, "Failed to change variant type");
590
+
591
+ if (0 == lstrcmpiW(vtVal.bstrVal, pwzID))
592
+ fMatch = TRUE;
593
+
594
+ ::VariantClear(&vtVal);
595
+ }
596
+
597
+ // compare name
598
+ if (pwzName && *pwzName)
599
+ {
600
+ hr = piObj->get_Name(&vtVal);
601
+ ExitOnFailure(hr, "Failed to get name");
602
+
603
+ hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
604
+ ExitOnFailure(hr, "Failed to change variant type");
605
+
606
+ if (0 == lstrcmpW(vtVal.bstrVal, pwzName))
607
+ fMatch = TRUE;
608
+
609
+ ::VariantClear(&vtVal);
610
+ }
611
+
612
+ // if it's a match, remove it
613
+ if (fMatch)
614
+ {
615
+ if (fResetDeleteable)
616
+ {
617
+ // reset deleteable property, if set
618
+ hr = CpiResetObjectProperty(piColl, piObj, L"Deleteable");
619
+ ExitOnFailure(hr, "Failed to reset deleteable property");
620
+ }
621
+
622
+ hr = piColl->Remove(i);
623
+ ExitOnFailure(hr, "Failed to remove item from collection");
624
+ break;
625
+ }
626
+
627
+ // release interface pointers
628
+ ReleaseNullObject(piDisp);
629
+ ReleaseNullObject(piObj);
630
+ }
631
+
632
+ hr = S_OK;
633
+
634
+LExit:
635
+ // clean up
636
+ ReleaseObject(piDisp);
637
+ ReleaseObject(piObj);
638
+
639
+ ::VariantClear(&vtVal);
640
+
641
+ return hr;
642
+}
643
+
644
+HRESULT CpiRemoveUserCollectionObject(
645
+ ICatalogCollection* piColl,
646
+ PSID pSid
647
+ )
648
+{
649
+ HRESULT hr = S_OK;
650
+
651
+ int i = 0;
652
+
653
+ // find index
654
+ hr = FindUserCollectionObjectIndex(piColl, pSid, &i);
655
+ ExitOnFailure(hr, "Failed to find user collection index");
656
+
657
+ if (S_FALSE == hr)
658
+ ExitFunction(); // not found, exit with hr = S_FALSE
659
+
660
+ // remove object
661
+ hr = piColl->Remove(i);
662
+ ExitOnFailure(hr, "Failed to remove object from collection");
663
+
664
+ hr = S_OK;
665
+
666
+LExit:
667
+ return hr;
668
+}
669
+
670
+HRESULT CpiFindCollectionObjectByStringKey(
671
+ ICatalogCollection* piColl,
672
+ LPCWSTR pwzKey,
673
+ ICatalogObject** ppiObj
674
+ )
675
+{
676
+ HRESULT hr = S_OK;
677
+
678
+ IDispatch* piDisp = NULL;
679
+ ICatalogObject* piObj = NULL;
680
+
681
+ VARIANT vtVal;
682
+ ::VariantInit(&vtVal);
683
+
684
+ long lCnt;
685
+ hr = piColl->get_Count(&lCnt);
686
+ ExitOnFailure(hr, "Failed to get to number of items in collection");
687
+
688
+ for (long i = 0; i < lCnt; i++)
689
+ {
690
+ // get ICatalogObject interface
691
+ hr = piColl->get_Item(i, &piDisp);
692
+ ExitOnFailure(hr, "Failed to get object from collection");
693
+
694
+ hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
695
+ ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
696
+
697
+ // compare key
698
+ hr = piObj->get_Key(&vtVal);
699
+ ExitOnFailure(hr, "Failed to get key");
700
+
701
+ hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
702
+ ExitOnFailure(hr, "Failed to change variant type");
703
+
704
+ if (0 == lstrcmpiW(vtVal.bstrVal, pwzKey))
705
+ {
706
+ if (ppiObj)
707
+ {
708
+ *ppiObj = piObj;
709
+ piObj = NULL;
710
+ }
711
+ ExitFunction1(hr = S_OK);
712
+ }
713
+
714
+ // clean up
715
+ ReleaseNullObject(piDisp);
716
+ ReleaseNullObject(piObj);
717
+
718
+ ::VariantClear(&vtVal);
719
+ }
720
+
721
+ hr = S_FALSE;
722
+
723
+LExit:
724
+ // clean up
725
+ ReleaseObject(piDisp);
726
+ ReleaseObject(piObj);
727
+
728
+ ::VariantClear(&vtVal);
729
+
730
+ return hr;
731
+}
732
+
733
+HRESULT CpiFindCollectionObjectByIntegerKey(
734
+ ICatalogCollection* piColl,
735
+ long lKey,
736
+ ICatalogObject** ppiObj
737
+ )
738
+{
739
+ HRESULT hr = S_OK;
740
+
741
+ IDispatch* piDisp = NULL;
742
+ ICatalogObject* piObj = NULL;
743
+
744
+ VARIANT vtVal;
745
+ ::VariantInit(&vtVal);
746
+
747
+ long lCnt;
748
+ hr = piColl->get_Count(&lCnt);
749
+ ExitOnFailure(hr, "Failed to get to number of items in collection");
750
+
751
+ for (long i = 0; i < lCnt; i++)
752
+ {
753
+ // get ICatalogObject interface
754
+ hr = piColl->get_Item(i, &piDisp);
755
+ ExitOnFailure(hr, "Failed to get object from collection");
756
+
757
+ hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
758
+ ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
759
+
760
+ // compare key
761
+ hr = piObj->get_Key(&vtVal);
762
+ ExitOnFailure(hr, "Failed to get key");
763
+
764
+ hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_I4);
765
+ ExitOnFailure(hr, "Failed to change variant type");
766
+
767
+ if (vtVal.lVal == lKey)
768
+ {
769
+ if (ppiObj)
770
+ {
771
+ *ppiObj = piObj;
772
+ piObj = NULL;
773
+ }
774
+ ExitFunction1(hr = S_OK);
775
+ }
776
+
777
+ // clean up
778
+ ReleaseNullObject(piDisp);
779
+ ReleaseNullObject(piObj);
780
+
781
+ ::VariantClear(&vtVal);
782
+ }
783
+
784
+ hr = S_FALSE;
785
+
786
+LExit:
787
+ // clean up
788
+ ReleaseObject(piDisp);
789
+ ReleaseObject(piObj);
790
+
791
+ ::VariantClear(&vtVal);
792
+
793
+ return hr;
794
+}
795
+
796
+HRESULT CpiFindCollectionObjectByName(
797
+ ICatalogCollection* piColl,
798
+ LPCWSTR pwzName,
799
+ ICatalogObject** ppiObj
800
+ )
801
+{
802
+ HRESULT hr = S_OK;
803
+
804
+ IDispatch* piDisp = NULL;
805
+ ICatalogObject* piObj = NULL;
806
+
807
+ VARIANT vtVal;
808
+ ::VariantInit(&vtVal);
809
+
810
+ long lCnt;
811
+ hr = piColl->get_Count(&lCnt);
812
+ ExitOnFailure(hr, "Failed to get to number of items in collection");
813
+
814
+ for (long i = 0; i < lCnt; i++)
815
+ {
816
+ // get ICatalogObject interface
817
+ hr = piColl->get_Item(i, &piDisp);
818
+ ExitOnFailure(hr, "Failed to get object from collection");
819
+
820
+ hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
821
+ ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
822
+
823
+ // compare key
824
+ hr = piObj->get_Name(&vtVal);
825
+ ExitOnFailure(hr, "Failed to get key");
826
+
827
+ hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
828
+ ExitOnFailure(hr, "Failed to change variant type");
829
+
830
+ if (0 == lstrcmpW(vtVal.bstrVal, pwzName))
831
+ {
832
+ if (ppiObj)
833
+ {
834
+ *ppiObj = piObj;
835
+ piObj = NULL;
836
+ }
837
+ ExitFunction1(hr = S_OK);
838
+ }
839
+
840
+ // clean up
841
+ ReleaseNullObject(piDisp);
842
+ ReleaseNullObject(piObj);
843
+
844
+ ::VariantClear(&vtVal);
845
+ }
846
+
847
+ hr = S_FALSE;
848
+
849
+LExit:
850
+ // clean up
851
+ ReleaseObject(piDisp);
852
+ ReleaseObject(piObj);
853
+
854
+ ::VariantClear(&vtVal);
855
+
856
+ return hr;
857
+}
858
+
859
+HRESULT CpiFindUserCollectionObject(
860
+ ICatalogCollection* piColl,
861
+ PSID pSid,
862
+ ICatalogObject** ppiObj
863
+ )
864
+{
865
+ HRESULT hr = S_OK;
866
+
867
+ int i = 0;
868
+
869
+ IDispatch* piDisp = NULL;
870
+
871
+ // find index
872
+ hr = FindUserCollectionObjectIndex(piColl, pSid, &i);
873
+ ExitOnFailure(hr, "Failed to find user collection index");
874
+
875
+ if (S_FALSE == hr)
876
+ ExitFunction(); // not found, exit with hr = S_FALSE
877
+
878
+ // get object
879
+ if (ppiObj)
880
+ {
881
+ hr = piColl->get_Item(i, &piDisp);
882
+ ExitOnFailure(hr, "Failed to get object from collection");
883
+
884
+ hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)ppiObj);
885
+ ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
886
+ }
887
+
888
+ hr = S_OK;
889
+
890
+LExit:
891
+ // clean up
892
+ ReleaseObject(piDisp);
893
+
894
+ return hr;
895
+}
896
+
897
+HRESULT CpiGetPartitionsCollection(
898
+ ICatalogCollection** ppiPartColl
899
+ )
900
+{
901
+ HRESULT hr = S_OK;
902
+
903
+ // get collection
904
+ hr = CpiGetCatalogCollection(L"Partitions", ppiPartColl);
905
+ ExitOnFailure(hr, "Failed to get catalog collection");
906
+
907
+ hr = S_OK;
908
+
909
+LExit:
910
+ return hr;
911
+}
912
+
913
+HRESULT CpiGetPartitionRolesCollection(
914
+ LPCWSTR pwzPartID,
915
+ ICatalogCollection** ppiRolesColl
916
+ )
917
+{
918
+ HRESULT hr = S_OK;
919
+
920
+ ICatalogCollection* piPartColl = NULL;
921
+ ICatalogObject* piPartObj = NULL;
922
+
923
+ // get partitions collection
924
+ hr = CpiGetPartitionsCollection(&piPartColl);
925
+ ExitOnFailure(hr, "Failed to get partitions collection");
926
+
927
+ if (S_FALSE == hr)
928
+ ExitFunction(); // partitions collection not found, exit with hr = S_FALSE
929
+
930
+ // find object
931
+ hr = CpiFindCollectionObjectByStringKey(piPartColl, pwzPartID, &piPartObj);
932
+ ExitOnFailure(hr, "Failed to find collection object");
933
+
934
+ if (S_FALSE == hr)
935
+ ExitFunction(); // partition not found, exit with hr = S_FALSE
936
+
937
+ // get roles collection
938
+ hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"RolesForPartition", ppiRolesColl);
939
+ ExitOnFailure(hr, "Failed to get catalog collection");
940
+
941
+ hr = S_OK;
942
+
943
+LExit:
944
+ // clean up
945
+ ReleaseObject(piPartColl);
946
+ ReleaseObject(piPartObj);
947
+
948
+ return hr;
949
+}
950
+
951
+HRESULT CpiGetUsersInPartitionRoleCollection(
952
+ LPCWSTR pwzPartID,
953
+ LPCWSTR pwzRoleName,
954
+ ICatalogCollection** ppiUsrInRoleColl
955
+ )
956
+{
957
+ HRESULT hr = S_OK;
958
+
959
+ ICatalogCollection* piRoleColl = NULL;
960
+ ICatalogObject* piRoleObj = NULL;
961
+
962
+ // get roles collection
963
+ hr = CpiGetPartitionRolesCollection(pwzPartID, &piRoleColl);
964
+ ExitOnFailure(hr, "Failed to get roles collection");
965
+
966
+ if (S_FALSE == hr)
967
+ ExitFunction(); // partition roles collection not found, exit with hr = S_FALSE
968
+
969
+ // find object
970
+ hr = CpiFindCollectionObjectByName(piRoleColl, pwzRoleName, &piRoleObj);
971
+ ExitOnFailure(hr, "Failed to find collection object");
972
+
973
+ if (S_FALSE == hr)
974
+ ExitFunction(); // user not found, exit with hr = S_FALSE
975
+
976
+ // get roles collection
977
+ hr = CpiGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInPartitionRole", ppiUsrInRoleColl);
978
+ ExitOnFailure(hr, "Failed to get catalog collection");
979
+
980
+ hr = S_OK;
981
+
982
+LExit:
983
+ // clean up
984
+ ReleaseObject(piRoleColl);
985
+ ReleaseObject(piRoleObj);
986
+
987
+ return hr;
988
+}
989
+
990
+HRESULT CpiGetPartitionUsersCollection(
991
+ ICatalogCollection** ppiUserColl
992
+ )
993
+{
994
+ HRESULT hr = S_OK;
995
+
996
+ // get roles collection
997
+ hr = CpiGetCatalogCollection(L"PartitionUsers", ppiUserColl);
998
+ ExitOnFailure(hr, "Failed to get catalog collection");
999
+
1000
+ hr = S_OK;
1001
+
1002
+LExit:
1003
+ return hr;
1004
+}
1005
+
1006
+HRESULT CpiGetApplicationsCollection(
1007
+ LPCWSTR pwzPartID,
1008
+ ICatalogCollection** ppiAppColl
1009
+ )
1010
+{
1011
+ HRESULT hr = S_OK;
1012
+
1013
+ ICOMAdminCatalog* piCatalog = NULL;
1014
+ ICOMAdminCatalog2* piCatalog2 = NULL;
1015
+ BSTR bstrGlobPartID = NULL;
1016
+
1017
+ ICatalogCollection* piPartColl = NULL;
1018
+ ICatalogObject* piPartObj = NULL;
1019
+
1020
+ // get catalog
1021
+ hr = CpiGetAdminCatalog(&piCatalog);
1022
+ ExitOnFailure(hr, "Failed to get COM+ admin catalog");
1023
+
1024
+ // get ICOMAdminCatalog2 interface
1025
+ hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2);
1026
+
1027
+ // COM+ 1.5 or later
1028
+ if (E_NOINTERFACE != hr)
1029
+ {
1030
+ ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface");
1031
+
1032
+ // partition id
1033
+ if (!pwzPartID || !*pwzPartID)
1034
+ {
1035
+ // get global partition id
1036
+ hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID);
1037
+ ExitOnFailure(hr, "Failed to get global partition id");
1038
+ }
1039
+
1040
+ // get partitions collection
1041
+ hr = CpiGetPartitionsCollection(&piPartColl);
1042
+ ExitOnFailure(hr, "Failed to get partitions collection");
1043
+
1044
+ // find object
1045
+ hr = CpiFindCollectionObjectByStringKey(piPartColl, bstrGlobPartID ? bstrGlobPartID : pwzPartID, &piPartObj);
1046
+ ExitOnFailure(hr, "Failed to find collection object");
1047
+
1048
+ if (S_FALSE == hr)
1049
+ ExitFunction(); // partition not found, exit with hr = S_FALSE
1050
+
1051
+ // get applications collection
1052
+ hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"Applications", ppiAppColl);
1053
+ ExitOnFailure(hr, "Failed to get catalog collection for partition");
1054
+ }
1055
+
1056
+ // COM+ pre 1.5
1057
+ else
1058
+ {
1059
+ // this version of COM+ does not support partitions, make sure a partition was not specified
1060
+ if (pwzPartID && *pwzPartID)
1061
+ ExitOnFailure(hr = E_FAIL, "Partitions are not supported by this version of COM+");
1062
+
1063
+ // get applications collection
1064
+ hr = CpiGetCatalogCollection(L"Applications", ppiAppColl);
1065
+ ExitOnFailure(hr, "Failed to get catalog collection");
1066
+ }
1067
+
1068
+ hr = S_OK;
1069
+
1070
+LExit:
1071
+ // clean up
1072
+ ReleaseObject(piCatalog);
1073
+ ReleaseObject(piCatalog2);
1074
+ ReleaseBSTR(bstrGlobPartID);
1075
+
1076
+ ReleaseObject(piPartColl);
1077
+ ReleaseObject(piPartObj);
1078
+
1079
+ return hr;
1080
+}
1081
+
1082
+HRESULT CpiGetRolesCollection(
1083
+ LPCWSTR pwzPartID,
1084
+ LPCWSTR pwzAppID,
1085
+ ICatalogCollection** ppiRolesColl
1086
+ )
1087
+{
1088
+ HRESULT hr = S_OK;
1089
+
1090
+ ICatalogCollection* piAppColl = NULL;
1091
+ ICatalogObject* piAppObj = NULL;
1092
+
1093
+ // get applications collection
1094
+ hr = CpiGetApplicationsCollection(pwzPartID, &piAppColl);
1095
+ ExitOnFailure(hr, "Failed to get applications collection");
1096
+
1097
+ if (S_FALSE == hr)
1098
+ ExitFunction(); // applications collection not found, exit with hr = S_FALSE
1099
+
1100
+ // find object
1101
+ hr = CpiFindCollectionObjectByStringKey(piAppColl, pwzAppID, &piAppObj);
1102
+ ExitOnFailure(hr, "Failed to find collection object");
1103
+
1104
+ if (S_FALSE == hr)
1105
+ ExitFunction(); // application not found, exit with hr = S_FALSE
1106
+
1107
+ // get roles collection
1108
+ hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Roles", ppiRolesColl);
1109
+ ExitOnFailure(hr, "Failed to catalog collection");
1110
+
1111
+ hr = S_OK;
1112
+
1113
+LExit:
1114
+ // clean up
1115
+ ReleaseObject(piAppColl);
1116
+ ReleaseObject(piAppObj);
1117
+
1118
+ return hr;
1119
+}
1120
+
1121
+HRESULT CpiGetUsersInRoleCollection(
1122
+ LPCWSTR pwzPartID,
1123
+ LPCWSTR pwzAppID,
1124
+ LPCWSTR pwzRoleName,
1125
+ ICatalogCollection** ppiUsrInRoleColl
1126
+ )
1127
+{
1128
+ HRESULT hr = S_OK;
1129
+
1130
+ ICatalogCollection* piRoleColl = NULL;
1131
+ ICatalogObject* piRoleObj = NULL;
1132
+
1133
+ // get roles collection
1134
+ hr = CpiGetRolesCollection(pwzPartID, pwzAppID, &piRoleColl);
1135
+ ExitOnFailure(hr, "Failed to get roles collection");
1136
+
1137
+ if (S_FALSE == hr)
1138
+ ExitFunction(); // roles collection not found, exit with hr = S_FALSE
1139
+
1140
+ // find object
1141
+ hr = CpiFindCollectionObjectByName(piRoleColl, pwzRoleName, &piRoleObj);
1142
+ ExitOnFailure(hr, "Failed to find collection object");
1143
+
1144
+ if (S_FALSE == hr)
1145
+ ExitFunction(); // role not found, exit with hr = S_FALSE
1146
+
1147
+ // get roles collection
1148
+ hr = CpiGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInRole", ppiUsrInRoleColl);
1149
+ ExitOnFailure(hr, "Failed to get catalog collection");
1150
+
1151
+ hr = S_OK;
1152
+
1153
+LExit:
1154
+ // clean up
1155
+ ReleaseObject(piRoleColl);
1156
+ ReleaseObject(piRoleObj);
1157
+
1158
+ return hr;
1159
+}
1160
+
1161
+HRESULT CpiGetComponentsCollection(
1162
+ LPCWSTR pwzPartID,
1163
+ LPCWSTR pwzAppID,
1164
+ ICatalogCollection** ppiCompsColl
1165
+ )
1166
+{
1167
+ HRESULT hr = S_OK;
1168
+
1169
+ ICatalogCollection* piAppColl = NULL;
1170
+ ICatalogObject* piAppObj = NULL;
1171
+
1172
+ // get applications collection
1173
+ hr = CpiGetApplicationsCollection(pwzPartID, &piAppColl);
1174
+ ExitOnFailure(hr, "Failed to get applications collection");
1175
+
1176
+ if (S_FALSE == hr)
1177
+ ExitFunction(); // applications collection not found, exit with hr = S_FALSE
1178
+
1179
+ // find object
1180
+ hr = CpiFindCollectionObjectByStringKey(piAppColl, pwzAppID, &piAppObj);
1181
+ ExitOnFailure(hr, "Failed to find collection object");
1182
+
1183
+ if (S_FALSE == hr)
1184
+ ExitFunction(); // application not found, exit with hr = S_FALSE
1185
+
1186
+ // get components collection
1187
+ hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Components", ppiCompsColl);
1188
+ ExitOnFailure(hr, "Failed to get catalog collection");
1189
+
1190
+ hr = S_OK;
1191
+
1192
+LExit:
1193
+ // clean up
1194
+ ReleaseObject(piAppColl);
1195
+ ReleaseObject(piAppObj);
1196
+
1197
+ return hr;
1198
+}
1199
+
1200
+HRESULT CpiGetInterfacesCollection(
1201
+ ICatalogCollection* piCompColl,
1202
+ ICatalogObject* piCompObj,
1203
+ ICatalogCollection** ppiIntfColl
1204
+ )
1205
+{
1206
+ HRESULT hr = S_OK;
1207
+
1208
+ // get interfaces collection
1209
+ hr = CpiGetCatalogCollection(piCompColl, piCompObj, L"InterfacesForComponent", ppiIntfColl);
1210
+ ExitOnFailure(hr, "Failed to get catalog collection");
1211
+
1212
+ hr = S_OK;
1213
+
1214
+LExit:
1215
+ return hr;
1216
+}
1217
+
1218
+HRESULT CpiGetMethodsCollection(
1219
+ ICatalogCollection* piIntfColl,
1220
+ ICatalogObject* piIntfObj,
1221
+ ICatalogCollection** ppiMethColl
1222
+ )
1223
+{
1224
+ HRESULT hr = S_OK;
1225
+
1226
+ // get interfaces collection
1227
+ hr = CpiGetCatalogCollection(piIntfColl, piIntfObj, L"MethodsForInterface", ppiMethColl);
1228
+ ExitOnFailure(hr, "Failed to get catalog collection");
1229
+
1230
+ hr = S_OK;
1231
+
1232
+LExit:
1233
+ return hr;
1234
+}
1235
+
1236
+HRESULT CpiGetSubscriptionsCollection(
1237
+ LPCWSTR pwzPartID,
1238
+ LPCWSTR pwzAppID,
1239
+ LPCWSTR pwzCompCLSID,
1240
+ ICatalogCollection** ppiSubsColl
1241
+ )
1242
+{
1243
+ HRESULT hr = S_OK;
1244
+
1245
+ ICatalogCollection* piCompColl = NULL;
1246
+ ICatalogObject* piCompObj = NULL;
1247
+
1248
+ // get components collection
1249
+ hr = CpiGetComponentsCollection(pwzPartID, pwzAppID, &piCompColl);
1250
+ ExitOnFailure(hr, "Failed to get components collection");
1251
+
1252
+ if (S_FALSE == hr)
1253
+ ExitFunction(); // components collection not found, exit with hr = S_FALSE
1254
+
1255
+ // find object
1256
+ hr = CpiFindCollectionObjectByStringKey(piCompColl, pwzCompCLSID, &piCompObj);
1257
+ ExitOnFailure(hr, "Failed to find collection object");
1258
+
1259
+ if (S_FALSE == hr)
1260
+ ExitFunction(); // component not found, exit with hr = S_FALSE
1261
+
1262
+ // get subscriptions collection
1263
+ hr = CpiGetCatalogCollection(piCompColl, piCompObj, L"SubscriptionsForComponent", ppiSubsColl);
1264
+ ExitOnFailure(hr, "Failed to get catalog collection");
1265
+
1266
+ hr = S_OK;
1267
+
1268
+LExit:
1269
+ // clean up
1270
+ ReleaseObject(piCompColl);
1271
+ ReleaseObject(piCompObj);
1272
+
1273
+ return hr;
1274
+}
1275
+
1276
+HRESULT CpiReadPropertyList(
1277
+ LPWSTR* ppwzData,
1278
+ CPI_PROPERTY** ppPropList
1279
+ )
1280
+{
1281
+ HRESULT hr = S_OK;
1282
+
1283
+ CPI_PROPERTY* pItm = NULL;
1284
+ LPWSTR pwzName = NULL;
1285
+
1286
+ // clear list if it already contains items
1287
+ if (*ppPropList)
1288
+ CpiFreePropertyList(*ppPropList);
1289
+ *ppPropList = NULL;
1290
+
1291
+ // read property count
1292
+ int iPropCnt = 0;
1293
+ hr = WcaReadIntegerFromCaData(ppwzData, &iPropCnt);
1294
+ ExitOnFailure(hr, "Failed to read property count");
1295
+
1296
+ for (int i = 0; i < iPropCnt; i++)
1297
+ {
1298
+ // allocate new element
1299
+ pItm = (CPI_PROPERTY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PROPERTY));
1300
+ if (!pItm)
1301
+ ExitFunction1(hr = E_OUTOFMEMORY);
1302
+
1303
+ // Name
1304
+ hr = WcaReadStringFromCaData(ppwzData, &pwzName);
1305
+ ExitOnFailure(hr, "Failed to read name");
1306
+ StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzName);
1307
+
1308
+ // Value
1309
+ hr = WcaReadStringFromCaData(ppwzData, &pItm->pwzValue);
1310
+ ExitOnFailure(hr, "Failed to read property value");
1311
+
1312
+ // add to list
1313
+ if (*ppPropList)
1314
+ pItm->pNext = *ppPropList;
1315
+ *ppPropList = pItm;
1316
+ pItm = NULL;
1317
+ }
1318
+
1319
+ hr = S_OK;
1320
+
1321
+LExit:
1322
+ // clean up
1323
+ ReleaseStr(pwzName);
1324
+
1325
+ if (pItm)
1326
+ CpiFreePropertyList(pItm);
1327
+
1328
+ return hr;
1329
+}
1330
+
1331
+void CpiFreePropertyList(
1332
+ CPI_PROPERTY* pList
1333
+ )
1334
+{
1335
+ while (pList)
1336
+ {
1337
+ ReleaseStr(pList->pwzValue);
1338
+
1339
+ CPI_PROPERTY* pDelete = pList;
1340
+ pList = pList->pNext;
1341
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
1342
+ }
1343
+}
1344
+
1345
+HRESULT CpiWriteKeyToRollbackFile(
1346
+ HANDLE hFile,
1347
+ LPCWSTR pwzKey
1348
+ )
1349
+{
1350
+ HRESULT hr = S_OK;
1351
+
1352
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
1353
+ ::ZeroMemory(wzKey, sizeof(wzKey));
1354
+ hr = StringCchCopyW(wzKey, countof(wzKey), pwzKey);
1355
+ ExitOnFailure(hr, "Failed to copy key");
1356
+
1357
+ hr = WriteFileAll(hFile, (PBYTE)wzKey, MAX_DARWIN_KEY * sizeof(WCHAR));
1358
+ ExitOnFailure(hr, "Failed to write buffer");
1359
+
1360
+ FlushFileBuffers(hFile);
1361
+
1362
+ hr = S_OK;
1363
+
1364
+LExit:
1365
+ return hr;
1366
+}
1367
+
1368
+HRESULT CpiWriteIntegerToRollbackFile(
1369
+ HANDLE hFile,
1370
+ int i
1371
+ )
1372
+{
1373
+ HRESULT hr = S_OK;
1374
+
1375
+ hr = WriteFileAll(hFile, (PBYTE)&i, sizeof(int));
1376
+ ExitOnFailure(hr, "Failed to write buffer");
1377
+
1378
+ FlushFileBuffers(hFile);
1379
+
1380
+ hr = S_OK;
1381
+
1382
+LExit:
1383
+ return hr;
1384
+}
1385
+
1386
+HRESULT CpiReadRollbackDataList(
1387
+ HANDLE hFile,
1388
+ CPI_ROLLBACK_DATA** pprdList
1389
+ )
1390
+{
1391
+ HRESULT hr = S_OK;
1392
+
1393
+ int iCount;
1394
+
1395
+ CPI_ROLLBACK_DATA* pItm = NULL;
1396
+
1397
+ // read count
1398
+ hr = ReadFileAll(hFile, (PBYTE)&iCount, sizeof(int));
1399
+ if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr)
1400
+ ExitFunction1(hr = S_OK); // EOF reached, nothing left to read
1401
+ ExitOnFailure(hr, "Failed to read count");
1402
+
1403
+ for (int i = 0; i < iCount; i++)
1404
+ {
1405
+ // allocate new element
1406
+ pItm = (CPI_ROLLBACK_DATA*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLLBACK_DATA));
1407
+ if (!pItm)
1408
+ ExitFunction1(hr = E_OUTOFMEMORY);
1409
+
1410
+ // read from file
1411
+ hr = ReadFileAll(hFile, (PBYTE)pItm->wzKey, MAX_DARWIN_KEY * sizeof(WCHAR));
1412
+ if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr)
1413
+ break; // EOF reached, nothing left to read
1414
+ ExitOnFailure(hr, "Failed to read key");
1415
+
1416
+ hr = ReadFileAll(hFile, (PBYTE)&pItm->iStatus, sizeof(int));
1417
+ if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr)
1418
+ pItm->iStatus = 0; // EOF reached, the operation was interupted; set status to zero
1419
+ else
1420
+ ExitOnFailure(hr, "Failed to read status");
1421
+
1422
+ // add to list
1423
+ if (*pprdList)
1424
+ pItm->pNext = *pprdList;
1425
+ *pprdList = pItm;
1426
+ pItm = NULL;
1427
+ }
1428
+
1429
+ hr = S_OK;
1430
+
1431
+LExit:
1432
+ // clean up
1433
+ if (pItm)
1434
+ CpiFreeRollbackDataList(pItm);
1435
+
1436
+ return hr;
1437
+}
1438
+
1439
+void CpiFreeRollbackDataList(
1440
+ CPI_ROLLBACK_DATA* pList
1441
+ )
1442
+{
1443
+ while (pList)
1444
+ {
1445
+ CPI_ROLLBACK_DATA* pDelete = pList;
1446
+ pList = pList->pNext;
1447
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
1448
+ }
1449
+}
1450
+
1451
+HRESULT CpiFindRollbackStatus(
1452
+ CPI_ROLLBACK_DATA* pList,
1453
+ LPCWSTR pwzKey,
1454
+ int* piStatus
1455
+ )
1456
+{
1457
+ HRESULT hr = S_OK;
1458
+
1459
+ for (; pList; pList = pList->pNext)
1460
+ {
1461
+ if (0 == lstrcmpW(pList->wzKey, pwzKey))
1462
+ {
1463
+ *piStatus = pList->iStatus;
1464
+ ExitFunction1(hr = S_OK);
1465
+ }
1466
+ }
1467
+
1468
+ hr = S_FALSE;
1469
+
1470
+LExit:
1471
+ return hr;
1472
+}
1473
+
1474
+HRESULT CpiAccountNameToSid(
1475
+ LPCWSTR pwzAccountName,
1476
+ PSID* ppSid
1477
+ )
1478
+{
1479
+ HRESULT hr = S_OK;
1480
+ UINT er = ERROR_SUCCESS;
1481
+ NTSTATUS st = 0;
1482
+
1483
+ PSID pSid = NULL;
1484
+ LSA_OBJECT_ATTRIBUTES loaAttributes;
1485
+ LSA_HANDLE lsahPolicy = NULL;
1486
+ LSA_UNICODE_STRING lusName;
1487
+ PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL;
1488
+ PLSA_TRANSLATED_SID pltsSid = NULL;
1489
+
1490
+ ::ZeroMemory(&loaAttributes, sizeof(loaAttributes));
1491
+ ::ZeroMemory(&lusName, sizeof(lusName));
1492
+
1493
+ // identify well known SIDs
1494
+ for (CPI_WELLKNOWN_SID* pWS = wsWellKnownSids; pWS->pwzName; pWS++)
1495
+ {
1496
+ if (0 == lstrcmpiW(pwzAccountName, pWS->pwzName))
1497
+ {
1498
+ // allocate SID buffer
1499
+ pSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, ::GetSidLengthRequired(pWS->nSubAuthorityCount));
1500
+ ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID");
1501
+
1502
+ // initialize SID
1503
+ ::InitializeSid(pSid, &pWS->iaIdentifierAuthority, pWS->nSubAuthorityCount);
1504
+
1505
+ // copy sub autorities
1506
+ for (DWORD i = 0; i < pWS->nSubAuthorityCount; i++)
1507
+ *::GetSidSubAuthority(pSid, i) = pWS->dwSubAuthority[i];
1508
+
1509
+ break;
1510
+ }
1511
+ }
1512
+
1513
+ // lookup name
1514
+ if (!pSid)
1515
+ {
1516
+ // open policy handle
1517
+ st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy);
1518
+ er = ::LsaNtStatusToWinError(st);
1519
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle");
1520
+
1521
+ // create account name lsa unicode string
1522
+ hr = InitLsaUnicodeString(&lusName, pwzAccountName, (DWORD)wcslen(pwzAccountName));
1523
+ ExitOnFailure(hr, "Failed to initialize account name string");
1524
+
1525
+ // lookup name
1526
+ st = ::LsaLookupNames(lsahPolicy, 1, &lusName, &plrdsDomains, &pltsSid);
1527
+ er = ::LsaNtStatusToWinError(st);
1528
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names");
1529
+
1530
+ if (SidTypeDomain == pltsSid->Use)
1531
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported");
1532
+
1533
+ // convert sid
1534
+ hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pSid);
1535
+ ExitOnFailure(hr, "Failed to convert SID");
1536
+ }
1537
+
1538
+ *ppSid = pSid;
1539
+ pSid = NULL;
1540
+
1541
+ hr = S_OK;
1542
+
1543
+LExit:
1544
+ // clean up
1545
+ if (pSid)
1546
+ ::HeapFree(::GetProcessHeap(), 0, pSid);
1547
+ if (lsahPolicy)
1548
+ ::LsaClose(lsahPolicy);
1549
+ if (plrdsDomains)
1550
+ ::LsaFreeMemory(plrdsDomains);
1551
+ if (pltsSid)
1552
+ ::LsaFreeMemory(pltsSid);
1553
+ FreeLsaUnicodeString(&lusName);
1554
+
1555
+ return hr;
1556
+}
1557
+
1558
+HRESULT CpiSidToAccountName(
1559
+ PSID pSid,
1560
+ LPWSTR* ppwzAccountName
1561
+ )
1562
+{
1563
+ HRESULT hr = S_OK;
1564
+ UINT er = ERROR_SUCCESS;
1565
+ NTSTATUS st = 0;
1566
+
1567
+ LSA_OBJECT_ATTRIBUTES loaAttributes;
1568
+ LSA_HANDLE lsahPolicy = NULL;
1569
+ PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL;
1570
+ PLSA_TRANSLATED_NAME pltnName = NULL;
1571
+
1572
+ LPWSTR pwzDomain = NULL;
1573
+ LPWSTR pwzName = NULL;
1574
+
1575
+ ::ZeroMemory(&loaAttributes, sizeof(loaAttributes));
1576
+
1577
+ // open policy handle
1578
+ st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy);
1579
+ er = ::LsaNtStatusToWinError(st);
1580
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle");
1581
+
1582
+ // lookup SID
1583
+ st = ::LsaLookupSids(lsahPolicy, 1, &pSid, &plrdsDomains, &pltnName);
1584
+ er = ::LsaNtStatusToWinError(st);
1585
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed lookup SID");
1586
+
1587
+ if (SidTypeDomain == pltnName->Use)
1588
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported");
1589
+
1590
+ // format account name string
1591
+ if (SidTypeWellKnownGroup != pltnName->Use)
1592
+ {
1593
+ PLSA_UNICODE_STRING plusDomain = &plrdsDomains->Domains[pltnName->DomainIndex].Name;
1594
+ hr = StrAllocString(&pwzDomain, plusDomain->Buffer, plusDomain->Length / sizeof(WCHAR));
1595
+ ExitOnFailure(hr, "Failed to allocate name string");
1596
+ }
1597
+
1598
+ hr = StrAllocString(&pwzName, pltnName->Name.Buffer, pltnName->Name.Length / sizeof(WCHAR));
1599
+ ExitOnFailure(hr, "Failed to allocate domain string");
1600
+
1601
+ hr = StrAllocFormatted(ppwzAccountName, L"%s\\%s", pwzDomain ? pwzDomain : L"", pwzName);
1602
+ ExitOnFailure(hr, "Failed to format account name string");
1603
+
1604
+ hr = S_OK;
1605
+
1606
+LExit:
1607
+ // clean up
1608
+ if (lsahPolicy)
1609
+ ::LsaClose(lsahPolicy);
1610
+ if (plrdsDomains)
1611
+ ::LsaFreeMemory(plrdsDomains);
1612
+ if (pltnName)
1613
+ ::LsaFreeMemory(pltnName);
1614
+
1615
+ ReleaseStr(pwzDomain);
1616
+ ReleaseStr(pwzName);
1617
+
1618
+ return hr;
1619
+}
1620
+
1621
+// helper function definitions
1622
+
1623
+static HRESULT FindUserCollectionObjectIndex(
1624
+ ICatalogCollection* piColl,
1625
+ PSID pSid,
1626
+ int* pi
1627
+ )
1628
+{
1629
+ HRESULT hr = S_OK;
1630
+ UINT er = ERROR_SUCCESS;
1631
+ NTSTATUS st = 0;
1632
+
1633
+ long i = 0;
1634
+ long lCollCnt = 0;
1635
+
1636
+ LSA_OBJECT_ATTRIBUTES loaAttributes;
1637
+ LSA_HANDLE lsahPolicy = NULL;
1638
+ PLSA_UNICODE_STRING plusNames = NULL;
1639
+ PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL;
1640
+ PLSA_TRANSLATED_SID pltsSids = NULL;
1641
+
1642
+ IDispatch* piDisp = NULL;
1643
+ ICatalogObject* piObj = NULL;
1644
+ VARIANT vtVal;
1645
+
1646
+ PSID pTmpSid = NULL;
1647
+
1648
+ PLSA_TRANSLATED_SID pltsSid;
1649
+
1650
+ ::VariantInit(&vtVal);
1651
+ ::ZeroMemory(&loaAttributes, sizeof(loaAttributes));
1652
+
1653
+ // open policy handle
1654
+ st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy);
1655
+ er = ::LsaNtStatusToWinError(st);
1656
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle");
1657
+
1658
+ // get number of elements in collection
1659
+ hr = piColl->get_Count(&lCollCnt);
1660
+ ExitOnFailure(hr, "Failed to get to number of objects in collection");
1661
+
1662
+ if (0 == lCollCnt)
1663
+ ExitFunction1(hr = S_FALSE); // not found
1664
+
1665
+ // allocate name buffer
1666
+ plusNames = (PLSA_UNICODE_STRING)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LSA_UNICODE_STRING) * lCollCnt);
1667
+ ExitOnNull(plusNames, hr, E_OUTOFMEMORY, "Failed to allocate names buffer");
1668
+
1669
+ // get accounts in collection
1670
+ for (i = 0; i < lCollCnt; i++)
1671
+ {
1672
+ // get ICatalogObject interface
1673
+ hr = piColl->get_Item(i, &piDisp);
1674
+ ExitOnFailure(hr, "Failed to get object from collection");
1675
+
1676
+ hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
1677
+ ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
1678
+
1679
+ // get value
1680
+ hr = piObj->get_Key(&vtVal);
1681
+ ExitOnFailure(hr, "Failed to get key");
1682
+
1683
+ hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
1684
+ ExitOnFailure(hr, "Failed to change variant type");
1685
+
1686
+ // copy account name string
1687
+ hr = InitLsaUnicodeString(&plusNames[i], vtVal.bstrVal, ::SysStringLen(vtVal.bstrVal));
1688
+ ExitOnFailure(hr, "Failed to initialize account name string");
1689
+
1690
+ // clean up
1691
+ ReleaseNullObject(piDisp);
1692
+ ReleaseNullObject(piObj);
1693
+ ::VariantClear(&vtVal);
1694
+ }
1695
+
1696
+ // lookup names
1697
+ st = ::LsaLookupNames(lsahPolicy, lCollCnt, plusNames, &plrdsDomains, &pltsSids);
1698
+ er = ::LsaNtStatusToWinError(st);
1699
+ if (ERROR_NONE_MAPPED != er && ERROR_SOME_NOT_MAPPED != er)
1700
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names");
1701
+
1702
+ // compare SIDs
1703
+ for (i = 0; i < lCollCnt; i++)
1704
+ {
1705
+ // get SID
1706
+ pltsSid = &pltsSids[i];
1707
+ if (SidTypeDomain == pltsSid->Use || SidTypeInvalid == pltsSid->Use || SidTypeUnknown == pltsSid->Use)
1708
+ continue; // ignore...
1709
+
1710
+ hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pTmpSid);
1711
+ ExitOnFailure(hr, "Failed to convert SID");
1712
+
1713
+ // compare SIDs
1714
+ if (::EqualSid(pSid, pTmpSid))
1715
+ {
1716
+ *pi = i;
1717
+ ExitFunction1(hr = S_OK);
1718
+ }
1719
+ }
1720
+
1721
+ if (ERROR_NONE_MAPPED == er || ERROR_SOME_NOT_MAPPED == er)
1722
+ hr = HRESULT_FROM_WIN32(er);
1723
+ else
1724
+ hr = S_FALSE; // not found
1725
+
1726
+LExit:
1727
+ // clean up
1728
+ ReleaseObject(piDisp);
1729
+ ReleaseObject(piObj);
1730
+ ::VariantClear(&vtVal);
1731
+
1732
+ if (plusNames)
1733
+ {
1734
+ for (i = 0; i < lCollCnt; i++)
1735
+ FreeLsaUnicodeString(&plusNames[i]);
1736
+ ::HeapFree(::GetProcessHeap(), 0, plusNames);
1737
+ }
1738
+
1739
+ if (lsahPolicy)
1740
+ ::LsaClose(lsahPolicy);
1741
+ if (plrdsDomains)
1742
+ ::LsaFreeMemory(plrdsDomains);
1743
+ if (pltsSids)
1744
+ ::LsaFreeMemory(pltsSids);
1745
+
1746
+ if (pTmpSid)
1747
+ ::HeapFree(::GetProcessHeap(), 0, pTmpSid);
1748
+
1749
+ return hr;
1750
+}
1751
+
1752
+static HRESULT CreateSidFromDomainRidPair(
1753
+ PSID pDomainSid,
1754
+ DWORD dwRid,
1755
+ PSID* ppSid
1756
+ )
1757
+{
1758
+ HRESULT hr = S_OK;
1759
+ PSID pSid = NULL;
1760
+
1761
+ // get domain SID sub authority count
1762
+ UCHAR ucSubAuthorityCount = *::GetSidSubAuthorityCount(pDomainSid);
1763
+
1764
+ // allocate SID buffer
1765
+ DWORD dwLengthRequired = ::GetSidLengthRequired(ucSubAuthorityCount + (UCHAR)1);
1766
+ if (*ppSid)
1767
+ {
1768
+ SIZE_T ccb = ::HeapSize(::GetProcessHeap(), 0, *ppSid);
1769
+ if (-1 == ccb)
1770
+ ExitOnFailure(hr = E_FAIL, "Failed to get size of SID buffer");
1771
+
1772
+ if (ccb < dwLengthRequired)
1773
+ {
1774
+ pSid = (PSID)::HeapReAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, *ppSid, dwLengthRequired);
1775
+ ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to reallocate buffer for SID, len: %d", dwLengthRequired);
1776
+ *ppSid = pSid;
1777
+ }
1778
+ }
1779
+ else
1780
+ {
1781
+ *ppSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwLengthRequired);
1782
+ ExitOnNull(*ppSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID, len: %d", dwLengthRequired);
1783
+ }
1784
+
1785
+ ::InitializeSid(*ppSid, ::GetSidIdentifierAuthority(pDomainSid), ucSubAuthorityCount + (UCHAR)1);
1786
+
1787
+ // copy sub autorities
1788
+ DWORD i = 0;
1789
+ for (; i < ucSubAuthorityCount; i++)
1790
+ *::GetSidSubAuthority(*ppSid, i) = *::GetSidSubAuthority(pDomainSid, i);
1791
+ *::GetSidSubAuthority(*ppSid, i) = dwRid;
1792
+
1793
+ hr = S_OK;
1794
+
1795
+LExit:
1796
+ return hr;
1797
+}
1798
+
1799
+static HRESULT InitLsaUnicodeString(
1800
+ PLSA_UNICODE_STRING plusStr,
1801
+ LPCWSTR pwzStr,
1802
+ DWORD dwLen
1803
+ )
1804
+{
1805
+ HRESULT hr = S_OK;
1806
+
1807
+ plusStr->Length = (USHORT)dwLen * sizeof(WCHAR);
1808
+ plusStr->MaximumLength = (USHORT)(dwLen + 1) * sizeof(WCHAR);
1809
+
1810
+ plusStr->Buffer = (WCHAR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) * (dwLen + 1));
1811
+ ExitOnNull(plusStr->Buffer, hr, E_OUTOFMEMORY, "Failed to allocate account name string");
1812
+
1813
+ hr = StringCchCopyW(plusStr->Buffer, dwLen + 1, pwzStr);
1814
+ ExitOnFailure(hr, "Failed to copy buffer");
1815
+
1816
+ hr = S_OK;
1817
+
1818
+LExit:
1819
+ return hr;
1820
+}
1821
+
1822
+static void FreeLsaUnicodeString(
1823
+ PLSA_UNICODE_STRING plusStr
1824
+ )
1825
+{
1826
+ if (plusStr->Buffer)
1827
+ ::HeapFree(::GetProcessHeap(), 0, plusStr->Buffer);
1828
+}
1829
+
1830
+static HRESULT WriteFileAll(
1831
+ HANDLE hFile,
1832
+ PBYTE pbBuffer,
1833
+ DWORD dwBufferLength
1834
+ )
1835
+{
1836
+ HRESULT hr = S_OK;
1837
+
1838
+ DWORD dwBytesWritten;
1839
+
1840
+ while (dwBufferLength)
1841
+ {
1842
+ if (!::WriteFile(hFile, pbBuffer, dwBufferLength, &dwBytesWritten, NULL))
1843
+ ExitFunction1(hr = HRESULT_FROM_WIN32(::GetLastError()));
1844
+
1845
+ dwBufferLength -= dwBytesWritten;
1846
+ pbBuffer += dwBytesWritten;
1847
+ }
1848
+
1849
+ hr = S_OK;
1850
+
1851
+LExit:
1852
+ return hr;
1853
+}
1854
+
1855
+static HRESULT ReadFileAll(
1856
+ HANDLE hFile,
1857
+ PBYTE pbBuffer,
1858
+ DWORD dwBufferLength
1859
+ )
1860
+{
1861
+ HRESULT hr = S_OK;
1862
+
1863
+ DWORD dwBytesRead;
1864
+
1865
+ while (dwBufferLength)
1866
+ {
1867
+ if (!::ReadFile(hFile, pbBuffer, dwBufferLength, &dwBytesRead, NULL))
1868
+ ExitFunction1(hr = HRESULT_FROM_WIN32(::GetLastError()));
1869
+
1870
+ if (0 == dwBytesRead)
1871
+ ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF));
1872
+
1873
+ dwBufferLength -= dwBytesRead;
1874
+ pbBuffer += dwBytesRead;
1875
+ }
1876
+
1877
+ hr = S_OK;
1878
+
1879
+LExit:
1880
+ return hr;
1881
+}
src/ca/cputilexec.h
new
+193
@@ -0,0 +1,193 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+#define CPI_MAX_GUID 38
6
+
7
+enum eActionType { atNoOp = 0, atCreate, atRemove };
8
+
9
+
10
+// structs
11
+
12
+struct CPI_PROPERTY
13
+{
14
+ WCHAR wzName[MAX_DARWIN_KEY + 1];
15
+ LPWSTR pwzValue;
16
+
17
+ CPI_PROPERTY* pNext;
18
+};
19
+
20
+struct CPI_ROLLBACK_DATA
21
+{
22
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
23
+ int iStatus;
24
+
25
+ CPI_ROLLBACK_DATA* pNext;
26
+};
27
+
28
+
29
+// function prototypes
30
+
31
+void CpiInitialize();
32
+void CpiFinalize();
33
+HRESULT CpiActionStartMessage(
34
+ LPWSTR* ppwzActionData,
35
+ BOOL fSuppress
36
+ );
37
+HRESULT CpiActionDataMessage(
38
+ DWORD cArgs,
39
+ ...
40
+ );
41
+HRESULT CpiGetAdminCatalog(
42
+ ICOMAdminCatalog** ppiCatalog
43
+ );
44
+HRESULT CpiLogCatalogErrorInfo();
45
+HRESULT CpiGetCatalogCollection(
46
+ LPCWSTR pwzName,
47
+ ICatalogCollection** ppiColl
48
+ );
49
+HRESULT CpiGetCatalogCollection(
50
+ ICatalogCollection* piColl,
51
+ ICatalogObject* piObj,
52
+ LPCWSTR pwzName,
53
+ ICatalogCollection** ppiColl
54
+ );
55
+HRESULT CpiAddCollectionObject(
56
+ ICatalogCollection* piColl,
57
+ ICatalogObject** ppiObj
58
+ );
59
+HRESULT CpiPutCollectionObjectValue(
60
+ ICatalogObject* piObj,
61
+ LPCWSTR pwzPropName,
62
+ LPCWSTR pwzValue
63
+ );
64
+HRESULT CpiPutCollectionObjectValues(
65
+ ICatalogObject* piObj,
66
+ CPI_PROPERTY* pPropList
67
+ );
68
+HRESULT CpiGetCollectionObjectValue(
69
+ ICatalogObject* piObj,
70
+ LPCWSTR szPropName,
71
+ LPWSTR* ppwzValue
72
+ );
73
+HRESULT CpiResetObjectProperty(
74
+ ICatalogCollection* piColl,
75
+ ICatalogObject* piObj,
76
+ LPCWSTR pwzPropName
77
+ );
78
+HRESULT CpiRemoveCollectionObject(
79
+ ICatalogCollection* piColl,
80
+ LPCWSTR pwzID,
81
+ LPCWSTR pwzName,
82
+ BOOL fResetDeleteable
83
+ );
84
+HRESULT CpiRemoveUserCollectionObject(
85
+ ICatalogCollection* piColl,
86
+ PSID pSid
87
+ );
88
+HRESULT CpiFindCollectionObjectByStringKey(
89
+ ICatalogCollection* piColl,
90
+ LPCWSTR pwzKey,
91
+ ICatalogObject** ppiObj
92
+ );
93
+HRESULT CpiFindCollectionObjectByIntegerKey(
94
+ ICatalogCollection* piColl,
95
+ long lKey,
96
+ ICatalogObject** ppiObj
97
+ );
98
+HRESULT CpiFindCollectionObjectByName(
99
+ ICatalogCollection* piColl,
100
+ LPCWSTR pwzName,
101
+ ICatalogObject** ppiObj
102
+ );
103
+HRESULT CpiFindUserCollectionObject(
104
+ ICatalogCollection* piColl,
105
+ PSID pSid,
106
+ ICatalogObject** ppiObj
107
+ );
108
+HRESULT CpiGetPartitionsCollection(
109
+ ICatalogCollection** ppiPartColl
110
+ );
111
+HRESULT CpiGetPartitionRolesCollection(
112
+ LPCWSTR pwzPartID,
113
+ ICatalogCollection** ppiRolesColl
114
+ );
115
+HRESULT CpiGetUsersInPartitionRoleCollection(
116
+ LPCWSTR pwzPartID,
117
+ LPCWSTR pwzRoleName,
118
+ ICatalogCollection** ppiUsrInRoleColl
119
+ );
120
+HRESULT CpiGetPartitionUsersCollection(
121
+ ICatalogCollection** ppiUserColl
122
+ );
123
+HRESULT CpiGetApplicationsCollection(
124
+ LPCWSTR pwzPartID,
125
+ ICatalogCollection** ppiAppColl
126
+ );
127
+HRESULT CpiGetRolesCollection(
128
+ LPCWSTR pwzPartID,
129
+ LPCWSTR pwzAppID,
130
+ ICatalogCollection** ppiRolesColl
131
+ );
132
+HRESULT CpiGetUsersInRoleCollection(
133
+ LPCWSTR pwzPartID,
134
+ LPCWSTR pwzAppID,
135
+ LPCWSTR pwzRoleName,
136
+ ICatalogCollection** ppiUsrInRoleColl
137
+ );
138
+HRESULT CpiGetComponentsCollection(
139
+ LPCWSTR pwzPartID,
140
+ LPCWSTR pwzAppID,
141
+ ICatalogCollection** ppiCompsColl
142
+ );
143
+HRESULT CpiGetInterfacesCollection(
144
+ ICatalogCollection* piCompColl,
145
+ ICatalogObject* piCompObj,
146
+ ICatalogCollection** ppiIntfColl
147
+ );
148
+HRESULT CpiGetMethodsCollection(
149
+ ICatalogCollection* piIntfColl,
150
+ ICatalogObject* piIntfObj,
151
+ ICatalogCollection** ppiMethColl
152
+ );
153
+HRESULT CpiGetSubscriptionsCollection(
154
+ LPCWSTR pwzPartID,
155
+ LPCWSTR pwzAppID,
156
+ LPCWSTR pwzCompCLSID,
157
+ ICatalogCollection** ppiCompsColl
158
+ );
159
+HRESULT CpiReadPropertyList(
160
+ LPWSTR* ppwzData,
161
+ CPI_PROPERTY** ppPropList
162
+ );
163
+void CpiFreePropertyList(
164
+ CPI_PROPERTY* pList
165
+ );
166
+HRESULT CpiWriteKeyToRollbackFile(
167
+ HANDLE hFile,
168
+ LPCWSTR pwzKey
169
+ );
170
+HRESULT CpiWriteIntegerToRollbackFile(
171
+ HANDLE hFile,
172
+ int i
173
+ );
174
+HRESULT CpiReadRollbackDataList(
175
+ HANDLE hFile,
176
+ CPI_ROLLBACK_DATA** pprdList
177
+ );
178
+void CpiFreeRollbackDataList(
179
+ CPI_ROLLBACK_DATA* pList
180
+ );
181
+HRESULT CpiFindRollbackStatus(
182
+ CPI_ROLLBACK_DATA* pList,
183
+ LPCWSTR pwzKey,
184
+ int* piStatus
185
+ );
186
+HRESULT CpiAccountNameToSid(
187
+ LPCWSTR pwzAccountName,
188
+ PSID* ppSid
189
+ );
190
+HRESULT CpiSidToAccountName(
191
+ PSID pSid,
192
+ LPWSTR* ppwzAccountName
193
+ );
src/ca/cputilsched.cpp
new
+885
@@ -0,0 +1,885 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+#include "precomp.h"
4
+
5
+
6
+// sql queries
7
+
8
+LPCWSTR vcsActionTextQuery =
9
+ L"SELECT `Description`, `Template` FROM `ActionText` WHERE `Action` = ?";
10
+enum eActionTextQuery { atqDescription = 1, atqTemplate };
11
+
12
+LPCWSTR vcsComponentAttributesQuery =
13
+ L"SELECT `Attributes` FROM `Component` WHERE `Component` = ?";
14
+enum eComponentAttributesQuery { caqAttributes = 1 };
15
+
16
+LPCWSTR vcsUserQuery = L"SELECT `Domain`, `Name` FROM `User` WHERE `User` = ?";
17
+enum eUserQuery { uqDomain = 1, uqName };
18
+
19
+enum ePropertyQuery { pqName = 1, pqValue };
20
+
21
+
22
+// prototypes for private helper functions
23
+
24
+static HRESULT FindPropertyDefinition(
25
+ CPI_PROPERTY_DEFINITION* pPropDefList,
26
+ LPCWSTR pwzName,
27
+ CPI_PROPERTY_DEFINITION** ppPropDef
28
+ );
29
+static HRESULT GetUserAccountName(
30
+ LPCWSTR pwzKey,
31
+ LPWSTR* ppwzAccount
32
+ );
33
+
34
+
35
+// variables
36
+
37
+static ICOMAdminCatalog* gpiCatalog;
38
+static ICatalogCollection* gpiPartColl;
39
+static ICatalogCollection* gpiAppColl;
40
+
41
+static int giTables;
42
+
43
+
44
+// function definitions
45
+
46
+void CpiInitialize()
47
+{
48
+ // collections
49
+ gpiCatalog = NULL;
50
+ gpiPartColl = NULL;
51
+ gpiAppColl = NULL;
52
+
53
+ // tables
54
+ giTables = 0;
55
+
56
+ if (S_OK == WcaTableExists(L"ComPlusPartition")) giTables |= cptComPlusPartition;
57
+ if (S_OK == WcaTableExists(L"ComPlusPartitionProperty")) giTables |= cptComPlusPartitionProperty;
58
+ if (S_OK == WcaTableExists(L"ComPlusPartitionRole")) giTables |= cptComPlusPartitionRole;
59
+ if (S_OK == WcaTableExists(L"ComPlusUserInPartitionRole")) giTables |= cptComPlusUserInPartitionRole;
60
+ if (S_OK == WcaTableExists(L"ComPlusGroupInPartitionRole")) giTables |= cptComPlusGroupInPartitionRole;
61
+ if (S_OK == WcaTableExists(L"ComPlusPartitionUser")) giTables |= cptComPlusPartitionUser;
62
+ if (S_OK == WcaTableExists(L"ComPlusApplication")) giTables |= cptComPlusApplication;
63
+ if (S_OK == WcaTableExists(L"ComPlusApplicationProperty")) giTables |= cptComPlusApplicationProperty;
64
+ if (S_OK == WcaTableExists(L"ComPlusApplicationRole")) giTables |= cptComPlusApplicationRole;
65
+ if (S_OK == WcaTableExists(L"ComPlusApplicationRoleProperty")) giTables |= cptComPlusApplicationRoleProperty;
66
+ if (S_OK == WcaTableExists(L"ComPlusUserInApplicationRole")) giTables |= cptComPlusUserInApplicationRole;
67
+ if (S_OK == WcaTableExists(L"ComPlusGroupInApplicationRole")) giTables |= cptComPlusGroupInApplicationRole;
68
+ if (S_OK == WcaTableExists(L"ComPlusAssembly")) giTables |= cptComPlusAssembly;
69
+ if (S_OK == WcaTableExists(L"ComPlusAssemblyDependency")) giTables |= cptComPlusAssemblyDependency;
70
+ if (S_OK == WcaTableExists(L"ComPlusComponent")) giTables |= cptComPlusComponent;
71
+ if (S_OK == WcaTableExists(L"ComPlusComponentProperty")) giTables |= cptComPlusComponentProperty;
72
+ if (S_OK == WcaTableExists(L"ComPlusRoleForComponent")) giTables |= cptComPlusRoleForComponent;
73
+ if (S_OK == WcaTableExists(L"ComPlusInterface")) giTables |= cptComPlusInterface;
74
+ if (S_OK == WcaTableExists(L"ComPlusInterfaceProperty")) giTables |= cptComPlusInterfaceProperty;
75
+ if (S_OK == WcaTableExists(L"ComPlusRoleForInterface")) giTables |= cptComPlusRoleForInterface;
76
+ if (S_OK == WcaTableExists(L"ComPlusMethod")) giTables |= cptComPlusMethod;
77
+ if (S_OK == WcaTableExists(L"ComPlusMethodProperty")) giTables |= cptComPlusMethodProperty;
78
+ if (S_OK == WcaTableExists(L"ComPlusRoleForMethod")) giTables |= cptComPlusRoleForMethod;
79
+ if (S_OK == WcaTableExists(L"ComPlusSubscription")) giTables |= cptComPlusSubscription;
80
+ if (S_OK == WcaTableExists(L"ComPlusSubscriptionProperty")) giTables |= cptComPlusSubscriptionProperty;
81
+}
82
+
83
+void CpiFinalize()
84
+{
85
+ // collections
86
+ ReleaseObject(gpiCatalog);
87
+ ReleaseObject(gpiPartColl);
88
+ ReleaseObject(gpiAppColl);
89
+}
90
+
91
+BOOL CpiTableExists(
92
+ int iTable
93
+ )
94
+{
95
+ return (giTables & iTable) == iTable;
96
+}
97
+
98
+HRESULT CpiGetAdminCatalog(
99
+ ICOMAdminCatalog** ppiCatalog
100
+ )
101
+{
102
+ HRESULT hr = S_OK;
103
+
104
+ if (!gpiCatalog)
105
+ {
106
+ // get collection
107
+ hr = ::CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_ALL, IID_ICOMAdminCatalog, (void**)&gpiCatalog);
108
+ ExitOnFailure(hr, "Failed to create COM+ admin catalog object");
109
+ }
110
+
111
+ // return value
112
+ gpiCatalog->AddRef();
113
+ *ppiCatalog = gpiCatalog;
114
+
115
+ hr = S_OK;
116
+
117
+LExit:
118
+ return hr;
119
+}
120
+
121
+HRESULT CpiGetCatalogCollection(
122
+ LPCWSTR pwzName,
123
+ ICatalogCollection** ppiColl
124
+ )
125
+{
126
+ HRESULT hr = S_OK;
127
+
128
+ ICOMAdminCatalog* piCatalog = NULL;
129
+ IDispatch* piDisp = NULL;
130
+ BSTR bstrName = NULL;
131
+
132
+ // copy name string
133
+ bstrName = ::SysAllocString(pwzName);
134
+ ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name");
135
+
136
+ // get catalog
137
+ hr = CpiGetAdminCatalog(&piCatalog);
138
+ ExitOnFailure(hr, "Failed to get COM+ admin catalog");
139
+
140
+ // get collecton from catalog
141
+ hr = piCatalog->GetCollection(bstrName, &piDisp);
142
+ ExitOnFailure(hr, "Failed to get collection");
143
+
144
+ hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl);
145
+ ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface");
146
+
147
+ // populate collection
148
+ hr = (*ppiColl)->Populate();
149
+ ExitOnFailure(hr, "Failed to populate collection");
150
+
151
+ hr = S_OK;
152
+
153
+LExit:
154
+ // clean up
155
+ ReleaseObject(piCatalog);
156
+ ReleaseObject(piDisp);
157
+ ReleaseBSTR(bstrName);
158
+
159
+ return hr;
160
+}
161
+
162
+HRESULT CpiGetCatalogCollection(
163
+ ICatalogCollection* piColl,
164
+ ICatalogObject* piObj,
165
+ LPCWSTR pwzName,
166
+ ICatalogCollection** ppiColl
167
+ )
168
+{
169
+ HRESULT hr = S_OK;
170
+
171
+ ICOMAdminCatalog* piCatalog = NULL;
172
+ IDispatch* piDisp = NULL;
173
+ BSTR bstrName = NULL;
174
+
175
+ VARIANT vtKey;
176
+ ::VariantInit(&vtKey);
177
+
178
+ // copy name string
179
+ bstrName = ::SysAllocString(pwzName);
180
+ ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name");
181
+
182
+ // get catalog
183
+ hr = CpiGetAdminCatalog(&piCatalog);
184
+ ExitOnFailure(hr, "Failed to get COM+ admin catalog");
185
+
186
+ // get key
187
+ hr = piObj->get_Key(&vtKey);
188
+ ExitOnFailure(hr, "Failed to get object key");
189
+
190
+ // get collecton from catalog
191
+ hr = piColl->GetCollection(bstrName, vtKey, &piDisp);
192
+ ExitOnFailure(hr, "Failed to get collection");
193
+
194
+ hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl);
195
+ ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface");
196
+
197
+ // populate collection
198
+ hr = (*ppiColl)->Populate();
199
+ ExitOnFailure(hr, "Failed to populate collection");
200
+
201
+ hr = S_OK;
202
+
203
+LExit:
204
+ // clean up
205
+ ReleaseObject(piCatalog);
206
+ ReleaseObject(piDisp);
207
+ ReleaseBSTR(bstrName);
208
+ ::VariantClear(&vtKey);
209
+
210
+ return hr;
211
+}
212
+
213
+HRESULT CpiGetKeyForObject(
214
+ ICatalogObject* piObj,
215
+ LPWSTR pwzKey,
216
+ SIZE_T cchKey
217
+ )
218
+{
219
+ HRESULT hr = S_OK;
220
+
221
+ VARIANT vtKey;
222
+ ::VariantInit(&vtKey);
223
+
224
+ // get key
225
+ hr = piObj->get_Key(&vtKey);
226
+ ExitOnFailure(hr, "Failed to get key");
227
+
228
+ // change variant type
229
+ hr = ::VariantChangeType(&vtKey, &vtKey, 0, VT_BSTR);
230
+ ExitOnFailure(hr, "Failed to change variant type");
231
+
232
+ // copy key
233
+ hr = StringCchCopyW(pwzKey, cchKey, vtKey.bstrVal);
234
+ ExitOnFailure(hr, "Failed to copy key");
235
+
236
+ hr = S_OK;
237
+
238
+LExit:
239
+ // clean up
240
+ ::VariantClear(&vtKey);
241
+
242
+ return hr;
243
+}
244
+
245
+HRESULT CpiFindCollectionObject(
246
+ ICatalogCollection* piColl,
247
+ LPCWSTR pwzID,
248
+ LPCWSTR pwzName,
249
+ ICatalogObject** ppiObj
250
+ )
251
+{
252
+ HRESULT hr = S_OK;
253
+
254
+ IDispatch* piDisp = NULL;
255
+ ICatalogObject* piObj = NULL;
256
+
257
+ VARIANT vtVal;
258
+ ::VariantInit(&vtVal);
259
+
260
+ long lCnt;
261
+ hr = piColl->get_Count(&lCnt);
262
+ ExitOnFailure(hr, "Failed to get to number of items in collection");
263
+
264
+ for (long i = 0; i < lCnt; i++)
265
+ {
266
+ // get ICatalogObject interface
267
+ hr = piColl->get_Item(i, &piDisp);
268
+ ExitOnFailure(hr, "Failed to get object from collection");
269
+
270
+ hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj);
271
+ ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface");
272
+
273
+ // compare id
274
+ if (pwzID && *pwzID)
275
+ {
276
+ hr = piObj->get_Key(&vtVal);
277
+ ExitOnFailure(hr, "Failed to get key");
278
+
279
+ hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
280
+ ExitOnFailure(hr, "Failed to change variant type");
281
+
282
+ if (0 == lstrcmpiW(vtVal.bstrVal, pwzID))
283
+ {
284
+ if (ppiObj)
285
+ {
286
+ *ppiObj = piObj;
287
+ piObj = NULL;
288
+ }
289
+ ExitFunction1(hr = S_OK);
290
+ }
291
+
292
+ ::VariantClear(&vtVal);
293
+ }
294
+
295
+ // compare name
296
+ if (pwzName && *pwzName)
297
+ {
298
+ hr = piObj->get_Name(&vtVal);
299
+ ExitOnFailure(hr, "Failed to get name");
300
+
301
+ hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR);
302
+ ExitOnFailure(hr, "Failed to change variant type");
303
+
304
+ if (0 == lstrcmpW(vtVal.bstrVal, pwzName))
305
+ {
306
+ if (ppiObj)
307
+ {
308
+ *ppiObj = piObj;
309
+ piObj = NULL;
310
+ }
311
+ ExitFunction1(hr = S_OK);
312
+ }
313
+
314
+ ::VariantClear(&vtVal);
315
+ }
316
+
317
+ // release interface pointers
318
+ ReleaseNullObject(piDisp);
319
+ ReleaseNullObject(piObj);
320
+ }
321
+
322
+ hr = S_FALSE;
323
+
324
+LExit:
325
+ // clean up
326
+ ReleaseObject(piDisp);
327
+ ReleaseObject(piObj);
328
+
329
+ ::VariantClear(&vtVal);
330
+
331
+ return hr;
332
+}
333
+
334
+HRESULT CpiGetPartitionsCollection(
335
+ ICatalogCollection** ppiPartColl
336
+ )
337
+{
338
+ HRESULT hr = S_OK;
339
+
340
+ if (!gpiPartColl)
341
+ {
342
+ // get collection
343
+ hr = CpiGetCatalogCollection(L"Partitions", &gpiPartColl);
344
+ ExitOnFailure(hr, "Failed to get partitions collection");
345
+ }
346
+
347
+ // return value
348
+ gpiPartColl->AddRef();
349
+ *ppiPartColl = gpiPartColl;
350
+
351
+ hr = S_OK;
352
+
353
+LExit:
354
+ return hr;
355
+}
356
+
357
+HRESULT CpiGetApplicationsCollection(
358
+ ICatalogCollection** ppiAppColl
359
+ )
360
+{
361
+ HRESULT hr = S_OK;
362
+
363
+ ICOMAdminCatalog* piCatalog = NULL;
364
+ ICOMAdminCatalog2* piCatalog2 = NULL;
365
+ ICatalogCollection* piPartColl = NULL;
366
+ ICatalogObject* piPartObj = NULL;
367
+ BSTR bstrGlobPartID = NULL;
368
+
369
+ if (!gpiAppColl)
370
+ {
371
+ // get catalog
372
+ hr = CpiGetAdminCatalog(&piCatalog);
373
+ ExitOnFailure(hr, "Failed to get COM+ admin catalog");
374
+
375
+ // get ICOMAdminCatalog2 interface
376
+ hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2);
377
+
378
+ // COM+ 1.5 or later
379
+ if (E_NOINTERFACE != hr)
380
+ {
381
+ ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface");
382
+
383
+ // get global partition id
384
+ hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID);
385
+ ExitOnFailure(hr, "Failed to get global partition id");
386
+
387
+ // get partitions collection
388
+ hr = CpiGetPartitionsCollection(&piPartColl);
389
+ ExitOnFailure(hr, "Failed to get partitions collection");
390
+
391
+ // find object
392
+ hr = CpiFindCollectionObject(piPartColl, bstrGlobPartID, NULL, &piPartObj);
393
+ ExitOnFailure(hr, "Failed to find collection object");
394
+
395
+ if (S_FALSE == hr)
396
+ ExitFunction(); // partition not found, exit with hr = S_FALSE
397
+
398
+ // get applications collection
399
+ hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"Applications", &gpiAppColl);
400
+ ExitOnFailure(hr, "Failed to get applications collection");
401
+ }
402
+
403
+ // COM+ pre 1.5
404
+ else
405
+ {
406
+ // get applications collection
407
+ hr = CpiGetCatalogCollection(L"Applications", &gpiAppColl);
408
+ ExitOnFailure(hr, "Failed to get applications collection");
409
+ }
410
+ }
411
+
412
+ // return value
413
+ gpiAppColl->AddRef();
414
+ *ppiAppColl = gpiAppColl;
415
+
416
+ hr = S_OK;
417
+
418
+LExit:
419
+ // clean up
420
+ ReleaseObject(piCatalog);
421
+ ReleaseObject(piCatalog2);
422
+ ReleaseObject(piPartColl);
423
+ ReleaseObject(piPartObj);
424
+ ReleaseBSTR(bstrGlobPartID);
425
+
426
+ return hr;
427
+}
428
+
429
+HRESULT CpiAddActionTextToActionData(
430
+ LPCWSTR pwzAction,
431
+ LPWSTR* ppwzActionData
432
+ )
433
+{
434
+ HRESULT hr = S_OK;
435
+
436
+ PMSIHANDLE hView, hRecKey, hRec;
437
+
438
+ LPWSTR pwzDescription = NULL;
439
+ LPWSTR pwzTemplate = NULL;
440
+
441
+ if (S_OK == WcaTableExists(L"ActionText"))
442
+ {
443
+ // create parameter record
444
+ hRecKey = ::MsiCreateRecord(1);
445
+ ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record");
446
+ hr = WcaSetRecordString(hRecKey, 1, pwzAction);
447
+ ExitOnFailure(hr, "Failed to set record string");
448
+
449
+ // open view
450
+ hr = WcaOpenView(vcsActionTextQuery, &hView);
451
+ ExitOnFailure(hr, "Failed to open view on ActionText table");
452
+ hr = WcaExecuteView(hView, hRecKey);
453
+ ExitOnFailure(hr, "Failed to execute view on ActionText table");
454
+
455
+ // fetch record
456
+ hr = WcaFetchSingleRecord(hView, &hRec);
457
+ if (S_FALSE != hr)
458
+ {
459
+ ExitOnFailure(hr, "Failed to fetch action text record");
460
+
461
+ // get description
462
+ hr = WcaGetRecordString(hRec, atqDescription, &pwzDescription);
463
+ ExitOnFailure(hr, "Failed to get description");
464
+
465
+ // get template
466
+ hr = WcaGetRecordString(hRec, atqTemplate, &pwzTemplate);
467
+ ExitOnFailure(hr, "Failed to get template");
468
+ }
469
+ }
470
+
471
+ // add action name to action data
472
+ hr = WcaWriteStringToCaData(pwzAction, ppwzActionData);
473
+ ExitOnFailure(hr, "Failed to add action name to custom action data");
474
+
475
+ // add description to action data
476
+ hr = WcaWriteStringToCaData(pwzDescription ? pwzDescription : L"", ppwzActionData);
477
+ ExitOnFailure(hr, "Failed to add description to custom action data");
478
+
479
+ // add template to action data
480
+ hr = WcaWriteStringToCaData(pwzTemplate ? pwzTemplate : L"", ppwzActionData);
481
+ ExitOnFailure(hr, "Failed to add template to custom action data");
482
+
483
+ hr = S_OK;
484
+
485
+LExit:
486
+ // clean up
487
+ ReleaseStr(pwzDescription);
488
+ ReleaseStr(pwzTemplate);
489
+
490
+ return hr;
491
+}
492
+
493
+HRESULT CpiVerifyComponentArchitecure(
494
+ LPCWSTR pwzComponent,
495
+ BOOL* pfMatchingArchitecture
496
+ )
497
+{
498
+ HRESULT hr = S_OK;
499
+
500
+ PMSIHANDLE hView, hRecKey, hRec;
501
+
502
+ int iAttributes = 0;
503
+
504
+ if (S_OK == WcaTableExists(L"Component"))
505
+ {
506
+ // create parameter record
507
+ hRecKey = ::MsiCreateRecord(1);
508
+ ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record");
509
+ hr = WcaSetRecordString(hRecKey, 1, pwzComponent);
510
+ ExitOnFailure(hr, "Failed to set record string");
511
+
512
+ // open view
513
+ hr = WcaOpenView(vcsComponentAttributesQuery, &hView);
514
+ ExitOnFailure(hr, "Failed to open view on ActionText table");
515
+ hr = WcaExecuteView(hView, hRecKey);
516
+ ExitOnFailure(hr, "Failed to execute view on ActionText table");
517
+
518
+ // fetch record
519
+ hr = WcaFetchSingleRecord(hView, &hRec);
520
+ if (S_FALSE != hr)
521
+ {
522
+ ExitOnFailure(hr, "Failed to fetch component record");
523
+
524
+ hr = WcaGetRecordInteger(hRec, caqAttributes, &iAttributes);
525
+ ExitOnFailure(hr, "Failed to get component attributes");
526
+ }
527
+ }
528
+
529
+ // return values
530
+#ifdef _WIN64
531
+ *pfMatchingArchitecture = 256 == (iAttributes & 256);
532
+#else
533
+ *pfMatchingArchitecture = 256 != (iAttributes & 256);
534
+#endif
535
+
536
+ hr = S_OK;
537
+
538
+LExit:
539
+ return hr;
540
+}
541
+
542
+HRESULT CpiPropertiesRead(
543
+ LPCWSTR pwzQuery,
544
+ LPCWSTR pwzKey,
545
+ CPI_PROPERTY_DEFINITION* pPropDefList,
546
+ CPI_PROPERTY** ppPropList,
547
+ int* piCount
548
+ )
549
+{
550
+ HRESULT hr = S_OK;
551
+
552
+ PMSIHANDLE hView, hRecKey, hRec;
553
+
554
+ CPI_PROPERTY* pItm = NULL;
555
+ LPWSTR pwzData = NULL;
556
+
557
+ int iVersionNT = 0;
558
+
559
+ CPI_PROPERTY_DEFINITION* pPropDef;
560
+
561
+ *piCount = 0;
562
+
563
+ // get NT version
564
+ hr = WcaGetIntProperty(L"VersionNT", &iVersionNT);
565
+ ExitOnFailure(hr, "Failed to set record string");
566
+
567
+ // create parameter record
568
+ hRecKey = ::MsiCreateRecord(1);
569
+ ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record");
570
+ hr = WcaSetRecordString(hRecKey, 1, pwzKey);
571
+ ExitOnFailure(hr, "Failed to set record string");
572
+
573
+ // open view
574
+ hr = WcaOpenView(pwzQuery, &hView);
575
+ ExitOnFailure(hr, "Failed to open view on property table");
576
+ hr = WcaExecuteView(hView, hRecKey);
577
+ ExitOnFailure(hr, "Failed to execute view on property table");
578
+
579
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
580
+ {
581
+ // create entry
582
+ pItm = (CPI_PROPERTY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PROPERTY));
583
+ if (!pItm)
584
+ ExitFunction1(hr = E_OUTOFMEMORY);
585
+
586
+ // get name
587
+ hr = WcaGetRecordString(hRec, pqName, &pwzData);
588
+ ExitOnFailure(hr, "Failed to get name");
589
+ StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
590
+
591
+ // get value
592
+ hr = WcaGetRecordFormattedString(hRec, pqValue, &pItm->pwzValue);
593
+ ExitOnFailure(hr, "Failed to get value");
594
+
595
+ // find property definition
596
+ hr = FindPropertyDefinition(pPropDefList, pItm->wzName, &pPropDef);
597
+ ExitOnFailure(hr, "Failed to find property definition");
598
+
599
+ if (S_FALSE == hr)
600
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Unknown property, key: %S, property: %S", pwzKey, pItm->wzName);
601
+
602
+ // check version, ignore if catalog version is too low
603
+ if (iVersionNT < pPropDef->iMinVersionNT)
604
+ {
605
+ WcaLog(LOGMSG_VERBOSE, "Skipping property since NT version is too low, key: %S, property: %S", pwzKey, pItm->wzName);
606
+ CpiPropertiesFreeList(pItm);
607
+ pItm = NULL;
608
+ continue;
609
+ }
610
+
611
+ // if the property is a user, replace the User table key with a user account name
612
+ if (cpptUser == pPropDef->iType)
613
+ {
614
+ hr = GetUserAccountName(pItm->pwzValue, &pItm->pwzValue);
615
+ ExitOnFailure(hr, "Failed to get user account name");
616
+ }
617
+
618
+ // add entry
619
+ ++*piCount;
620
+ if (*ppPropList)
621
+ pItm->pNext = *ppPropList;
622
+ *ppPropList = pItm;
623
+ pItm = NULL;
624
+ }
625
+
626
+ if (E_NOMOREITEMS == hr)
627
+ hr = S_OK;
628
+
629
+LExit:
630
+ // clean up
631
+ if (pItm)
632
+ CpiPropertiesFreeList(pItm);
633
+
634
+ ReleaseStr(pwzData);
635
+
636
+ return hr;
637
+}
638
+
639
+void CpiPropertiesFreeList(
640
+ CPI_PROPERTY* pList
641
+ )
642
+{
643
+ while (pList)
644
+ {
645
+ ReleaseStr(pList->pwzValue);
646
+
647
+ CPI_PROPERTY* pDelete = pList;
648
+ pList = pList->pNext;
649
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
650
+ }
651
+}
652
+
653
+HRESULT CpiAddPropertiesToActionData(
654
+ int iPropCount,
655
+ CPI_PROPERTY* pPropList,
656
+ LPWSTR* ppwzActionData
657
+ )
658
+{
659
+ HRESULT hr = S_OK;
660
+
661
+ hr = WcaWriteIntegerToCaData(iPropCount, ppwzActionData);
662
+ ExitOnFailure(hr, "Failed to add count to custom action data");
663
+
664
+ if (iPropCount) // count might be 0 event thought there are elements in the list
665
+ {
666
+ for (CPI_PROPERTY* pProp = pPropList; pProp; pProp = pProp->pNext)
667
+ {
668
+ hr = WcaWriteStringToCaData(pProp->wzName, ppwzActionData);
669
+ ExitOnFailure(hr, "Failed to add property name to custom action data, name: %S", pProp->wzName);
670
+
671
+ hr = WcaWriteStringToCaData(pProp->pwzValue, ppwzActionData);
672
+ ExitOnFailure(hr, "Failed to add property value to custom action data, name: %S", pProp->wzName);
673
+ }
674
+ }
675
+
676
+ hr = S_OK;
677
+
678
+LExit:
679
+ return hr;
680
+}
681
+
682
+HRESULT CpiBuildAccountName(
683
+ LPCWSTR pwzDomain,
684
+ LPCWSTR pwzName,
685
+ LPWSTR* ppwzAccount
686
+ )
687
+{
688
+ HRESULT hr = S_OK;
689
+
690
+ WCHAR wzComputerName[MAX_COMPUTERNAME_LENGTH + 1];
691
+ ::ZeroMemory(wzComputerName, sizeof(wzComputerName));
692
+
693
+ // if domain is '.', get computer name
694
+ if (0 == lstrcmpW(pwzDomain, L"."))
695
+ {
696
+ DWORD dwSize = countof(wzComputerName);
697
+ if (!::GetComputerNameW(wzComputerName, &dwSize))
698
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to get computer name");
699
+ }
700
+
701
+ // build account name
702
+ hr = StrAllocFormatted(ppwzAccount, L"%s\\%s", *wzComputerName ? wzComputerName : pwzDomain, pwzName);
703
+ ExitOnFailure(hr, "Failed to build domain user name");
704
+
705
+ hr = S_OK;
706
+
707
+LExit:
708
+ return hr;
709
+}
710
+
711
+HRESULT CpiGetTempFileName(
712
+ LPWSTR* ppwzTempFile
713
+ )
714
+{
715
+ HRESULT hr = S_OK;
716
+
717
+ // get temp path
718
+ WCHAR wzTempPath[MAX_PATH];
719
+ DWORD dw = ::GetTempPathW(countof(wzTempPath), wzTempPath);
720
+ if (countof(wzTempPath) <= dw)
721
+ ExitOnFailure(hr = E_FAIL, "TEMP directory path too long");
722
+
723
+ // get unique number
724
+ LARGE_INTEGER liCount;
725
+ if (!::QueryPerformanceCounter(&liCount))
726
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to query performance counter");
727
+
728
+ // create temp file name
729
+ hr = StrAllocFormatted(ppwzTempFile, L"%sCPI%I64X.tmp", wzTempPath, liCount.QuadPart);
730
+ ExitOnFailure(hr, "Failed to create temp file name string");
731
+
732
+ hr = S_OK;
733
+
734
+LExit:
735
+ return hr;
736
+}
737
+
738
+HRESULT CpiCreateId(
739
+ LPWSTR pwzDest,
740
+ SIZE_T cchDest
741
+ )
742
+{
743
+ HRESULT hr = S_OK;
744
+
745
+ GUID guid;
746
+
747
+ // create new guid
748
+ hr = ::CoCreateGuid(&guid);
749
+ ExitOnFailure(hr, "Failed to create new guid");
750
+
751
+ // convert guid to string
752
+ if (0 == ::StringFromGUID2(guid, pwzDest, (int)cchDest))
753
+ ExitOnFailure(hr = E_FAIL, "Failed to convert guid to string");
754
+
755
+ hr = S_OK;
756
+
757
+LExit:
758
+ return hr;
759
+}
760
+
761
+BOOL CpiIsInstalled(
762
+ INSTALLSTATE isInstalled
763
+ )
764
+{
765
+ return INSTALLSTATE_LOCAL == isInstalled || INSTALLSTATE_SOURCE == isInstalled;
766
+}
767
+
768
+BOOL CpiWillBeInstalled(
769
+ INSTALLSTATE isInstalled,
770
+ INSTALLSTATE isAction
771
+ )
772
+{
773
+ return WcaIsInstalling(isInstalled, isAction) ||
774
+ (CpiIsInstalled(isInstalled) && !WcaIsUninstalling(isInstalled, isAction));
775
+}
776
+
777
+HRESULT PcaGuidToRegFormat(
778
+ LPWSTR pwzGuid,
779
+ LPWSTR pwzDest,
780
+ SIZE_T cchDest
781
+ )
782
+{
783
+ HRESULT hr = S_OK;
784
+
785
+ GUID guid = GUID_NULL;
786
+ int cch = 0;
787
+
788
+ WCHAR wz[39];
789
+ ::ZeroMemory(wz, sizeof(wz));
790
+
791
+ cch = lstrlenW(pwzGuid);
792
+
793
+ if (38 == cch && L'{' == pwzGuid[0] && L'}' == pwzGuid[37])
794
+ StringCchCopyW(wz, countof(wz), pwzGuid);
795
+ else if (36 == cch)
796
+ StringCchPrintfW(wz, countof(wz), L"{%s}", pwzGuid);
797
+ else
798
+ ExitFunction1(hr = E_INVALIDARG);
799
+
800
+ // convert string to guid
801
+ hr = ::CLSIDFromString(wz, &guid);
802
+ ExitOnFailure(hr, "Failed to parse guid string");
803
+
804
+ // convert guid to string
805
+ if (0 == ::StringFromGUID2(guid, pwzDest, (int)cchDest))
806
+ ExitOnFailure(hr = E_FAIL, "Failed to convert guid to string");
807
+
808
+ hr = S_OK;
809
+
810
+LExit:
811
+ return hr;
812
+}
813
+
814
+
815
+// helper function definitions
816
+
817
+static HRESULT FindPropertyDefinition(
818
+ CPI_PROPERTY_DEFINITION* pPropDefList,
819
+ LPCWSTR pwzName,
820
+ CPI_PROPERTY_DEFINITION** ppPropDef
821
+ )
822
+{
823
+ for (CPI_PROPERTY_DEFINITION* pItm = pPropDefList; pItm->pwzName; pItm++)
824
+ {
825
+ if (0 == lstrcmpW(pItm->pwzName, pwzName))
826
+ {
827
+ *ppPropDef = pItm;
828
+ return S_OK;
829
+ }
830
+ }
831
+
832
+ return S_FALSE;
833
+}
834
+
835
+static HRESULT GetUserAccountName(
836
+ LPCWSTR pwzKey,
837
+ LPWSTR* ppwzAccount
838
+ )
839
+{
840
+ HRESULT hr = S_OK;
841
+
842
+ PMSIHANDLE hView, hRecKey, hRec;
843
+
844
+ LPWSTR pwzDomain = NULL;
845
+ LPWSTR pwzName = NULL;
846
+
847
+ // create parameter record
848
+ hRecKey = ::MsiCreateRecord(1);
849
+ ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record");
850
+ hr = WcaSetRecordString(hRecKey, 1, pwzKey);
851
+ ExitOnFailure(hr, "Failed to set record string");
852
+
853
+ // open view
854
+ hr = WcaOpenView(vcsUserQuery, &hView);
855
+ ExitOnFailure(hr, "Failed to open view on User table");
856
+ hr = WcaExecuteView(hView, hRecKey);
857
+ ExitOnFailure(hr, "Failed to execute view on User table");
858
+
859
+ // fetch record
860
+ hr = WcaFetchSingleRecord(hView, &hRec);
861
+ if (S_FALSE == hr)
862
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "User not found, key: %S", pwzKey);
863
+ ExitOnFailure(hr, "Failed to fetch user record");
864
+
865
+ // get user domain
866
+ hr = WcaGetRecordFormattedString(hRec, uqDomain, &pwzDomain);
867
+ ExitOnFailure(hr, "Failed to get domain");
868
+
869
+ // get user name
870
+ hr = WcaGetRecordFormattedString(hRec, uqName, &pwzName);
871
+ ExitOnFailure(hr, "Failed to get name");
872
+
873
+ // build account name
874
+ hr = CpiBuildAccountName(pwzDomain, pwzName, ppwzAccount);
875
+ ExitOnFailure(hr, "Failed to build account name");
876
+
877
+ hr = S_OK;
878
+
879
+LExit:
880
+ // clean up
881
+ ReleaseStr(pwzDomain);
882
+ ReleaseStr(pwzName);
883
+
884
+ return hr;
885
+}
src/ca/cputilsched.h
new
+144
@@ -0,0 +1,144 @@
1
+#pragma once
2
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
+
4
+
5
+#define CPI_MAX_GUID 38
6
+
7
+enum eRunMode { rmDeferred = 1, rmCommit, rmRollback };
8
+
9
+enum eActionType { atNoOp = 0, atCreate, atRemove };
10
+
11
+enum eComPlusPropertyType { cpptNone = 0, cpptBoolean, cpptInteger, cpptString, cpptUser };
12
+
13
+enum eComPlusTables
14
+{
15
+ cptComPlusPartition = (1 << 0),
16
+ cptComPlusPartitionProperty = (1 << 1),
17
+ cptComPlusPartitionRole = (1 << 2),
18
+ cptComPlusUserInPartitionRole = (1 << 3),
19
+ cptComPlusGroupInPartitionRole = (1 << 4),
20
+ cptComPlusPartitionUser = (1 << 5),
21
+ cptComPlusApplication = (1 << 6),
22
+ cptComPlusApplicationProperty = (1 << 7),
23
+ cptComPlusApplicationRole = (1 << 8),
24
+ cptComPlusApplicationRoleProperty = (1 << 9),
25
+ cptComPlusUserInApplicationRole = (1 << 10),
26
+ cptComPlusGroupInApplicationRole = (1 << 11),
27
+ cptComPlusAssembly = (1 << 12),
28
+ cptComPlusAssemblyDependency = (1 << 13),
29
+ cptComPlusComponent = (1 << 14),
30
+ cptComPlusComponentProperty = (1 << 15),
31
+ cptComPlusRoleForComponent = (1 << 16),
32
+ cptComPlusInterface = (1 << 17),
33
+ cptComPlusInterfaceProperty = (1 << 18),
34
+ cptComPlusRoleForInterface = (1 << 19),
35
+ cptComPlusMethod = (1 << 20),
36
+ cptComPlusMethodProperty = (1 << 21),
37
+ cptComPlusRoleForMethod = (1 << 22),
38
+ cptComPlusSubscription = (1 << 23),
39
+ cptComPlusSubscriptionProperty = (1 << 24)
40
+};
41
+
42
+
43
+// structs
44
+
45
+struct CPI_PROPERTY
46
+{
47
+ WCHAR wzName[MAX_DARWIN_KEY + 1];
48
+ LPWSTR pwzValue;
49
+
50
+ CPI_PROPERTY* pNext;
51
+};
52
+
53
+struct CPI_PROPERTY_DEFINITION
54
+{
55
+ LPCWSTR pwzName;
56
+ int iType;
57
+ int iMinVersionNT;
58
+};
59
+
60
+
61
+// function prototypes
62
+
63
+void CpiInitialize();
64
+void CpiFinalize();
65
+BOOL CpiTableExists(
66
+ int iTable
67
+ );
68
+HRESULT CpiGetAdminCatalog(
69
+ ICOMAdminCatalog** ppiCatalog
70
+ );
71
+HRESULT CpiGetCatalogCollection(
72
+ LPCWSTR pwzName,
73
+ ICatalogCollection** ppiColl
74
+ );
75
+HRESULT CpiGetCatalogCollection(
76
+ ICatalogCollection* piColl,
77
+ ICatalogObject* piObj,
78
+ LPCWSTR pwzName,
79
+ ICatalogCollection** ppiColl
80
+ );
81
+HRESULT CpiGetKeyForObject(
82
+ ICatalogObject* piObj,
83
+ LPWSTR pwzKey,
84
+ SIZE_T cchKey
85
+ );
86
+HRESULT CpiFindCollectionObject(
87
+ ICatalogCollection* piColl,
88
+ LPCWSTR pwzID,
89
+ LPCWSTR pwzName,
90
+ ICatalogObject** ppiObj
91
+ );
92
+HRESULT CpiGetPartitionsCollection(
93
+ ICatalogCollection** ppiPartColl
94
+ );
95
+HRESULT CpiGetApplicationsCollection(
96
+ ICatalogCollection** ppiAppColl
97
+ );
98
+HRESULT CpiAddActionTextToActionData(
99
+ LPCWSTR pwzAction,
100
+ LPWSTR* ppwzActionData
101
+ );
102
+HRESULT CpiVerifyComponentArchitecure(
103
+ LPCWSTR pwzComponent,
104
+ BOOL* pfMatchingArchitecture
105
+ );
106
+HRESULT CpiPropertiesRead(
107
+ LPCWSTR pwzQuery,
108
+ LPCWSTR pwzKey,
109
+ CPI_PROPERTY_DEFINITION* pPropDefList,
110
+ CPI_PROPERTY** ppPropList,
111
+ int* piCount
112
+ );
113
+void CpiPropertiesFreeList(
114
+ CPI_PROPERTY* pList
115
+ );
116
+HRESULT CpiAddPropertiesToActionData(
117
+ int iPropCount,
118
+ CPI_PROPERTY* pPropList,
119
+ LPWSTR* ppwzActionData
120
+ );
121
+HRESULT CpiBuildAccountName(
122
+ LPCWSTR pwzDomain,
123
+ LPCWSTR pwzName,
124
+ LPWSTR* ppwzAccount
125
+ );
126
+HRESULT CpiGetTempFileName(
127
+ LPWSTR* ppwzTempFile
128
+ );
129
+HRESULT CpiCreateId(
130
+ LPWSTR pwzDest,
131
+ SIZE_T cchDest
132
+ );
133
+BOOL CpiIsInstalled(
134
+ INSTALLSTATE isInstalled
135
+ );
136
+BOOL CpiWillBeInstalled(
137
+ INSTALLSTATE isInstalled,
138
+ INSTALLSTATE isAction
139
+ );
140
+HRESULT PcaGuidToRegFormat(
141
+ LPWSTR pwzGuid,
142
+ LPWSTR pwzDest,
143
+ SIZE_T cchDest
144
+ );
src/wixext/ComPlusCompiler.cs
new
+2188
@@ -0,0 +1,2188 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Extensions
4
+{
5
+ using System;
6
+ using System.Collections;
7
+ using System.Collections.Generic;
8
+ using System.Globalization;
9
+ using System.Reflection;
10
+ using System.Xml;
11
+ using System.Xml.Linq;
12
+ using System.Xml.Schema;
13
+ using WixToolset.Data;
14
+ using WixToolset.Extensibility;
15
+
16
+ /// <summary>
17
+ /// The compiler for the WiX Toolset Internet Information Services Extension.
18
+ /// </summary>
19
+ public sealed class ComPlusCompiler : CompilerExtension
20
+ {
21
+ /// <summary>
22
+ /// Instantiate a new ComPlusCompiler.
23
+ /// </summary>
24
+ public ComPlusCompiler()
25
+ {
26
+ this.Namespace = "http://wixtoolset.org/schemas/v4/wxs/complus";
27
+ }
28
+
29
+ /// <summary>
30
+ /// </summary>
31
+ /// <remarks></remarks>
32
+ public enum CpiAssemblyAttributes
33
+ {
34
+ EventClass = (1 << 0),
35
+ DotNetAssembly = (1 << 1),
36
+ DllPathFromGAC = (1 << 2),
37
+ RegisterInCommit = (1 << 3)
38
+ }
39
+
40
+ /// <summary>
41
+ /// Processes an element for the Compiler.
42
+ /// </summary>
43
+ /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
44
+ /// <param name="parentElement">Parent element of element to process.</param>
45
+ /// <param name="element">Element to process.</param>
46
+ /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
47
+ public override void ParseElement(XElement parentElement, XElement element, IDictionary<string, string> context)
48
+ {
49
+ switch (parentElement.Name.LocalName)
50
+ {
51
+ case "Component":
52
+ string componentId = context["ComponentId"];
53
+ string directoryId = context["DirectoryId"];
54
+ bool win64 = Boolean.Parse(context["Win64"]);
55
+
56
+ switch (element.Name.LocalName)
57
+ {
58
+ case "ComPlusPartition":
59
+ this.ParseComPlusPartitionElement(element, componentId, win64);
60
+ break;
61
+ case "ComPlusPartitionRole":
62
+ this.ParseComPlusPartitionRoleElement(element, componentId, null);
63
+ break;
64
+ case "ComPlusUserInPartitionRole":
65
+ this.ParseComPlusUserInPartitionRoleElement(element, componentId, null);
66
+ break;
67
+ case "ComPlusGroupInPartitionRole":
68
+ this.ParseComPlusGroupInPartitionRoleElement(element, componentId, null);
69
+ break;
70
+ case "ComPlusPartitionUser":
71
+ this.ParseComPlusPartitionUserElement(element, componentId, null);
72
+ break;
73
+ case "ComPlusApplication":
74
+ this.ParseComPlusApplicationElement(element, componentId, win64, null);
75
+ break;
76
+ case "ComPlusApplicationRole":
77
+ this.ParseComPlusApplicationRoleElement(element, componentId, null);
78
+ break;
79
+ case "ComPlusUserInApplicationRole":
80
+ this.ParseComPlusUserInApplicationRoleElement(element, componentId, null);
81
+ break;
82
+ case "ComPlusGroupInApplicationRole":
83
+ this.ParseComPlusGroupInApplicationRoleElement(element, componentId, null);
84
+ break;
85
+ case "ComPlusAssembly":
86
+ this.ParseComPlusAssemblyElement(element, componentId, win64, null);
87
+ break;
88
+ case "ComPlusRoleForComponent":
89
+ this.ParseComPlusRoleForComponentElement(element, componentId, null);
90
+ break;
91
+ case "ComPlusRoleForInterface":
92
+ this.ParseComPlusRoleForInterfaceElement(element, componentId, null);
93
+ break;
94
+ case "ComPlusRoleForMethod":
95
+ this.ParseComPlusRoleForMethodElement(element, componentId, null);
96
+ break;
97
+ case "ComPlusSubscription":
98
+ this.ParseComPlusSubscriptionElement(element, componentId, null);
99
+ break;
100
+ default:
101
+ this.Core.UnexpectedElement(parentElement, element);
102
+ break;
103
+ }
104
+ break;
105
+ case "Fragment":
106
+ case "Module":
107
+ case "Product":
108
+ switch (element.Name.LocalName)
109
+ {
110
+ case "ComPlusPartition":
111
+ this.ParseComPlusPartitionElement(element, null, false);
112
+ break;
113
+ case "ComPlusPartitionRole":
114
+ this.ParseComPlusPartitionRoleElement(element, null, null);
115
+ break;
116
+ case "ComPlusApplication":
117
+ this.ParseComPlusApplicationElement(element, null, false, null);
118
+ break;
119
+ case "ComPlusApplicationRole":
120
+ this.ParseComPlusApplicationRoleElement(element, null, null);
121
+ break;
122
+ default:
123
+ this.Core.UnexpectedElement(parentElement, element);
124
+ break;
125
+ }
126
+ break;
127
+ default:
128
+ this.Core.UnexpectedElement(parentElement, element);
129
+ break;
130
+ }
131
+ }
132
+
133
+ /// <summary>
134
+ /// Parses a COM+ partition element.
135
+ /// </summary>
136
+ /// <param name="node">Element to parse.</param>
137
+ /// <param name="componentKey">Identifier of parent component.</param>
138
+ private void ParseComPlusPartitionElement(XElement node, string componentKey, bool win64)
139
+ {
140
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
141
+
142
+ string key = null;
143
+ string id = null;
144
+ string name = null;
145
+
146
+ Hashtable properties = new Hashtable();
147
+
148
+ foreach (XAttribute attrib in node.Attributes())
149
+ {
150
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
151
+ {
152
+ switch (attrib.Name.LocalName)
153
+ {
154
+ case "Id":
155
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
156
+ break;
157
+ case "PartitionId":
158
+ id = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib));
159
+ break;
160
+ case "Name":
161
+ name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
162
+ break;
163
+ case "Changeable":
164
+ this.Core.OnMessage(WixWarnings.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
165
+ break;
166
+ case "Deleteable":
167
+ if (null == componentKey)
168
+ {
169
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
170
+ }
171
+ properties["Deleteable"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
172
+ break;
173
+ case "Description":
174
+ if (null == componentKey)
175
+ {
176
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
177
+ }
178
+ properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
179
+ break;
180
+ default:
181
+ this.Core.UnexpectedAttribute(node, attrib);
182
+ break;
183
+ }
184
+ }
185
+ else
186
+ {
187
+ this.Core.ParseExtensionAttribute(node, attrib);
188
+ }
189
+ }
190
+
191
+ if (null != componentKey && null == name)
192
+ {
193
+ this.Core.OnMessage(ComPlusErrors.RequiredAttributeUnderComponent(sourceLineNumbers, node.Name.LocalName, "Name"));
194
+ }
195
+ if (null == componentKey && null == id && null == name)
196
+ {
197
+ this.Core.OnMessage(ComPlusErrors.RequiredAttributeNotUnderComponent(sourceLineNumbers, node.Name.LocalName, "Id", "Name"));
198
+ }
199
+
200
+ foreach (XElement child in node.Elements())
201
+ {
202
+ if (this.Namespace == child.Name.Namespace)
203
+ {
204
+ switch (child.Name.LocalName)
205
+ {
206
+ case "ComPlusPartitionRole":
207
+ this.ParseComPlusPartitionRoleElement(child, componentKey, key);
208
+ break;
209
+ case "ComPlusPartitionUser":
210
+ this.ParseComPlusPartitionUserElement(child, componentKey, key);
211
+ break;
212
+ case "ComPlusApplication":
213
+ this.ParseComPlusApplicationElement(child, componentKey, win64, key);
214
+ break;
215
+ default:
216
+ this.Core.UnexpectedElement(node, child);
217
+ break;
218
+ }
219
+ }
220
+ else
221
+ {
222
+ this.Core.ParseExtensionElement(node, child);
223
+ }
224
+ }
225
+
226
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartition");
227
+ row[0] = key;
228
+ row[1] = componentKey;
229
+ row[2] = id;
230
+ row[3] = name;
231
+
232
+ IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator();
233
+ while (propertiesEnumerator.MoveNext())
234
+ {
235
+ Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartitionProperty");
236
+ propertyRow[0] = key;
237
+ propertyRow[1] = (string)propertiesEnumerator.Key;
238
+ propertyRow[2] = (string)propertiesEnumerator.Value;
239
+ }
240
+
241
+ if (componentKey != null)
242
+ {
243
+ if (win64)
244
+ {
245
+ if (this.Core.CurrentPlatform == Platform.IA64)
246
+ {
247
+ this.Core.OnMessage(WixErrors.UnsupportedPlatformForElement(sourceLineNumbers, "ia64", node.Name.LocalName));
248
+ }
249
+ else
250
+ {
251
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall_x64");
252
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall_x64");
253
+ }
254
+ }
255
+ else
256
+ {
257
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall");
258
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall");
259
+ }
260
+ }
261
+ }
262
+
263
+ /// <summary>
264
+ /// Parses a COM+ partition role element.
265
+ /// </summary>
266
+ /// <param name="node">Element to parse.</param>
267
+ /// <param name="componentKey">Identifier of parent component.</param>
268
+ /// <param name="applicationKey">Optional identifier of parent application.</param>
269
+ private void ParseComPlusPartitionRoleElement(XElement node, string componentKey, string partitionKey)
270
+ {
271
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
272
+
273
+ string key = null;
274
+ string name = null;
275
+
276
+ foreach (XAttribute attrib in node.Attributes())
277
+ {
278
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
279
+ {
280
+ switch (attrib.Name.LocalName)
281
+ {
282
+ case "Id":
283
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
284
+ break;
285
+ case "Partition":
286
+ if (null != partitionKey)
287
+ {
288
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
289
+ }
290
+ partitionKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
291
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartition", partitionKey);
292
+ break;
293
+ case "Name":
294
+ name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
295
+ break;
296
+ default:
297
+ this.Core.UnexpectedAttribute(node, attrib);
298
+ break;
299
+ }
300
+ }
301
+ else
302
+ {
303
+ this.Core.ParseExtensionAttribute(node, attrib);
304
+ }
305
+ }
306
+
307
+ if (null == partitionKey)
308
+ {
309
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Partition"));
310
+ }
311
+
312
+ foreach (XElement child in node.Elements())
313
+ {
314
+ if (this.Namespace == child.Name.Namespace)
315
+ {
316
+ switch (child.Name.LocalName)
317
+ {
318
+ case "ComPlusUserInPartitionRole":
319
+ this.ParseComPlusUserInPartitionRoleElement(child, componentKey, key);
320
+ break;
321
+ case "ComPlusGroupInPartitionRole":
322
+ this.ParseComPlusGroupInPartitionRoleElement(child, componentKey, key);
323
+ break;
324
+ default:
325
+ this.Core.UnexpectedElement(node, child);
326
+ break;
327
+ }
328
+ }
329
+ else
330
+ {
331
+ this.Core.ParseExtensionElement(node, child);
332
+ }
333
+ }
334
+
335
+ // add table row
336
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartitionRole");
337
+ row[0] = key;
338
+ row[1] = partitionKey;
339
+ row[3] = name;
340
+ }
341
+
342
+ /// <summary>
343
+ /// Parses a COM+ partition role user element.
344
+ /// </summary>
345
+ /// <param name="node">Element to parse.</param>
346
+ /// <param name="componentKey">Identifier of parent component.</param>
347
+ /// <param name="applicationKey">Optional identifier of parent application role.</param>
348
+ private void ParseComPlusUserInPartitionRoleElement(XElement node, string componentKey, string partitionRoleKey)
349
+ {
350
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
351
+
352
+ string key = null;
353
+ string user = null;
354
+
355
+ foreach (XAttribute attrib in node.Attributes())
356
+ {
357
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
358
+ {
359
+ switch (attrib.Name.LocalName)
360
+ {
361
+ case "Id":
362
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
363
+ break;
364
+ case "PartitionRole":
365
+ if (null != partitionRoleKey)
366
+ {
367
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
368
+ }
369
+ partitionRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
370
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartitionRole", partitionRoleKey);
371
+ break;
372
+ case "User":
373
+ user = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
374
+ this.Core.CreateSimpleReference(sourceLineNumbers, "User", user);
375
+ break;
376
+ default:
377
+ this.Core.UnexpectedAttribute(node, attrib);
378
+ break;
379
+ }
380
+ }
381
+ else
382
+ {
383
+ this.Core.ParseExtensionAttribute(node, attrib);
384
+ }
385
+ }
386
+
387
+ if (null == partitionRoleKey)
388
+ {
389
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "PartitionRole"));
390
+ }
391
+
392
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusUserInPartitionRole");
393
+ row[0] = key;
394
+ row[1] = partitionRoleKey;
395
+ row[2] = componentKey;
396
+ row[3] = user;
397
+ }
398
+
399
+ /// <summary>
400
+ /// Parses a COM+ partition role user element.
401
+ /// </summary>
402
+ /// <param name="node">Element to parse.</param>
403
+ /// <param name="componentKey">Identifier of parent component.</param>
404
+ /// <param name="applicationKey">Optional identifier of parent application role.</param>
405
+ private void ParseComPlusGroupInPartitionRoleElement(XElement node, string componentKey, string partitionRoleKey)
406
+ {
407
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
408
+
409
+ string key = null;
410
+ string group = null;
411
+
412
+ foreach (XAttribute attrib in node.Attributes())
413
+ {
414
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
415
+ {
416
+ switch (attrib.Name.LocalName)
417
+ {
418
+ case "Id":
419
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
420
+ break;
421
+ case "PartitionRole":
422
+ if (null != partitionRoleKey)
423
+ {
424
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
425
+ }
426
+ partitionRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
427
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartitionRole", partitionRoleKey);
428
+ break;
429
+ case "Group":
430
+ group = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
431
+ this.Core.CreateSimpleReference(sourceLineNumbers, "Group", group);
432
+ break;
433
+ default:
434
+ this.Core.UnexpectedAttribute(node, attrib);
435
+ break;
436
+ }
437
+ }
438
+ else
439
+ {
440
+ this.Core.ParseExtensionAttribute(node, attrib);
441
+ }
442
+ }
443
+
444
+ if (null == partitionRoleKey)
445
+ {
446
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "PartitionRole"));
447
+ }
448
+
449
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusGroupInPartitionRole");
450
+ row[0] = key;
451
+ row[1] = partitionRoleKey;
452
+ row[2] = componentKey;
453
+ row[3] = group;
454
+ }
455
+
456
+ /// <summary>
457
+ /// Parses a COM+ partition element.
458
+ /// </summary>
459
+ /// <param name="node">Element to parse.</param>
460
+ /// <param name="componentKey">Identifier of parent component.</param>
461
+ private void ParseComPlusPartitionUserElement(XElement node, string componentKey, string partitionKey)
462
+ {
463
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
464
+
465
+ string key = null;
466
+ string user = null;
467
+
468
+ foreach (XAttribute attrib in node.Attributes())
469
+ {
470
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
471
+ {
472
+ switch (attrib.Name.LocalName)
473
+ {
474
+ case "Id":
475
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
476
+ break;
477
+ case "Partition":
478
+ if (null != partitionKey)
479
+ {
480
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
481
+ }
482
+ partitionKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
483
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartition", partitionKey);
484
+ break;
485
+ case "User":
486
+ user = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
487
+ this.Core.CreateSimpleReference(sourceLineNumbers, "User", user);
488
+ break;
489
+ default:
490
+ this.Core.UnexpectedAttribute(node, attrib);
491
+ break;
492
+ }
493
+ }
494
+ else
495
+ {
496
+ this.Core.ParseExtensionAttribute(node, attrib);
497
+ }
498
+ }
499
+
500
+ if (null == partitionKey)
501
+ {
502
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Partition"));
503
+ }
504
+
505
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartitionUser");
506
+ row[0] = key;
507
+ row[1] = partitionKey;
508
+ row[2] = componentKey;
509
+ row[3] = user;
510
+ }
511
+
512
+ /// <summary>
513
+ /// Parses a COM+ application element.
514
+ /// </summary>
515
+ /// <param name="node">Element to parse.</param>
516
+ /// <param name="componentKey">Identifier of parent component.</param>
517
+ /// <param name="partitionKey">Optional identifier of parent partition.</param>
518
+ private void ParseComPlusApplicationElement(XElement node, string componentKey, bool win64, string partitionKey)
519
+ {
520
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
521
+
522
+ string key = null;
523
+ string id = null;
524
+ string name = null;
525
+
526
+ Hashtable properties = new Hashtable();
527
+
528
+ foreach (XAttribute attrib in node.Attributes())
529
+ {
530
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
531
+ {
532
+ switch (attrib.Name.LocalName)
533
+ {
534
+ case "Id":
535
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
536
+ break;
537
+ case "Partition":
538
+ if (null != partitionKey)
539
+ {
540
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
541
+ }
542
+ partitionKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
543
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartition", partitionKey);
544
+ break;
545
+ case "ApplicationId":
546
+ id = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib));
547
+ break;
548
+ case "Name":
549
+ name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
550
+ break;
551
+ case "ThreeGigSupportEnabled":
552
+ if (null == componentKey)
553
+ {
554
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
555
+ }
556
+ properties["3GigSupportEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
557
+ break;
558
+ case "AccessChecksLevel":
559
+ if (null == componentKey)
560
+ {
561
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
562
+ }
563
+ string accessChecksLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
564
+ switch (accessChecksLevelValue)
565
+ {
566
+ case "applicationLevel":
567
+ properties["AccessChecksLevel"] = "0";
568
+ break;
569
+ case "applicationComponentLevel":
570
+ properties["AccessChecksLevel"] = "1";
571
+ break;
572
+ default:
573
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "AccessChecksLevel", accessChecksLevelValue, "applicationLevel", "applicationComponentLevel"));
574
+ break;
575
+ }
576
+ break;
577
+ case "Activation":
578
+ if (null == componentKey)
579
+ {
580
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
581
+ }
582
+ string activationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
583
+ switch (activationValue)
584
+ {
585
+ case "inproc":
586
+ properties["Activation"] = "Inproc";
587
+ break;
588
+ case "local":
589
+ properties["Activation"] = "Local";
590
+ break;
591
+ default:
592
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "Activation", activationValue, "inproc", "local"));
593
+ break;
594
+ }
595
+ break;
596
+ case "ApplicationAccessChecksEnabled":
597
+ if (null == componentKey)
598
+ {
599
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
600
+ }
601
+ properties["ApplicationAccessChecksEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
602
+ break;
603
+ case "ApplicationDirectory":
604
+ if (null == componentKey)
605
+ {
606
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
607
+ }
608
+ properties["ApplicationDirectory"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
609
+ break;
610
+ case "Authentication":
611
+ if (null == componentKey)
612
+ {
613
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
614
+ }
615
+ string authenticationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
616
+ switch (authenticationValue)
617
+ {
618
+ case "default":
619
+ properties["Authentication"] = "0";
620
+ break;
621
+ case "none":
622
+ properties["Authentication"] = "1";
623
+ break;
624
+ case "connect":
625
+ properties["Authentication"] = "2";
626
+ break;
627
+ case "call":
628
+ properties["Authentication"] = "3";
629
+ break;
630
+ case "packet":
631
+ properties["Authentication"] = "4";
632
+ break;
633
+ case "integrity":
634
+ properties["Authentication"] = "5";
635
+ break;
636
+ case "privacy":
637
+ properties["Authentication"] = "6";
638
+ break;
639
+ default:
640
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "Authentication", authenticationValue, "default", "none", "connect", "call", "packet", "integrity", "privacy"));
641
+ break;
642
+ }
643
+ break;
644
+ case "AuthenticationCapability":
645
+ if (null == componentKey)
646
+ {
647
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
648
+ }
649
+ string authenticationCapabilityValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
650
+ switch (authenticationCapabilityValue)
651
+ {
652
+ case "none":
653
+ properties["AuthenticationCapability"] = "0";
654
+ break;
655
+ case "secureReference":
656
+ properties["AuthenticationCapability"] = "2";
657
+ break;
658
+ case "staticCloaking":
659
+ properties["AuthenticationCapability"] = "32";
660
+ break;
661
+ case "dynamicCloaking":
662
+ properties["AuthenticationCapability"] = "64";
663
+ break;
664
+ default:
665
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "AuthenticationCapability", authenticationCapabilityValue, "none", "secureReference", "staticCloaking", "dynamicCloaking"));
666
+ break;
667
+ }
668
+ break;
669
+ case "Changeable":
670
+ this.Core.OnMessage(WixWarnings.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
671
+ break;
672
+ case "CommandLine":
673
+ if (null == componentKey)
674
+ {
675
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
676
+ }
677
+ properties["CommandLine"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
678
+ break;
679
+ case "ConcurrentApps":
680
+ if (null == componentKey)
681
+ {
682
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
683
+ }
684
+ properties["ConcurrentApps"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
685
+ break;
686
+ case "CreatedBy":
687
+ if (null == componentKey)
688
+ {
689
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
690
+ }
691
+ properties["CreatedBy"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
692
+ break;
693
+ case "CRMEnabled":
694
+ if (null == componentKey)
695
+ {
696
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
697
+ }
698
+ properties["CRMEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
699
+ break;
700
+ case "CRMLogFile":
701
+ if (null == componentKey)
702
+ {
703
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
704
+ }
705
+ properties["CRMLogFile"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
706
+ break;
707
+ case "Deleteable":
708
+ if (null == componentKey)
709
+ {
710
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
711
+ }
712
+ properties["Deleteable"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
713
+ break;
714
+ case "Description":
715
+ if (null == componentKey)
716
+ {
717
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
718
+ }
719
+ properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
720
+ break;
721
+ case "DumpEnabled":
722
+ if (null == componentKey)
723
+ {
724
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
725
+ }
726
+ properties["DumpEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
727
+ break;
728
+ case "DumpOnException":
729
+ if (null == componentKey)
730
+ {
731
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
732
+ }
733
+ properties["DumpOnException"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
734
+ break;
735
+ case "DumpOnFailfast":
736
+ if (null == componentKey)
737
+ {
738
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
739
+ }
740
+ properties["DumpOnFailfast"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
741
+ break;
742
+ case "DumpPath":
743
+ if (null == componentKey)
744
+ {
745
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
746
+ }
747
+ properties["DumpPath"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
748
+ break;
749
+ case "EventsEnabled":
750
+ if (null == componentKey)
751
+ {
752
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
753
+ }
754
+ properties["EventsEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
755
+ break;
756
+ case "Identity":
757
+ if (null == componentKey)
758
+ {
759
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
760
+ }
761
+ properties["Identity"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
762
+ break;
763
+ case "ImpersonationLevel":
764
+ if (null == componentKey)
765
+ {
766
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
767
+ }
768
+ string impersonationLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
769
+ switch (impersonationLevelValue)
770
+ {
771
+ case "anonymous":
772
+ properties["ImpersonationLevel"] = "1";
773
+ break;
774
+ case "identify":
775
+ properties["ImpersonationLevel"] = "2";
776
+ break;
777
+ case "impersonate":
778
+ properties["ImpersonationLevel"] = "3";
779
+ break;
780
+ case "delegate":
781
+ properties["ImpersonationLevel"] = "4";
782
+ break;
783
+ default:
784
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "ImpersonationLevel", impersonationLevelValue, "anonymous", "identify", "impersonate", "delegate"));
785
+ break;
786
+ }
787
+ break;
788
+ case "IsEnabled":
789
+ if (null == componentKey)
790
+ {
791
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
792
+ }
793
+ properties["IsEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
794
+ break;
795
+ case "MaxDumpCount":
796
+ if (null == componentKey)
797
+ {
798
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
799
+ }
800
+ properties["MaxDumpCount"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
801
+ break;
802
+ case "Password":
803
+ if (null == componentKey)
804
+ {
805
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
806
+ }
807
+ properties["Password"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
808
+ break;
809
+ case "QCAuthenticateMsgs":
810
+ if (null == componentKey)
811
+ {
812
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
813
+ }
814
+ string qcAuthenticateMsgsValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
815
+ switch (qcAuthenticateMsgsValue)
816
+ {
817
+ case "secureApps":
818
+ properties["QCAuthenticateMsgs"] = "0";
819
+ break;
820
+ case "off":
821
+ properties["QCAuthenticateMsgs"] = "1";
822
+ break;
823
+ case "on":
824
+ properties["QCAuthenticateMsgs"] = "2";
825
+ break;
826
+ default:
827
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "QCAuthenticateMsgs", qcAuthenticateMsgsValue, "secureApps", "off", "on"));
828
+ break;
829
+ }
830
+ break;
831
+ case "QCListenerMaxThreads":
832
+ if (null == componentKey)
833
+ {
834
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
835
+ }
836
+ properties["QCListenerMaxThreads"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
837
+ break;
838
+ case "QueueListenerEnabled":
839
+ if (null == componentKey)
840
+ {
841
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
842
+ }
843
+ properties["QueueListenerEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
844
+ break;
845
+ case "QueuingEnabled":
846
+ if (null == componentKey)
847
+ {
848
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
849
+ }
850
+ properties["QueuingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
851
+ break;
852
+ case "RecycleActivationLimit":
853
+ if (null == componentKey)
854
+ {
855
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
856
+ }
857
+ properties["RecycleActivationLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
858
+ break;
859
+ case "RecycleCallLimit":
860
+ if (null == componentKey)
861
+ {
862
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
863
+ }
864
+ properties["RecycleCallLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
865
+ break;
866
+ case "RecycleExpirationTimeout":
867
+ if (null == componentKey)
868
+ {
869
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
870
+ }
871
+ properties["RecycleExpirationTimeout"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
872
+ break;
873
+ case "RecycleLifetimeLimit":
874
+ if (null == componentKey)
875
+ {
876
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
877
+ }
878
+ properties["RecycleLifetimeLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
879
+ break;
880
+ case "RecycleMemoryLimit":
881
+ if (null == componentKey)
882
+ {
883
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
884
+ }
885
+ properties["RecycleMemoryLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
886
+ break;
887
+ case "Replicable":
888
+ if (null == componentKey)
889
+ {
890
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
891
+ }
892
+ properties["Replicable"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
893
+ break;
894
+ case "RunForever":
895
+ if (null == componentKey)
896
+ {
897
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
898
+ }
899
+ properties["RunForever"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
900
+ break;
901
+ case "ShutdownAfter":
902
+ if (null == componentKey)
903
+ {
904
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
905
+ }
906
+ properties["ShutdownAfter"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
907
+ break;
908
+ case "SoapActivated":
909
+ if (null == componentKey)
910
+ {
911
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
912
+ }
913
+ properties["SoapActivated"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
914
+ break;
915
+ case "SoapBaseUrl":
916
+ if (null == componentKey)
917
+ {
918
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
919
+ }
920
+ properties["SoapBaseUrl"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
921
+ break;
922
+ case "SoapMailTo":
923
+ if (null == componentKey)
924
+ {
925
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
926
+ }
927
+ properties["SoapMailTo"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
928
+ break;
929
+ case "SoapVRoot":
930
+ if (null == componentKey)
931
+ {
932
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
933
+ }
934
+ properties["SoapVRoot"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
935
+ break;
936
+ case "SRPEnabled":
937
+ if (null == componentKey)
938
+ {
939
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
940
+ }
941
+ properties["SRPEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
942
+ break;
943
+ case "SRPTrustLevel":
944
+ if (null == componentKey)
945
+ {
946
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
947
+ }
948
+ string srpTrustLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
949
+ switch (srpTrustLevelValue)
950
+ {
951
+ case "disallowed":
952
+ properties["SRPTrustLevel"] = "0";
953
+ break;
954
+ case "fullyTrusted":
955
+ properties["SRPTrustLevel"] = "262144";
956
+ break;
957
+ default:
958
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "SRPTrustLevel", srpTrustLevelValue, "disallowed", "fullyTrusted"));
959
+ break;
960
+ }
961
+ break;
962
+ default:
963
+ this.Core.UnexpectedAttribute(node, attrib);
964
+ break;
965
+ }
966
+ }
967
+ else
968
+ {
969
+ this.Core.ParseExtensionAttribute(node, attrib);
970
+ }
971
+ }
972
+
973
+ if (null != componentKey && null == name)
974
+ {
975
+ this.Core.OnMessage(ComPlusErrors.RequiredAttributeUnderComponent(sourceLineNumbers, node.Name.LocalName, "Name"));
976
+ }
977
+ if (null == componentKey && null == id && null == name)
978
+ {
979
+ this.Core.OnMessage(ComPlusErrors.RequiredAttributeNotUnderComponent(sourceLineNumbers, node.Name.LocalName, "Id", "Name"));
980
+ }
981
+
982
+ foreach (XElement child in node.Elements())
983
+ {
984
+ if (this.Namespace == child.Name.Namespace)
985
+ {
986
+ switch (child.Name.LocalName)
987
+ {
988
+ case "ComPlusApplicationRole":
989
+ this.ParseComPlusApplicationRoleElement(child, componentKey, key);
990
+ break;
991
+ case "ComPlusAssembly":
992
+ this.ParseComPlusAssemblyElement(child, componentKey, win64, key);
993
+ break;
994
+ default:
995
+ this.Core.UnexpectedElement(node, child);
996
+ break;
997
+ }
998
+ }
999
+ else
1000
+ {
1001
+ this.Core.ParseExtensionElement(node, child);
1002
+ }
1003
+ }
1004
+
1005
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplication");
1006
+ row[0] = key;
1007
+ row[1] = partitionKey;
1008
+ row[2] = componentKey;
1009
+ row[3] = id;
1010
+ row[4] = name;
1011
+
1012
+ IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator();
1013
+ while (propertiesEnumerator.MoveNext())
1014
+ {
1015
+ Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplicationProperty");
1016
+ propertyRow[0] = key;
1017
+ propertyRow[1] = (string)propertiesEnumerator.Key;
1018
+ propertyRow[2] = (string)propertiesEnumerator.Value;
1019
+ }
1020
+
1021
+ if (componentKey != null)
1022
+ {
1023
+ if (win64)
1024
+ {
1025
+ if (this.Core.CurrentPlatform == Platform.IA64)
1026
+ {
1027
+ this.Core.OnMessage(WixErrors.UnsupportedPlatformForElement(sourceLineNumbers, "ia64", node.Name.LocalName));
1028
+ }
1029
+ else
1030
+ {
1031
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall_x64");
1032
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall_x64");
1033
+ }
1034
+ }
1035
+ else
1036
+ {
1037
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall");
1038
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall");
1039
+ }
1040
+ }
1041
+ }
1042
+
1043
+ /// <summary>
1044
+ /// Parses a COM+ application role element.
1045
+ /// </summary>
1046
+ /// <param name="node">Element to parse.</param>
1047
+ /// <param name="componentKey">Identifier of parent component.</param>
1048
+ /// <param name="applicationKey">Optional identifier of parent application.</param>
1049
+ private void ParseComPlusApplicationRoleElement(XElement node, string componentKey, string applicationKey)
1050
+ {
1051
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1052
+
1053
+ string key = null;
1054
+ string name = null;
1055
+
1056
+ Hashtable properties = new Hashtable();
1057
+
1058
+ foreach (XAttribute attrib in node.Attributes())
1059
+ {
1060
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1061
+ {
1062
+ switch (attrib.Name.LocalName)
1063
+ {
1064
+ case "Id":
1065
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1066
+ break;
1067
+ case "Application":
1068
+ if (null != applicationKey)
1069
+ {
1070
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
1071
+ }
1072
+ applicationKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1073
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplication", applicationKey);
1074
+ break;
1075
+ case "Name":
1076
+ name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1077
+ break;
1078
+ case "Description":
1079
+ if (null == componentKey)
1080
+ {
1081
+ this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
1082
+ }
1083
+ properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1084
+ break;
1085
+ default:
1086
+ this.Core.UnexpectedAttribute(node, attrib);
1087
+ break;
1088
+ }
1089
+ }
1090
+ else
1091
+ {
1092
+ this.Core.ParseExtensionAttribute(node, attrib);
1093
+ }
1094
+ }
1095
+
1096
+ if (null == applicationKey)
1097
+ {
1098
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Application"));
1099
+ }
1100
+
1101
+ foreach (XElement child in node.Elements())
1102
+ {
1103
+ if (this.Namespace == child.Name.Namespace)
1104
+ {
1105
+ switch (child.Name.LocalName)
1106
+ {
1107
+ case "ComPlusUserInApplicationRole":
1108
+ this.ParseComPlusUserInApplicationRoleElement(child, componentKey, key);
1109
+ break;
1110
+ case "ComPlusGroupInApplicationRole":
1111
+ this.ParseComPlusGroupInApplicationRoleElement(child, componentKey, key);
1112
+ break;
1113
+ default:
1114
+ this.Core.UnexpectedElement(node, child);
1115
+ break;
1116
+ }
1117
+ }
1118
+ else
1119
+ {
1120
+ this.Core.ParseExtensionElement(node, child);
1121
+ }
1122
+ }
1123
+
1124
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplicationRole");
1125
+ row[0] = key;
1126
+ row[1] = applicationKey;
1127
+ row[2] = componentKey;
1128
+ row[3] = name;
1129
+
1130
+ IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator();
1131
+ while (propertiesEnumerator.MoveNext())
1132
+ {
1133
+ Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplicationRoleProperty");
1134
+ propertyRow[0] = key;
1135
+ propertyRow[1] = (string)propertiesEnumerator.Key;
1136
+ propertyRow[2] = (string)propertiesEnumerator.Value;
1137
+ }
1138
+ }
1139
+
1140
+ /// <summary>
1141
+ /// Parses a COM+ application role user element.
1142
+ /// </summary>
1143
+ /// <param name="node">Element to parse.</param>
1144
+ /// <param name="componentKey">Identifier of parent component.</param>
1145
+ /// <param name="applicationKey">Optional identifier of parent application role.</param>
1146
+ private void ParseComPlusUserInApplicationRoleElement(XElement node, string componentKey, string applicationRoleKey)
1147
+ {
1148
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1149
+
1150
+ string key = null;
1151
+ string user = null;
1152
+
1153
+ foreach (XAttribute attrib in node.Attributes())
1154
+ {
1155
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1156
+ {
1157
+ switch (attrib.Name.LocalName)
1158
+ {
1159
+ case "Id":
1160
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1161
+ break;
1162
+ case "ApplicationRole":
1163
+ if (null != applicationRoleKey)
1164
+ {
1165
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
1166
+ }
1167
+ applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1168
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplicationRole", applicationRoleKey);
1169
+ break;
1170
+ case "User":
1171
+ user = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1172
+ this.Core.CreateSimpleReference(sourceLineNumbers, "User", user);
1173
+ break;
1174
+ default:
1175
+ this.Core.UnexpectedAttribute(node, attrib);
1176
+ break;
1177
+ }
1178
+ }
1179
+ else
1180
+ {
1181
+ this.Core.ParseExtensionAttribute(node, attrib);
1182
+ }
1183
+ }
1184
+
1185
+ if (null == applicationRoleKey)
1186
+ {
1187
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ApplicationRole"));
1188
+ }
1189
+
1190
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusUserInApplicationRole");
1191
+ row[0] = key;
1192
+ row[1] = applicationRoleKey;
1193
+ row[2] = componentKey;
1194
+ row[3] = user;
1195
+ }
1196
+
1197
+ /// <summary>
1198
+ /// Parses a COM+ application role group element.
1199
+ /// </summary>
1200
+ /// <param name="node">Element to parse.</param>
1201
+ /// <param name="componentKey">Identifier of parent component.</param>
1202
+ /// <param name="applicationKey">Optional identifier of parent application role.</param>
1203
+ private void ParseComPlusGroupInApplicationRoleElement(XElement node, string componentKey, string applicationRoleKey)
1204
+ {
1205
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1206
+
1207
+ string key = null;
1208
+ string group = null;
1209
+
1210
+ foreach (XAttribute attrib in node.Attributes())
1211
+ {
1212
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1213
+ {
1214
+ switch (attrib.Name.LocalName)
1215
+ {
1216
+ case "Id":
1217
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1218
+ break;
1219
+ case "ApplicationRole":
1220
+ if (null != applicationRoleKey)
1221
+ {
1222
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
1223
+ }
1224
+ applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1225
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplicationRole", applicationRoleKey);
1226
+ break;
1227
+ case "Group":
1228
+ group = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1229
+ this.Core.CreateSimpleReference(sourceLineNumbers, "Group", group);
1230
+ break;
1231
+ default:
1232
+ this.Core.UnexpectedAttribute(node, attrib);
1233
+ break;
1234
+ }
1235
+ }
1236
+ else
1237
+ {
1238
+ this.Core.ParseExtensionAttribute(node, attrib);
1239
+ }
1240
+ }
1241
+
1242
+ if (null == applicationRoleKey)
1243
+ {
1244
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ApplicationRole"));
1245
+ }
1246
+
1247
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusGroupInApplicationRole");
1248
+ row[0] = key;
1249
+ row[1] = applicationRoleKey;
1250
+ row[2] = componentKey;
1251
+ row[3] = group;
1252
+ }
1253
+
1254
+ /// <summary>
1255
+ /// Parses a COM+ assembly element.
1256
+ /// </summary>
1257
+ /// <param name="node">Element to parse.</param>
1258
+ /// <param name="componentKey">Identifier of parent component.</param>
1259
+ /// <param name="applicationKey">Optional identifier of parent application.</param>
1260
+ private void ParseComPlusAssemblyElement(XElement node, string componentKey, bool win64, string applicationKey)
1261
+ {
1262
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1263
+
1264
+ string key = null;
1265
+ string assemblyName = null;
1266
+ string dllPath = null;
1267
+ string tlbPath = null;
1268
+ string psDllPath = null;
1269
+ int attributes = 0;
1270
+
1271
+ bool hasComponents = false;
1272
+
1273
+ foreach (XAttribute attrib in node.Attributes())
1274
+ {
1275
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1276
+ {
1277
+ switch (attrib.Name.LocalName)
1278
+ {
1279
+ case "Id":
1280
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1281
+ break;
1282
+ case "Application":
1283
+ if (null != applicationKey)
1284
+ {
1285
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
1286
+ }
1287
+ applicationKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1288
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplication", applicationKey);
1289
+ break;
1290
+ case "AssemblyName":
1291
+ assemblyName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1292
+ break;
1293
+ case "DllPath":
1294
+ dllPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1295
+ break;
1296
+ case "TlbPath":
1297
+ tlbPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1298
+ break;
1299
+ case "PSDllPath":
1300
+ psDllPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1301
+ break;
1302
+ case "Type":
1303
+ string typeValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1304
+ switch (typeValue)
1305
+ {
1306
+ case ".net":
1307
+ attributes |= (int)CpiAssemblyAttributes.DotNetAssembly;
1308
+ break;
1309
+ case "native":
1310
+ attributes &= ~(int)CpiAssemblyAttributes.DotNetAssembly;
1311
+ break;
1312
+ default:
1313
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusAssembly", "Type", typeValue, ".net", "native"));
1314
+ break;
1315
+ }
1316
+ break;
1317
+ case "EventClass":
1318
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1319
+ {
1320
+ attributes |= (int)CpiAssemblyAttributes.EventClass;
1321
+ }
1322
+ else
1323
+ {
1324
+ attributes &= ~(int)CpiAssemblyAttributes.EventClass;
1325
+ }
1326
+ break;
1327
+ case "DllPathFromGAC":
1328
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1329
+ {
1330
+ attributes |= (int)CpiAssemblyAttributes.DllPathFromGAC;
1331
+ }
1332
+ else
1333
+ {
1334
+ attributes &= ~(int)CpiAssemblyAttributes.DllPathFromGAC;
1335
+ }
1336
+ break;
1337
+ case "RegisterInCommit":
1338
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1339
+ {
1340
+ attributes |= (int)CpiAssemblyAttributes.RegisterInCommit;
1341
+ }
1342
+ else
1343
+ {
1344
+ attributes &= ~(int)CpiAssemblyAttributes.RegisterInCommit;
1345
+ }
1346
+ break;
1347
+ default:
1348
+ this.Core.UnexpectedAttribute(node, attrib);
1349
+ break;
1350
+ }
1351
+ }
1352
+ else
1353
+ {
1354
+ this.Core.ParseExtensionAttribute(node, attrib);
1355
+ }
1356
+ }
1357
+
1358
+ if (null == applicationKey && 0 == (attributes & (int)CpiAssemblyAttributes.DotNetAssembly))
1359
+ {
1360
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Application", "Type", "native"));
1361
+ }
1362
+ if (null != assemblyName && 0 == (attributes & (int)CpiAssemblyAttributes.DllPathFromGAC))
1363
+ {
1364
+ this.Core.OnMessage(ComPlusErrors.UnexpectedAttributeWithoutOtherValue(sourceLineNumbers, node.Name.LocalName, "AssemblyName", "DllPathFromGAC", "no"));
1365
+ }
1366
+ if (null == tlbPath && 0 != (attributes & (int)CpiAssemblyAttributes.DotNetAssembly))
1367
+ {
1368
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "TlbPath", "Type", ".net"));
1369
+ }
1370
+ if (null != psDllPath && 0 != (attributes & (int)CpiAssemblyAttributes.DotNetAssembly))
1371
+ {
1372
+ this.Core.OnMessage(ComPlusErrors.UnexpectedAttributeWithOtherValue(sourceLineNumbers, node.Name.LocalName, "PSDllPath", "Type", ".net"));
1373
+ }
1374
+ if (0 != (attributes & (int)CpiAssemblyAttributes.EventClass) && 0 != (attributes & (int)CpiAssemblyAttributes.DotNetAssembly))
1375
+ {
1376
+ this.Core.OnMessage(ComPlusErrors.UnexpectedAttributeWithOtherValue(sourceLineNumbers, node.Name.LocalName, "EventClass", "yes", "Type", ".net"));
1377
+ }
1378
+
1379
+ foreach (XElement child in node.Elements())
1380
+ {
1381
+ if (this.Namespace == child.Name.Namespace)
1382
+ {
1383
+ switch (child.Name.LocalName)
1384
+ {
1385
+ case "ComPlusAssemblyDependency":
1386
+ this.ParseComPlusAssemblyDependencyElement(child, key);
1387
+ break;
1388
+ case "ComPlusComponent":
1389
+ this.ParseComPlusComponentElement(child, componentKey, key);
1390
+ hasComponents = true;
1391
+ break;
1392
+ default:
1393
+ this.Core.UnexpectedElement(node, child);
1394
+ break;
1395
+ }
1396
+ }
1397
+ else
1398
+ {
1399
+ this.Core.ParseExtensionElement(node, child);
1400
+ }
1401
+ }
1402
+
1403
+ if (0 == (attributes & (int)CpiAssemblyAttributes.DotNetAssembly) && !hasComponents)
1404
+ {
1405
+ this.Core.OnMessage(ComPlusWarnings.MissingComponents(sourceLineNumbers));
1406
+ }
1407
+
1408
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusAssembly");
1409
+ row[0] = key;
1410
+ row[1] = applicationKey;
1411
+ row[2] = componentKey;
1412
+ row[3] = assemblyName;
1413
+ row[4] = dllPath;
1414
+ row[5] = tlbPath;
1415
+ row[6] = psDllPath;
1416
+ row[7] = attributes;
1417
+
1418
+ if (win64)
1419
+ {
1420
+ if (this.Core.CurrentPlatform == Platform.IA64)
1421
+ {
1422
+ this.Core.OnMessage(WixErrors.UnsupportedPlatformForElement(sourceLineNumbers, "ia64", node.Name.LocalName));
1423
+ }
1424
+ else
1425
+ {
1426
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall_x64");
1427
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall_x64");
1428
+ }
1429
+ }
1430
+ else
1431
+ {
1432
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall");
1433
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall");
1434
+ }
1435
+ }
1436
+
1437
+ /// <summary>
1438
+ /// Parses a COM+ assembly dependency element.
1439
+ /// </summary>
1440
+ /// <param name="node">Element to parse.</param>
1441
+ /// <param name="assemblyKey">Identifier of parent assembly.</param>
1442
+ private void ParseComPlusAssemblyDependencyElement(XElement node, string assemblyKey)
1443
+ {
1444
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1445
+
1446
+ string requiredAssemblyKey = null;
1447
+
1448
+ foreach (XAttribute attrib in node.Attributes())
1449
+ {
1450
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1451
+ {
1452
+ switch (attrib.Name.LocalName)
1453
+ {
1454
+ case "RequiredAssembly":
1455
+ requiredAssemblyKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1456
+ break;
1457
+ default:
1458
+ this.Core.UnexpectedAttribute(node, attrib);
1459
+ break;
1460
+ }
1461
+ }
1462
+ else
1463
+ {
1464
+ this.Core.ParseExtensionAttribute(node, attrib);
1465
+ }
1466
+ }
1467
+
1468
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusAssemblyDependency");
1469
+ row[0] = assemblyKey;
1470
+ row[1] = requiredAssemblyKey;
1471
+ }
1472
+
1473
+ /// <summary>
1474
+ /// Parses a COM+ component element.
1475
+ /// </summary>
1476
+ /// <param name="node">Element to parse.</param>
1477
+ /// <param name="componentKey">Identifier of parent component.</param>
1478
+ /// <param name="assemblyKey">Identifier of parent assembly.</param>
1479
+ private void ParseComPlusComponentElement(XElement node, string componentKey, string assemblyKey)
1480
+ {
1481
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1482
+
1483
+ string key = null;
1484
+ string clsid = null;
1485
+
1486
+ Hashtable properties = new Hashtable();
1487
+
1488
+ foreach (XAttribute attrib in node.Attributes())
1489
+ {
1490
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1491
+ {
1492
+ switch (attrib.Name.LocalName)
1493
+ {
1494
+ case "Id":
1495
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1496
+ break;
1497
+ case "CLSID":
1498
+ clsid = "{" + this.Core.GetAttributeValue(sourceLineNumbers, attrib) + "}";
1499
+ break;
1500
+ case "AllowInprocSubscribers":
1501
+ properties["AllowInprocSubscribers"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1502
+ break;
1503
+ case "ComponentAccessChecksEnabled":
1504
+ properties["ComponentAccessChecksEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1505
+ break;
1506
+ case "ComponentTransactionTimeout":
1507
+ properties["ComponentTransactionTimeout"] = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 3600).ToString();
1508
+ break;
1509
+ case "ComponentTransactionTimeoutEnabled":
1510
+ properties["ComponentTransactionTimeoutEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1511
+ break;
1512
+ case "COMTIIntrinsics":
1513
+ properties["COMTIIntrinsics"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1514
+ break;
1515
+ case "ConstructionEnabled":
1516
+ properties["ConstructionEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1517
+ break;
1518
+ case "ConstructorString":
1519
+ properties["ConstructorString"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1520
+ break;
1521
+ case "CreationTimeout":
1522
+ properties["CreationTimeout"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1523
+ break;
1524
+ case "Description":
1525
+ properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1526
+ break;
1527
+ case "EventTrackingEnabled":
1528
+ properties["EventTrackingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1529
+ break;
1530
+ case "ExceptionClass":
1531
+ properties["ExceptionClass"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1532
+ break;
1533
+ case "FireInParallel":
1534
+ properties["FireInParallel"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1535
+ break;
1536
+ case "IISIntrinsics":
1537
+ properties["IISIntrinsics"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1538
+ break;
1539
+ case "InitializesServerApplication":
1540
+ properties["InitializesServerApplication"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1541
+ break;
1542
+ case "IsEnabled":
1543
+ properties["IsEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1544
+ break;
1545
+ case "IsPrivateComponent":
1546
+ properties["IsPrivateComponent"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1547
+ break;
1548
+ case "JustInTimeActivation":
1549
+ properties["JustInTimeActivation"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1550
+ break;
1551
+ case "LoadBalancingSupported":
1552
+ properties["LoadBalancingSupported"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1553
+ break;
1554
+ case "MaxPoolSize":
1555
+ properties["MaxPoolSize"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1556
+ break;
1557
+ case "MinPoolSize":
1558
+ properties["MinPoolSize"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1559
+ break;
1560
+ case "MultiInterfacePublisherFilterCLSID":
1561
+ properties["MultiInterfacePublisherFilterCLSID"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1562
+ break;
1563
+ case "MustRunInClientContext":
1564
+ properties["MustRunInClientContext"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1565
+ break;
1566
+ case "MustRunInDefaultContext":
1567
+ properties["MustRunInDefaultContext"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1568
+ break;
1569
+ case "ObjectPoolingEnabled":
1570
+ properties["ObjectPoolingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1571
+ break;
1572
+ case "PublisherID":
1573
+ properties["PublisherID"] = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib));
1574
+ break;
1575
+ case "SoapAssemblyName":
1576
+ properties["SoapAssemblyName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1577
+ break;
1578
+ case "SoapTypeName":
1579
+ properties["SoapTypeName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1580
+ break;
1581
+ case "Synchronization":
1582
+ string synchronizationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1583
+ switch (synchronizationValue)
1584
+ {
1585
+ case "ignored":
1586
+ properties["Synchronization"] = "0";
1587
+ break;
1588
+ case "none":
1589
+ properties["Synchronization"] = "1";
1590
+ break;
1591
+ case "supported":
1592
+ properties["Synchronization"] = "2";
1593
+ break;
1594
+ case "required":
1595
+ properties["Synchronization"] = "3";
1596
+ break;
1597
+ case "requiresNew":
1598
+ properties["Synchronization"] = "4";
1599
+ break;
1600
+ default:
1601
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusComponent", "Synchronization", synchronizationValue, "ignored", "none", "supported", "required", "requiresNew"));
1602
+ break;
1603
+ }
1604
+ break;
1605
+ case "Transaction":
1606
+ string transactionValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1607
+ switch (transactionValue)
1608
+ {
1609
+ case "ignored":
1610
+ properties["Transaction"] = "0";
1611
+ break;
1612
+ case "none":
1613
+ properties["Transaction"] = "1";
1614
+ break;
1615
+ case "supported":
1616
+ properties["Transaction"] = "2";
1617
+ break;
1618
+ case "required":
1619
+ properties["Transaction"] = "3";
1620
+ break;
1621
+ case "requiresNew":
1622
+ properties["Transaction"] = "4";
1623
+ break;
1624
+ default:
1625
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusComponent", "Transaction", transactionValue, "ignored", "none", "supported", "required", "requiresNew"));
1626
+ break;
1627
+ }
1628
+ break;
1629
+ case "TxIsolationLevel":
1630
+ string txIsolationLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1631
+ switch (txIsolationLevelValue)
1632
+ {
1633
+ case "any":
1634
+ properties["TxIsolationLevel"] = "0";
1635
+ break;
1636
+ case "readUnCommitted":
1637
+ properties["TxIsolationLevel"] = "1";
1638
+ break;
1639
+ case "readCommitted":
1640
+ properties["TxIsolationLevel"] = "2";
1641
+ break;
1642
+ case "repeatableRead":
1643
+ properties["TxIsolationLevel"] = "3";
1644
+ break;
1645
+ case "serializable":
1646
+ properties["TxIsolationLevel"] = "4";
1647
+ break;
1648
+ default:
1649
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusComponent", "TxIsolationLevel", txIsolationLevelValue, "any", "readUnCommitted", "readCommitted", "repeatableRead", "serializable"));
1650
+ break;
1651
+ }
1652
+ break;
1653
+ default:
1654
+ this.Core.UnexpectedAttribute(node, attrib);
1655
+ break;
1656
+ }
1657
+ }
1658
+ else
1659
+ {
1660
+ this.Core.ParseExtensionAttribute(node, attrib);
1661
+ }
1662
+ }
1663
+
1664
+ foreach (XElement child in node.Elements())
1665
+ {
1666
+ if (this.Namespace == child.Name.Namespace)
1667
+ {
1668
+ switch (child.Name.LocalName)
1669
+ {
1670
+ case "ComPlusRoleForComponent":
1671
+ this.ParseComPlusRoleForComponentElement(child, componentKey, key);
1672
+ break;
1673
+ case "ComPlusInterface":
1674
+ this.ParseComPlusInterfaceElement(child, componentKey, key);
1675
+ break;
1676
+ case "ComPlusSubscription":
1677
+ this.ParseComPlusSubscriptionElement(child, componentKey, key);
1678
+ break;
1679
+ default:
1680
+ this.Core.UnexpectedElement(node, child);
1681
+ break;
1682
+ }
1683
+ }
1684
+ else
1685
+ {
1686
+ this.Core.ParseExtensionElement(node, child);
1687
+ }
1688
+ }
1689
+
1690
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusComponent");
1691
+ row[0] = key;
1692
+ row[1] = assemblyKey;
1693
+ row[2] = clsid;
1694
+
1695
+ IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator();
1696
+ while (propertiesEnumerator.MoveNext())
1697
+ {
1698
+ Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusComponentProperty");
1699
+ propertyRow[0] = key;
1700
+ propertyRow[1] = (string)propertiesEnumerator.Key;
1701
+ propertyRow[2] = (string)propertiesEnumerator.Value;
1702
+ }
1703
+ }
1704
+
1705
+ /// <summary>
1706
+ /// Parses a COM+ application role for component element.
1707
+ /// </summary>
1708
+ /// <param name="node">Element to parse.</param>
1709
+ /// <param name="componentKey">Identifier of parent component.</param>
1710
+ /// <param name="cpcomponentKey">Identifier of parent COM+ component.</param>
1711
+ private void ParseComPlusRoleForComponentElement(XElement node, string componentKey, string cpcomponentKey)
1712
+ {
1713
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1714
+
1715
+ string key = null;
1716
+ string applicationRoleKey = null;
1717
+
1718
+ foreach (XAttribute attrib in node.Attributes())
1719
+ {
1720
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1721
+ {
1722
+ switch (attrib.Name.LocalName)
1723
+ {
1724
+ case "Id":
1725
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1726
+ break;
1727
+ case "Component":
1728
+ if (null != cpcomponentKey)
1729
+ {
1730
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
1731
+ }
1732
+ cpcomponentKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1733
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusComponent", cpcomponentKey);
1734
+ break;
1735
+ case "ApplicationRole":
1736
+ applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1737
+ break;
1738
+ default:
1739
+ this.Core.UnexpectedAttribute(node, attrib);
1740
+ break;
1741
+ }
1742
+ }
1743
+ else
1744
+ {
1745
+ this.Core.ParseExtensionAttribute(node, attrib);
1746
+ }
1747
+ }
1748
+
1749
+ if (null == cpcomponentKey)
1750
+ {
1751
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Component"));
1752
+ }
1753
+
1754
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusRoleForComponent");
1755
+ row[0] = key;
1756
+ row[1] = cpcomponentKey;
1757
+ row[2] = applicationRoleKey;
1758
+ row[3] = componentKey;
1759
+ }
1760
+
1761
+ /// <summary>
1762
+ /// Parses a COM+ interface element.
1763
+ /// </summary>
1764
+ /// <param name="node">Element to parse.</param>
1765
+ /// <param name="componentKey">Identifier of parent component.</param>
1766
+ /// <param name="cpcomponentKey">Identifier of parent COM+ component.</param>
1767
+ private void ParseComPlusInterfaceElement(XElement node, string componentKey, string cpcomponentKey)
1768
+ {
1769
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1770
+
1771
+ // parse attributes
1772
+ string key = null;
1773
+ string iid = null;
1774
+
1775
+ Hashtable properties = new Hashtable();
1776
+
1777
+ foreach (XAttribute attrib in node.Attributes())
1778
+ {
1779
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1780
+ {
1781
+ switch (attrib.Name.LocalName)
1782
+ {
1783
+ case "Id":
1784
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1785
+ break;
1786
+ case "IID":
1787
+ iid = "{" + this.Core.GetAttributeValue(sourceLineNumbers, attrib) + "}";
1788
+ break;
1789
+ case "Description":
1790
+ properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1791
+ break;
1792
+ case "QueuingEnabled":
1793
+ properties["QueuingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1794
+ break;
1795
+ default:
1796
+ this.Core.UnexpectedAttribute(node, attrib);
1797
+ break;
1798
+ }
1799
+ }
1800
+ else
1801
+ {
1802
+ this.Core.ParseExtensionAttribute(node, attrib);
1803
+ }
1804
+ }
1805
+
1806
+ foreach (XElement child in node.Elements())
1807
+ {
1808
+ if (this.Namespace == child.Name.Namespace)
1809
+ {
1810
+ switch (child.Name.LocalName)
1811
+ {
1812
+ case "ComPlusRoleForInterface":
1813
+ this.ParseComPlusRoleForInterfaceElement(child, componentKey, key);
1814
+ break;
1815
+ case "ComPlusMethod":
1816
+ this.ParseComPlusMethodElement(child, componentKey, key);
1817
+ break;
1818
+ default:
1819
+ this.Core.UnexpectedElement(node, child);
1820
+ break;
1821
+ }
1822
+ }
1823
+ else
1824
+ {
1825
+ this.Core.ParseExtensionElement(node, child);
1826
+ }
1827
+ }
1828
+
1829
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusInterface");
1830
+ row[0] = key;
1831
+ row[1] = cpcomponentKey;
1832
+ row[2] = iid;
1833
+
1834
+ IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator();
1835
+ while (propertiesEnumerator.MoveNext())
1836
+ {
1837
+ Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusInterfaceProperty");
1838
+ propertyRow[0] = key;
1839
+ propertyRow[1] = (string)propertiesEnumerator.Key;
1840
+ propertyRow[2] = (string)propertiesEnumerator.Value;
1841
+ }
1842
+ }
1843
+
1844
+ /// <summary>
1845
+ /// Parses a COM+ application role for interface element.
1846
+ /// </summary>
1847
+ /// <param name="node">Element to parse.</param>
1848
+ /// <param name="componentKey">Identifier of parent component.</param>
1849
+ /// <param name="interfaceKey">Identifier of parent interface.</param>
1850
+ private void ParseComPlusRoleForInterfaceElement(XElement node, string componentKey, string interfaceKey)
1851
+ {
1852
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1853
+
1854
+ string key = null;
1855
+ string applicationRoleKey = null;
1856
+
1857
+ foreach (XAttribute attrib in node.Attributes())
1858
+ {
1859
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1860
+ {
1861
+ switch (attrib.Name.LocalName)
1862
+ {
1863
+ case "Id":
1864
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1865
+ break;
1866
+ case "Interface":
1867
+ if (null != interfaceKey)
1868
+ {
1869
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
1870
+ }
1871
+ interfaceKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1872
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusInterface", interfaceKey);
1873
+ break;
1874
+ case "ApplicationRole":
1875
+ applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1876
+ break;
1877
+ default:
1878
+ this.Core.UnexpectedAttribute(node, attrib);
1879
+ break;
1880
+ }
1881
+ }
1882
+ else
1883
+ {
1884
+ this.Core.ParseExtensionAttribute(node, attrib);
1885
+ }
1886
+ }
1887
+
1888
+ if (null == interfaceKey)
1889
+ {
1890
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Interface"));
1891
+ }
1892
+
1893
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusRoleForInterface");
1894
+ row[0] = key;
1895
+ row[1] = interfaceKey;
1896
+ row[2] = applicationRoleKey;
1897
+ row[3] = componentKey;
1898
+ }
1899
+
1900
+ /// <summary>
1901
+ /// Parses a COM+ method element.
1902
+ /// </summary>
1903
+ /// <param name="node">Element to parse.</param>
1904
+ /// <param name="componentKey">Identifier of parent component.</param>
1905
+ /// <param name="interfaceKey">Identifier of parent interface.</param>
1906
+ private void ParseComPlusMethodElement(XElement node, string componentKey, string interfaceKey)
1907
+ {
1908
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1909
+
1910
+ string key = null;
1911
+ int index = CompilerConstants.IntegerNotSet;
1912
+ string name = null;
1913
+
1914
+ Hashtable properties = new Hashtable();
1915
+
1916
+ foreach (XAttribute attrib in node.Attributes())
1917
+ {
1918
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1919
+ {
1920
+ switch (attrib.Name.LocalName)
1921
+ {
1922
+ case "Id":
1923
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1924
+ break;
1925
+ case "Index":
1926
+ index = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
1927
+ break;
1928
+ case "Name":
1929
+ name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1930
+ break;
1931
+ case "AutoComplete":
1932
+ properties["AutoComplete"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
1933
+ break;
1934
+ case "Description":
1935
+ properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1936
+ break;
1937
+ default:
1938
+ this.Core.UnexpectedAttribute(node, attrib);
1939
+ break;
1940
+ }
1941
+ }
1942
+ else
1943
+ {
1944
+ this.Core.ParseExtensionAttribute(node, attrib);
1945
+ }
1946
+ }
1947
+
1948
+ foreach (XElement child in node.Elements())
1949
+ {
1950
+ if (this.Namespace == child.Name.Namespace)
1951
+ {
1952
+ switch (child.Name.LocalName)
1953
+ {
1954
+ case "ComPlusRoleForMethod":
1955
+ this.ParseComPlusRoleForMethodElement(child, componentKey, key);
1956
+ break;
1957
+ default:
1958
+ this.Core.UnexpectedElement(node, child);
1959
+ break;
1960
+ }
1961
+ }
1962
+ else
1963
+ {
1964
+ this.Core.ParseExtensionElement(node, child);
1965
+ }
1966
+ }
1967
+
1968
+ if (CompilerConstants.IntegerNotSet == index && null == name)
1969
+ {
1970
+ this.Core.OnMessage(ComPlusErrors.RequiredAttribute(sourceLineNumbers, node.Name.LocalName, "Index", "Name"));
1971
+ }
1972
+
1973
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusMethod");
1974
+ row[0] = key;
1975
+ row[1] = interfaceKey;
1976
+ if (CompilerConstants.IntegerNotSet != index)
1977
+ {
1978
+ row[2] = index;
1979
+ }
1980
+ row[3] = name;
1981
+
1982
+ IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator();
1983
+ while (propertiesEnumerator.MoveNext())
1984
+ {
1985
+ Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusMethodProperty");
1986
+ propertyRow[0] = key;
1987
+ propertyRow[1] = (string)propertiesEnumerator.Key;
1988
+ propertyRow[2] = (string)propertiesEnumerator.Value;
1989
+ }
1990
+ }
1991
+
1992
+ /// <summary>
1993
+ /// Parses a COM+ application role for method element.
1994
+ /// </summary>
1995
+ /// <param name="node">Element to parse.</param>
1996
+ /// <param name="componentKey">Identifier of parent component.</param>
1997
+ /// <param name="methodKey">Identifier of parent method.</param>
1998
+ private void ParseComPlusRoleForMethodElement(XElement node, string componentKey, string methodKey)
1999
+ {
2000
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
2001
+
2002
+ string key = null;
2003
+ string applicationRoleKey = null;
2004
+
2005
+ foreach (XAttribute attrib in node.Attributes())
2006
+ {
2007
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2008
+ {
2009
+ switch (attrib.Name.LocalName)
2010
+ {
2011
+ case "Id":
2012
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
2013
+ break;
2014
+ case "Method":
2015
+ if (null != methodKey)
2016
+ {
2017
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
2018
+ }
2019
+ methodKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2020
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusMethod", methodKey);
2021
+ break;
2022
+ case "ApplicationRole":
2023
+ applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2024
+ break;
2025
+ default:
2026
+ this.Core.UnexpectedAttribute(node, attrib);
2027
+ break;
2028
+ }
2029
+ }
2030
+ else
2031
+ {
2032
+ this.Core.ParseExtensionAttribute(node, attrib);
2033
+ }
2034
+ }
2035
+
2036
+ if (null == methodKey)
2037
+ {
2038
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Method"));
2039
+ }
2040
+
2041
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusRoleForMethod");
2042
+ row[0] = key;
2043
+ row[1] = methodKey;
2044
+ row[2] = applicationRoleKey;
2045
+ row[3] = componentKey;
2046
+ }
2047
+
2048
+ /// <summary>
2049
+ /// Parses a COM+ event subscription element.
2050
+ /// </summary>
2051
+ /// <param name="node">Element to parse.</param>
2052
+ /// <param name="componentKey">Identifier of parent component.</param>
2053
+ /// <param name="cpcomponentKey">Identifier of parent COM+ component.</param>
2054
+ private void ParseComPlusSubscriptionElement(XElement node, string componentKey, string cpcomponentKey)
2055
+ {
2056
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
2057
+
2058
+ string key = null;
2059
+ string id = null;
2060
+ string name = null;
2061
+ string eventCLSID = null;
2062
+ string publisherID = null;
2063
+
2064
+ Hashtable properties = new Hashtable();
2065
+
2066
+ foreach (XAttribute attrib in node.Attributes())
2067
+ {
2068
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2069
+ {
2070
+ switch (attrib.Name.LocalName)
2071
+ {
2072
+ case "Id":
2073
+ key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
2074
+ break;
2075
+ case "Component":
2076
+ if (null != cpcomponentKey)
2077
+ {
2078
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
2079
+ }
2080
+ cpcomponentKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2081
+ this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusComponent", cpcomponentKey);
2082
+ break;
2083
+ case "SubscriptionId":
2084
+ id = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib));
2085
+ break;
2086
+ case "Name":
2087
+ name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2088
+ break;
2089
+ case "EventCLSID":
2090
+ eventCLSID = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2091
+ break;
2092
+ case "PublisherID":
2093
+ publisherID = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib));
2094
+ break;
2095
+ case "Description":
2096
+ properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2097
+ break;
2098
+ case "Enabled":
2099
+ properties["Enabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
2100
+ break;
2101
+ case "EventClassPartitionID":
2102
+ properties["EventClassPartitionID"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2103
+ break;
2104
+ case "FilterCriteria":
2105
+ properties["FilterCriteria"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2106
+ break;
2107
+ case "InterfaceID":
2108
+ properties["InterfaceID"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2109
+ break;
2110
+ case "MachineName":
2111
+ properties["MachineName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2112
+ break;
2113
+ case "MethodName":
2114
+ properties["MethodName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2115
+ break;
2116
+ case "PerUser":
2117
+ properties["PerUser"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
2118
+ break;
2119
+ case "Queued":
2120
+ properties["Queued"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0";
2121
+ break;
2122
+ case "SubscriberMoniker":
2123
+ properties["SubscriberMoniker"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2124
+ break;
2125
+ case "UserName":
2126
+ properties["UserName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
2127
+ break;
2128
+ default:
2129
+ this.Core.UnexpectedAttribute(node, attrib);
2130
+ break;
2131
+ }
2132
+ }
2133
+ else
2134
+ {
2135
+ this.Core.ParseExtensionAttribute(node, attrib);
2136
+ }
2137
+ }
2138
+
2139
+ if (null == cpcomponentKey)
2140
+ {
2141
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Component"));
2142
+ }
2143
+
2144
+ this.Core.ParseForExtensionElements(node);
2145
+
2146
+ Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusSubscription");
2147
+ row[0] = key;
2148
+ row[1] = cpcomponentKey;
2149
+ row[2] = componentKey;
2150
+ row[3] = id;
2151
+ row[4] = name;
2152
+ row[5] = eventCLSID;
2153
+ row[6] = publisherID;
2154
+
2155
+ IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator();
2156
+ while (propertiesEnumerator.MoveNext())
2157
+ {
2158
+ Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusSubscriptionProperty");
2159
+ propertyRow[0] = key;
2160
+ propertyRow[1] = (string)propertiesEnumerator.Key;
2161
+ propertyRow[2] = (string)propertiesEnumerator.Value;
2162
+ }
2163
+ }
2164
+
2165
+ /// <summary>
2166
+ /// Attempts to parse the input value as a GUID, and in case the value is a valid
2167
+ /// GUID returnes it in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}".
2168
+ /// </summary>
2169
+ /// <param name="val"></param>
2170
+ /// <returns></returns>
2171
+ string TryFormatGuidValue(string val)
2172
+ {
2173
+ try
2174
+ {
2175
+ Guid guid = new Guid(val);
2176
+ return guid.ToString("B").ToUpper();
2177
+ }
2178
+ catch (FormatException)
2179
+ {
2180
+ return val;
2181
+ }
2182
+ catch (OverflowException)
2183
+ {
2184
+ return val;
2185
+ }
2186
+ }
2187
+ }
2188
+}
src/wixext/ComPlusDecompiler.cs
new
+1843
@@ -0,0 +1,1843 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Extensions
4
+{
5
+ using System;
6
+ using System.Collections;
7
+ using System.Globalization;
8
+ using WixToolset.Data;
9
+ using WixToolset.Extensibility;
10
+ using ComPlus = WixToolset.Extensions.Serialize.ComPlus;
11
+ using Wix = WixToolset.Data.Serialize;
12
+
13
+ /// <summary>
14
+ /// The decompiler for the WiX Toolset COM+ Extension.
15
+ /// </summary>
16
+ public sealed class ComPlusDecompiler : DecompilerExtension
17
+ {
18
+ /// <summary>
19
+ /// Creates a decompiler for ComPlus Extension.
20
+ /// </summary>
21
+ public ComPlusDecompiler()
22
+ {
23
+ this.TableDefinitions = ComPlusExtensionData.GetExtensionTableDefinitions();
24
+ }
25
+
26
+ /// <summary>
27
+ /// Get the extensions library to be removed.
28
+ /// </summary>
29
+ /// <param name="tableDefinitions">Table definitions for library.</param>
30
+ /// <returns>Library to remove from decompiled output.</returns>
31
+ public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
32
+ {
33
+ return ComPlusExtensionData.GetExtensionLibrary(tableDefinitions);
34
+ }
35
+
36
+ /// <summary>
37
+ /// Decompiles an extension table.
38
+ /// </summary>
39
+ /// <param name="table">The table to decompile.</param>
40
+ public override void DecompileTable(Table table)
41
+ {
42
+ switch (table.Name)
43
+ {
44
+ case "ComPlusPartition":
45
+ this.DecompileComPlusPartitionTable(table);
46
+ break;
47
+ case "ComPlusPartitionProperty":
48
+ this.DecompileComPlusPartitionPropertyTable(table);
49
+ break;
50
+ case "ComPlusPartitionRole":
51
+ this.DecompileComPlusPartitionRoleTable(table);
52
+ break;
53
+ case "ComPlusUserInPartitionRole":
54
+ this.DecompileComPlusUserInPartitionRoleTable(table);
55
+ break;
56
+ case "ComPlusGroupInPartitionRole":
57
+ this.DecompileComPlusGroupInPartitionRoleTable(table);
58
+ break;
59
+ case "ComPlusPartitionUser":
60
+ this.DecompileComPlusPartitionUserTable(table);
61
+ break;
62
+ case "ComPlusApplication":
63
+ this.DecompileComPlusApplicationTable(table);
64
+ break;
65
+ case "ComPlusApplicationProperty":
66
+ this.DecompileComPlusApplicationPropertyTable(table);
67
+ break;
68
+ case "ComPlusApplicationRole":
69
+ this.DecompileComPlusApplicationRoleTable(table);
70
+ break;
71
+ case "ComPlusApplicationRoleProperty":
72
+ this.DecompileComPlusApplicationRolePropertyTable(table);
73
+ break;
74
+ case "ComPlusUserInApplicationRole":
75
+ this.DecompileComPlusUserInApplicationRoleTable(table);
76
+ break;
77
+ case "ComPlusGroupInApplicationRole":
78
+ this.DecompileComPlusGroupInApplicationRoleTable(table);
79
+ break;
80
+ case "ComPlusAssembly":
81
+ this.DecompileComPlusAssemblyTable(table);
82
+ break;
83
+ case "ComPlusComponent":
84
+ this.DecompileComPlusComponentTable(table);
85
+ break;
86
+ case "ComPlusComponentProperty":
87
+ this.DecompileComPlusComponentPropertyTable(table);
88
+ break;
89
+ case "ComPlusRoleForComponent":
90
+ this.DecompileComPlusRoleForComponentTable(table);
91
+ break;
92
+ case "ComPlusInterface":
93
+ this.DecompileComPlusInterfaceTable(table);
94
+ break;
95
+ case "ComPlusInterfaceProperty":
96
+ this.DecompileComPlusInterfacePropertyTable(table);
97
+ break;
98
+ case "ComPlusRoleForInterface":
99
+ this.DecompileComPlusRoleForInterfaceTable(table);
100
+ break;
101
+ case "ComPlusMethod":
102
+ this.DecompileComPlusMethodTable(table);
103
+ break;
104
+ case "ComPlusMethodProperty":
105
+ this.DecompileComPlusMethodPropertyTable(table);
106
+ break;
107
+ case "ComPlusRoleForMethod":
108
+ this.DecompileComPlusRoleForMethodTable(table);
109
+ break;
110
+ case "ComPlusSubscription":
111
+ this.DecompileComPlusSubscriptionTable(table);
112
+ break;
113
+ case "ComPlusSubscriptionProperty":
114
+ this.DecompileComPlusSubscriptionPropertyTable(table);
115
+ break;
116
+ default:
117
+ base.DecompileTable(table);
118
+ break;
119
+ }
120
+ }
121
+
122
+ /// <summary>
123
+ /// Decompile the ComPlusPartition table.
124
+ /// </summary>
125
+ /// <param name="table">The table to decompile.</param>
126
+ private void DecompileComPlusPartitionTable(Table table)
127
+ {
128
+ foreach (Row row in table.Rows)
129
+ {
130
+ ComPlus.ComPlusPartition partition = new ComPlus.ComPlusPartition();
131
+
132
+ partition.Id = (string)row[0];
133
+
134
+ if (null != row[2])
135
+ {
136
+ partition.PartitionId = (string)row[2];
137
+ }
138
+
139
+ if (null != row[3])
140
+ {
141
+ partition.Name = (string)row[3];
142
+ }
143
+
144
+ if (null != row[1])
145
+ {
146
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
147
+ if (null != component)
148
+ {
149
+ component.AddChild(partition);
150
+ }
151
+ else
152
+ {
153
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
154
+ }
155
+ }
156
+ else
157
+ {
158
+ this.Core.RootElement.AddChild(partition);
159
+ }
160
+ this.Core.IndexElement(row, partition);
161
+ }
162
+ }
163
+
164
+ /// <summary>
165
+ /// Decompile the ComPlusPartitionProperty table.
166
+ /// </summary>
167
+ /// <param name="table">The table to decompile.</param>
168
+ private void DecompileComPlusPartitionPropertyTable(Table table)
169
+ {
170
+ foreach (Row row in table.Rows)
171
+ {
172
+ ComPlus.ComPlusPartition partition = (ComPlus.ComPlusPartition)this.Core.GetIndexedElement("ComPlusPartition", (string)row[0]);
173
+ if (null == partition)
174
+ {
175
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Partition_", (string)row[0], "ComPlusPartition"));
176
+ }
177
+
178
+ switch ((string)row[1])
179
+ {
180
+ case "Changeable":
181
+ switch ((string)row[2])
182
+ {
183
+ case "1":
184
+ partition.Changeable = ComPlus.YesNoType.yes;
185
+ break;
186
+ case "0":
187
+ partition.Changeable = ComPlus.YesNoType.no;
188
+ break;
189
+ default:
190
+ // TODO: Warning
191
+ break;
192
+ }
193
+ break;
194
+ case "Deleteable":
195
+ switch ((string)row[2])
196
+ {
197
+ case "1":
198
+ partition.Deleteable = ComPlus.YesNoType.yes;
199
+ break;
200
+ case "0":
201
+ partition.Deleteable = ComPlus.YesNoType.no;
202
+ break;
203
+ default:
204
+ // TODO: Warning
205
+ break;
206
+ }
207
+ break;
208
+ case "Description":
209
+ partition.Description = (string)row[2];
210
+ break;
211
+ default:
212
+ // TODO: Warning
213
+ break;
214
+ }
215
+ }
216
+ }
217
+
218
+ /// <summary>
219
+ /// Decompile the ComPlusPartitionRole table.
220
+ /// </summary>
221
+ /// <param name="table">The table to decompile.</param>
222
+ private void DecompileComPlusPartitionRoleTable(Table table)
223
+ {
224
+ foreach (Row row in table.Rows)
225
+ {
226
+ ComPlus.ComPlusPartitionRole partitionRole = new ComPlus.ComPlusPartitionRole();
227
+
228
+ partitionRole.Id = (string)row[0];
229
+ partitionRole.Partition = (string)row[1];
230
+ partitionRole.Name = (string)row[3];
231
+
232
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
233
+ if (null != component)
234
+ {
235
+ component.AddChild(partitionRole);
236
+ }
237
+ else
238
+ {
239
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
240
+ }
241
+ }
242
+ }
243
+
244
+ /// <summary>
245
+ /// Decompile the ComPlusUserInPartitionRole table.
246
+ /// </summary>
247
+ /// <param name="table">The table to decompile.</param>
248
+ private void DecompileComPlusUserInPartitionRoleTable(Table table)
249
+ {
250
+ foreach (Row row in table.Rows)
251
+ {
252
+ ComPlus.ComPlusUserInPartitionRole userInPartitionRole = new ComPlus.ComPlusUserInPartitionRole();
253
+
254
+ userInPartitionRole.Id = (string)row[0];
255
+ userInPartitionRole.PartitionRole = (string)row[1];
256
+ userInPartitionRole.User = (string)row[3];
257
+
258
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
259
+ if (null != component)
260
+ {
261
+ component.AddChild(userInPartitionRole);
262
+ }
263
+ else
264
+ {
265
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
266
+ }
267
+ }
268
+ }
269
+
270
+ /// <summary>
271
+ /// Decompile the ComPlusGroupInPartitionRole table.
272
+ /// </summary>
273
+ /// <param name="table">The table to decompile.</param>
274
+ private void DecompileComPlusGroupInPartitionRoleTable(Table table)
275
+ {
276
+ foreach (Row row in table.Rows)
277
+ {
278
+ ComPlus.ComPlusGroupInPartitionRole groupInPartitionRole = new ComPlus.ComPlusGroupInPartitionRole();
279
+
280
+ groupInPartitionRole.Id = (string)row[0];
281
+ groupInPartitionRole.PartitionRole = (string)row[1];
282
+ groupInPartitionRole.Group = (string)row[3];
283
+
284
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
285
+ if (null != component)
286
+ {
287
+ component.AddChild(groupInPartitionRole);
288
+ }
289
+ else
290
+ {
291
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
292
+ }
293
+ }
294
+ }
295
+
296
+ /// <summary>
297
+ /// Decompile the ComPlusPartitionUser table.
298
+ /// </summary>
299
+ /// <param name="table">The table to decompile.</param>
300
+ private void DecompileComPlusPartitionUserTable(Table table)
301
+ {
302
+ foreach (Row row in table.Rows)
303
+ {
304
+ ComPlus.ComPlusPartitionUser partitionUser = new ComPlus.ComPlusPartitionUser();
305
+
306
+ partitionUser.Id = (string)row[0];
307
+ partitionUser.Partition = (string)row[1];
308
+ partitionUser.User = (string)row[3];
309
+
310
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
311
+ if (null != component)
312
+ {
313
+ component.AddChild(partitionUser);
314
+ }
315
+ else
316
+ {
317
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
318
+ }
319
+ }
320
+ }
321
+
322
+ /// <summary>
323
+ /// Decompile the ComPlusApplication table.
324
+ /// </summary>
325
+ /// <param name="table">The table to decompile.</param>
326
+ private void DecompileComPlusApplicationTable(Table table)
327
+ {
328
+ foreach (Row row in table.Rows)
329
+ {
330
+ ComPlus.ComPlusApplication application = new ComPlus.ComPlusApplication();
331
+
332
+ application.Id = (string)row[0];
333
+ application.Partition = (string)row[1];
334
+
335
+ if (null != row[3])
336
+ {
337
+ application.ApplicationId = (string)row[3];
338
+ }
339
+
340
+ if (null != row[4])
341
+ {
342
+ application.Name = (string)row[4];
343
+ }
344
+
345
+ if (null != row[2])
346
+ {
347
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
348
+ if (null != component)
349
+ {
350
+ component.AddChild(application);
351
+ }
352
+ else
353
+ {
354
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
355
+ }
356
+ }
357
+ else
358
+ {
359
+ this.Core.RootElement.AddChild(application);
360
+ }
361
+ this.Core.IndexElement(row, application);
362
+ }
363
+ }
364
+
365
+ /// <summary>
366
+ /// Decompile the ComPlusApplicationProperty table.
367
+ /// </summary>
368
+ /// <param name="table">The table to decompile.</param>
369
+ private void DecompileComPlusApplicationPropertyTable(Table table)
370
+ {
371
+ foreach (Row row in table.Rows)
372
+ {
373
+ ComPlus.ComPlusApplication application = (ComPlus.ComPlusApplication)this.Core.GetIndexedElement("ComPlusApplication", (string)row[0]);
374
+ if (null == application)
375
+ {
376
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Application_", (string)row[0], "ComPlusApplication"));
377
+ }
378
+
379
+ switch ((string)row[1])
380
+ {
381
+ case "3GigSupportEnabled":
382
+ switch ((string)row[2])
383
+ {
384
+ case "1":
385
+ application.ThreeGigSupportEnabled = ComPlus.YesNoType.yes;
386
+ break;
387
+ case "0":
388
+ application.ThreeGigSupportEnabled = ComPlus.YesNoType.no;
389
+ break;
390
+ default:
391
+ // TODO: Warning
392
+ break;
393
+ }
394
+ break;
395
+ case "AccessChecksLevel":
396
+ switch ((string)row[2])
397
+ {
398
+ case "0":
399
+ application.AccessChecksLevel = ComPlus.ComPlusApplication.AccessChecksLevelType.applicationLevel;
400
+ break;
401
+ case "1":
402
+ application.AccessChecksLevel = ComPlus.ComPlusApplication.AccessChecksLevelType.applicationComponentLevel;
403
+ break;
404
+ default:
405
+ // TODO: Warning
406
+ break;
407
+ }
408
+ break;
409
+ case "Activation":
410
+ switch ((string)row[2])
411
+ {
412
+ case "Inproc":
413
+ application.Activation = ComPlus.ComPlusApplication.ActivationType.inproc;
414
+ break;
415
+ case "Local":
416
+ application.Activation = ComPlus.ComPlusApplication.ActivationType.local;
417
+ break;
418
+ default:
419
+ // TODO: Warning
420
+ break;
421
+ }
422
+ break;
423
+ case "ApplicationAccessChecksEnabled":
424
+ switch ((string)row[2])
425
+ {
426
+ case "1":
427
+ application.ApplicationAccessChecksEnabled = ComPlus.YesNoType.yes;
428
+ break;
429
+ case "0":
430
+ application.ApplicationAccessChecksEnabled = ComPlus.YesNoType.no;
431
+ break;
432
+ default:
433
+ // TODO: Warning
434
+ break;
435
+ }
436
+ break;
437
+ case "ApplicationDirectory":
438
+ application.ApplicationDirectory = (string)row[2];
439
+ break;
440
+ case "Authentication":
441
+ switch ((string)row[2])
442
+ {
443
+ case "0":
444
+ application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.@default;
445
+ break;
446
+ case "1":
447
+ application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.none;
448
+ break;
449
+ case "2":
450
+ application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.connect;
451
+ break;
452
+ case "3":
453
+ application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.call;
454
+ break;
455
+ case "4":
456
+ application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.packet;
457
+ break;
458
+ case "5":
459
+ application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.integrity;
460
+ break;
461
+ case "6":
462
+ application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.privacy;
463
+ break;
464
+ default:
465
+ // TODO: Warning
466
+ break;
467
+ }
468
+ break;
469
+ case "AuthenticationCapability":
470
+ switch ((string)row[2])
471
+ {
472
+ case "0":
473
+ application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.none;
474
+ break;
475
+ case "2":
476
+ application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.secureReference;
477
+ break;
478
+ case "32":
479
+ application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.staticCloaking;
480
+ break;
481
+ case "64":
482
+ application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.dynamicCloaking;
483
+ break;
484
+ default:
485
+ // TODO: Warning
486
+ break;
487
+ }
488
+ break;
489
+ case "Changeable":
490
+ switch ((string)row[2])
491
+ {
492
+ case "1":
493
+ application.Changeable = ComPlus.YesNoType.yes;
494
+ break;
495
+ case "0":
496
+ application.Changeable = ComPlus.YesNoType.no;
497
+ break;
498
+ default:
499
+ // TODO: Warning
500
+ break;
501
+ }
502
+ break;
503
+ case "CommandLine":
504
+ application.CommandLine = (string)row[2];
505
+ break;
506
+ case "ConcurrentApps":
507
+ int concurrentApps;
508
+ if (Int32.TryParse((string)row[2], out concurrentApps))
509
+ {
510
+ application.ConcurrentApps = concurrentApps;
511
+ }
512
+ else
513
+ {
514
+ // TODO: Warning
515
+ }
516
+ break;
517
+ case "CreatedBy":
518
+ application.CreatedBy = (string)row[2];
519
+ break;
520
+ case "CRMEnabled":
521
+ switch ((string)row[2])
522
+ {
523
+ case "1":
524
+ application.CRMEnabled = ComPlus.YesNoType.yes;
525
+ break;
526
+ case "0":
527
+ application.CRMEnabled = ComPlus.YesNoType.no;
528
+ break;
529
+ default:
530
+ // TODO: Warning
531
+ break;
532
+ }
533
+ break;
534
+ case "CRMLogFile":
535
+ application.CRMLogFile = (string)row[2];
536
+ break;
537
+ case "Deleteable":
538
+ switch ((string)row[2])
539
+ {
540
+ case "1":
541
+ application.Deleteable = ComPlus.YesNoType.yes;
542
+ break;
543
+ case "0":
544
+ application.Deleteable = ComPlus.YesNoType.no;
545
+ break;
546
+ default:
547
+ // TODO: Warning
548
+ break;
549
+ }
550
+ break;
551
+ case "Description":
552
+ application.Description = (string)row[2];
553
+ break;
554
+ case "DumpEnabled":
555
+ switch ((string)row[2])
556
+ {
557
+ case "1":
558
+ application.DumpEnabled = ComPlus.YesNoType.yes;
559
+ break;
560
+ case "0":
561
+ application.DumpEnabled = ComPlus.YesNoType.no;
562
+ break;
563
+ default:
564
+ // TODO: Warning
565
+ break;
566
+ }
567
+ break;
568
+ case "DumpOnException":
569
+ switch ((string)row[2])
570
+ {
571
+ case "1":
572
+ application.DumpOnException = ComPlus.YesNoType.yes;
573
+ break;
574
+ case "0":
575
+ application.DumpOnException = ComPlus.YesNoType.no;
576
+ break;
577
+ default:
578
+ // TODO: Warning
579
+ break;
580
+ }
581
+ break;
582
+ case "DumpOnFailfast":
583
+ switch ((string)row[2])
584
+ {
585
+ case "1":
586
+ application.DumpOnFailfast = ComPlus.YesNoType.yes;
587
+ break;
588
+ case "0":
589
+ application.DumpOnFailfast = ComPlus.YesNoType.no;
590
+ break;
591
+ default:
592
+ // TODO: Warning
593
+ break;
594
+ }
595
+ break;
596
+ case "DumpPath":
597
+ application.DumpPath = (string)row[2];
598
+ break;
599
+ case "EventsEnabled":
600
+ switch ((string)row[2])
601
+ {
602
+ case "1":
603
+ application.EventsEnabled = ComPlus.YesNoType.yes;
604
+ break;
605
+ case "0":
606
+ application.EventsEnabled = ComPlus.YesNoType.no;
607
+ break;
608
+ default:
609
+ // TODO: Warning
610
+ break;
611
+ }
612
+ break;
613
+ case "Identity":
614
+ application.Identity = (string)row[2];
615
+ break;
616
+ case "ImpersonationLevel":
617
+ switch ((string)row[2])
618
+ {
619
+ case "1":
620
+ application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.anonymous;
621
+ break;
622
+ case "2":
623
+ application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.identify;
624
+ break;
625
+ case "3":
626
+ application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.impersonate;
627
+ break;
628
+ case "4":
629
+ application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.@delegate;
630
+ break;
631
+ default:
632
+ // TODO: Warning
633
+ break;
634
+ }
635
+ break;
636
+ case "IsEnabled":
637
+ switch ((string)row[2])
638
+ {
639
+ case "1":
640
+ application.IsEnabled = ComPlus.YesNoType.yes;
641
+ break;
642
+ case "0":
643
+ application.IsEnabled = ComPlus.YesNoType.no;
644
+ break;
645
+ default:
646
+ // TODO: Warning
647
+ break;
648
+ }
649
+ break;
650
+ case "MaxDumpCount":
651
+ int maxDumpCount;
652
+ if (Int32.TryParse((string)row[2], out maxDumpCount))
653
+ {
654
+ application.MaxDumpCount = maxDumpCount;
655
+ }
656
+ else
657
+ {
658
+ // TODO: Warning
659
+ }
660
+ break;
661
+ case "Password":
662
+ application.Password = (string)row[2];
663
+ break;
664
+ case "QCAuthenticateMsgs":
665
+ switch ((string)row[2])
666
+ {
667
+ case "0":
668
+ application.QCAuthenticateMsgs = ComPlus.ComPlusApplication.QCAuthenticateMsgsType.secureApps;
669
+ break;
670
+ case "1":
671
+ application.QCAuthenticateMsgs = ComPlus.ComPlusApplication.QCAuthenticateMsgsType.off;
672
+ break;
673
+ case "2":
674
+ application.QCAuthenticateMsgs = ComPlus.ComPlusApplication.QCAuthenticateMsgsType.on;
675
+ break;
676
+ default:
677
+ // TODO: Warning
678
+ break;
679
+ }
680
+ break;
681
+ case "QCListenerMaxThreads":
682
+ int qcListenerMaxThreads;
683
+ if (Int32.TryParse((string)row[2], out qcListenerMaxThreads))
684
+ {
685
+ application.QCListenerMaxThreads = qcListenerMaxThreads;
686
+ }
687
+ else
688
+ {
689
+ // TODO: Warning
690
+ }
691
+ break;
692
+ case "QueueListenerEnabled":
693
+ switch ((string)row[2])
694
+ {
695
+ case "1":
696
+ application.QueueListenerEnabled = ComPlus.YesNoType.yes;
697
+ break;
698
+ case "0":
699
+ application.QueueListenerEnabled = ComPlus.YesNoType.no;
700
+ break;
701
+ default:
702
+ // TODO: Warning
703
+ break;
704
+ }
705
+ break;
706
+ case "QueuingEnabled":
707
+ switch ((string)row[2])
708
+ {
709
+ case "1":
710
+ application.QueuingEnabled = ComPlus.YesNoType.yes;
711
+ break;
712
+ case "0":
713
+ application.QueuingEnabled = ComPlus.YesNoType.no;
714
+ break;
715
+ default:
716
+ // TODO: Warning
717
+ break;
718
+ }
719
+ break;
720
+ case "RecycleActivationLimit":
721
+ int recycleActivationLimit;
722
+ if (Int32.TryParse((string)row[2], out recycleActivationLimit))
723
+ {
724
+ application.RecycleActivationLimit = recycleActivationLimit;
725
+ }
726
+ else
727
+ {
728
+ // TODO: Warning
729
+ }
730
+ break;
731
+ case "RecycleCallLimit":
732
+ int recycleCallLimit;
733
+ if (Int32.TryParse((string)row[2], out recycleCallLimit))
734
+ {
735
+ application.RecycleCallLimit = recycleCallLimit;
736
+ }
737
+ else
738
+ {
739
+ // TODO: Warning
740
+ }
741
+ break;
742
+ case "RecycleExpirationTimeout":
743
+ int recycleExpirationTimeout;
744
+ if (Int32.TryParse((string)row[2], out recycleExpirationTimeout))
745
+ {
746
+ application.RecycleExpirationTimeout = recycleExpirationTimeout;
747
+ }
748
+ else
749
+ {
750
+ // TODO: Warning
751
+ }
752
+ break;
753
+ case "RecycleLifetimeLimit":
754
+ int recycleLifetimeLimit;
755
+ if (Int32.TryParse((string)row[2], out recycleLifetimeLimit))
756
+ {
757
+ application.RecycleLifetimeLimit = recycleLifetimeLimit;
758
+ }
759
+ else
760
+ {
761
+ // TODO: Warning
762
+ }
763
+ break;
764
+ case "RecycleMemoryLimit":
765
+ int recycleMemoryLimit;
766
+ if (Int32.TryParse((string)row[2], out recycleMemoryLimit))
767
+ {
768
+ application.RecycleMemoryLimit = recycleMemoryLimit;
769
+ }
770
+ else
771
+ {
772
+ // TODO: Warning
773
+ }
774
+ break;
775
+ case "Replicable":
776
+ switch ((string)row[2])
777
+ {
778
+ case "1":
779
+ application.Replicable = ComPlus.YesNoType.yes;
780
+ break;
781
+ case "0":
782
+ application.Replicable = ComPlus.YesNoType.no;
783
+ break;
784
+ default:
785
+ // TODO: Warning
786
+ break;
787
+ }
788
+ break;
789
+ case "RunForever":
790
+ switch ((string)row[2])
791
+ {
792
+ case "1":
793
+ application.RunForever = ComPlus.YesNoType.yes;
794
+ break;
795
+ case "0":
796
+ application.RunForever = ComPlus.YesNoType.no;
797
+ break;
798
+ default:
799
+ // TODO: Warning
800
+ break;
801
+ }
802
+ break;
803
+ case "ShutdownAfter":
804
+ int shutdownAfter;
805
+ if (Int32.TryParse((string)row[2], out shutdownAfter))
806
+ {
807
+ application.ShutdownAfter = shutdownAfter;
808
+ }
809
+ else
810
+ {
811
+ // TODO: Warning
812
+ }
813
+ break;
814
+ case "SoapActivated":
815
+ switch ((string)row[2])
816
+ {
817
+ case "1":
818
+ application.SoapActivated = ComPlus.YesNoType.yes;
819
+ break;
820
+ case "0":
821
+ application.SoapActivated = ComPlus.YesNoType.no;
822
+ break;
823
+ default:
824
+ // TODO: Warning
825
+ break;
826
+ }
827
+ break;
828
+ case "SoapBaseUrl":
829
+ application.SoapBaseUrl = (string)row[2];
830
+ break;
831
+ case "SoapMailTo":
832
+ application.SoapMailTo = (string)row[2];
833
+ break;
834
+ case "SoapVRoot":
835
+ application.SoapVRoot = (string)row[2];
836
+ break;
837
+ case "SRPEnabled":
838
+ switch ((string)row[2])
839
+ {
840
+ case "1":
841
+ application.SRPEnabled = ComPlus.YesNoType.yes;
842
+ break;
843
+ case "0":
844
+ application.SRPEnabled = ComPlus.YesNoType.no;
845
+ break;
846
+ default:
847
+ // TODO: Warning
848
+ break;
849
+ }
850
+ break;
851
+ case "SRPTrustLevel":
852
+ switch ((string)row[2])
853
+ {
854
+ case "0":
855
+ application.SRPTrustLevel = ComPlus.ComPlusApplication.SRPTrustLevelType.disallowed;
856
+ break;
857
+ case "262144":
858
+ application.SRPTrustLevel = ComPlus.ComPlusApplication.SRPTrustLevelType.fullyTrusted;
859
+ break;
860
+ default:
861
+ // TODO: Warning
862
+ break;
863
+ }
864
+ break;
865
+ default:
866
+ // TODO: Warning
867
+ break;
868
+ }
869
+ }
870
+ }
871
+
872
+ /// <summary>
873
+ /// Decompile the ComPlusApplicationRole table.
874
+ /// </summary>
875
+ /// <param name="table">The table to decompile.</param>
876
+ private void DecompileComPlusApplicationRoleTable(Table table)
877
+ {
878
+ foreach (Row row in table.Rows)
879
+ {
880
+ ComPlus.ComPlusApplicationRole applicationRole = new ComPlus.ComPlusApplicationRole();
881
+
882
+ applicationRole.Id = (string)row[0];
883
+ applicationRole.Application = (string)row[1];
884
+
885
+ if (null != row[3])
886
+ {
887
+ applicationRole.Name = (string)row[3];
888
+ }
889
+
890
+ if (null != row[2])
891
+ {
892
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
893
+ if (null != component)
894
+ {
895
+ component.AddChild(applicationRole);
896
+ }
897
+ else
898
+ {
899
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
900
+ }
901
+ }
902
+ else
903
+ {
904
+ this.Core.RootElement.AddChild(applicationRole);
905
+ }
906
+ this.Core.IndexElement(row, applicationRole);
907
+ }
908
+ }
909
+
910
+ /// <summary>
911
+ /// Decompile the ComPlusApplicationRoleProperty table.
912
+ /// </summary>
913
+ /// <param name="table">The table to decompile.</param>
914
+ private void DecompileComPlusApplicationRolePropertyTable(Table table)
915
+ {
916
+ foreach (Row row in table.Rows)
917
+ {
918
+ ComPlus.ComPlusApplicationRole applicationRole = (ComPlus.ComPlusApplicationRole)this.Core.GetIndexedElement("ComPlusApplicationRole", (string)row[0]);
919
+ if (null == applicationRole)
920
+ {
921
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ApplicationRole_", (string)row[0], "ComPlusApplicationRole"));
922
+ }
923
+
924
+ switch ((string)row[1])
925
+ {
926
+ case "Description":
927
+ applicationRole.Description = (string)row[2];
928
+ break;
929
+ default:
930
+ // TODO: Warning
931
+ break;
932
+ }
933
+ }
934
+ }
935
+
936
+ /// <summary>
937
+ /// Decompile the ComPlusUserInApplicationRole table.
938
+ /// </summary>
939
+ /// <param name="table">The table to decompile.</param>
940
+ private void DecompileComPlusUserInApplicationRoleTable(Table table)
941
+ {
942
+ foreach (Row row in table.Rows)
943
+ {
944
+ ComPlus.ComPlusUserInApplicationRole userInApplicationRole = new ComPlus.ComPlusUserInApplicationRole();
945
+
946
+ userInApplicationRole.Id = (string)row[0];
947
+ userInApplicationRole.ApplicationRole = (string)row[1];
948
+ userInApplicationRole.User = (string)row[3];
949
+
950
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
951
+ if (null != component)
952
+ {
953
+ component.AddChild(userInApplicationRole);
954
+ }
955
+ else
956
+ {
957
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
958
+ }
959
+ }
960
+ }
961
+
962
+ /// <summary>
963
+ /// Decompile the ComPlusGroupInApplicationRole table.
964
+ /// </summary>
965
+ /// <param name="table">The table to decompile.</param>
966
+ private void DecompileComPlusGroupInApplicationRoleTable(Table table)
967
+ {
968
+ foreach (Row row in table.Rows)
969
+ {
970
+ ComPlus.ComPlusGroupInApplicationRole groupInApplicationRole = new ComPlus.ComPlusGroupInApplicationRole();
971
+
972
+ groupInApplicationRole.Id = (string)row[0];
973
+ groupInApplicationRole.ApplicationRole = (string)row[1];
974
+ groupInApplicationRole.Group = (string)row[3];
975
+
976
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
977
+ if (null != component)
978
+ {
979
+ component.AddChild(groupInApplicationRole);
980
+ }
981
+ else
982
+ {
983
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
984
+ }
985
+ }
986
+ }
987
+
988
+ /// <summary>
989
+ /// Decompile the ComPlusAssembly table.
990
+ /// </summary>
991
+ /// <param name="table">The table to decompile.</param>
992
+ private void DecompileComPlusAssemblyTable(Table table)
993
+ {
994
+ foreach (Row row in table.Rows)
995
+ {
996
+ ComPlus.ComPlusAssembly assembly = new ComPlus.ComPlusAssembly();
997
+
998
+ assembly.Id = (string)row[0];
999
+ assembly.Application = (string)row[1];
1000
+
1001
+ if (null != row[3])
1002
+ {
1003
+ assembly.AssemblyName = (string)row[3];
1004
+ }
1005
+
1006
+ if (null != row[4])
1007
+ {
1008
+ assembly.DllPath = (string)row[4];
1009
+ }
1010
+
1011
+ if (null != row[5])
1012
+ {
1013
+ assembly.TlbPath = (string)row[5];
1014
+ }
1015
+
1016
+ if (null != row[6])
1017
+ {
1018
+ assembly.PSDllPath = (string)row[6];
1019
+ }
1020
+
1021
+ int attributes = (int)row[7];
1022
+
1023
+ if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.EventClass))
1024
+ {
1025
+ assembly.EventClass = ComPlus.YesNoType.yes;
1026
+ }
1027
+
1028
+ if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.DotNetAssembly))
1029
+ {
1030
+ assembly.Type = ComPlus.ComPlusAssembly.TypeType.net;
1031
+ }
1032
+
1033
+ if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.DllPathFromGAC))
1034
+ {
1035
+ assembly.DllPathFromGAC = ComPlus.YesNoType.yes;
1036
+ }
1037
+
1038
+ if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.RegisterInCommit))
1039
+ {
1040
+ assembly.RegisterInCommit = ComPlus.YesNoType.yes;
1041
+ }
1042
+
1043
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
1044
+ if (null != component)
1045
+ {
1046
+ component.AddChild(assembly);
1047
+ }
1048
+ else
1049
+ {
1050
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
1051
+ }
1052
+ this.Core.IndexElement(row, assembly);
1053
+ }
1054
+ }
1055
+
1056
+ /// <summary>
1057
+ /// Decompile the ComPlusAssemblyDependency table.
1058
+ /// </summary>
1059
+ /// <param name="table">The table to decompile.</param>
1060
+ private void DecompileComPlusAssemblyDependencyTable(Table table)
1061
+ {
1062
+ foreach (Row row in table.Rows)
1063
+ {
1064
+ ComPlus.ComPlusAssemblyDependency assemblyDependency = new ComPlus.ComPlusAssemblyDependency();
1065
+
1066
+ assemblyDependency.RequiredAssembly = (string)row[1];
1067
+
1068
+ ComPlus.ComPlusAssembly assembly = (ComPlus.ComPlusAssembly)this.Core.GetIndexedElement("ComPlusAssembly", (string)row[0]);
1069
+ if (null != assembly)
1070
+ {
1071
+ assembly.AddChild(assemblyDependency);
1072
+ }
1073
+ else
1074
+ {
1075
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Assembly_", (string)row[0], "ComPlusAssembly"));
1076
+ }
1077
+ }
1078
+ }
1079
+
1080
+ /// <summary>
1081
+ /// Decompile the ComPlusComponent table.
1082
+ /// </summary>
1083
+ /// <param name="table">The table to decompile.</param>
1084
+ private void DecompileComPlusComponentTable(Table table)
1085
+ {
1086
+ foreach (Row row in table.Rows)
1087
+ {
1088
+ ComPlus.ComPlusComponent comPlusComponent = new ComPlus.ComPlusComponent();
1089
+
1090
+ comPlusComponent.Id = (string)row[0];
1091
+
1092
+ try
1093
+ {
1094
+ Guid clsid = new Guid((string)row[2]);
1095
+ comPlusComponent.CLSID = clsid.ToString().ToUpper();
1096
+ }
1097
+ catch
1098
+ {
1099
+ // TODO: Warning
1100
+ }
1101
+
1102
+ ComPlus.ComPlusAssembly assembly = (ComPlus.ComPlusAssembly)this.Core.GetIndexedElement("ComPlusAssembly", (string)row[1]);
1103
+ if (null != assembly)
1104
+ {
1105
+ assembly.AddChild(comPlusComponent);
1106
+ }
1107
+ else
1108
+ {
1109
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Assembly_", (string)row[1], "ComPlusAssembly"));
1110
+ }
1111
+ this.Core.IndexElement(row, comPlusComponent);
1112
+ }
1113
+ }
1114
+
1115
+ /// <summary>
1116
+ /// Decompile the ComPlusComponentProperty table.
1117
+ /// </summary>
1118
+ /// <param name="table">The table to decompile.</param>
1119
+ private void DecompileComPlusComponentPropertyTable(Table table)
1120
+ {
1121
+ foreach (Row row in table.Rows)
1122
+ {
1123
+ ComPlus.ComPlusComponent comPlusComponent = (ComPlus.ComPlusComponent)this.Core.GetIndexedElement("ComPlusComponent", (string)row[0]);
1124
+ if (null == comPlusComponent)
1125
+ {
1126
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ComPlusComponent_", (string)row[0], "ComPlusComponent"));
1127
+ }
1128
+
1129
+ switch ((string)row[1])
1130
+ {
1131
+ case "AllowInprocSubscribers":
1132
+ switch ((string)row[2])
1133
+ {
1134
+ case "1":
1135
+ comPlusComponent.AllowInprocSubscribers = ComPlus.YesNoType.yes;
1136
+ break;
1137
+ case "0":
1138
+ comPlusComponent.AllowInprocSubscribers = ComPlus.YesNoType.no;
1139
+ break;
1140
+ default:
1141
+ // TODO: Warning
1142
+ break;
1143
+ }
1144
+ break;
1145
+ case "ComponentAccessChecksEnabled":
1146
+ switch ((string)row[2])
1147
+ {
1148
+ case "1":
1149
+ comPlusComponent.ComponentAccessChecksEnabled = ComPlus.YesNoType.yes;
1150
+ break;
1151
+ case "0":
1152
+ comPlusComponent.ComponentAccessChecksEnabled = ComPlus.YesNoType.no;
1153
+ break;
1154
+ default:
1155
+ // TODO: Warning
1156
+ break;
1157
+ }
1158
+ break;
1159
+ case "ComponentTransactionTimeout":
1160
+ int componentTransactionTimeout;
1161
+ if (Int32.TryParse((string)row[2], out componentTransactionTimeout))
1162
+ {
1163
+ comPlusComponent.ComponentTransactionTimeout = componentTransactionTimeout;
1164
+ }
1165
+ else
1166
+ {
1167
+ // TODO: Warning
1168
+ }
1169
+ break;
1170
+ case "ComponentTransactionTimeoutEnabled":
1171
+ switch ((string)row[2])
1172
+ {
1173
+ case "1":
1174
+ comPlusComponent.ComponentTransactionTimeoutEnabled = ComPlus.YesNoType.yes;
1175
+ break;
1176
+ case "0":
1177
+ comPlusComponent.ComponentTransactionTimeoutEnabled = ComPlus.YesNoType.no;
1178
+ break;
1179
+ default:
1180
+ // TODO: Warning
1181
+ break;
1182
+ }
1183
+ break;
1184
+ case "COMTIIntrinsics":
1185
+ switch ((string)row[2])
1186
+ {
1187
+ case "1":
1188
+ comPlusComponent.COMTIIntrinsics = ComPlus.YesNoType.yes;
1189
+ break;
1190
+ case "0":
1191
+ comPlusComponent.COMTIIntrinsics = ComPlus.YesNoType.no;
1192
+ break;
1193
+ default:
1194
+ // TODO: Warning
1195
+ break;
1196
+ }
1197
+ break;
1198
+ case "ConstructionEnabled":
1199
+ switch ((string)row[2])
1200
+ {
1201
+ case "1":
1202
+ comPlusComponent.ConstructionEnabled = ComPlus.YesNoType.yes;
1203
+ break;
1204
+ case "0":
1205
+ comPlusComponent.ConstructionEnabled = ComPlus.YesNoType.no;
1206
+ break;
1207
+ default:
1208
+ // TODO: Warning
1209
+ break;
1210
+ }
1211
+ break;
1212
+ case "ConstructorString":
1213
+ comPlusComponent.ConstructorString = (string)row[2];
1214
+ break;
1215
+ case "CreationTimeout":
1216
+ int creationTimeout;
1217
+ if (Int32.TryParse((string)row[2], out creationTimeout))
1218
+ {
1219
+ comPlusComponent.CreationTimeout = creationTimeout;
1220
+ }
1221
+ else
1222
+ {
1223
+ // TODO: Warning
1224
+ }
1225
+ break;
1226
+ case "Description":
1227
+ comPlusComponent.Description = (string)row[2];
1228
+ break;
1229
+ case "EventTrackingEnabled":
1230
+ switch ((string)row[2])
1231
+ {
1232
+ case "1":
1233
+ comPlusComponent.EventTrackingEnabled = ComPlus.YesNoType.yes;
1234
+ break;
1235
+ case "0":
1236
+ comPlusComponent.EventTrackingEnabled = ComPlus.YesNoType.no;
1237
+ break;
1238
+ default:
1239
+ // TODO: Warning
1240
+ break;
1241
+ }
1242
+ break;
1243
+ case "ExceptionClass":
1244
+ comPlusComponent.ExceptionClass = (string)row[2];
1245
+ break;
1246
+ case "FireInParallel":
1247
+ switch ((string)row[2])
1248
+ {
1249
+ case "1":
1250
+ comPlusComponent.FireInParallel = ComPlus.YesNoType.yes;
1251
+ break;
1252
+ case "0":
1253
+ comPlusComponent.FireInParallel = ComPlus.YesNoType.no;
1254
+ break;
1255
+ default:
1256
+ // TODO: Warning
1257
+ break;
1258
+ }
1259
+ break;
1260
+ case "IISIntrinsics":
1261
+ switch ((string)row[2])
1262
+ {
1263
+ case "1":
1264
+ comPlusComponent.IISIntrinsics = ComPlus.YesNoType.yes;
1265
+ break;
1266
+ case "0":
1267
+ comPlusComponent.IISIntrinsics = ComPlus.YesNoType.no;
1268
+ break;
1269
+ default:
1270
+ // TODO: Warning
1271
+ break;
1272
+ }
1273
+ break;
1274
+ case "InitializesServerApplication":
1275
+ switch ((string)row[2])
1276
+ {
1277
+ case "1":
1278
+ comPlusComponent.InitializesServerApplication = ComPlus.YesNoType.yes;
1279
+ break;
1280
+ case "0":
1281
+ comPlusComponent.InitializesServerApplication = ComPlus.YesNoType.no;
1282
+ break;
1283
+ default:
1284
+ // TODO: Warning
1285
+ break;
1286
+ }
1287
+ break;
1288
+ case "IsEnabled":
1289
+ switch ((string)row[2])
1290
+ {
1291
+ case "1":
1292
+ comPlusComponent.IsEnabled = ComPlus.YesNoType.yes;
1293
+ break;
1294
+ case "0":
1295
+ comPlusComponent.IsEnabled = ComPlus.YesNoType.no;
1296
+ break;
1297
+ default:
1298
+ // TODO: Warning
1299
+ break;
1300
+ }
1301
+ break;
1302
+ case "IsPrivateComponent":
1303
+ switch ((string)row[2])
1304
+ {
1305
+ case "1":
1306
+ comPlusComponent.IsPrivateComponent = ComPlus.YesNoType.yes;
1307
+ break;
1308
+ case "0":
1309
+ comPlusComponent.IsPrivateComponent = ComPlus.YesNoType.no;
1310
+ break;
1311
+ default:
1312
+ // TODO: Warning
1313
+ break;
1314
+ }
1315
+ break;
1316
+ case "JustInTimeActivation":
1317
+ switch ((string)row[2])
1318
+ {
1319
+ case "1":
1320
+ comPlusComponent.JustInTimeActivation = ComPlus.YesNoType.yes;
1321
+ break;
1322
+ case "0":
1323
+ comPlusComponent.JustInTimeActivation = ComPlus.YesNoType.no;
1324
+ break;
1325
+ default:
1326
+ // TODO: Warning
1327
+ break;
1328
+ }
1329
+ break;
1330
+ case "LoadBalancingSupported":
1331
+ switch ((string)row[2])
1332
+ {
1333
+ case "1":
1334
+ comPlusComponent.LoadBalancingSupported = ComPlus.YesNoType.yes;
1335
+ break;
1336
+ case "0":
1337
+ comPlusComponent.LoadBalancingSupported = ComPlus.YesNoType.no;
1338
+ break;
1339
+ default:
1340
+ // TODO: Warning
1341
+ break;
1342
+ }
1343
+ break;
1344
+ case "MaxPoolSize":
1345
+ int maxPoolSize;
1346
+ if (Int32.TryParse((string)row[2], out maxPoolSize))
1347
+ {
1348
+ comPlusComponent.MaxPoolSize = maxPoolSize;
1349
+ }
1350
+ else
1351
+ {
1352
+ // TODO: Warning
1353
+ }
1354
+ break;
1355
+ case "MinPoolSize":
1356
+ int minPoolSize;
1357
+ if (Int32.TryParse((string)row[2], out minPoolSize))
1358
+ {
1359
+ comPlusComponent.MinPoolSize = minPoolSize;
1360
+ }
1361
+ else
1362
+ {
1363
+ // TODO: Warning
1364
+ }
1365
+ break;
1366
+ case "MultiInterfacePublisherFilterCLSID":
1367
+ comPlusComponent.MultiInterfacePublisherFilterCLSID = (string)row[2];
1368
+ break;
1369
+ case "MustRunInClientContext":
1370
+ switch ((string)row[2])
1371
+ {
1372
+ case "1":
1373
+ comPlusComponent.MustRunInClientContext = ComPlus.YesNoType.yes;
1374
+ break;
1375
+ case "0":
1376
+ comPlusComponent.MustRunInClientContext = ComPlus.YesNoType.no;
1377
+ break;
1378
+ default:
1379
+ // TODO: Warning
1380
+ break;
1381
+ }
1382
+ break;
1383
+ case "MustRunInDefaultContext":
1384
+ switch ((string)row[2])
1385
+ {
1386
+ case "1":
1387
+ comPlusComponent.MustRunInDefaultContext = ComPlus.YesNoType.yes;
1388
+ break;
1389
+ case "0":
1390
+ comPlusComponent.MustRunInDefaultContext = ComPlus.YesNoType.no;
1391
+ break;
1392
+ default:
1393
+ // TODO: Warning
1394
+ break;
1395
+ }
1396
+ break;
1397
+ case "ObjectPoolingEnabled":
1398
+ switch ((string)row[2])
1399
+ {
1400
+ case "1":
1401
+ comPlusComponent.ObjectPoolingEnabled = ComPlus.YesNoType.yes;
1402
+ break;
1403
+ case "0":
1404
+ comPlusComponent.ObjectPoolingEnabled = ComPlus.YesNoType.no;
1405
+ break;
1406
+ default:
1407
+ // TODO: Warning
1408
+ break;
1409
+ }
1410
+ break;
1411
+ case "PublisherID":
1412
+ comPlusComponent.PublisherID = (string)row[2];
1413
+ break;
1414
+ case "SoapAssemblyName":
1415
+ comPlusComponent.SoapAssemblyName = (string)row[2];
1416
+ break;
1417
+ case "SoapTypeName":
1418
+ comPlusComponent.SoapTypeName = (string)row[2];
1419
+ break;
1420
+ case "Synchronization":
1421
+ switch ((string)row[2])
1422
+ {
1423
+ case "0":
1424
+ comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.ignored;
1425
+ break;
1426
+ case "1":
1427
+ comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.none;
1428
+ break;
1429
+ case "2":
1430
+ comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.supported;
1431
+ break;
1432
+ case "3":
1433
+ comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.required;
1434
+ break;
1435
+ case "4":
1436
+ comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.requiresNew;
1437
+ break;
1438
+ default:
1439
+ // TODO: Warning
1440
+ break;
1441
+ }
1442
+ break;
1443
+ case "Transaction":
1444
+ switch ((string)row[2])
1445
+ {
1446
+ case "0":
1447
+ comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.ignored;
1448
+ break;
1449
+ case "1":
1450
+ comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.none;
1451
+ break;
1452
+ case "2":
1453
+ comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.supported;
1454
+ break;
1455
+ case "3":
1456
+ comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.required;
1457
+ break;
1458
+ case "4":
1459
+ comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.requiresNew;
1460
+ break;
1461
+ default:
1462
+ // TODO: Warning
1463
+ break;
1464
+ }
1465
+ break;
1466
+ case "TxIsolationLevel":
1467
+ switch ((string)row[2])
1468
+ {
1469
+ case "0":
1470
+ comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.any;
1471
+ break;
1472
+ case "1":
1473
+ comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.readUnCommitted;
1474
+ break;
1475
+ case "2":
1476
+ comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.readCommitted;
1477
+ break;
1478
+ case "3":
1479
+ comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.repeatableRead;
1480
+ break;
1481
+ case "4":
1482
+ comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.serializable;
1483
+ break;
1484
+ default:
1485
+ // TODO: Warning
1486
+ break;
1487
+ }
1488
+ break;
1489
+ default:
1490
+ // TODO: Warning
1491
+ break;
1492
+ }
1493
+ }
1494
+ }
1495
+
1496
+ /// <summary>
1497
+ /// Decompile the ComPlusRoleForComponent table.
1498
+ /// </summary>
1499
+ /// <param name="table">The table to decompile.</param>
1500
+ private void DecompileComPlusRoleForComponentTable(Table table)
1501
+ {
1502
+ foreach (Row row in table.Rows)
1503
+ {
1504
+ ComPlus.ComPlusRoleForComponent roleForComponent = new ComPlus.ComPlusRoleForComponent();
1505
+
1506
+ roleForComponent.Id = (string)row[0];
1507
+ roleForComponent.Component = (string)row[1];
1508
+ roleForComponent.ApplicationRole = (string)row[2];
1509
+
1510
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[3]);
1511
+ if (null != component)
1512
+ {
1513
+ component.AddChild(roleForComponent);
1514
+ }
1515
+ else
1516
+ {
1517
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[3], "Component"));
1518
+ }
1519
+ }
1520
+ }
1521
+
1522
+ /// <summary>
1523
+ /// Decompile the ComPlusInterface table.
1524
+ /// </summary>
1525
+ /// <param name="table">The table to decompile.</param>
1526
+ private void DecompileComPlusInterfaceTable(Table table)
1527
+ {
1528
+ foreach (Row row in table.Rows)
1529
+ {
1530
+ ComPlus.ComPlusInterface comPlusInterface = new ComPlus.ComPlusInterface();
1531
+
1532
+ comPlusInterface.Id = (string)row[0];
1533
+
1534
+ try
1535
+ {
1536
+ Guid iid = new Guid((string)row[2]);
1537
+ comPlusInterface.IID = iid.ToString().ToUpper();
1538
+ }
1539
+ catch
1540
+ {
1541
+ // TODO: Warning
1542
+ }
1543
+
1544
+ ComPlus.ComPlusComponent comPlusComponent = (ComPlus.ComPlusComponent)this.Core.GetIndexedElement("ComPlusComponent", (string)row[1]);
1545
+ if (null != comPlusComponent)
1546
+ {
1547
+ comPlusComponent.AddChild(comPlusInterface);
1548
+ }
1549
+ else
1550
+ {
1551
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ComPlusComponent_", (string)row[1], "ComPlusComponent"));
1552
+ }
1553
+ this.Core.IndexElement(row, comPlusInterface);
1554
+ }
1555
+ }
1556
+
1557
+ /// <summary>
1558
+ /// Decompile the ComPlusInterfaceProperty table.
1559
+ /// </summary>
1560
+ /// <param name="table">The table to decompile.</param>
1561
+ private void DecompileComPlusInterfacePropertyTable(Table table)
1562
+ {
1563
+ foreach (Row row in table.Rows)
1564
+ {
1565
+ ComPlus.ComPlusInterface comPlusInterface = (ComPlus.ComPlusInterface)this.Core.GetIndexedElement("ComPlusInterface", (string)row[0]);
1566
+ if (null == comPlusInterface)
1567
+ {
1568
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Interface_", (string)row[0], "ComPlusInterface"));
1569
+ }
1570
+
1571
+ switch ((string)row[1])
1572
+ {
1573
+ case "Description":
1574
+ comPlusInterface.Description = (string)row[2];
1575
+ break;
1576
+ case "QueuingEnabled":
1577
+ switch ((string)row[2])
1578
+ {
1579
+ case "1":
1580
+ comPlusInterface.QueuingEnabled = ComPlus.YesNoType.yes;
1581
+ break;
1582
+ case "0":
1583
+ comPlusInterface.QueuingEnabled = ComPlus.YesNoType.no;
1584
+ break;
1585
+ default:
1586
+ // TODO: Warning
1587
+ break;
1588
+ }
1589
+ break;
1590
+ default:
1591
+ // TODO: Warning
1592
+ break;
1593
+ }
1594
+ }
1595
+ }
1596
+
1597
+ /// <summary>
1598
+ /// Decompile the ComPlusRoleForInterface table.
1599
+ /// </summary>
1600
+ /// <param name="table">The table to decompile.</param>
1601
+ private void DecompileComPlusRoleForInterfaceTable(Table table)
1602
+ {
1603
+ foreach (Row row in table.Rows)
1604
+ {
1605
+ ComPlus.ComPlusRoleForInterface roleForInterface = new ComPlus.ComPlusRoleForInterface();
1606
+
1607
+ roleForInterface.Id = (string)row[0];
1608
+ roleForInterface.Interface = (string)row[1];
1609
+ roleForInterface.ApplicationRole = (string)row[2];
1610
+
1611
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[3]);
1612
+ if (null != component)
1613
+ {
1614
+ component.AddChild(roleForInterface);
1615
+ }
1616
+ else
1617
+ {
1618
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[3], "Component"));
1619
+ }
1620
+ }
1621
+ }
1622
+
1623
+ /// <summary>
1624
+ /// Decompile the ComPlusMethod table.
1625
+ /// </summary>
1626
+ /// <param name="table">The table to decompile.</param>
1627
+ private void DecompileComPlusMethodTable(Table table)
1628
+ {
1629
+ foreach (Row row in table.Rows)
1630
+ {
1631
+ ComPlus.ComPlusMethod comPlusMethod = new ComPlus.ComPlusMethod();
1632
+
1633
+ comPlusMethod.Id = (string)row[0];
1634
+
1635
+ if (null != row[2])
1636
+ {
1637
+ comPlusMethod.Index = (int)row[2];
1638
+ }
1639
+
1640
+ if (null != row[3])
1641
+ {
1642
+ comPlusMethod.Name = (string)row[3];
1643
+ }
1644
+
1645
+ ComPlus.ComPlusInterface comPlusInterface = (ComPlus.ComPlusInterface)this.Core.GetIndexedElement("ComPlusInterface", (string)row[1]);
1646
+ if (null != comPlusInterface)
1647
+ {
1648
+ comPlusInterface.AddChild(comPlusMethod);
1649
+ }
1650
+ else
1651
+ {
1652
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Interface_", (string)row[1], "ComPlusInterface"));
1653
+ }
1654
+ this.Core.IndexElement(row, comPlusMethod);
1655
+ }
1656
+ }
1657
+
1658
+ /// <summary>
1659
+ /// Decompile the ComPlusMethodProperty table.
1660
+ /// </summary>
1661
+ /// <param name="table">The table to decompile.</param>
1662
+ private void DecompileComPlusMethodPropertyTable(Table table)
1663
+ {
1664
+ foreach (Row row in table.Rows)
1665
+ {
1666
+ ComPlus.ComPlusMethod comPlusMethod = (ComPlus.ComPlusMethod)this.Core.GetIndexedElement("ComPlusMethod", (string)row[0]);
1667
+ if (null == comPlusMethod)
1668
+ {
1669
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Method_", (string)row[0], "ComPlusMethod"));
1670
+ }
1671
+
1672
+ switch ((string)row[1])
1673
+ {
1674
+ case "AutoComplete":
1675
+ switch ((string)row[2])
1676
+ {
1677
+ case "1":
1678
+ comPlusMethod.AutoComplete = ComPlus.YesNoType.yes;
1679
+ break;
1680
+ case "0":
1681
+ comPlusMethod.AutoComplete = ComPlus.YesNoType.no;
1682
+ break;
1683
+ default:
1684
+ // TODO: Warning
1685
+ break;
1686
+ }
1687
+ break;
1688
+ case "Description":
1689
+ comPlusMethod.Description = (string)row[2];
1690
+ break;
1691
+ default:
1692
+ // TODO: Warning
1693
+ break;
1694
+ }
1695
+ }
1696
+ }
1697
+
1698
+ /// <summary>
1699
+ /// Decompile the ComPlusRoleForMethod table.
1700
+ /// </summary>
1701
+ /// <param name="table">The table to decompile.</param>
1702
+ private void DecompileComPlusRoleForMethodTable(Table table)
1703
+ {
1704
+ foreach (Row row in table.Rows)
1705
+ {
1706
+ ComPlus.ComPlusRoleForMethod roleForMethod = new ComPlus.ComPlusRoleForMethod();
1707
+
1708
+ roleForMethod.Id = (string)row[0];
1709
+ roleForMethod.Method = (string)row[1];
1710
+ roleForMethod.ApplicationRole = (string)row[2];
1711
+
1712
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[3]);
1713
+ if (null != component)
1714
+ {
1715
+ component.AddChild(roleForMethod);
1716
+ }
1717
+ else
1718
+ {
1719
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[3], "Component"));
1720
+ }
1721
+ }
1722
+ }
1723
+
1724
+ /// <summary>
1725
+ /// Decompile the ComPlusSubscription table.
1726
+ /// </summary>
1727
+ /// <param name="table">The table to decompile.</param>
1728
+ private void DecompileComPlusSubscriptionTable(Table table)
1729
+ {
1730
+ foreach (Row row in table.Rows)
1731
+ {
1732
+ ComPlus.ComPlusSubscription subscription = new ComPlus.ComPlusSubscription();
1733
+
1734
+ subscription.Id = (string)row[0];
1735
+ subscription.Component = (string)row[1];
1736
+ subscription.SubscriptionId = (string)row[3];
1737
+ subscription.Name = (string)row[4];
1738
+ subscription.EventCLSID = (string)row[5];
1739
+ subscription.PublisherID = (string)row[6];
1740
+
1741
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
1742
+ if (null != component)
1743
+ {
1744
+ component.AddChild(subscription);
1745
+ }
1746
+ else
1747
+ {
1748
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
1749
+ }
1750
+ this.Core.IndexElement(row, subscription);
1751
+ }
1752
+ }
1753
+
1754
+ /// <summary>
1755
+ /// Decompile the ComPlusSubscriptionProperty table.
1756
+ /// </summary>
1757
+ /// <param name="table">The table to decompile.</param>
1758
+ private void DecompileComPlusSubscriptionPropertyTable(Table table)
1759
+ {
1760
+ foreach (Row row in table.Rows)
1761
+ {
1762
+ ComPlus.ComPlusSubscription subscription = (ComPlus.ComPlusSubscription)this.Core.GetIndexedElement("ComPlusSubscription", (string)row[0]);
1763
+ if (null == subscription)
1764
+ {
1765
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Subscription_", (string)row[0], "ComPlusSubscription"));
1766
+ }
1767
+
1768
+ switch ((string)row[1])
1769
+ {
1770
+ case "Description":
1771
+ subscription.Description = (string)row[2];
1772
+ break;
1773
+ case "Enabled":
1774
+ switch ((string)row[2])
1775
+ {
1776
+ case "1":
1777
+ subscription.Enabled = ComPlus.YesNoType.yes;
1778
+ break;
1779
+ case "0":
1780
+ subscription.Enabled = ComPlus.YesNoType.no;
1781
+ break;
1782
+ default:
1783
+ // TODO: Warning
1784
+ break;
1785
+ }
1786
+ break;
1787
+ case "EventClassPartitionID":
1788
+ subscription.EventClassPartitionID = (string)row[2];
1789
+ break;
1790
+ case "FilterCriteria":
1791
+ subscription.FilterCriteria = (string)row[2];
1792
+ break;
1793
+ case "InterfaceID":
1794
+ subscription.InterfaceID = (string)row[2];
1795
+ break;
1796
+ case "MachineName":
1797
+ subscription.MachineName = (string)row[2];
1798
+ break;
1799
+ case "MethodName":
1800
+ subscription.MethodName = (string)row[2];
1801
+ break;
1802
+ case "PerUser":
1803
+ switch ((string)row[2])
1804
+ {
1805
+ case "1":
1806
+ subscription.PerUser = ComPlus.YesNoType.yes;
1807
+ break;
1808
+ case "0":
1809
+ subscription.PerUser = ComPlus.YesNoType.no;
1810
+ break;
1811
+ default:
1812
+ // TODO: Warning
1813
+ break;
1814
+ }
1815
+ break;
1816
+ case "Queued":
1817
+ switch ((string)row[2])
1818
+ {
1819
+ case "1":
1820
+ subscription.Queued = ComPlus.YesNoType.yes;
1821
+ break;
1822
+ case "0":
1823
+ subscription.Queued = ComPlus.YesNoType.no;
1824
+ break;
1825
+ default:
1826
+ // TODO: Warning
1827
+ break;
1828
+ }
1829
+ break;
1830
+ case "SubscriberMoniker":
1831
+ subscription.SubscriberMoniker = (string)row[2];
1832
+ break;
1833
+ case "UserName":
1834
+ subscription.UserName = (string)row[2];
1835
+ break;
1836
+ default:
1837
+ // TODO: Warning
1838
+ break;
1839
+ }
1840
+ }
1841
+ }
1842
+ }
1843
+}
src/wixext/ComPlusExtensionData.cs
new
+64
@@ -0,0 +1,64 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Extensions
4
+{
5
+ using System;
6
+ using System.Reflection;
7
+ using WixToolset.Data;
8
+ using WixToolset.Extensibility;
9
+
10
+ /// <summary>
11
+ /// The WiX Toolset COM+ Extension.
12
+ /// </summary>
13
+ public sealed class ComPlusExtensionData : ExtensionData
14
+ {
15
+ /// <summary>
16
+ /// Gets the default culture.
17
+ /// </summary>
18
+ /// <value>The default culture.</value>
19
+ public override string DefaultCulture
20
+ {
21
+ get { return "en-us"; }
22
+ }
23
+
24
+ /// <summary>
25
+ /// Gets the optional table definitions for this extension.
26
+ /// </summary>
27
+ /// <value>The optional table definitions for this extension.</value>
28
+ public override TableDefinitionCollection TableDefinitions
29
+ {
30
+ get
31
+ {
32
+ return ComPlusExtensionData.GetExtensionTableDefinitions();
33
+ }
34
+ }
35
+
36
+ /// <summary>
37
+ /// Gets the library associated with this extension.
38
+ /// </summary>
39
+ /// <param name="tableDefinitions">The table definitions to use while loading the library.</param>
40
+ /// <returns>The loaded library.</returns>
41
+ public override Library GetLibrary(TableDefinitionCollection tableDefinitions)
42
+ {
43
+ return ComPlusExtensionData.GetExtensionLibrary(tableDefinitions);
44
+ }
45
+
46
+ /// <summary>
47
+ /// Internal mechanism to access the extension's table definitions.
48
+ /// </summary>
49
+ /// <returns>Extension's table definitions.</returns>
50
+ internal static TableDefinitionCollection GetExtensionTableDefinitions()
51
+ {
52
+ return ExtensionData.LoadTableDefinitionHelper(Assembly.GetExecutingAssembly(), "WixToolset.Extensions.Data.tables.xml");
53
+ }
54
+
55
+ /// <summary>
56
+ /// Internal mechanism to access the extension's library.
57
+ /// </summary>
58
+ /// <returns>Extension's library.</returns>
59
+ internal static Library GetExtensionLibrary(TableDefinitionCollection tableDefinitions)
60
+ {
61
+ return ExtensionData.LoadLibraryHelper(Assembly.GetExecutingAssembly(), "WixToolset.Extensions.Data.complus.wixlib", tableDefinitions);
62
+ }
63
+ }
64
+}
src/wixext/WixComPlusExtension.csproj
new
+50
@@ -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>
src/wixext/complus.xsd
new
+944
@@ -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>
src/wixext/messages.xml
new
+77
@@ -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>
src/wixext/tables.xml
new
+250
@@ -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>
src/wixlib/ComPlusExtension.wixproj
new
+26
@@ -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>
src/wixlib/ComPlusExtension.wxs
new
+139
@@ -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>
src/wixlib/en-us.wxl
new
+71
@@ -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>
src/wixlib/es-es.wxl
new
+72
@@ -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
+
src/wixlib/ja-jp.wxl
new
+71
@@ -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>