diff options
| author | Sean Hall <r.sean.hall@gmail.com> | 2019-02-04 20:05:54 -0600 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2019-02-04 20:05:54 -0600 |
| commit | cbc09b6cd6d0d0b8bf095a88d4d8333616637f71 (patch) | |
| tree | a0893e8b8772765747630052018312a2d77f97e4 /src | |
| parent | c94f50e3d8dc958f8a0b9540e63e920a079c1779 (diff) | |
| download | wix-cbc09b6cd6d0d0b8bf095a88d4d8333616637f71.tar.gz wix-cbc09b6cd6d0d0b8bf095a88d4d8333616637f71.tar.bz2 wix-cbc09b6cd6d0d0b8bf095a88d4d8333616637f71.zip | |
Import code from old v4 repo
Diffstat (limited to 'src')
44 files changed, 21074 insertions, 0 deletions
diff --git a/src/ca/cpappexec.cpp b/src/ca/cpappexec.cpp new file mode 100644 index 00000000..43d6cd6d --- /dev/null +++ b/src/ca/cpappexec.cpp | |||
| @@ -0,0 +1,344 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // private structs | ||
| 7 | |||
| 8 | struct CPI_APPLICATION_ATTRIBUTES | ||
| 9 | { | ||
| 10 | int iActionType; | ||
| 11 | int iActionCost; | ||
| 12 | LPWSTR pwzKey; | ||
| 13 | LPWSTR pwzID; | ||
| 14 | LPWSTR pwzName; | ||
| 15 | LPWSTR pwzPartID; | ||
| 16 | CPI_PROPERTY* pPropList; | ||
| 17 | }; | ||
| 18 | |||
| 19 | |||
| 20 | // prototypes for private helper functions | ||
| 21 | |||
| 22 | static HRESULT ReadApplicationAttributes( | ||
| 23 | LPWSTR* ppwzData, | ||
| 24 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
| 25 | ); | ||
| 26 | static void FreeApplicationAttributes( | ||
| 27 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
| 28 | ); | ||
| 29 | static HRESULT CreateApplication( | ||
| 30 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
| 31 | ); | ||
| 32 | static HRESULT RemoveApplication( | ||
| 33 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
| 34 | ); | ||
| 35 | |||
| 36 | |||
| 37 | // function definitions | ||
| 38 | |||
| 39 | HRESULT CpiConfigureApplications( | ||
| 40 | LPWSTR* ppwzData, | ||
| 41 | HANDLE hRollbackFile | ||
| 42 | ) | ||
| 43 | { | ||
| 44 | HRESULT hr = S_OK; | ||
| 45 | |||
| 46 | CPI_APPLICATION_ATTRIBUTES attrs; | ||
| 47 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 48 | |||
| 49 | // read action text | ||
| 50 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
| 51 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 52 | |||
| 53 | // get count | ||
| 54 | int iCnt = 0; | ||
| 55 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 56 | ExitOnFailure(hr, "Failed to read count"); | ||
| 57 | |||
| 58 | // write count to rollback file | ||
| 59 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
| 60 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
| 61 | |||
| 62 | for (int i = 0; i < iCnt; i++) | ||
| 63 | { | ||
| 64 | // read attributes from CustomActionData | ||
| 65 | hr = ReadApplicationAttributes(ppwzData, &attrs); | ||
| 66 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 67 | |||
| 68 | // progress message | ||
| 69 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
| 70 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 71 | |||
| 72 | if (S_FALSE == hr) | ||
| 73 | ExitFunction(); | ||
| 74 | |||
| 75 | // write key to rollback file | ||
| 76 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
| 77 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
| 78 | |||
| 79 | // action | ||
| 80 | switch (attrs.iActionType) | ||
| 81 | { | ||
| 82 | case atCreate: | ||
| 83 | hr = CreateApplication(&attrs); | ||
| 84 | ExitOnFailure(hr, "Failed to create application, key: %S", attrs.pwzKey); | ||
| 85 | break; | ||
| 86 | case atRemove: | ||
| 87 | hr = RemoveApplication(&attrs); | ||
| 88 | ExitOnFailure(hr, "Failed to remove application, key: %S", attrs.pwzKey); | ||
| 89 | break; | ||
| 90 | } | ||
| 91 | |||
| 92 | // write completion status to rollback file | ||
| 93 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
| 94 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
| 95 | |||
| 96 | // progress | ||
| 97 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 98 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 99 | } | ||
| 100 | |||
| 101 | hr = S_OK; | ||
| 102 | |||
| 103 | LExit: | ||
| 104 | // clean up | ||
| 105 | FreeApplicationAttributes(&attrs); | ||
| 106 | |||
| 107 | return hr; | ||
| 108 | } | ||
| 109 | |||
| 110 | HRESULT CpiRollbackConfigureApplications( | ||
| 111 | LPWSTR* ppwzData, | ||
| 112 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 113 | ) | ||
| 114 | { | ||
| 115 | HRESULT hr = S_OK; | ||
| 116 | |||
| 117 | int iRollbackStatus; | ||
| 118 | |||
| 119 | CPI_APPLICATION_ATTRIBUTES attrs; | ||
| 120 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 121 | |||
| 122 | // read action text | ||
| 123 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
| 124 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 125 | |||
| 126 | // get count | ||
| 127 | int iCnt = 0; | ||
| 128 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 129 | ExitOnFailure(hr, "Failed to read count"); | ||
| 130 | |||
| 131 | for (int i = 0; i < iCnt; i++) | ||
| 132 | { | ||
| 133 | // read attributes from CustomActionData | ||
| 134 | hr = ReadApplicationAttributes(ppwzData, &attrs); | ||
| 135 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 136 | |||
| 137 | // rollback status | ||
| 138 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
| 139 | |||
| 140 | if (S_FALSE == hr) | ||
| 141 | continue; // not found, nothing to rollback | ||
| 142 | |||
| 143 | // progress message | ||
| 144 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
| 145 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 146 | |||
| 147 | if (S_FALSE == hr) | ||
| 148 | ExitFunction(); | ||
| 149 | |||
| 150 | // action | ||
| 151 | switch (attrs.iActionType) | ||
| 152 | { | ||
| 153 | case atCreate: | ||
| 154 | hr = CreateApplication(&attrs); | ||
| 155 | if (FAILED(hr)) | ||
| 156 | WcaLog(LOGMSG_STANDARD, "Failed to create application, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 157 | break; | ||
| 158 | case atRemove: | ||
| 159 | hr = RemoveApplication(&attrs); | ||
| 160 | if (FAILED(hr)) | ||
| 161 | WcaLog(LOGMSG_STANDARD, "Failed to remove application, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 162 | break; | ||
| 163 | } | ||
| 164 | |||
| 165 | // check rollback status | ||
| 166 | if (0 == iRollbackStatus) | ||
| 167 | continue; // operation did not complete, skip progress | ||
| 168 | |||
| 169 | // progress | ||
| 170 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 171 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 172 | } | ||
| 173 | |||
| 174 | hr = S_OK; | ||
| 175 | |||
| 176 | LExit: | ||
| 177 | // clean up | ||
| 178 | FreeApplicationAttributes(&attrs); | ||
| 179 | |||
| 180 | return hr; | ||
| 181 | } | ||
| 182 | |||
| 183 | |||
| 184 | // helper function definitions | ||
| 185 | |||
| 186 | static HRESULT ReadApplicationAttributes( | ||
| 187 | LPWSTR* ppwzData, | ||
| 188 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
| 189 | ) | ||
| 190 | { | ||
| 191 | HRESULT hr = S_OK; | ||
| 192 | |||
| 193 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
| 194 | ExitOnFailure(hr, "Failed to read action type"); | ||
| 195 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
| 196 | ExitOnFailure(hr, "Failed to read action cost"); | ||
| 197 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
| 198 | ExitOnFailure(hr, "Failed to read key"); | ||
| 199 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzID); | ||
| 200 | ExitOnFailure(hr, "Failed to read id"); | ||
| 201 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName); | ||
| 202 | ExitOnFailure(hr, "Failed to read name"); | ||
| 203 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
| 204 | ExitOnFailure(hr, "Failed to read partition id"); | ||
| 205 | hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList); | ||
| 206 | ExitOnFailure(hr, "Failed to read properties"); | ||
| 207 | |||
| 208 | hr = S_OK; | ||
| 209 | |||
| 210 | LExit: | ||
| 211 | return hr; | ||
| 212 | } | ||
| 213 | |||
| 214 | static void FreeApplicationAttributes( | ||
| 215 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
| 216 | ) | ||
| 217 | { | ||
| 218 | ReleaseStr(pAttrs->pwzKey); | ||
| 219 | ReleaseStr(pAttrs->pwzID); | ||
| 220 | ReleaseStr(pAttrs->pwzName); | ||
| 221 | ReleaseStr(pAttrs->pwzPartID); | ||
| 222 | |||
| 223 | if (pAttrs->pPropList) | ||
| 224 | CpiFreePropertyList(pAttrs->pPropList); | ||
| 225 | } | ||
| 226 | |||
| 227 | static HRESULT CreateApplication( | ||
| 228 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
| 229 | ) | ||
| 230 | { | ||
| 231 | HRESULT hr = S_OK; | ||
| 232 | |||
| 233 | ICatalogCollection* piAppColl = NULL; | ||
| 234 | ICatalogObject* piAppObj = NULL; | ||
| 235 | |||
| 236 | long lChanges = 0; | ||
| 237 | |||
| 238 | // log | ||
| 239 | WcaLog(LOGMSG_VERBOSE, "Creating application, key: %S", pAttrs->pwzKey); | ||
| 240 | |||
| 241 | // get applications collection | ||
| 242 | hr = CpiGetApplicationsCollection(pAttrs->pwzPartID, &piAppColl); | ||
| 243 | if (S_FALSE == hr) | ||
| 244 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 245 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 246 | |||
| 247 | // check if application exists | ||
| 248 | hr = CpiFindCollectionObjectByStringKey(piAppColl, pAttrs->pwzID, &piAppObj); | ||
| 249 | ExitOnFailure(hr, "Failed to find application"); | ||
| 250 | |||
| 251 | if (S_FALSE == hr) | ||
| 252 | { | ||
| 253 | // create application | ||
| 254 | hr = CpiAddCollectionObject(piAppColl, &piAppObj); | ||
| 255 | ExitOnFailure(hr, "Failed to add application to collection"); | ||
| 256 | |||
| 257 | hr = CpiPutCollectionObjectValue(piAppObj, L"ID", pAttrs->pwzID); | ||
| 258 | ExitOnFailure(hr, "Failed to set application id property"); | ||
| 259 | |||
| 260 | hr = CpiPutCollectionObjectValue(piAppObj, L"Name", pAttrs->pwzName); | ||
| 261 | ExitOnFailure(hr, "Failed to set application name property"); | ||
| 262 | |||
| 263 | // save changes | ||
| 264 | hr = piAppColl->SaveChanges(&lChanges); | ||
| 265 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 266 | CpiLogCatalogErrorInfo(); | ||
| 267 | ExitOnFailure(hr, "Failed to add application"); | ||
| 268 | } | ||
| 269 | |||
| 270 | // properties | ||
| 271 | hr = CpiPutCollectionObjectValues(piAppObj, pAttrs->pPropList); | ||
| 272 | ExitOnFailure(hr, "Failed to write properties"); | ||
| 273 | |||
| 274 | // save changes | ||
| 275 | hr = piAppColl->SaveChanges(&lChanges); | ||
| 276 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 277 | CpiLogCatalogErrorInfo(); | ||
| 278 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 279 | |||
| 280 | // log | ||
| 281 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 282 | |||
| 283 | hr = S_OK; | ||
| 284 | |||
| 285 | LExit: | ||
| 286 | // clean up | ||
| 287 | ReleaseObject(piAppColl); | ||
| 288 | ReleaseObject(piAppObj); | ||
| 289 | |||
| 290 | return hr; | ||
| 291 | } | ||
| 292 | |||
| 293 | static HRESULT RemoveApplication( | ||
| 294 | CPI_APPLICATION_ATTRIBUTES* pAttrs | ||
| 295 | ) | ||
| 296 | { | ||
| 297 | HRESULT hr = S_OK; | ||
| 298 | |||
| 299 | ICatalogCollection* piAppColl = NULL; | ||
| 300 | |||
| 301 | long lChanges = 0; | ||
| 302 | |||
| 303 | // log | ||
| 304 | WcaLog(LOGMSG_VERBOSE, "Removing application, key: %S", pAttrs->pwzKey); | ||
| 305 | |||
| 306 | // get applications collection | ||
| 307 | hr = CpiGetApplicationsCollection(pAttrs->pwzPartID, &piAppColl); | ||
| 308 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 309 | |||
| 310 | if (S_FALSE == hr) | ||
| 311 | { | ||
| 312 | // applications collection not found | ||
| 313 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve applications collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 314 | ExitFunction1(hr = S_OK); | ||
| 315 | } | ||
| 316 | |||
| 317 | // remove | ||
| 318 | hr = CpiRemoveCollectionObject(piAppColl, pAttrs->pwzID, NULL, TRUE); | ||
| 319 | ExitOnFailure(hr, "Failed to remove application"); | ||
| 320 | |||
| 321 | if (S_FALSE == hr) | ||
| 322 | { | ||
| 323 | // application not found | ||
| 324 | WcaLog(LOGMSG_VERBOSE, "Application not found, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 325 | ExitFunction1(hr = S_OK); | ||
| 326 | } | ||
| 327 | |||
| 328 | // save changes | ||
| 329 | hr = piAppColl->SaveChanges(&lChanges); | ||
| 330 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 331 | CpiLogCatalogErrorInfo(); | ||
| 332 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 333 | |||
| 334 | // log | ||
| 335 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 336 | |||
| 337 | hr = S_OK; | ||
| 338 | |||
| 339 | LExit: | ||
| 340 | // clean up | ||
| 341 | ReleaseObject(piAppColl); | ||
| 342 | |||
| 343 | return hr; | ||
| 344 | } | ||
diff --git a/src/ca/cpappexec.h b/src/ca/cpappexec.h new file mode 100644 index 00000000..5003b046 --- /dev/null +++ b/src/ca/cpappexec.h | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT CpiConfigureApplications( | ||
| 6 | LPWSTR* ppwzData, | ||
| 7 | HANDLE hRollbackFile | ||
| 8 | ); | ||
| 9 | HRESULT CpiRollbackConfigureApplications( | ||
| 10 | LPWSTR* ppwzData, | ||
| 11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 12 | ); | ||
diff --git a/src/ca/cpapproleexec.cpp b/src/ca/cpapproleexec.cpp new file mode 100644 index 00000000..e3b71e93 --- /dev/null +++ b/src/ca/cpapproleexec.cpp | |||
| @@ -0,0 +1,720 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // private structs | ||
| 7 | |||
| 8 | struct CPI_APPLICATION_ROLE_ATTRIBUTES | ||
| 9 | { | ||
| 10 | int iActionType; | ||
| 11 | int iActionCost; | ||
| 12 | LPWSTR pwzKey; | ||
| 13 | LPWSTR pwzName; | ||
| 14 | LPWSTR pwzAppID; | ||
| 15 | LPWSTR pwzPartID; | ||
| 16 | CPI_PROPERTY* pPropList; | ||
| 17 | }; | ||
| 18 | |||
| 19 | struct CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES | ||
| 20 | { | ||
| 21 | int iActionType; | ||
| 22 | int iActionCost; | ||
| 23 | LPWSTR pwzKey; | ||
| 24 | LPWSTR pwzRoleName; | ||
| 25 | LPWSTR pwzAccount; | ||
| 26 | LPWSTR pwzAppID; | ||
| 27 | LPWSTR pwzPartID; | ||
| 28 | }; | ||
| 29 | |||
| 30 | |||
| 31 | // prototypes for private helper functions | ||
| 32 | |||
| 33 | static HRESULT ReadApplicationRoleAttributes( | ||
| 34 | LPWSTR* ppwzData, | ||
| 35 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 36 | ); | ||
| 37 | static void FreeApplicationRoleAttributes( | ||
| 38 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 39 | ); | ||
| 40 | static HRESULT CreateApplicationRole( | ||
| 41 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 42 | ); | ||
| 43 | static HRESULT RemoveApplicationRole( | ||
| 44 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 45 | ); | ||
| 46 | static HRESULT ReadUsersInApplicationRoleAttributes( | ||
| 47 | LPWSTR* ppwzData, | ||
| 48 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 49 | ); | ||
| 50 | static void FreeUsersInApplicationRoleAttributes( | ||
| 51 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 52 | ); | ||
| 53 | static HRESULT CreateUsersInApplicationRole( | ||
| 54 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 55 | ); | ||
| 56 | static HRESULT RemoveUsersInApplicationRole( | ||
| 57 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 58 | ); | ||
| 59 | |||
| 60 | |||
| 61 | // function definitions | ||
| 62 | |||
| 63 | HRESULT CpiConfigureApplicationRoles( | ||
| 64 | LPWSTR* ppwzData, | ||
| 65 | HANDLE hRollbackFile | ||
| 66 | ) | ||
| 67 | { | ||
| 68 | HRESULT hr = S_OK; | ||
| 69 | |||
| 70 | CPI_APPLICATION_ROLE_ATTRIBUTES attrs; | ||
| 71 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 72 | |||
| 73 | // read action text | ||
| 74 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
| 75 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 76 | |||
| 77 | // ger count | ||
| 78 | int iCnt = 0; | ||
| 79 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 80 | ExitOnFailure(hr, "Failed to read count"); | ||
| 81 | |||
| 82 | // write count to rollback file | ||
| 83 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
| 84 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
| 85 | |||
| 86 | for (int i = 0; i < iCnt; i++) | ||
| 87 | { | ||
| 88 | // read attributes from CustomActionData | ||
| 89 | hr = ReadApplicationRoleAttributes(ppwzData, &attrs); | ||
| 90 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 91 | |||
| 92 | // progress message | ||
| 93 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
| 94 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 95 | |||
| 96 | if (S_FALSE == hr) | ||
| 97 | ExitFunction(); | ||
| 98 | |||
| 99 | // write key to rollback file | ||
| 100 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
| 101 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
| 102 | |||
| 103 | // action | ||
| 104 | switch (attrs.iActionType) | ||
| 105 | { | ||
| 106 | case atCreate: | ||
| 107 | hr = CreateApplicationRole(&attrs); | ||
| 108 | ExitOnFailure(hr, "Failed to create application role, key: %S", attrs.pwzKey); | ||
| 109 | break; | ||
| 110 | case atRemove: | ||
| 111 | hr = RemoveApplicationRole(&attrs); | ||
| 112 | ExitOnFailure(hr, "Failed to remove application role, key: %S", attrs.pwzKey); | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | |||
| 116 | // write completion status to rollback file | ||
| 117 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
| 118 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
| 119 | |||
| 120 | // progress | ||
| 121 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 122 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 123 | } | ||
| 124 | |||
| 125 | hr = S_OK; | ||
| 126 | |||
| 127 | LExit: | ||
| 128 | // clean up | ||
| 129 | FreeApplicationRoleAttributes(&attrs); | ||
| 130 | |||
| 131 | return hr; | ||
| 132 | } | ||
| 133 | |||
| 134 | HRESULT CpiRollbackConfigureApplicationRoles( | ||
| 135 | LPWSTR* ppwzData, | ||
| 136 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 137 | ) | ||
| 138 | { | ||
| 139 | HRESULT hr = S_OK; | ||
| 140 | |||
| 141 | int iRollbackStatus; | ||
| 142 | |||
| 143 | CPI_APPLICATION_ROLE_ATTRIBUTES attrs; | ||
| 144 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 145 | |||
| 146 | // read action text | ||
| 147 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
| 148 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 149 | |||
| 150 | // get count | ||
| 151 | int iCnt = 0; | ||
| 152 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 153 | ExitOnFailure(hr, "Failed to read count"); | ||
| 154 | |||
| 155 | for (int i = 0; i < iCnt; i++) | ||
| 156 | { | ||
| 157 | // read attributes from CustomActionData | ||
| 158 | hr = ReadApplicationRoleAttributes(ppwzData, &attrs); | ||
| 159 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 160 | |||
| 161 | // rollback status | ||
| 162 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
| 163 | |||
| 164 | if (S_FALSE == hr) | ||
| 165 | continue; // not found, nothing to rollback | ||
| 166 | |||
| 167 | // progress message | ||
| 168 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
| 169 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 170 | |||
| 171 | if (S_FALSE == hr) | ||
| 172 | ExitFunction(); | ||
| 173 | |||
| 174 | // action | ||
| 175 | switch (attrs.iActionType) | ||
| 176 | { | ||
| 177 | case atCreate: | ||
| 178 | hr = CreateApplicationRole(&attrs); | ||
| 179 | if (FAILED(hr)) | ||
| 180 | WcaLog(LOGMSG_STANDARD, "Failed to create application role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 181 | break; | ||
| 182 | case atRemove: | ||
| 183 | hr = RemoveApplicationRole(&attrs); | ||
| 184 | if (FAILED(hr)) | ||
| 185 | WcaLog(LOGMSG_STANDARD, "Failed to remove application role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 186 | break; | ||
| 187 | } | ||
| 188 | |||
| 189 | // check rollback status | ||
| 190 | if (0 == iRollbackStatus) | ||
| 191 | continue; // operation did not complete, skip progress | ||
| 192 | |||
| 193 | // progress | ||
| 194 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 195 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 196 | } | ||
| 197 | |||
| 198 | hr = S_OK; | ||
| 199 | |||
| 200 | LExit: | ||
| 201 | // clean up | ||
| 202 | FreeApplicationRoleAttributes(&attrs); | ||
| 203 | |||
| 204 | return hr; | ||
| 205 | } | ||
| 206 | |||
| 207 | HRESULT CpiConfigureUsersInApplicationRoles( | ||
| 208 | LPWSTR* ppwzData, | ||
| 209 | HANDLE hRollbackFile | ||
| 210 | ) | ||
| 211 | { | ||
| 212 | HRESULT hr = S_OK; | ||
| 213 | |||
| 214 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES attrs; | ||
| 215 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 216 | |||
| 217 | // read action text | ||
| 218 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
| 219 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 220 | |||
| 221 | // ger count | ||
| 222 | int iCnt = 0; | ||
| 223 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 224 | ExitOnFailure(hr, "Failed to read count"); | ||
| 225 | |||
| 226 | // write count to rollback file | ||
| 227 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
| 228 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
| 229 | |||
| 230 | for (int i = 0; i < iCnt; i++) | ||
| 231 | { | ||
| 232 | // read attributes from CustomActionData | ||
| 233 | hr = ReadUsersInApplicationRoleAttributes(ppwzData, &attrs); | ||
| 234 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 235 | |||
| 236 | // progress message | ||
| 237 | hr = CpiActionDataMessage(1, attrs.pwzRoleName); | ||
| 238 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 239 | |||
| 240 | if (S_FALSE == hr) | ||
| 241 | ExitFunction(); | ||
| 242 | |||
| 243 | // write key to rollback file | ||
| 244 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
| 245 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
| 246 | |||
| 247 | // action | ||
| 248 | switch (attrs.iActionType) | ||
| 249 | { | ||
| 250 | case atCreate: | ||
| 251 | hr = CreateUsersInApplicationRole(&attrs); | ||
| 252 | ExitOnFailure(hr, "Failed to create user in application role, key: %S", attrs.pwzKey); | ||
| 253 | break; | ||
| 254 | case atRemove: | ||
| 255 | hr = RemoveUsersInApplicationRole(&attrs); | ||
| 256 | ExitOnFailure(hr, "Failed to remove user from application role, key: %S", attrs.pwzKey); | ||
| 257 | break; | ||
| 258 | } | ||
| 259 | |||
| 260 | // write completion status to rollback file | ||
| 261 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
| 262 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
| 263 | |||
| 264 | // progress | ||
| 265 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 266 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 267 | } | ||
| 268 | |||
| 269 | hr = S_OK; | ||
| 270 | |||
| 271 | LExit: | ||
| 272 | // clean up | ||
| 273 | FreeUsersInApplicationRoleAttributes(&attrs); | ||
| 274 | |||
| 275 | return hr; | ||
| 276 | } | ||
| 277 | |||
| 278 | HRESULT CpiRollbackConfigureUsersInApplicationRoles( | ||
| 279 | LPWSTR* ppwzData, | ||
| 280 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 281 | ) | ||
| 282 | { | ||
| 283 | HRESULT hr = S_OK; | ||
| 284 | |||
| 285 | int iRollbackStatus; | ||
| 286 | |||
| 287 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES attrs; | ||
| 288 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 289 | |||
| 290 | // read action text | ||
| 291 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
| 292 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 293 | |||
| 294 | // get count | ||
| 295 | int iCnt = 0; | ||
| 296 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 297 | ExitOnFailure(hr, "Failed to read count"); | ||
| 298 | |||
| 299 | for (int i = 0; i < iCnt; i++) | ||
| 300 | { | ||
| 301 | // read attributes from CustomActionData | ||
| 302 | hr = ReadUsersInApplicationRoleAttributes(ppwzData, &attrs); | ||
| 303 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 304 | |||
| 305 | // rollback status | ||
| 306 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
| 307 | |||
| 308 | if (S_FALSE == hr) | ||
| 309 | continue; // not found, nothing to rollback | ||
| 310 | |||
| 311 | // progress message | ||
| 312 | hr = CpiActionDataMessage(1, attrs.pwzRoleName); | ||
| 313 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 314 | |||
| 315 | if (S_FALSE == hr) | ||
| 316 | ExitFunction(); | ||
| 317 | |||
| 318 | // action | ||
| 319 | switch (attrs.iActionType) | ||
| 320 | { | ||
| 321 | case atCreate: | ||
| 322 | hr = CreateUsersInApplicationRole(&attrs); | ||
| 323 | if (FAILED(hr)) | ||
| 324 | WcaLog(LOGMSG_STANDARD, "Failed to add user to application role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 325 | break; | ||
| 326 | case atRemove: | ||
| 327 | hr = RemoveUsersInApplicationRole(&attrs); | ||
| 328 | if (FAILED(hr)) | ||
| 329 | WcaLog(LOGMSG_STANDARD, "Failed to remove user from application role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 330 | break; | ||
| 331 | } | ||
| 332 | |||
| 333 | // check rollback status | ||
| 334 | if (0 == iRollbackStatus) | ||
| 335 | continue; // operation did not complete, skip progress | ||
| 336 | |||
| 337 | // progress | ||
| 338 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 339 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 340 | } | ||
| 341 | |||
| 342 | hr = S_OK; | ||
| 343 | |||
| 344 | LExit: | ||
| 345 | // clean up | ||
| 346 | FreeUsersInApplicationRoleAttributes(&attrs); | ||
| 347 | |||
| 348 | return hr; | ||
| 349 | } | ||
| 350 | |||
| 351 | |||
| 352 | // helper function definitions | ||
| 353 | |||
| 354 | static HRESULT ReadApplicationRoleAttributes( | ||
| 355 | LPWSTR* ppwzData, | ||
| 356 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 357 | ) | ||
| 358 | { | ||
| 359 | HRESULT hr = S_OK; | ||
| 360 | |||
| 361 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
| 362 | ExitOnFailure(hr, "Failed to read action type"); | ||
| 363 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
| 364 | ExitOnFailure(hr, "Failed to read action cost"); | ||
| 365 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
| 366 | ExitOnFailure(hr, "Failed to read key"); | ||
| 367 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName); | ||
| 368 | ExitOnFailure(hr, "Failed to read name"); | ||
| 369 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
| 370 | ExitOnFailure(hr, "Failed to read application id"); | ||
| 371 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
| 372 | ExitOnFailure(hr, "Failed to read partition id"); | ||
| 373 | hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList); | ||
| 374 | ExitOnFailure(hr, "Failed to read properties"); | ||
| 375 | |||
| 376 | hr = S_OK; | ||
| 377 | |||
| 378 | LExit: | ||
| 379 | return hr; | ||
| 380 | } | ||
| 381 | |||
| 382 | static void FreeApplicationRoleAttributes( | ||
| 383 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 384 | ) | ||
| 385 | { | ||
| 386 | ReleaseStr(pAttrs->pwzKey); | ||
| 387 | ReleaseStr(pAttrs->pwzName); | ||
| 388 | ReleaseStr(pAttrs->pwzAppID); | ||
| 389 | ReleaseStr(pAttrs->pwzPartID); | ||
| 390 | |||
| 391 | if (pAttrs->pPropList) | ||
| 392 | CpiFreePropertyList(pAttrs->pPropList); | ||
| 393 | } | ||
| 394 | |||
| 395 | static HRESULT CreateApplicationRole( | ||
| 396 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 397 | ) | ||
| 398 | { | ||
| 399 | HRESULT hr = S_OK; | ||
| 400 | |||
| 401 | ICatalogCollection* piRolesColl = NULL; | ||
| 402 | ICatalogObject* piRoleObj = NULL; | ||
| 403 | |||
| 404 | long lChanges = 0; | ||
| 405 | |||
| 406 | // log | ||
| 407 | WcaLog(LOGMSG_VERBOSE, "Creating application role, key: %S", pAttrs->pwzKey); | ||
| 408 | |||
| 409 | // get roles collection | ||
| 410 | hr = CpiGetRolesCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piRolesColl); | ||
| 411 | if (S_FALSE == hr) | ||
| 412 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 413 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
| 414 | |||
| 415 | // check if role exists | ||
| 416 | hr = CpiFindCollectionObjectByName(piRolesColl, pAttrs->pwzName, &piRoleObj); | ||
| 417 | ExitOnFailure(hr, "Failed to find role"); | ||
| 418 | |||
| 419 | if (S_FALSE == hr) | ||
| 420 | { | ||
| 421 | // create role | ||
| 422 | hr = CpiAddCollectionObject(piRolesColl, &piRoleObj); | ||
| 423 | ExitOnFailure(hr, "Failed to add role to collection"); | ||
| 424 | |||
| 425 | hr = CpiPutCollectionObjectValue(piRoleObj, L"Name", pAttrs->pwzName); | ||
| 426 | ExitOnFailure(hr, "Failed to set role name property"); | ||
| 427 | } | ||
| 428 | |||
| 429 | // properties | ||
| 430 | hr = CpiPutCollectionObjectValues(piRoleObj, pAttrs->pPropList); | ||
| 431 | ExitOnFailure(hr, "Failed to write properties"); | ||
| 432 | |||
| 433 | // save changes | ||
| 434 | hr = piRolesColl->SaveChanges(&lChanges); | ||
| 435 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 436 | CpiLogCatalogErrorInfo(); | ||
| 437 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 438 | |||
| 439 | // log | ||
| 440 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 441 | |||
| 442 | hr = S_OK; | ||
| 443 | |||
| 444 | LExit: | ||
| 445 | // clean up | ||
| 446 | ReleaseObject(piRolesColl); | ||
| 447 | ReleaseObject(piRoleObj); | ||
| 448 | |||
| 449 | return hr; | ||
| 450 | } | ||
| 451 | |||
| 452 | static HRESULT RemoveApplicationRole( | ||
| 453 | CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 454 | ) | ||
| 455 | { | ||
| 456 | HRESULT hr = S_OK; | ||
| 457 | |||
| 458 | ICatalogCollection* piRolesColl = NULL; | ||
| 459 | |||
| 460 | long lChanges = 0; | ||
| 461 | |||
| 462 | // log | ||
| 463 | WcaLog(LOGMSG_VERBOSE, "Removing application role, key: %S", pAttrs->pwzKey); | ||
| 464 | |||
| 465 | // get roles collection | ||
| 466 | hr = CpiGetRolesCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piRolesColl); | ||
| 467 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
| 468 | |||
| 469 | if (S_FALSE == hr) | ||
| 470 | { | ||
| 471 | // roles collection not found | ||
| 472 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve roles collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 473 | ExitFunction1(hr = S_OK); | ||
| 474 | } | ||
| 475 | |||
| 476 | // remove | ||
| 477 | hr = CpiRemoveCollectionObject(piRolesColl, NULL, pAttrs->pwzName, FALSE); | ||
| 478 | ExitOnFailure(hr, "Failed to remove role"); | ||
| 479 | |||
| 480 | if (S_FALSE == hr) | ||
| 481 | { | ||
| 482 | // role not found | ||
| 483 | WcaLog(LOGMSG_VERBOSE, "Role not found, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 484 | ExitFunction1(hr = S_OK); | ||
| 485 | } | ||
| 486 | |||
| 487 | // save changes | ||
| 488 | hr = piRolesColl->SaveChanges(&lChanges); | ||
| 489 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 490 | CpiLogCatalogErrorInfo(); | ||
| 491 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 492 | |||
| 493 | // log | ||
| 494 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 495 | |||
| 496 | hr = S_OK; | ||
| 497 | |||
| 498 | LExit: | ||
| 499 | // clean up | ||
| 500 | ReleaseObject(piRolesColl); | ||
| 501 | |||
| 502 | return hr; | ||
| 503 | } | ||
| 504 | |||
| 505 | static HRESULT ReadUsersInApplicationRoleAttributes( | ||
| 506 | LPWSTR* ppwzData, | ||
| 507 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 508 | ) | ||
| 509 | { | ||
| 510 | HRESULT hr = S_OK; | ||
| 511 | |||
| 512 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
| 513 | ExitOnFailure(hr, "Failed to read action type"); | ||
| 514 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
| 515 | ExitOnFailure(hr, "Failed to read action cost"); | ||
| 516 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
| 517 | ExitOnFailure(hr, "Failed to read key"); | ||
| 518 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzRoleName); | ||
| 519 | ExitOnFailure(hr, "Failed to read role name"); | ||
| 520 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount); | ||
| 521 | ExitOnFailure(hr, "Failed to read account name"); | ||
| 522 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
| 523 | ExitOnFailure(hr, "Failed to read application id"); | ||
| 524 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
| 525 | ExitOnFailure(hr, "Failed to read partition id"); | ||
| 526 | |||
| 527 | hr = S_OK; | ||
| 528 | |||
| 529 | LExit: | ||
| 530 | return hr; | ||
| 531 | } | ||
| 532 | |||
| 533 | static void FreeUsersInApplicationRoleAttributes( | ||
| 534 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 535 | ) | ||
| 536 | { | ||
| 537 | ReleaseStr(pAttrs->pwzKey); | ||
| 538 | ReleaseStr(pAttrs->pwzRoleName); | ||
| 539 | ReleaseStr(pAttrs->pwzAccount); | ||
| 540 | ReleaseStr(pAttrs->pwzAppID); | ||
| 541 | ReleaseStr(pAttrs->pwzPartID); | ||
| 542 | } | ||
| 543 | |||
| 544 | static HRESULT CreateUsersInApplicationRole( | ||
| 545 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 546 | ) | ||
| 547 | { | ||
| 548 | HRESULT hr = S_OK; | ||
| 549 | UINT er = ERROR_SUCCESS; | ||
| 550 | |||
| 551 | ICatalogCollection* piUsrInRoleColl = NULL; | ||
| 552 | ICatalogObject* piUsrInRoleObj = NULL; | ||
| 553 | |||
| 554 | PSID pSid = NULL; | ||
| 555 | long lChanges = 0; | ||
| 556 | |||
| 557 | // log | ||
| 558 | WcaLog(LOGMSG_VERBOSE, "Adding user to application role, key: %S", pAttrs->pwzKey); | ||
| 559 | |||
| 560 | // get users in role collection | ||
| 561 | hr = CpiGetUsersInRoleCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzRoleName, &piUsrInRoleColl); | ||
| 562 | if (S_FALSE == hr) | ||
| 563 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 564 | ExitOnFailure(hr, "Failed to get users in role collection"); | ||
| 565 | |||
| 566 | // get SID for account | ||
| 567 | do { | ||
| 568 | er = ERROR_SUCCESS; | ||
| 569 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
| 570 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
| 571 | { | ||
| 572 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
| 573 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 574 | switch (er) | ||
| 575 | { | ||
| 576 | case IDABORT: | ||
| 577 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
| 578 | case IDRETRY: | ||
| 579 | break; | ||
| 580 | case IDIGNORE: | ||
| 581 | default: | ||
| 582 | ExitFunction1(hr = S_OK); | ||
| 583 | } | ||
| 584 | } | ||
| 585 | else | ||
| 586 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
| 587 | } while (IDRETRY == er); | ||
| 588 | |||
| 589 | // find any existing entry | ||
| 590 | hr = CpiFindUserCollectionObject(piUsrInRoleColl, pSid, NULL); | ||
| 591 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
| 592 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
| 593 | else | ||
| 594 | ExitOnFailure(hr, "Failed to find user in application role"); | ||
| 595 | |||
| 596 | if (S_OK == hr) | ||
| 597 | { | ||
| 598 | WcaLog(LOGMSG_VERBOSE, "User already assigned to application role, key: %S", pAttrs->pwzKey); | ||
| 599 | ExitFunction(); // exit with hr = S_OK | ||
| 600 | } | ||
| 601 | |||
| 602 | // convert SID back to account name | ||
| 603 | hr = CpiSidToAccountName(pSid, &pAttrs->pwzAccount); | ||
| 604 | ExitOnFailure(hr, "Failed to convert SID to account name"); | ||
| 605 | |||
| 606 | // add user | ||
| 607 | hr = CpiAddCollectionObject(piUsrInRoleColl, &piUsrInRoleObj); | ||
| 608 | ExitOnFailure(hr, "Failed to add user in role to collection"); | ||
| 609 | |||
| 610 | hr = CpiPutCollectionObjectValue(piUsrInRoleObj, L"User", pAttrs->pwzAccount); | ||
| 611 | ExitOnFailure(hr, "Failed to set role name property"); | ||
| 612 | |||
| 613 | // save changes | ||
| 614 | hr = piUsrInRoleColl->SaveChanges(&lChanges); | ||
| 615 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 616 | CpiLogCatalogErrorInfo(); | ||
| 617 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 618 | |||
| 619 | // log | ||
| 620 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 621 | |||
| 622 | hr = S_OK; | ||
| 623 | |||
| 624 | LExit: | ||
| 625 | // clean up | ||
| 626 | ReleaseObject(piUsrInRoleColl); | ||
| 627 | ReleaseObject(piUsrInRoleObj); | ||
| 628 | |||
| 629 | if (pSid) | ||
| 630 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
| 631 | |||
| 632 | return hr; | ||
| 633 | } | ||
| 634 | |||
| 635 | static HRESULT RemoveUsersInApplicationRole( | ||
| 636 | CPI_USER_IN_APPLICATION_ROLE_ATTRIBUTES* pAttrs | ||
| 637 | ) | ||
| 638 | { | ||
| 639 | HRESULT hr = S_OK; | ||
| 640 | UINT er = ERROR_SUCCESS; | ||
| 641 | |||
| 642 | ICatalogCollection* piUsrInRoleColl = NULL; | ||
| 643 | |||
| 644 | PSID pSid = NULL; | ||
| 645 | long lChanges = 0; | ||
| 646 | |||
| 647 | // log | ||
| 648 | WcaLog(LOGMSG_VERBOSE, "Removing user from application role, key: %S", pAttrs->pwzKey); | ||
| 649 | |||
| 650 | // get users in role collection | ||
| 651 | hr = CpiGetUsersInRoleCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzRoleName, &piUsrInRoleColl); | ||
| 652 | ExitOnFailure(hr, "Failed to get users in role collection"); | ||
| 653 | |||
| 654 | if (S_FALSE == hr) | ||
| 655 | { | ||
| 656 | // users in role collection not found | ||
| 657 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve users in role collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 658 | ExitFunction1(hr = S_OK); | ||
| 659 | } | ||
| 660 | |||
| 661 | // get SID for account | ||
| 662 | do { | ||
| 663 | er = ERROR_SUCCESS; | ||
| 664 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
| 665 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
| 666 | { | ||
| 667 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
| 668 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 669 | switch (er) | ||
| 670 | { | ||
| 671 | case IDABORT: | ||
| 672 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
| 673 | case IDRETRY: | ||
| 674 | break; | ||
| 675 | case IDIGNORE: | ||
| 676 | default: | ||
| 677 | ExitFunction1(hr = S_OK); | ||
| 678 | } | ||
| 679 | } | ||
| 680 | else | ||
| 681 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
| 682 | } while (IDRETRY == er); | ||
| 683 | |||
| 684 | // remove | ||
| 685 | hr = CpiRemoveUserCollectionObject(piUsrInRoleColl, pSid); | ||
| 686 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
| 687 | { | ||
| 688 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
| 689 | hr = S_FALSE; | ||
| 690 | } | ||
| 691 | else | ||
| 692 | ExitOnFailure(hr, "Failed to remove user"); | ||
| 693 | |||
| 694 | if (S_FALSE == hr) | ||
| 695 | { | ||
| 696 | // role not found | ||
| 697 | WcaLog(LOGMSG_VERBOSE, "User not found for application role, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 698 | ExitFunction1(hr = S_OK); | ||
| 699 | } | ||
| 700 | |||
| 701 | // save changes | ||
| 702 | hr = piUsrInRoleColl->SaveChanges(&lChanges); | ||
| 703 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 704 | CpiLogCatalogErrorInfo(); | ||
| 705 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 706 | |||
| 707 | // log | ||
| 708 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 709 | |||
| 710 | hr = S_OK; | ||
| 711 | |||
| 712 | LExit: | ||
| 713 | // clean up | ||
| 714 | ReleaseObject(piUsrInRoleColl); | ||
| 715 | |||
| 716 | if (pSid) | ||
| 717 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
| 718 | |||
| 719 | return hr; | ||
| 720 | } | ||
diff --git a/src/ca/cpapproleexec.h b/src/ca/cpapproleexec.h new file mode 100644 index 00000000..1251cbdb --- /dev/null +++ b/src/ca/cpapproleexec.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT CpiConfigureApplicationRoles( | ||
| 6 | LPWSTR* ppwzData, | ||
| 7 | HANDLE hRollbackFile | ||
| 8 | ); | ||
| 9 | HRESULT CpiRollbackConfigureApplicationRoles( | ||
| 10 | LPWSTR* ppwzData, | ||
| 11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 12 | ); | ||
| 13 | HRESULT CpiConfigureUsersInApplicationRoles( | ||
| 14 | LPWSTR* ppwzData, | ||
| 15 | HANDLE hRollbackFile | ||
| 16 | ); | ||
| 17 | HRESULT CpiRollbackConfigureUsersInApplicationRoles( | ||
| 18 | LPWSTR* ppwzData, | ||
| 19 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 20 | ); | ||
diff --git a/src/ca/cpapprolesched.cpp b/src/ca/cpapprolesched.cpp new file mode 100644 index 00000000..a268d156 --- /dev/null +++ b/src/ca/cpapprolesched.cpp | |||
| @@ -0,0 +1,843 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // sql queries | ||
| 7 | |||
| 8 | LPCWSTR vcsApplicationRoleQuery = | ||
| 9 | L"SELECT `ApplicationRole`, `Application_`, `Component_`, `Name` FROM `ComPlusApplicationRole`"; | ||
| 10 | enum eApplicationRoleQuery { arqApplicationRole = 1, arqApplication, arqComponent, arqName }; | ||
| 11 | |||
| 12 | LPCWSTR vcsUserInApplicationRoleQuery = | ||
| 13 | L"SELECT `UserInApplicationRole`, `ApplicationRole_`, `ComPlusUserInApplicationRole`.`Component_`, `Domain`, `Name` FROM `ComPlusUserInApplicationRole`, `User` WHERE `User_` = `User`"; | ||
| 14 | LPCWSTR vcsGroupInApplicationRoleQuery = | ||
| 15 | L"SELECT `GroupInApplicationRole`, `ApplicationRole_`, `ComPlusGroupInApplicationRole`.`Component_`, `Domain`, `Name` FROM `ComPlusGroupInApplicationRole`, `Group` WHERE `Group_` = `Group`"; | ||
| 16 | enum eTrusteeInApplicationRoleQuery { tiarqUserInApplicationRole = 1, tiarqApplicationRole, tiarqComponent, tiarqDomain, tiarqName }; | ||
| 17 | |||
| 18 | LPCWSTR vcsApplicationRolePropertyQuery = | ||
| 19 | L"SELECT `Name`, `Value` FROM `ComPlusApplicationRoleProperty` WHERE `ApplicationRole_` = ?"; | ||
| 20 | |||
| 21 | |||
| 22 | // property definitions | ||
| 23 | |||
| 24 | CPI_PROPERTY_DEFINITION pdlApplicationRoleProperties[] = | ||
| 25 | { | ||
| 26 | {L"Description", cpptString, 500}, | ||
| 27 | {NULL, cpptNone, 0} | ||
| 28 | }; | ||
| 29 | |||
| 30 | |||
| 31 | // prototypes for private helper functions | ||
| 32 | |||
| 33 | static HRESULT TrusteesInApplicationRolesRead( | ||
| 34 | LPCWSTR pwzQuery, | ||
| 35 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 36 | CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList | ||
| 37 | ); | ||
| 38 | static void FreeApplicationRole( | ||
| 39 | CPI_APPLICATION_ROLE* pItm | ||
| 40 | ); | ||
| 41 | static void FreeUserInApplicationRole( | ||
| 42 | CPI_USER_IN_APPLICATION_ROLE* pItm | ||
| 43 | ); | ||
| 44 | //static HRESULT GetUsersCollForApplicationRole( | ||
| 45 | // CPI_APPLICATION_ROLE* pAppRole, | ||
| 46 | // ICatalogCollection** ppiUsersColl | ||
| 47 | // ); | ||
| 48 | static HRESULT FindObjectForApplicationRole( | ||
| 49 | CPI_APPLICATION_ROLE* pItm, | ||
| 50 | ICatalogObject** ppiRoleObj | ||
| 51 | ); | ||
| 52 | static HRESULT AddApplicationRoleToActionData( | ||
| 53 | CPI_APPLICATION_ROLE* pItm, | ||
| 54 | int iActionType, | ||
| 55 | int iActionCost, | ||
| 56 | LPWSTR* ppwzActionData | ||
| 57 | ); | ||
| 58 | static HRESULT AddUserInApplicationRoleToActionData( | ||
| 59 | CPI_USER_IN_APPLICATION_ROLE* pItm, | ||
| 60 | int iActionType, | ||
| 61 | int iActionCost, | ||
| 62 | LPWSTR* ppwzActionData | ||
| 63 | ); | ||
| 64 | |||
| 65 | |||
| 66 | // function definitions | ||
| 67 | |||
| 68 | void CpiApplicationRoleListFree( | ||
| 69 | CPI_APPLICATION_ROLE_LIST* pList | ||
| 70 | ) | ||
| 71 | { | ||
| 72 | CPI_APPLICATION_ROLE* pItm = pList->pFirst; | ||
| 73 | |||
| 74 | while (pItm) | ||
| 75 | { | ||
| 76 | CPI_APPLICATION_ROLE* pDelete = pItm; | ||
| 77 | pItm = pItm->pNext; | ||
| 78 | FreeApplicationRole(pDelete); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | HRESULT CpiApplicationRolesRead( | ||
| 83 | CPI_APPLICATION_LIST* pAppList, | ||
| 84 | CPI_APPLICATION_ROLE_LIST* pAppRoleList | ||
| 85 | ) | ||
| 86 | { | ||
| 87 | HRESULT hr = S_OK; | ||
| 88 | UINT er = ERROR_SUCCESS; | ||
| 89 | |||
| 90 | PMSIHANDLE hView, hRec; | ||
| 91 | |||
| 92 | CPI_APPLICATION_ROLE* pItm = NULL; | ||
| 93 | LPWSTR pwzData = NULL; | ||
| 94 | BOOL fMatchingArchitecture = FALSE; | ||
| 95 | |||
| 96 | // loop through all application roles | ||
| 97 | hr = WcaOpenExecuteView(vcsApplicationRoleQuery, &hView); | ||
| 98 | ExitOnFailure(hr, "Failed to execute view on ComPlusApplicationRole table"); | ||
| 99 | |||
| 100 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 101 | { | ||
| 102 | // get component | ||
| 103 | hr = WcaGetRecordString(hRec, arqComponent, &pwzData); | ||
| 104 | ExitOnFailure(hr, "Failed to get component"); | ||
| 105 | |||
| 106 | // check if the component is our processor architecture | ||
| 107 | if (pwzData && *pwzData) | ||
| 108 | { | ||
| 109 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
| 110 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
| 111 | |||
| 112 | if (!fMatchingArchitecture) | ||
| 113 | { | ||
| 114 | continue; // not the same architecture, ignore | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | // create entry | ||
| 119 | pItm = (CPI_APPLICATION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_APPLICATION_ROLE)); | ||
| 120 | if (!pItm) | ||
| 121 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 122 | |||
| 123 | // get component install state | ||
| 124 | if (pwzData && *pwzData) | ||
| 125 | { | ||
| 126 | pItm->fHasComponent = TRUE; | ||
| 127 | |||
| 128 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
| 129 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
| 130 | } | ||
| 131 | |||
| 132 | // get key | ||
| 133 | hr = WcaGetRecordString(hRec, arqApplicationRole, &pwzData); | ||
| 134 | ExitOnFailure(hr, "Failed to get key"); | ||
| 135 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 136 | |||
| 137 | // get application | ||
| 138 | hr = WcaGetRecordString(hRec, arqApplication, &pwzData); | ||
| 139 | ExitOnFailure(hr, "Failed to get application"); | ||
| 140 | |||
| 141 | hr = CpiApplicationFindByKey(pAppList, pwzData, &pItm->pApplication); | ||
| 142 | if (S_FALSE == hr) | ||
| 143 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 144 | ExitOnFailure(hr, "Failed to find application, key: %S", pwzData); | ||
| 145 | |||
| 146 | // get name | ||
| 147 | hr = WcaGetRecordFormattedString(hRec, arqName, &pwzData); | ||
| 148 | ExitOnFailure(hr, "Failed to get name"); | ||
| 149 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
| 150 | |||
| 151 | // get properties | ||
| 152 | if (CpiTableExists(cptComPlusApplicationRoleProperty)) | ||
| 153 | { | ||
| 154 | hr = CpiPropertiesRead(vcsApplicationRolePropertyQuery, pItm->wzKey, pdlApplicationRoleProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
| 155 | ExitOnFailure(hr, "Failed to get properties"); | ||
| 156 | } | ||
| 157 | |||
| 158 | // set references & increment counters | ||
| 159 | if (pItm->fHasComponent) | ||
| 160 | { | ||
| 161 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 162 | { | ||
| 163 | CpiApplicationAddReferenceInstall(pItm->pApplication); | ||
| 164 | pAppRoleList->iInstallCount++; | ||
| 165 | } | ||
| 166 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 167 | { | ||
| 168 | CpiApplicationAddReferenceUninstall(pItm->pApplication); | ||
| 169 | pAppRoleList->iUninstallCount++; | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | // add entry | ||
| 174 | if (pAppRoleList->pFirst) | ||
| 175 | pItm->pNext = pAppRoleList->pFirst; | ||
| 176 | pAppRoleList->pFirst = pItm; | ||
| 177 | pItm = NULL; | ||
| 178 | } | ||
| 179 | |||
| 180 | if (E_NOMOREITEMS == hr) | ||
| 181 | hr = S_OK; | ||
| 182 | |||
| 183 | LExit: | ||
| 184 | // clean up | ||
| 185 | if (pItm) | ||
| 186 | FreeApplicationRole(pItm); | ||
| 187 | |||
| 188 | ReleaseStr(pwzData); | ||
| 189 | |||
| 190 | return hr; | ||
| 191 | } | ||
| 192 | |||
| 193 | HRESULT CpiApplicationRolesVerifyInstall( | ||
| 194 | CPI_APPLICATION_ROLE_LIST* pList | ||
| 195 | ) | ||
| 196 | { | ||
| 197 | HRESULT hr = S_OK; | ||
| 198 | UINT er = ERROR_SUCCESS; | ||
| 199 | |||
| 200 | ICatalogObject* piRoleObj = NULL; | ||
| 201 | |||
| 202 | for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 203 | { | ||
| 204 | // referenced locaters or roles that are being installed | ||
| 205 | if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction))) | ||
| 206 | continue; | ||
| 207 | |||
| 208 | // if the role is referensed and is not a locater, it must be installed | ||
| 209 | if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction)) | ||
| 210 | MessageExitOnFailure(hr = E_FAIL, msierrComPlusApplicationRoleDependency, "An application role is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey); | ||
| 211 | |||
| 212 | // role is a locater | ||
| 213 | if (!pItm->fHasComponent) | ||
| 214 | { | ||
| 215 | // get collection object for role | ||
| 216 | hr = FindObjectForApplicationRole(pItm, &piRoleObj); | ||
| 217 | ExitOnFailure(hr, "Failed to find collection object for role"); | ||
| 218 | |||
| 219 | // if the role was not found | ||
| 220 | if (S_FALSE == hr) | ||
| 221 | MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusApplicationRoleNotFound, "An application role required by this installation was not found, key: %S", pItm->wzKey); | ||
| 222 | } | ||
| 223 | |||
| 224 | // role is supposed to be created | ||
| 225 | else if (!CpiIsInstalled(pItm->isInstalled)) | ||
| 226 | { | ||
| 227 | do { | ||
| 228 | // find roles with conflicting name or id | ||
| 229 | hr = FindObjectForApplicationRole(pItm, NULL); | ||
| 230 | ExitOnFailure(hr, "Failed to find collection object for role"); | ||
| 231 | |||
| 232 | if (S_OK == hr) | ||
| 233 | { | ||
| 234 | er = WcaErrorMessage(msierrComPlusApplicationRoleConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 235 | switch (er) | ||
| 236 | { | ||
| 237 | case IDABORT: | ||
| 238 | ExitOnFailure(hr = E_FAIL, "An application with a conflictiong name exists, key: %S", pItm->wzKey); | ||
| 239 | break; | ||
| 240 | case IDRETRY: | ||
| 241 | break; | ||
| 242 | case IDIGNORE: | ||
| 243 | default: | ||
| 244 | hr = S_FALSE; // indicate that this is not a conflict | ||
| 245 | } | ||
| 246 | } | ||
| 247 | } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts | ||
| 248 | } | ||
| 249 | |||
| 250 | // clean up | ||
| 251 | ReleaseNullObject(piRoleObj); | ||
| 252 | } | ||
| 253 | |||
| 254 | hr = S_OK; | ||
| 255 | |||
| 256 | LExit: | ||
| 257 | // clean up | ||
| 258 | ReleaseObject(piRoleObj); | ||
| 259 | |||
| 260 | return hr; | ||
| 261 | } | ||
| 262 | |||
| 263 | HRESULT CpiApplicationRolesVerifyUninstall( | ||
| 264 | CPI_APPLICATION_ROLE_LIST* pList | ||
| 265 | ) | ||
| 266 | { | ||
| 267 | HRESULT hr = S_OK; | ||
| 268 | |||
| 269 | for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 270 | { | ||
| 271 | // referenced locaters or roles that are being installed | ||
| 272 | if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction))) | ||
| 273 | continue; | ||
| 274 | |||
| 275 | // get collection object for role | ||
| 276 | hr = FindObjectForApplicationRole(pItm, NULL); | ||
| 277 | ExitOnFailure(hr, "Failed to find collection object for role"); | ||
| 278 | |||
| 279 | // if the role was not found | ||
| 280 | if (S_FALSE == hr) | ||
| 281 | { | ||
| 282 | pItm->fObjectNotFound = TRUE; | ||
| 283 | if (pItm->fHasComponent) | ||
| 284 | pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall | ||
| 285 | } | ||
| 286 | } | ||
| 287 | |||
| 288 | hr = S_OK; | ||
| 289 | |||
| 290 | LExit: | ||
| 291 | return hr; | ||
| 292 | } | ||
| 293 | |||
| 294 | void CpiApplicationRoleAddReferenceInstall( | ||
| 295 | CPI_APPLICATION_ROLE* pItm | ||
| 296 | ) | ||
| 297 | { | ||
| 298 | pItm->fReferencedForInstall = TRUE; | ||
| 299 | CpiApplicationAddReferenceInstall(pItm->pApplication); | ||
| 300 | } | ||
| 301 | |||
| 302 | void CpiApplicationRoleAddReferenceUninstall( | ||
| 303 | CPI_APPLICATION_ROLE* pItm | ||
| 304 | ) | ||
| 305 | { | ||
| 306 | pItm->fReferencedForUninstall = TRUE; | ||
| 307 | CpiApplicationAddReferenceUninstall(pItm->pApplication); | ||
| 308 | } | ||
| 309 | |||
| 310 | HRESULT CpiApplicationRolesInstall( | ||
| 311 | CPI_APPLICATION_ROLE_LIST* pList, | ||
| 312 | int iRunMode, | ||
| 313 | LPWSTR* ppwzActionData, | ||
| 314 | int* piProgress | ||
| 315 | ) | ||
| 316 | { | ||
| 317 | HRESULT hr = S_OK; | ||
| 318 | |||
| 319 | int iActionType; | ||
| 320 | |||
| 321 | // add action text | ||
| 322 | hr = CpiAddActionTextToActionData(L"CreateComPlusApplicationRoles", ppwzActionData); | ||
| 323 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 324 | |||
| 325 | // add count to action data | ||
| 326 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
| 327 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 328 | |||
| 329 | // add roles to custom action data | ||
| 330 | for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 331 | { | ||
| 332 | // roles that are being installed only | ||
| 333 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 334 | continue; | ||
| 335 | |||
| 336 | // action type | ||
| 337 | if (rmRollback == iRunMode) | ||
| 338 | { | ||
| 339 | if (CpiIsInstalled(pItm->isInstalled)) | ||
| 340 | iActionType = atNoOp; | ||
| 341 | else | ||
| 342 | iActionType = atRemove; | ||
| 343 | } | ||
| 344 | else | ||
| 345 | iActionType = atCreate; | ||
| 346 | |||
| 347 | // add to action data | ||
| 348 | hr = AddApplicationRoleToActionData(pItm, iActionType, COST_APPLICATION_ROLE_CREATE, ppwzActionData); | ||
| 349 | ExitOnFailure(hr, "Failed to add application role to custom action data, key: %S", pItm->wzKey); | ||
| 350 | } | ||
| 351 | |||
| 352 | // add progress tics | ||
| 353 | if (piProgress) | ||
| 354 | *piProgress += COST_APPLICATION_ROLE_CREATE * pList->iInstallCount; | ||
| 355 | |||
| 356 | hr = S_OK; | ||
| 357 | |||
| 358 | LExit: | ||
| 359 | return hr; | ||
| 360 | } | ||
| 361 | |||
| 362 | HRESULT CpiApplicationRolesUninstall( | ||
| 363 | CPI_APPLICATION_ROLE_LIST* pList, | ||
| 364 | int iRunMode, | ||
| 365 | LPWSTR* ppwzActionData, | ||
| 366 | int* piProgress | ||
| 367 | ) | ||
| 368 | { | ||
| 369 | HRESULT hr = S_OK; | ||
| 370 | |||
| 371 | int iActionType; | ||
| 372 | |||
| 373 | // add action text | ||
| 374 | hr = CpiAddActionTextToActionData(L"RemoveComPlusApplicationRoles", ppwzActionData); | ||
| 375 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 376 | |||
| 377 | // add count to action data | ||
| 378 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
| 379 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 380 | |||
| 381 | // add roles to custom action data | ||
| 382 | for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 383 | { | ||
| 384 | // roles that are being uninstalled only | ||
| 385 | if (pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 386 | continue; | ||
| 387 | |||
| 388 | // action type | ||
| 389 | if (rmRollback == iRunMode) | ||
| 390 | iActionType = atCreate; | ||
| 391 | else | ||
| 392 | iActionType = atRemove; | ||
| 393 | |||
| 394 | // add to action data | ||
| 395 | hr = AddApplicationRoleToActionData(pItm, iActionType, COST_APPLICATION_ROLE_DELETE, ppwzActionData); | ||
| 396 | ExitOnFailure(hr, "Failed to add application role to custom action data, key: %S", pItm->wzKey); | ||
| 397 | } | ||
| 398 | |||
| 399 | // add progress tics | ||
| 400 | if (piProgress) | ||
| 401 | *piProgress += COST_APPLICATION_ROLE_DELETE * pList->iUninstallCount; | ||
| 402 | |||
| 403 | hr = S_OK; | ||
| 404 | |||
| 405 | LExit: | ||
| 406 | return hr; | ||
| 407 | } | ||
| 408 | |||
| 409 | HRESULT CpiApplicationRoleFindByKey( | ||
| 410 | CPI_APPLICATION_ROLE_LIST* pList, | ||
| 411 | LPCWSTR pwzKey, | ||
| 412 | CPI_APPLICATION_ROLE** ppAppRole | ||
| 413 | ) | ||
| 414 | { | ||
| 415 | for (CPI_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 416 | { | ||
| 417 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
| 418 | { | ||
| 419 | *ppAppRole = pItm; | ||
| 420 | return S_OK; | ||
| 421 | } | ||
| 422 | } | ||
| 423 | |||
| 424 | return S_FALSE; | ||
| 425 | } | ||
| 426 | |||
| 427 | void CpiUserInApplicationRoleListFree( | ||
| 428 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList | ||
| 429 | ) | ||
| 430 | { | ||
| 431 | CPI_USER_IN_APPLICATION_ROLE* pItm = pList->pFirst; | ||
| 432 | |||
| 433 | while (pItm) | ||
| 434 | { | ||
| 435 | CPI_USER_IN_APPLICATION_ROLE* pDelete = pItm; | ||
| 436 | pItm = pItm->pNext; | ||
| 437 | FreeUserInApplicationRole(pDelete); | ||
| 438 | } | ||
| 439 | } | ||
| 440 | |||
| 441 | HRESULT CpiUsersInApplicationRolesRead( | ||
| 442 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 443 | CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList | ||
| 444 | ) | ||
| 445 | { | ||
| 446 | HRESULT hr = S_OK; | ||
| 447 | |||
| 448 | // read users in application roles | ||
| 449 | if (CpiTableExists(cptComPlusUserInApplicationRole)) | ||
| 450 | { | ||
| 451 | hr = TrusteesInApplicationRolesRead(vcsUserInApplicationRoleQuery, pAppRoleList, pUsrInAppRoleList); | ||
| 452 | ExitOnFailure(hr, "Failed to read users in application roles"); | ||
| 453 | } | ||
| 454 | |||
| 455 | // read groups in application roles | ||
| 456 | if (CpiTableExists(cptComPlusGroupInApplicationRole)) | ||
| 457 | { | ||
| 458 | hr = TrusteesInApplicationRolesRead(vcsGroupInApplicationRoleQuery, pAppRoleList, pUsrInAppRoleList); | ||
| 459 | ExitOnFailure(hr, "Failed to read groups in application roles"); | ||
| 460 | } | ||
| 461 | |||
| 462 | hr = S_OK; | ||
| 463 | |||
| 464 | LExit: | ||
| 465 | return hr; | ||
| 466 | } | ||
| 467 | |||
| 468 | HRESULT CpiUsersInApplicationRolesInstall( | ||
| 469 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList, | ||
| 470 | int iRunMode, | ||
| 471 | LPWSTR* ppwzActionData, | ||
| 472 | int* piProgress | ||
| 473 | ) | ||
| 474 | { | ||
| 475 | HRESULT hr = S_OK; | ||
| 476 | |||
| 477 | int iActionType; | ||
| 478 | |||
| 479 | // add action text | ||
| 480 | hr = CpiAddActionTextToActionData(L"AddUsersToComPlusApplicationRoles", ppwzActionData); | ||
| 481 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 482 | |||
| 483 | // add count to action data | ||
| 484 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
| 485 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 486 | |||
| 487 | // add roles to custom action data | ||
| 488 | for (CPI_USER_IN_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 489 | { | ||
| 490 | // roles that are being installed only | ||
| 491 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 492 | continue; | ||
| 493 | |||
| 494 | // action type | ||
| 495 | if (rmRollback == iRunMode) | ||
| 496 | { | ||
| 497 | if (CpiIsInstalled(pItm->isInstalled)) | ||
| 498 | iActionType = atNoOp; | ||
| 499 | else | ||
| 500 | iActionType = atRemove; | ||
| 501 | } | ||
| 502 | else | ||
| 503 | iActionType = atCreate; | ||
| 504 | |||
| 505 | // add to action data | ||
| 506 | hr = AddUserInApplicationRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_CREATE, ppwzActionData); | ||
| 507 | ExitOnFailure(hr, "Failed to add user in application role to custom action data, key: %S", pItm->wzKey); | ||
| 508 | } | ||
| 509 | |||
| 510 | // add progress tics | ||
| 511 | if (piProgress) | ||
| 512 | *piProgress += COST_USER_IN_APPLICATION_ROLE_CREATE * pList->iInstallCount; | ||
| 513 | |||
| 514 | hr = S_OK; | ||
| 515 | |||
| 516 | LExit: | ||
| 517 | return hr; | ||
| 518 | } | ||
| 519 | |||
| 520 | HRESULT CpiUsersInApplicationRolesUninstall( | ||
| 521 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList, | ||
| 522 | int iRunMode, | ||
| 523 | LPWSTR* ppwzActionData, | ||
| 524 | int* piProgress | ||
| 525 | ) | ||
| 526 | { | ||
| 527 | HRESULT hr = S_OK; | ||
| 528 | |||
| 529 | int iActionType; | ||
| 530 | |||
| 531 | // add action text | ||
| 532 | hr = CpiAddActionTextToActionData(L"RemoveUsersFromComPlusAppRoles", ppwzActionData); | ||
| 533 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 534 | |||
| 535 | // add count to action data | ||
| 536 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
| 537 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 538 | |||
| 539 | // add roles to custom action data | ||
| 540 | for (CPI_USER_IN_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 541 | { | ||
| 542 | // roles that are being uninstalled only | ||
| 543 | if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 544 | continue; | ||
| 545 | |||
| 546 | // action type | ||
| 547 | if (rmRollback == iRunMode) | ||
| 548 | iActionType = atCreate; | ||
| 549 | else | ||
| 550 | iActionType = atRemove; | ||
| 551 | |||
| 552 | // add to action data | ||
| 553 | hr = AddUserInApplicationRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_DELETE, ppwzActionData); | ||
| 554 | ExitOnFailure(hr, "Failed to add user in application role to custom action data, key: %S", pItm->wzKey); | ||
| 555 | } | ||
| 556 | |||
| 557 | // add progress tics | ||
| 558 | if (piProgress) | ||
| 559 | *piProgress += COST_USER_IN_APPLICATION_ROLE_DELETE * pList->iUninstallCount; | ||
| 560 | |||
| 561 | hr = S_OK; | ||
| 562 | |||
| 563 | LExit: | ||
| 564 | return hr; | ||
| 565 | } | ||
| 566 | |||
| 567 | |||
| 568 | // helper function definitions | ||
| 569 | |||
| 570 | static HRESULT TrusteesInApplicationRolesRead( | ||
| 571 | LPCWSTR pwzQuery, | ||
| 572 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 573 | CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList | ||
| 574 | ) | ||
| 575 | { | ||
| 576 | HRESULT hr = S_OK; | ||
| 577 | UINT er = ERROR_SUCCESS; | ||
| 578 | |||
| 579 | PMSIHANDLE hView, hRec; | ||
| 580 | |||
| 581 | CPI_USER_IN_APPLICATION_ROLE* pItm = NULL; | ||
| 582 | LPWSTR pwzData = NULL; | ||
| 583 | LPWSTR pwzDomain = NULL; | ||
| 584 | LPWSTR pwzName = NULL; | ||
| 585 | BOOL fMatchingArchitecture = FALSE; | ||
| 586 | |||
| 587 | // loop through all application roles | ||
| 588 | hr = WcaOpenExecuteView(pwzQuery, &hView); | ||
| 589 | ExitOnFailure(hr, "Failed to execute view on table"); | ||
| 590 | |||
| 591 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 592 | { | ||
| 593 | // get component | ||
| 594 | hr = WcaGetRecordString(hRec, tiarqComponent, &pwzData); | ||
| 595 | ExitOnFailure(hr, "Failed to get component"); | ||
| 596 | |||
| 597 | // check if the component is our processor architecture | ||
| 598 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
| 599 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
| 600 | |||
| 601 | if (!fMatchingArchitecture) | ||
| 602 | { | ||
| 603 | continue; // not the same architecture, ignore | ||
| 604 | } | ||
| 605 | |||
| 606 | // create entry | ||
| 607 | pItm = (CPI_USER_IN_APPLICATION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_USER_IN_APPLICATION_ROLE)); | ||
| 608 | if (!pItm) | ||
| 609 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 610 | |||
| 611 | // get component install state | ||
| 612 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
| 613 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
| 614 | |||
| 615 | // get key | ||
| 616 | hr = WcaGetRecordString(hRec, tiarqUserInApplicationRole, &pwzData); | ||
| 617 | ExitOnFailure(hr, "Failed to get key"); | ||
| 618 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 619 | |||
| 620 | // get application role | ||
| 621 | hr = WcaGetRecordString(hRec, tiarqApplicationRole, &pwzData); | ||
| 622 | ExitOnFailure(hr, "Failed to get application role"); | ||
| 623 | |||
| 624 | hr = CpiApplicationRoleFindByKey(pAppRoleList, pwzData, &pItm->pApplicationRole); | ||
| 625 | if (S_FALSE == hr) | ||
| 626 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 627 | ExitOnFailure(hr, "Failed to find application role, key: %S", pwzData); | ||
| 628 | |||
| 629 | // get user domain | ||
| 630 | hr = WcaGetRecordFormattedString(hRec, tiarqDomain, &pwzDomain); | ||
| 631 | ExitOnFailure(hr, "Failed to get domain"); | ||
| 632 | |||
| 633 | // get user name | ||
| 634 | hr = WcaGetRecordFormattedString(hRec, tiarqName, &pwzName); | ||
| 635 | ExitOnFailure(hr, "Failed to get name"); | ||
| 636 | |||
| 637 | // build account name | ||
| 638 | hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount); | ||
| 639 | ExitOnFailure(hr, "Failed to build account name"); | ||
| 640 | |||
| 641 | // set references & increment counters | ||
| 642 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 643 | { | ||
| 644 | CpiApplicationRoleAddReferenceInstall(pItm->pApplicationRole); | ||
| 645 | pUsrInAppRoleList->iInstallCount++; | ||
| 646 | } | ||
| 647 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 648 | { | ||
| 649 | CpiApplicationRoleAddReferenceUninstall(pItm->pApplicationRole); | ||
| 650 | pUsrInAppRoleList->iUninstallCount++; | ||
| 651 | } | ||
| 652 | |||
| 653 | // add entry | ||
| 654 | if (pUsrInAppRoleList->pFirst) | ||
| 655 | pItm->pNext = pUsrInAppRoleList->pFirst; | ||
| 656 | pUsrInAppRoleList->pFirst = pItm; | ||
| 657 | pItm = NULL; | ||
| 658 | } | ||
| 659 | |||
| 660 | if (E_NOMOREITEMS == hr) | ||
| 661 | hr = S_OK; | ||
| 662 | |||
| 663 | LExit: | ||
| 664 | // clean up | ||
| 665 | if (pItm) | ||
| 666 | FreeUserInApplicationRole(pItm); | ||
| 667 | |||
| 668 | ReleaseStr(pwzData); | ||
| 669 | ReleaseStr(pwzDomain); | ||
| 670 | ReleaseStr(pwzName); | ||
| 671 | |||
| 672 | return hr; | ||
| 673 | } | ||
| 674 | |||
| 675 | static void FreeApplicationRole( | ||
| 676 | CPI_APPLICATION_ROLE* pItm | ||
| 677 | ) | ||
| 678 | { | ||
| 679 | if (pItm->pProperties) | ||
| 680 | CpiPropertiesFreeList(pItm->pProperties); | ||
| 681 | |||
| 682 | ReleaseObject(pItm->piUsersColl); | ||
| 683 | |||
| 684 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
| 685 | } | ||
| 686 | |||
| 687 | static void FreeUserInApplicationRole( | ||
| 688 | CPI_USER_IN_APPLICATION_ROLE* pItm | ||
| 689 | ) | ||
| 690 | { | ||
| 691 | ReleaseStr(pItm->pwzAccount); | ||
| 692 | |||
| 693 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
| 694 | } | ||
| 695 | |||
| 696 | //static HRESULT GetUsersCollForApplicationRole( | ||
| 697 | // CPI_APPLICATION_ROLE* pAppRole, | ||
| 698 | // ICatalogCollection** ppiUsersColl | ||
| 699 | // ) | ||
| 700 | //{ | ||
| 701 | // HRESULT hr = S_OK; | ||
| 702 | // | ||
| 703 | // ICatalogCollection* piRoleColl = NULL; | ||
| 704 | // ICatalogObject* piRoleObj = NULL; | ||
| 705 | // | ||
| 706 | // // if a previous attempt to locate the collection object failed | ||
| 707 | // if (pAppRole->fObjectNotFound) | ||
| 708 | // ExitFunction1(hr = S_FALSE); | ||
| 709 | // | ||
| 710 | // // get applications collection | ||
| 711 | // if (!pAppRole->piUsersColl) | ||
| 712 | // { | ||
| 713 | // // get collection object for role | ||
| 714 | // hr = FindObjectForApplicationRole(pAppRole, &piRoleObj); | ||
| 715 | // ExitOnFailure(hr, "Failed to find collection object for role"); | ||
| 716 | // | ||
| 717 | // if (S_FALSE == hr) | ||
| 718 | // ExitFunction(); // exit with hr = S_FALSE | ||
| 719 | // | ||
| 720 | // // get users collection | ||
| 721 | // hr = CpiGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInRole", &pAppRole->piUsersColl); | ||
| 722 | // ExitOnFailure(hr, "Failed to get users in role collection"); | ||
| 723 | // } | ||
| 724 | // | ||
| 725 | // // return value | ||
| 726 | // *ppiUsersColl = pAppRole->piUsersColl; | ||
| 727 | // (*ppiUsersColl)->AddRef(); | ||
| 728 | // | ||
| 729 | // hr = S_OK; | ||
| 730 | // | ||
| 731 | //LExit: | ||
| 732 | // // clean up | ||
| 733 | // ReleaseObject(piRoleColl); | ||
| 734 | // ReleaseObject(piRoleObj); | ||
| 735 | // | ||
| 736 | // return hr; | ||
| 737 | //} | ||
| 738 | |||
| 739 | static HRESULT FindObjectForApplicationRole( | ||
| 740 | CPI_APPLICATION_ROLE* pItm, | ||
| 741 | ICatalogObject** ppiRoleObj | ||
| 742 | ) | ||
| 743 | { | ||
| 744 | HRESULT hr = S_OK; | ||
| 745 | |||
| 746 | ICatalogCollection* piRoleColl = NULL; | ||
| 747 | |||
| 748 | // get roles collection | ||
| 749 | hr = CpiGetRolesCollForApplication(pItm->pApplication, &piRoleColl); | ||
| 750 | ExitOnFailure(hr, "Failed to get collection"); | ||
| 751 | |||
| 752 | if (S_FALSE == hr) | ||
| 753 | ExitFunction(); // exit with hr = S_FALSE | ||
| 754 | |||
| 755 | // find role object | ||
| 756 | hr = CpiFindCollectionObject(piRoleColl, NULL, pItm->wzName, ppiRoleObj); | ||
| 757 | ExitOnFailure(hr, "Failed to find object"); | ||
| 758 | |||
| 759 | // exit with hr from CpiFindCollectionObject() | ||
| 760 | |||
| 761 | LExit: | ||
| 762 | // clean up | ||
| 763 | ReleaseObject(piRoleColl); | ||
| 764 | |||
| 765 | return hr; | ||
| 766 | } | ||
| 767 | |||
| 768 | static HRESULT AddApplicationRoleToActionData( | ||
| 769 | CPI_APPLICATION_ROLE* pItm, | ||
| 770 | int iActionType, | ||
| 771 | int iActionCost, | ||
| 772 | LPWSTR* ppwzActionData | ||
| 773 | ) | ||
| 774 | { | ||
| 775 | HRESULT hr = S_OK; | ||
| 776 | |||
| 777 | // add action information to custom action data | ||
| 778 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
| 779 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
| 780 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
| 781 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
| 782 | |||
| 783 | // add application role information to custom action data | ||
| 784 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
| 785 | ExitOnFailure(hr, "Failed to add application role key to custom action data"); | ||
| 786 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
| 787 | ExitOnFailure(hr, "Failed to add application role name to custom action data"); | ||
| 788 | |||
| 789 | // add application information to custom action data | ||
| 790 | hr = WcaWriteStringToCaData(pItm->pApplication->wzID, ppwzActionData); | ||
| 791 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
| 792 | |||
| 793 | // add partition information to custom action data | ||
| 794 | hr = WcaWriteStringToCaData(pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L"", ppwzActionData); | ||
| 795 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
| 796 | |||
| 797 | // add properties to custom action data | ||
| 798 | hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
| 799 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
| 800 | |||
| 801 | hr = S_OK; | ||
| 802 | |||
| 803 | LExit: | ||
| 804 | return hr; | ||
| 805 | } | ||
| 806 | |||
| 807 | static HRESULT AddUserInApplicationRoleToActionData( | ||
| 808 | CPI_USER_IN_APPLICATION_ROLE* pItm, | ||
| 809 | int iActionType, | ||
| 810 | int iActionCost, | ||
| 811 | LPWSTR* ppwzActionData | ||
| 812 | ) | ||
| 813 | { | ||
| 814 | HRESULT hr = S_OK; | ||
| 815 | |||
| 816 | // add action information to custom action data | ||
| 817 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
| 818 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
| 819 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
| 820 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
| 821 | |||
| 822 | // add application role information to custom action data | ||
| 823 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
| 824 | ExitOnFailure(hr, "Failed to add key to custom action data"); | ||
| 825 | hr = WcaWriteStringToCaData(pItm->pApplicationRole->wzName, ppwzActionData); | ||
| 826 | ExitOnFailure(hr, "Failed to add role name to custom action data"); | ||
| 827 | hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData); | ||
| 828 | ExitOnFailure(hr, "Failed to add user account to custom action data"); | ||
| 829 | |||
| 830 | // add application information to custom action data | ||
| 831 | CPI_APPLICATION* pApplication = pItm->pApplicationRole->pApplication; | ||
| 832 | hr = WcaWriteStringToCaData(pApplication->wzID, ppwzActionData); | ||
| 833 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
| 834 | |||
| 835 | // add partition information to custom action data | ||
| 836 | hr = WcaWriteStringToCaData(pApplication->pPartition ? pApplication->pPartition->wzID : L"", ppwzActionData); | ||
| 837 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
| 838 | |||
| 839 | hr = S_OK; | ||
| 840 | |||
| 841 | LExit: | ||
| 842 | return hr; | ||
| 843 | } | ||
diff --git a/src/ca/cpapprolesched.h b/src/ca/cpapprolesched.h new file mode 100644 index 00000000..02852eef --- /dev/null +++ b/src/ca/cpapprolesched.h | |||
| @@ -0,0 +1,112 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | struct CPI_APPLICATION_ROLE | ||
| 6 | { | ||
| 7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 8 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 9 | |||
| 10 | int iPropertyCount; | ||
| 11 | CPI_PROPERTY* pProperties; | ||
| 12 | |||
| 13 | BOOL fHasComponent; | ||
| 14 | BOOL fReferencedForInstall; | ||
| 15 | BOOL fReferencedForUninstall; | ||
| 16 | BOOL fObjectNotFound; | ||
| 17 | |||
| 18 | INSTALLSTATE isInstalled, isAction; | ||
| 19 | |||
| 20 | CPI_APPLICATION* pApplication; | ||
| 21 | |||
| 22 | ICatalogCollection* piUsersColl; | ||
| 23 | |||
| 24 | CPI_APPLICATION_ROLE* pNext; | ||
| 25 | }; | ||
| 26 | |||
| 27 | struct CPI_APPLICATION_ROLE_LIST | ||
| 28 | { | ||
| 29 | CPI_APPLICATION_ROLE* pFirst; | ||
| 30 | |||
| 31 | int iInstallCount; | ||
| 32 | int iUninstallCount; | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct CPI_USER_IN_APPLICATION_ROLE | ||
| 36 | { | ||
| 37 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 38 | LPWSTR pwzAccount; | ||
| 39 | |||
| 40 | INSTALLSTATE isInstalled, isAction; | ||
| 41 | |||
| 42 | CPI_APPLICATION_ROLE* pApplicationRole; | ||
| 43 | |||
| 44 | CPI_USER_IN_APPLICATION_ROLE* pNext; | ||
| 45 | }; | ||
| 46 | |||
| 47 | struct CPI_USER_IN_APPLICATION_ROLE_LIST | ||
| 48 | { | ||
| 49 | CPI_USER_IN_APPLICATION_ROLE* pFirst; | ||
| 50 | |||
| 51 | int iInstallCount; | ||
| 52 | int iUninstallCount; | ||
| 53 | }; | ||
| 54 | |||
| 55 | |||
| 56 | // function prototypes | ||
| 57 | |||
| 58 | void CpiApplicationRoleListFree( | ||
| 59 | CPI_APPLICATION_ROLE_LIST* pList | ||
| 60 | ); | ||
| 61 | HRESULT CpiApplicationRolesRead( | ||
| 62 | CPI_APPLICATION_LIST* pAppList, | ||
| 63 | CPI_APPLICATION_ROLE_LIST* pAppRoleList | ||
| 64 | ); | ||
| 65 | HRESULT CpiApplicationRolesVerifyInstall( | ||
| 66 | CPI_APPLICATION_ROLE_LIST* pList | ||
| 67 | ); | ||
| 68 | HRESULT CpiApplicationRolesVerifyUninstall( | ||
| 69 | CPI_APPLICATION_ROLE_LIST* pList | ||
| 70 | ); | ||
| 71 | void CpiApplicationRoleAddReferenceInstall( | ||
| 72 | CPI_APPLICATION_ROLE* pItm | ||
| 73 | ); | ||
| 74 | void CpiApplicationRoleAddReferenceUninstall( | ||
| 75 | CPI_APPLICATION_ROLE* pItm | ||
| 76 | ); | ||
| 77 | HRESULT CpiApplicationRolesInstall( | ||
| 78 | CPI_APPLICATION_ROLE_LIST* pList, | ||
| 79 | int iRunMode, | ||
| 80 | LPWSTR* ppwzActionData, | ||
| 81 | int* piProgress | ||
| 82 | ); | ||
| 83 | HRESULT CpiApplicationRolesUninstall( | ||
| 84 | CPI_APPLICATION_ROLE_LIST* pList, | ||
| 85 | int iRunMode, | ||
| 86 | LPWSTR* ppwzActionData, | ||
| 87 | int* piProgress | ||
| 88 | ); | ||
| 89 | HRESULT CpiApplicationRoleFindByKey( | ||
| 90 | CPI_APPLICATION_ROLE_LIST* pList, | ||
| 91 | LPCWSTR pwzKey, | ||
| 92 | CPI_APPLICATION_ROLE** ppAppRole | ||
| 93 | ); | ||
| 94 | void CpiUserInApplicationRoleListFree( | ||
| 95 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList | ||
| 96 | ); | ||
| 97 | HRESULT CpiUsersInApplicationRolesRead( | ||
| 98 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 99 | CPI_USER_IN_APPLICATION_ROLE_LIST* pUsrInAppRoleList | ||
| 100 | ); | ||
| 101 | HRESULT CpiUsersInApplicationRolesInstall( | ||
| 102 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList, | ||
| 103 | int iRunMode, | ||
| 104 | LPWSTR* ppwzActionData, | ||
| 105 | int* piProgress | ||
| 106 | ); | ||
| 107 | HRESULT CpiUsersInApplicationRolesUninstall( | ||
| 108 | CPI_USER_IN_APPLICATION_ROLE_LIST* pList, | ||
| 109 | int iRunMode, | ||
| 110 | LPWSTR* ppwzActionData, | ||
| 111 | int* piProgress | ||
| 112 | ); | ||
diff --git a/src/ca/cpappsched.cpp b/src/ca/cpappsched.cpp new file mode 100644 index 00000000..cec99794 --- /dev/null +++ b/src/ca/cpappsched.cpp | |||
| @@ -0,0 +1,752 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // sql queries | ||
| 7 | |||
| 8 | LPCWSTR vcsApplicationQuery = | ||
| 9 | L"SELECT `Application`, `Component_`, `Partition_`, `Id`, `Name` FROM `ComPlusApplication`"; | ||
| 10 | enum eApplicationQuery { aqApplication = 1, aqComponent, aqPartition, aqID, aqName }; | ||
| 11 | |||
| 12 | LPCWSTR vcsApplicationPropertyQuery = | ||
| 13 | L"SELECT `Name`, `Value` FROM `ComPlusApplicationProperty` WHERE `Application_` = ?"; | ||
| 14 | |||
| 15 | |||
| 16 | // property definitions | ||
| 17 | |||
| 18 | CPI_PROPERTY_DEFINITION pdlApplicationProperties[] = | ||
| 19 | { | ||
| 20 | {L"3GigSupportEnabled", cpptBoolean, 500}, | ||
| 21 | {L"AccessChecksLevel", cpptInteger, 500}, | ||
| 22 | {L"Activation", cpptInteger, 500}, | ||
| 23 | {L"ApplicationAccessChecksEnabled", cpptBoolean, 500}, | ||
| 24 | {L"ApplicationDirectory", cpptString, 501}, | ||
| 25 | {L"Authentication", cpptInteger, 500}, | ||
| 26 | {L"AuthenticationCapability", cpptInteger, 500}, | ||
| 27 | {L"Changeable", cpptBoolean, 500}, | ||
| 28 | {L"CommandLine", cpptString, 500}, | ||
| 29 | {L"ConcurrentApps", cpptInteger, 501}, | ||
| 30 | {L"CreatedBy", cpptString, 500}, | ||
| 31 | {L"CRMEnabled", cpptBoolean, 500}, | ||
| 32 | {L"CRMLogFile", cpptString, 500}, | ||
| 33 | {L"Deleteable", cpptBoolean, 500}, | ||
| 34 | {L"Description", cpptString, 500}, | ||
| 35 | {L"DumpEnabled", cpptBoolean, 501}, | ||
| 36 | {L"DumpOnException", cpptBoolean, 501}, | ||
| 37 | {L"DumpOnFailfast", cpptBoolean, 501}, | ||
| 38 | {L"DumpPath", cpptString, 501}, | ||
| 39 | {L"EventsEnabled", cpptBoolean, 500}, | ||
| 40 | {L"Identity", cpptString, 500}, | ||
| 41 | {L"ImpersonationLevel", cpptInteger, 500}, | ||
| 42 | {L"IsEnabled", cpptBoolean, 501}, | ||
| 43 | {L"MaxDumpCount", cpptInteger, 501}, | ||
| 44 | {L"Password", cpptString, 500}, | ||
| 45 | {L"QCAuthenticateMsgs", cpptInteger, 501}, | ||
| 46 | {L"QCListenerMaxThreads", cpptInteger, 501}, | ||
| 47 | {L"QueueListenerEnabled", cpptBoolean, 500}, | ||
| 48 | {L"QueuingEnabled", cpptBoolean, 500}, | ||
| 49 | {L"RecycleActivationLimit", cpptInteger, 501}, | ||
| 50 | {L"RecycleCallLimit", cpptInteger, 501}, | ||
| 51 | {L"RecycleExpirationTimeout", cpptInteger, 501}, | ||
| 52 | {L"RecycleLifetimeLimit", cpptInteger, 501}, | ||
| 53 | {L"RecycleMemoryLimit", cpptInteger, 501}, | ||
| 54 | {L"Replicable", cpptBoolean, 501}, | ||
| 55 | {L"RunForever", cpptBoolean, 500}, | ||
| 56 | {L"ShutdownAfter", cpptInteger, 500}, | ||
| 57 | {L"SoapActivated", cpptBoolean, 502}, | ||
| 58 | {L"SoapBaseUrl", cpptString, 502}, | ||
| 59 | {L"SoapMailTo", cpptString, 502}, | ||
| 60 | {L"SoapVRoot", cpptString, 502}, | ||
| 61 | {L"SRPEnabled", cpptBoolean, 501}, | ||
| 62 | {L"SRPTrustLevel", cpptInteger, 501}, | ||
| 63 | {NULL, cpptNone, 0} | ||
| 64 | }; | ||
| 65 | |||
| 66 | |||
| 67 | // prototypes for private helper functions | ||
| 68 | |||
| 69 | static void FreeApplication( | ||
| 70 | CPI_APPLICATION* pItm | ||
| 71 | ); | ||
| 72 | static HRESULT FindObjectForApplication( | ||
| 73 | CPI_APPLICATION* pItm, | ||
| 74 | BOOL fFindId, | ||
| 75 | BOOL fFindName, | ||
| 76 | ICatalogObject** ppiAppObj | ||
| 77 | ); | ||
| 78 | static HRESULT AddApplicationToActionData( | ||
| 79 | CPI_APPLICATION* pItm, | ||
| 80 | int iActionType, | ||
| 81 | int iActionCost, | ||
| 82 | LPWSTR* ppwzActionData | ||
| 83 | ); | ||
| 84 | |||
| 85 | |||
| 86 | // function definitions | ||
| 87 | |||
| 88 | void CpiApplicationListFree( | ||
| 89 | CPI_APPLICATION_LIST* pList | ||
| 90 | ) | ||
| 91 | { | ||
| 92 | CPI_APPLICATION* pItm = pList->pFirst; | ||
| 93 | |||
| 94 | while (pItm) | ||
| 95 | { | ||
| 96 | CPI_APPLICATION* pDelete = pItm; | ||
| 97 | pItm = pItm->pNext; | ||
| 98 | FreeApplication(pDelete); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | HRESULT CpiApplicationsRead( | ||
| 103 | CPI_PARTITION_LIST* pPartList, | ||
| 104 | CPI_APPLICATION_LIST* pAppList | ||
| 105 | ) | ||
| 106 | { | ||
| 107 | HRESULT hr = S_OK; | ||
| 108 | UINT er = ERROR_SUCCESS; | ||
| 109 | |||
| 110 | int iVersionNT = 0; | ||
| 111 | |||
| 112 | PMSIHANDLE hView, hRec; | ||
| 113 | |||
| 114 | CPI_APPLICATION* pItm = NULL; | ||
| 115 | LPWSTR pwzData = NULL; | ||
| 116 | BOOL fMatchingArchitecture = FALSE; | ||
| 117 | |||
| 118 | // get NT version | ||
| 119 | hr = WcaGetIntProperty(L"VersionNT", &iVersionNT); | ||
| 120 | ExitOnFailure(hr, "Failed to get VersionNT property"); | ||
| 121 | |||
| 122 | // loop through all applications | ||
| 123 | hr = WcaOpenExecuteView(vcsApplicationQuery, &hView); | ||
| 124 | ExitOnFailure(hr, "Failed to execute view on ComPlusApplication table"); | ||
| 125 | |||
| 126 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 127 | { | ||
| 128 | // get component | ||
| 129 | hr = WcaGetRecordString(hRec, aqComponent, &pwzData); | ||
| 130 | ExitOnFailure(hr, "Failed to get component"); | ||
| 131 | |||
| 132 | // check if the component is our processor architecture | ||
| 133 | if (pwzData && *pwzData) | ||
| 134 | { | ||
| 135 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
| 136 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
| 137 | |||
| 138 | if (!fMatchingArchitecture) | ||
| 139 | { | ||
| 140 | continue; // not the same architecture, ignore | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | // create entry | ||
| 145 | pItm = (CPI_APPLICATION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_APPLICATION)); | ||
| 146 | if (!pItm) | ||
| 147 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 148 | |||
| 149 | // get component install state | ||
| 150 | if (pwzData && *pwzData) | ||
| 151 | { | ||
| 152 | pItm->fHasComponent = TRUE; | ||
| 153 | |||
| 154 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
| 155 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
| 156 | } | ||
| 157 | |||
| 158 | // get key | ||
| 159 | hr = WcaGetRecordString(hRec, aqApplication, &pwzData); | ||
| 160 | ExitOnFailure(hr, "Failed to get key"); | ||
| 161 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 162 | |||
| 163 | // get partition | ||
| 164 | if (502 <= iVersionNT) | ||
| 165 | { | ||
| 166 | hr = WcaGetRecordString(hRec, aqPartition, &pwzData); | ||
| 167 | ExitOnFailure(hr, "Failed to get partition"); | ||
| 168 | |||
| 169 | if (pwzData && *pwzData) | ||
| 170 | { | ||
| 171 | hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition); | ||
| 172 | ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData); | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | // get id | ||
| 177 | hr = WcaGetRecordFormattedString(hRec, aqID, &pwzData); | ||
| 178 | ExitOnFailure(hr, "Failed to get id"); | ||
| 179 | |||
| 180 | if (pwzData && *pwzData) | ||
| 181 | { | ||
| 182 | hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID)); | ||
| 183 | ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData); | ||
| 184 | } | ||
| 185 | |||
| 186 | // get name | ||
| 187 | hr = WcaGetRecordFormattedString(hRec, aqName, &pwzData); | ||
| 188 | ExitOnFailure(hr, "Failed to get name"); | ||
| 189 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
| 190 | |||
| 191 | // if application is a locater, either an id or a name must be provided | ||
| 192 | if (!pItm->fHasComponent && !*pItm->wzID && !*pItm->wzName) | ||
| 193 | ExitOnFailure(hr = E_FAIL, "An application locater must have either an id or a name associated, key: %S", pItm->wzKey); | ||
| 194 | |||
| 195 | // if application is not a locater, an name must be provided | ||
| 196 | if (pItm->fHasComponent && !*pItm->wzName) | ||
| 197 | ExitOnFailure(hr = E_FAIL, "An application must have a name associated, key: %S", pItm->wzKey); | ||
| 198 | |||
| 199 | // get properties | ||
| 200 | if (CpiTableExists(cptComPlusApplicationProperty) && pItm->fHasComponent) | ||
| 201 | { | ||
| 202 | hr = CpiPropertiesRead(vcsApplicationPropertyQuery, pItm->wzKey, pdlApplicationProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
| 203 | ExitOnFailure(hr, "Failed to get properties"); | ||
| 204 | } | ||
| 205 | |||
| 206 | // set references & increment counters | ||
| 207 | if (pItm->fHasComponent) | ||
| 208 | { | ||
| 209 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 210 | { | ||
| 211 | if (pItm->pPartition) | ||
| 212 | CpiPartitionAddReferenceInstall(pItm->pPartition); | ||
| 213 | pAppList->iInstallCount++; | ||
| 214 | } | ||
| 215 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 216 | { | ||
| 217 | if (pItm->pPartition) | ||
| 218 | CpiPartitionAddReferenceUninstall(pItm->pPartition); | ||
| 219 | pAppList->iUninstallCount++; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | // add entry | ||
| 224 | if (pAppList->pFirst) | ||
| 225 | pItm->pNext = pAppList->pFirst; | ||
| 226 | pAppList->pFirst = pItm; | ||
| 227 | pItm = NULL; | ||
| 228 | } | ||
| 229 | |||
| 230 | if (E_NOMOREITEMS == hr) | ||
| 231 | hr = S_OK; | ||
| 232 | |||
| 233 | LExit: | ||
| 234 | // clean up | ||
| 235 | if (pItm) | ||
| 236 | FreeApplication(pItm); | ||
| 237 | |||
| 238 | ReleaseStr(pwzData); | ||
| 239 | |||
| 240 | return hr; | ||
| 241 | } | ||
| 242 | |||
| 243 | HRESULT CpiApplicationsVerifyInstall( | ||
| 244 | CPI_APPLICATION_LIST* pList | ||
| 245 | ) | ||
| 246 | { | ||
| 247 | HRESULT hr = S_OK; | ||
| 248 | UINT er = ERROR_SUCCESS; | ||
| 249 | |||
| 250 | ICatalogObject* piAppObj = NULL; | ||
| 251 | |||
| 252 | for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 253 | { | ||
| 254 | // referenced locaters or applications that are being installed | ||
| 255 | if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction))) | ||
| 256 | continue; | ||
| 257 | |||
| 258 | // if the application is referensed and is not a locater, it must be installed | ||
| 259 | if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction)) | ||
| 260 | MessageExitOnFailure(hr = E_FAIL, msierrComPlusApplicationDependency, "An application is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey); | ||
| 261 | |||
| 262 | // application is supposed to exist | ||
| 263 | if (!pItm->fHasComponent || CpiIsInstalled(pItm->isInstalled)) | ||
| 264 | { | ||
| 265 | // get collection object for application | ||
| 266 | hr = FindObjectForApplication(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piAppObj); | ||
| 267 | ExitOnFailure(hr, "Failed to find collection object for application"); | ||
| 268 | |||
| 269 | // if the application was found | ||
| 270 | if (S_OK == hr) | ||
| 271 | { | ||
| 272 | // if we don't have an id, copy id from object | ||
| 273 | if (!*pItm->wzID) | ||
| 274 | { | ||
| 275 | hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID)); | ||
| 276 | ExitOnFailure(hr, "Failed to get id"); | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | // if the application was not found | ||
| 281 | else | ||
| 282 | { | ||
| 283 | // if the application is a locater, this is an error | ||
| 284 | if (!pItm->fHasComponent) | ||
| 285 | MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusApplicationNotFound, "An application required by this installation was not found, key: %S", pItm->wzKey); | ||
| 286 | |||
| 287 | // create a new id if one is missing | ||
| 288 | if (!*pItm->wzID) | ||
| 289 | { | ||
| 290 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
| 291 | ExitOnFailure(hr, "Failed to create id"); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | // application is supposed to be created | ||
| 297 | else | ||
| 298 | { | ||
| 299 | // check for conflicts | ||
| 300 | do { | ||
| 301 | if (*pItm->wzID) | ||
| 302 | { | ||
| 303 | // find applications with conflicting id | ||
| 304 | hr = FindObjectForApplication(pItm, TRUE, FALSE, &piAppObj); | ||
| 305 | ExitOnFailure(hr, "Failed to find collection object for application"); | ||
| 306 | |||
| 307 | if (S_FALSE == hr) | ||
| 308 | { | ||
| 309 | // find applications with conflicting name | ||
| 310 | hr = FindObjectForApplication(pItm, FALSE, TRUE, &piAppObj); | ||
| 311 | ExitOnFailure(hr, "Failed to find collection object for application"); | ||
| 312 | |||
| 313 | if (S_OK == hr) | ||
| 314 | // "A application with a conflictiong name exists. retry cancel" | ||
| 315 | er = WcaErrorMessage(msierrComPlusApplicationNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0); | ||
| 316 | else | ||
| 317 | break; // no conflicting entry found, break loop | ||
| 318 | } | ||
| 319 | else | ||
| 320 | // "A application with a conflicting id exists. abort retry ignore" | ||
| 321 | er = WcaErrorMessage(msierrComPlusApplicationIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 322 | } | ||
| 323 | else | ||
| 324 | { | ||
| 325 | // find applications with conflicting name | ||
| 326 | hr = FindObjectForApplication(pItm, FALSE, TRUE, &piAppObj); | ||
| 327 | ExitOnFailure(hr, "Failed to find collection object for application"); | ||
| 328 | |||
| 329 | if (S_OK == hr) | ||
| 330 | // "A subscription with a conflictiong name exists. abort retry ignore" | ||
| 331 | er = WcaErrorMessage(msierrComPlusApplicationNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 332 | else | ||
| 333 | break; // no conflicting entry found, break loop | ||
| 334 | } | ||
| 335 | |||
| 336 | switch (er) | ||
| 337 | { | ||
| 338 | case IDCANCEL: | ||
| 339 | case IDABORT: | ||
| 340 | ExitOnFailure(hr = E_FAIL, "An application with a conflictiong name or id exists, key: %S", pItm->wzKey); | ||
| 341 | break; | ||
| 342 | case IDRETRY: | ||
| 343 | break; | ||
| 344 | case IDIGNORE: | ||
| 345 | default: | ||
| 346 | // if we don't have an id, copy id from object | ||
| 347 | if (!*pItm->wzID) | ||
| 348 | { | ||
| 349 | hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID)); | ||
| 350 | ExitOnFailure(hr, "Failed to get id"); | ||
| 351 | } | ||
| 352 | hr = S_FALSE; // indicate that this is not a conflict | ||
| 353 | } | ||
| 354 | } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts | ||
| 355 | |||
| 356 | // create a new id if one is missing | ||
| 357 | if (!*pItm->wzID) | ||
| 358 | { | ||
| 359 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
| 360 | ExitOnFailure(hr, "Failed to create id"); | ||
| 361 | } | ||
| 362 | } | ||
| 363 | |||
| 364 | // clean up | ||
| 365 | ReleaseNullObject(piAppObj); | ||
| 366 | } | ||
| 367 | |||
| 368 | hr = S_OK; | ||
| 369 | |||
| 370 | LExit: | ||
| 371 | // clean up | ||
| 372 | ReleaseObject(piAppObj); | ||
| 373 | |||
| 374 | return hr; | ||
| 375 | } | ||
| 376 | |||
| 377 | HRESULT CpiApplicationsVerifyUninstall( | ||
| 378 | CPI_APPLICATION_LIST* pList | ||
| 379 | ) | ||
| 380 | { | ||
| 381 | HRESULT hr = S_OK; | ||
| 382 | ICatalogObject* piAppObj = NULL; | ||
| 383 | |||
| 384 | for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 385 | { | ||
| 386 | // referenced locaters or applications that are being installed | ||
| 387 | if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction))) | ||
| 388 | continue; | ||
| 389 | |||
| 390 | // get collection object for application | ||
| 391 | hr = FindObjectForApplication(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piAppObj); | ||
| 392 | ExitOnFailure(hr, "Failed to find collection object for application"); | ||
| 393 | |||
| 394 | // if the application was found | ||
| 395 | if (S_OK == hr) | ||
| 396 | { | ||
| 397 | // if we don't have an id, copy id from object | ||
| 398 | if (!*pItm->wzID) | ||
| 399 | { | ||
| 400 | hr = CpiGetKeyForObject(piAppObj, pItm->wzID, countof(pItm->wzID)); | ||
| 401 | ExitOnFailure(hr, "Failed to get id"); | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | // if the application was not found | ||
| 406 | else | ||
| 407 | { | ||
| 408 | pItm->fObjectNotFound = TRUE; | ||
| 409 | if (pItm->fHasComponent) | ||
| 410 | pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall | ||
| 411 | } | ||
| 412 | |||
| 413 | // clean up | ||
| 414 | ReleaseNullObject(piAppObj); | ||
| 415 | } | ||
| 416 | |||
| 417 | hr = S_OK; | ||
| 418 | |||
| 419 | LExit: | ||
| 420 | // clean up | ||
| 421 | ReleaseObject(piAppObj); | ||
| 422 | |||
| 423 | return hr; | ||
| 424 | } | ||
| 425 | |||
| 426 | void CpiApplicationAddReferenceInstall( | ||
| 427 | CPI_APPLICATION* pItm | ||
| 428 | ) | ||
| 429 | { | ||
| 430 | pItm->fReferencedForInstall = TRUE; | ||
| 431 | if (pItm->pPartition) | ||
| 432 | CpiPartitionAddReferenceInstall(pItm->pPartition); | ||
| 433 | } | ||
| 434 | |||
| 435 | void CpiApplicationAddReferenceUninstall( | ||
| 436 | CPI_APPLICATION* pItm | ||
| 437 | ) | ||
| 438 | { | ||
| 439 | pItm->fReferencedForUninstall = TRUE; | ||
| 440 | if (pItm->pPartition) | ||
| 441 | CpiPartitionAddReferenceUninstall(pItm->pPartition); | ||
| 442 | } | ||
| 443 | |||
| 444 | HRESULT CpiApplicationsInstall( | ||
| 445 | CPI_APPLICATION_LIST* pList, | ||
| 446 | int iRunMode, | ||
| 447 | LPWSTR* ppwzActionData, | ||
| 448 | int* piProgress | ||
| 449 | ) | ||
| 450 | { | ||
| 451 | HRESULT hr = S_OK; | ||
| 452 | |||
| 453 | int iActionType; | ||
| 454 | |||
| 455 | // add action text | ||
| 456 | hr = CpiAddActionTextToActionData(L"CreateComPlusApplications", ppwzActionData); | ||
| 457 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 458 | |||
| 459 | // add applicaton count to action data | ||
| 460 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
| 461 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 462 | |||
| 463 | // add applications to custom action data | ||
| 464 | for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 465 | { | ||
| 466 | // applications that are being installed only | ||
| 467 | if (!pItm->fHasComponent || !WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 468 | continue; | ||
| 469 | |||
| 470 | // action type | ||
| 471 | if (rmRollback == iRunMode) | ||
| 472 | { | ||
| 473 | if (CpiIsInstalled(pItm->isInstalled)) | ||
| 474 | iActionType = atNoOp; | ||
| 475 | else | ||
| 476 | iActionType = atRemove; | ||
| 477 | } | ||
| 478 | else | ||
| 479 | iActionType = atCreate; | ||
| 480 | |||
| 481 | // add to action data | ||
| 482 | hr = AddApplicationToActionData(pItm, iActionType, COST_APPLICATION_CREATE, ppwzActionData); | ||
| 483 | ExitOnFailure(hr, "Failed to add applicaton to custom action data, key: %S", pItm->wzKey); | ||
| 484 | } | ||
| 485 | |||
| 486 | // add progress tics | ||
| 487 | if (piProgress) | ||
| 488 | *piProgress += COST_APPLICATION_CREATE * pList->iInstallCount; | ||
| 489 | |||
| 490 | hr = S_OK; | ||
| 491 | |||
| 492 | LExit: | ||
| 493 | return hr; | ||
| 494 | } | ||
| 495 | |||
| 496 | HRESULT CpiApplicationsUninstall( | ||
| 497 | CPI_APPLICATION_LIST* pList, | ||
| 498 | int iRunMode, | ||
| 499 | LPWSTR* ppwzActionData, | ||
| 500 | int* piProgress | ||
| 501 | ) | ||
| 502 | { | ||
| 503 | HRESULT hr = S_OK; | ||
| 504 | |||
| 505 | int iActionType; | ||
| 506 | |||
| 507 | // add action text | ||
| 508 | hr = CpiAddActionTextToActionData(L"RemoveComPlusApplications", ppwzActionData); | ||
| 509 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 510 | |||
| 511 | // add applicaton count to action data | ||
| 512 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
| 513 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 514 | |||
| 515 | // add applications to custom action data | ||
| 516 | for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 517 | { | ||
| 518 | // applications that are being uninstalled only | ||
| 519 | if (!pItm->fHasComponent || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 520 | continue; | ||
| 521 | |||
| 522 | // action type | ||
| 523 | if (rmRollback == iRunMode) | ||
| 524 | iActionType = atCreate; | ||
| 525 | else | ||
| 526 | iActionType = atRemove; | ||
| 527 | |||
| 528 | // add to action data | ||
| 529 | hr = AddApplicationToActionData(pItm, iActionType, COST_APPLICATION_DELETE, ppwzActionData); | ||
| 530 | ExitOnFailure(hr, "Failed to add applicaton to custom action data, key: %S", pItm->wzKey); | ||
| 531 | } | ||
| 532 | |||
| 533 | // add progress tics | ||
| 534 | if (piProgress) | ||
| 535 | *piProgress += COST_APPLICATION_DELETE * pList->iUninstallCount; | ||
| 536 | |||
| 537 | hr = S_OK; | ||
| 538 | |||
| 539 | LExit: | ||
| 540 | return hr; | ||
| 541 | } | ||
| 542 | |||
| 543 | HRESULT CpiApplicationFindByKey( | ||
| 544 | CPI_APPLICATION_LIST* pList, | ||
| 545 | LPCWSTR pwzKey, | ||
| 546 | CPI_APPLICATION** ppApp | ||
| 547 | ) | ||
| 548 | { | ||
| 549 | for (CPI_APPLICATION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 550 | { | ||
| 551 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
| 552 | { | ||
| 553 | *ppApp = pItm; | ||
| 554 | return S_OK; | ||
| 555 | } | ||
| 556 | } | ||
| 557 | |||
| 558 | return S_FALSE; | ||
| 559 | } | ||
| 560 | |||
| 561 | HRESULT CpiGetRolesCollForApplication( | ||
| 562 | CPI_APPLICATION* pApp, | ||
| 563 | ICatalogCollection** ppiRolesColl | ||
| 564 | ) | ||
| 565 | { | ||
| 566 | HRESULT hr = S_OK; | ||
| 567 | |||
| 568 | ICatalogCollection* piAppColl = NULL; | ||
| 569 | ICatalogObject* piAppObj = NULL; | ||
| 570 | |||
| 571 | // if a previous attempt to locate the collection object failed | ||
| 572 | if (pApp->fObjectNotFound) | ||
| 573 | ExitFunction1(hr = S_FALSE); | ||
| 574 | |||
| 575 | // get applications collection | ||
| 576 | if (!pApp->piRolesColl) | ||
| 577 | { | ||
| 578 | // get applications collection | ||
| 579 | if (pApp->pPartition) | ||
| 580 | hr = CpiGetApplicationsCollForPartition(pApp->pPartition, &piAppColl); | ||
| 581 | else | ||
| 582 | hr = CpiGetApplicationsCollection(&piAppColl); | ||
| 583 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 584 | |||
| 585 | if (S_FALSE == hr) | ||
| 586 | ExitFunction(); // exit with hr = S_FALSE | ||
| 587 | |||
| 588 | // find application object | ||
| 589 | hr = CpiFindCollectionObject(piAppColl, pApp->wzID, *pApp->wzID ? NULL : pApp->wzName, &piAppObj); | ||
| 590 | ExitOnFailure(hr, "Failed to find application object"); | ||
| 591 | |||
| 592 | if (S_FALSE == hr) | ||
| 593 | ExitFunction(); // exit with hr = S_FALSE | ||
| 594 | |||
| 595 | // get roles collection | ||
| 596 | hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Roles", &pApp->piRolesColl); | ||
| 597 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
| 598 | } | ||
| 599 | |||
| 600 | // return value | ||
| 601 | *ppiRolesColl = pApp->piRolesColl; | ||
| 602 | (*ppiRolesColl)->AddRef(); | ||
| 603 | |||
| 604 | hr = S_OK; | ||
| 605 | |||
| 606 | LExit: | ||
| 607 | // clean up | ||
| 608 | ReleaseObject(piAppColl); | ||
| 609 | ReleaseObject(piAppObj); | ||
| 610 | |||
| 611 | return hr; | ||
| 612 | } | ||
| 613 | |||
| 614 | HRESULT CpiGetComponentsCollForApplication( | ||
| 615 | CPI_APPLICATION* pApp, | ||
| 616 | ICatalogCollection** ppiCompsColl | ||
| 617 | ) | ||
| 618 | { | ||
| 619 | HRESULT hr = S_OK; | ||
| 620 | |||
| 621 | ICatalogCollection* piAppColl = NULL; | ||
| 622 | ICatalogObject* piAppObj = NULL; | ||
| 623 | |||
| 624 | // if a previous attempt to locate the collection object failed | ||
| 625 | if (pApp->fObjectNotFound) | ||
| 626 | ExitFunction1(hr = S_FALSE); | ||
| 627 | |||
| 628 | // get applications collection | ||
| 629 | if (!pApp->piCompsColl) | ||
| 630 | { | ||
| 631 | // get applications collection | ||
| 632 | if (pApp->pPartition) | ||
| 633 | hr = CpiGetApplicationsCollForPartition(pApp->pPartition, &piAppColl); | ||
| 634 | else | ||
| 635 | hr = CpiGetApplicationsCollection(&piAppColl); | ||
| 636 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 637 | |||
| 638 | if (S_FALSE == hr) | ||
| 639 | ExitFunction(); // exit with hr = S_FALSE | ||
| 640 | |||
| 641 | // find application object | ||
| 642 | hr = CpiFindCollectionObject(piAppColl, pApp->wzID, *pApp->wzID ? NULL : pApp->wzName, &piAppObj); | ||
| 643 | ExitOnFailure(hr, "Failed to find application object"); | ||
| 644 | |||
| 645 | if (S_FALSE == hr) | ||
| 646 | ExitFunction(); // exit with hr = S_FALSE | ||
| 647 | |||
| 648 | // get roles collection | ||
| 649 | hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Components", &pApp->piCompsColl); | ||
| 650 | ExitOnFailure(hr, "Failed to get components collection"); | ||
| 651 | } | ||
| 652 | |||
| 653 | // return value | ||
| 654 | *ppiCompsColl = pApp->piCompsColl; | ||
| 655 | (*ppiCompsColl)->AddRef(); | ||
| 656 | |||
| 657 | hr = S_OK; | ||
| 658 | |||
| 659 | LExit: | ||
| 660 | // clean up | ||
| 661 | ReleaseObject(piAppColl); | ||
| 662 | ReleaseObject(piAppObj); | ||
| 663 | |||
| 664 | return hr; | ||
| 665 | } | ||
| 666 | |||
| 667 | |||
| 668 | // helper function definitions | ||
| 669 | |||
| 670 | static void FreeApplication( | ||
| 671 | CPI_APPLICATION* pItm | ||
| 672 | ) | ||
| 673 | { | ||
| 674 | if (pItm->pProperties) | ||
| 675 | CpiPropertiesFreeList(pItm->pProperties); | ||
| 676 | |||
| 677 | ReleaseObject(pItm->piRolesColl); | ||
| 678 | ReleaseObject(pItm->piCompsColl); | ||
| 679 | |||
| 680 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
| 681 | } | ||
| 682 | |||
| 683 | static HRESULT FindObjectForApplication( | ||
| 684 | CPI_APPLICATION* pItm, | ||
| 685 | BOOL fFindId, | ||
| 686 | BOOL fFindName, | ||
| 687 | ICatalogObject** ppiAppObj | ||
| 688 | ) | ||
| 689 | { | ||
| 690 | HRESULT hr = S_OK; | ||
| 691 | |||
| 692 | ICatalogCollection* piAppColl = NULL; | ||
| 693 | |||
| 694 | // get applications collection | ||
| 695 | if (pItm->pPartition) | ||
| 696 | hr = CpiGetApplicationsCollForPartition(pItm->pPartition, &piAppColl); | ||
| 697 | else | ||
| 698 | hr = CpiGetApplicationsCollection(&piAppColl); | ||
| 699 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 700 | |||
| 701 | if (S_FALSE == hr) | ||
| 702 | ExitFunction(); // exit with hr = S_FALSE | ||
| 703 | |||
| 704 | // find application object | ||
| 705 | hr = CpiFindCollectionObject(piAppColl, fFindId ? pItm->wzID : NULL, fFindName ? pItm->wzName : NULL, ppiAppObj); | ||
| 706 | ExitOnFailure(hr, "Failed to find application object"); | ||
| 707 | |||
| 708 | // exit with hr from CpiFindCollectionObject() | ||
| 709 | |||
| 710 | LExit: | ||
| 711 | // clean up | ||
| 712 | ReleaseObject(piAppColl); | ||
| 713 | |||
| 714 | return hr; | ||
| 715 | } | ||
| 716 | |||
| 717 | static HRESULT AddApplicationToActionData( | ||
| 718 | CPI_APPLICATION* pItm, | ||
| 719 | int iActionType, | ||
| 720 | int iActionCost, | ||
| 721 | LPWSTR* ppwzActionData | ||
| 722 | ) | ||
| 723 | { | ||
| 724 | HRESULT hr = S_OK; | ||
| 725 | |||
| 726 | // add action information to custom action data | ||
| 727 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
| 728 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
| 729 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
| 730 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
| 731 | |||
| 732 | // add application information to custom action data | ||
| 733 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
| 734 | ExitOnFailure(hr, "Failed to add application key to custom action data"); | ||
| 735 | hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData); | ||
| 736 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
| 737 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
| 738 | ExitOnFailure(hr, "Failed to add application name to custom action data"); | ||
| 739 | |||
| 740 | // add partition information to custom action data | ||
| 741 | hr = WcaWriteStringToCaData(pItm->pPartition ? pItm->pPartition->wzID : L"", ppwzActionData); | ||
| 742 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
| 743 | |||
| 744 | // add properties to custom action data | ||
| 745 | hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
| 746 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
| 747 | |||
| 748 | hr = S_OK; | ||
| 749 | |||
| 750 | LExit: | ||
| 751 | return hr; | ||
| 752 | } | ||
diff --git a/src/ca/cpappsched.h b/src/ca/cpappsched.h new file mode 100644 index 00000000..2cd6a0ee --- /dev/null +++ b/src/ca/cpappsched.h | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | struct CPI_APPLICATION | ||
| 6 | { | ||
| 7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 8 | WCHAR wzID[CPI_MAX_GUID + 1]; | ||
| 9 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 10 | |||
| 11 | int iPropertyCount; | ||
| 12 | CPI_PROPERTY* pProperties; | ||
| 13 | |||
| 14 | BOOL fHasComponent; | ||
| 15 | BOOL fReferencedForInstall; | ||
| 16 | BOOL fReferencedForUninstall; | ||
| 17 | BOOL fObjectNotFound; | ||
| 18 | |||
| 19 | INSTALLSTATE isInstalled, isAction; | ||
| 20 | |||
| 21 | CPI_PARTITION* pPartition; | ||
| 22 | |||
| 23 | ICatalogCollection* piRolesColl; | ||
| 24 | ICatalogCollection* piCompsColl; | ||
| 25 | |||
| 26 | CPI_APPLICATION* pNext; | ||
| 27 | }; | ||
| 28 | |||
| 29 | struct CPI_APPLICATION_LIST | ||
| 30 | { | ||
| 31 | CPI_APPLICATION* pFirst; | ||
| 32 | |||
| 33 | int iInstallCount; | ||
| 34 | int iUninstallCount; | ||
| 35 | }; | ||
| 36 | |||
| 37 | |||
| 38 | // function prototypes | ||
| 39 | |||
| 40 | void CpiApplicationListFree( | ||
| 41 | CPI_APPLICATION_LIST* pList | ||
| 42 | ); | ||
| 43 | HRESULT CpiApplicationsRead( | ||
| 44 | CPI_PARTITION_LIST* pPartList, | ||
| 45 | CPI_APPLICATION_LIST* pAppList | ||
| 46 | ); | ||
| 47 | HRESULT CpiApplicationsVerifyInstall( | ||
| 48 | CPI_APPLICATION_LIST* pList | ||
| 49 | ); | ||
| 50 | HRESULT CpiApplicationsVerifyUninstall( | ||
| 51 | CPI_APPLICATION_LIST* pList | ||
| 52 | ); | ||
| 53 | void CpiApplicationAddReferenceInstall( | ||
| 54 | CPI_APPLICATION* pItm | ||
| 55 | ); | ||
| 56 | void CpiApplicationAddReferenceUninstall( | ||
| 57 | CPI_APPLICATION* pItm | ||
| 58 | ); | ||
| 59 | HRESULT CpiApplicationsInstall( | ||
| 60 | CPI_APPLICATION_LIST* pList, | ||
| 61 | int iRunMode, | ||
| 62 | LPWSTR* ppwzActionData, | ||
| 63 | int* piProgress | ||
| 64 | ); | ||
| 65 | HRESULT CpiApplicationsUninstall( | ||
| 66 | CPI_APPLICATION_LIST* pList, | ||
| 67 | int iRunMode, | ||
| 68 | LPWSTR* ppwzActionData, | ||
| 69 | int* piProgress | ||
| 70 | ); | ||
| 71 | HRESULT CpiApplicationFindByKey( | ||
| 72 | CPI_APPLICATION_LIST* pList, | ||
| 73 | LPCWSTR pwzKey, | ||
| 74 | CPI_APPLICATION** ppApp | ||
| 75 | ); | ||
| 76 | HRESULT CpiGetRolesCollForApplication( | ||
| 77 | CPI_APPLICATION* pApp, | ||
| 78 | ICatalogCollection** ppiRolesColl | ||
| 79 | ); | ||
| 80 | HRESULT CpiGetComponentsCollForApplication( | ||
| 81 | CPI_APPLICATION* pApp, | ||
| 82 | ICatalogCollection** ppiCompsColl | ||
| 83 | ); | ||
diff --git a/src/ca/cpasmexec.cpp b/src/ca/cpasmexec.cpp new file mode 100644 index 00000000..339c08e1 --- /dev/null +++ b/src/ca/cpasmexec.cpp | |||
| @@ -0,0 +1,1888 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // GAC related declarations | ||
| 7 | |||
| 8 | typedef struct _FUSION_INSTALL_REFERENCE_ | ||
| 9 | { | ||
| 10 | DWORD cbSize; | ||
| 11 | DWORD dwFlags; | ||
| 12 | GUID guidScheme; | ||
| 13 | LPCWSTR szIdentifier; | ||
| 14 | LPCWSTR szNonCannonicalData; | ||
| 15 | } FUSION_INSTALL_REFERENCE; | ||
| 16 | |||
| 17 | typedef struct _FUSION_INSTALL_REFERENCE_ *LPFUSION_INSTALL_REFERENCE; | ||
| 18 | |||
| 19 | typedef const FUSION_INSTALL_REFERENCE *LPCFUSION_INSTALL_REFERENCE; | ||
| 20 | |||
| 21 | typedef struct _ASSEMBLY_INFO | ||
| 22 | { | ||
| 23 | ULONG cbAssemblyInfo; | ||
| 24 | DWORD dwAssemblyFlags; | ||
| 25 | ULARGE_INTEGER uliAssemblySizeInKB; | ||
| 26 | LPWSTR pszCurrentAssemblyPathBuf; | ||
| 27 | ULONG cchBuf; | ||
| 28 | } ASSEMBLY_INFO; | ||
| 29 | |||
| 30 | typedef interface IAssemblyCacheItem IAssemblyCacheItem; | ||
| 31 | |||
| 32 | MIDL_INTERFACE("e707dcde-d1cd-11d2-bab9-00c04f8eceae") | ||
| 33 | IAssemblyCache : public IUnknown | ||
| 34 | { | ||
| 35 | public: | ||
| 36 | virtual HRESULT STDMETHODCALLTYPE UninstallAssembly( | ||
| 37 | /* [in] */ DWORD dwFlags, | ||
| 38 | /* [in] */ LPCWSTR pszAssemblyName, | ||
| 39 | /* [in] */ LPCFUSION_INSTALL_REFERENCE pRefData, | ||
| 40 | /* [optional][out] */ ULONG *pulDisposition) = 0; | ||
| 41 | |||
| 42 | virtual HRESULT STDMETHODCALLTYPE QueryAssemblyInfo( | ||
| 43 | /* [in] */ DWORD dwFlags, | ||
| 44 | /* [in] */ LPCWSTR pszAssemblyName, | ||
| 45 | /* [out][in] */ ASSEMBLY_INFO *pAsmInfo) = 0; | ||
| 46 | |||
| 47 | virtual HRESULT STDMETHODCALLTYPE CreateAssemblyCacheItem( | ||
| 48 | /* [in] */ DWORD dwFlags, | ||
| 49 | /* [in] */ PVOID pvReserved, | ||
| 50 | /* [out] */ IAssemblyCacheItem **ppAsmItem, | ||
| 51 | /* [optional][in] */ LPCWSTR pszAssemblyName) = 0; | ||
| 52 | |||
| 53 | virtual HRESULT STDMETHODCALLTYPE CreateAssemblyScavenger( | ||
| 54 | /* [out] */ IUnknown **ppUnkReserved) = 0; | ||
| 55 | |||
| 56 | virtual HRESULT STDMETHODCALLTYPE InstallAssembly( | ||
| 57 | /* [in] */ DWORD dwFlags, | ||
| 58 | /* [in] */ LPCWSTR pszManifestFilePath, | ||
| 59 | /* [in] */ LPCFUSION_INSTALL_REFERENCE pRefData) = 0; | ||
| 60 | }; | ||
| 61 | |||
| 62 | typedef HRESULT (__stdcall *LoadLibraryShimFunc)(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll); | ||
| 63 | typedef HRESULT (__stdcall *CreateAssemblyCacheFunc)(IAssemblyCache **ppAsmCache, DWORD dwReserved); | ||
| 64 | |||
| 65 | |||
| 66 | // RegistrationHelper related declarations | ||
| 67 | |||
| 68 | static const GUID CLSID_RegistrationHelper = | ||
| 69 | { 0x89a86e7b, 0xc229, 0x4008, { 0x9b, 0xaa, 0x2f, 0x5c, 0x84, 0x11, 0xd7, 0xe0 } }; | ||
| 70 | |||
| 71 | enum eInstallationFlags { | ||
| 72 | ifConfigureComponentsOnly = 16, | ||
| 73 | ifFindOrCreateTargetApplication = 4, | ||
| 74 | ifExpectExistingTypeLib = 1 | ||
| 75 | }; | ||
| 76 | |||
| 77 | |||
| 78 | // private constants | ||
| 79 | |||
| 80 | enum eAssemblyAttributes | ||
| 81 | { | ||
| 82 | aaEventClass = (1 << 0), | ||
| 83 | aaDotNetAssembly = (1 << 1), | ||
| 84 | aaPathFromGAC = (1 << 2), | ||
| 85 | aaRunInCommit = (1 << 3) | ||
| 86 | }; | ||
| 87 | |||
| 88 | |||
| 89 | // private structs | ||
| 90 | |||
| 91 | struct CPI_ROLE_ASSIGNMENT | ||
| 92 | { | ||
| 93 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 94 | WCHAR wzRoleName[MAX_DARWIN_COLUMN + 1]; | ||
| 95 | |||
| 96 | CPI_ROLE_ASSIGNMENT* pNext; | ||
| 97 | }; | ||
| 98 | |||
| 99 | struct CPI_METHOD | ||
| 100 | { | ||
| 101 | WCHAR wzIndex[11 + 1]; | ||
| 102 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 103 | |||
| 104 | CPI_PROPERTY* pPropertyList; | ||
| 105 | CPI_ROLE_ASSIGNMENT* pRoleAssignmentList; | ||
| 106 | |||
| 107 | CPI_METHOD* pNext; | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct CPI_INTERFACE | ||
| 111 | { | ||
| 112 | WCHAR wzIID[CPI_MAX_GUID + 1]; | ||
| 113 | |||
| 114 | CPI_PROPERTY* pPropertyList; | ||
| 115 | CPI_ROLE_ASSIGNMENT* pRoleAssignmentList; | ||
| 116 | CPI_METHOD* pMethodList; | ||
| 117 | |||
| 118 | CPI_INTERFACE* pNext; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct CPI_COMPONENT | ||
| 122 | { | ||
| 123 | WCHAR wzCLSID[CPI_MAX_GUID + 1]; | ||
| 124 | |||
| 125 | CPI_PROPERTY* pPropertyList; | ||
| 126 | CPI_ROLE_ASSIGNMENT* pRoleAssignmentList; | ||
| 127 | CPI_INTERFACE* pInterfaceList; | ||
| 128 | |||
| 129 | CPI_COMPONENT* pNext; | ||
| 130 | }; | ||
| 131 | |||
| 132 | struct CPI_ASSEMBLY_ATTRIBUTES | ||
| 133 | { | ||
| 134 | int iActionType; | ||
| 135 | int iActionCost; | ||
| 136 | LPWSTR pwzKey; | ||
| 137 | LPWSTR pwzAssemblyName; | ||
| 138 | LPWSTR pwzDllPath; | ||
| 139 | LPWSTR pwzTlbPath; | ||
| 140 | LPWSTR pwzPSDllPath; | ||
| 141 | LPWSTR pwzAppID; | ||
| 142 | LPWSTR pwzPartID; | ||
| 143 | int iAttributes; | ||
| 144 | CPI_COMPONENT* pCompList; | ||
| 145 | }; | ||
| 146 | |||
| 147 | struct CPI_ROLE_ASSIGNMENTS_ATTRIBUTES | ||
| 148 | { | ||
| 149 | int iActionType; | ||
| 150 | int iActionCost; | ||
| 151 | LPWSTR pwzKey; | ||
| 152 | LPWSTR pwzAppID; | ||
| 153 | LPWSTR pwzPartID; | ||
| 154 | int iRoleCount; | ||
| 155 | CPI_COMPONENT* pCompList; | ||
| 156 | }; | ||
| 157 | |||
| 158 | |||
| 159 | // prototypes for private helper functions | ||
| 160 | |||
| 161 | static HRESULT RegisterAssembly( | ||
| 162 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 163 | ); | ||
| 164 | static HRESULT UnregisterAssembly( | ||
| 165 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 166 | ); | ||
| 167 | static void InitAssemblyExec(); | ||
| 168 | static void UninitAssemblyExec(); | ||
| 169 | static HRESULT GetRegistrationHelper( | ||
| 170 | IDispatch** ppiRegHlp | ||
| 171 | ); | ||
| 172 | static HRESULT GetAssemblyCacheObject( | ||
| 173 | IAssemblyCache** ppAssemblyCache | ||
| 174 | ); | ||
| 175 | static HRESULT GetAssemblyPathFromGAC( | ||
| 176 | LPCWSTR pwzAssemblyName, | ||
| 177 | LPWSTR* ppwzAssemblyPath | ||
| 178 | ); | ||
| 179 | static HRESULT RegisterDotNetAssembly( | ||
| 180 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 181 | ); | ||
| 182 | static HRESULT RegisterNativeAssembly( | ||
| 183 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 184 | ); | ||
| 185 | static HRESULT UnregisterDotNetAssembly( | ||
| 186 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 187 | ); | ||
| 188 | static HRESULT RemoveComponents( | ||
| 189 | ICatalogCollection* piCompColl, | ||
| 190 | CPI_COMPONENT* pCompList | ||
| 191 | ); | ||
| 192 | static HRESULT ReadAssemblyAttributes( | ||
| 193 | LPWSTR* ppwzData, | ||
| 194 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 195 | ); | ||
| 196 | static void FreeAssemblyAttributes( | ||
| 197 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 198 | ); | ||
| 199 | static HRESULT ReadRoleAssignmentsAttributes( | ||
| 200 | LPWSTR* ppwzData, | ||
| 201 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
| 202 | ); | ||
| 203 | static void FreeRoleAssignmentsAttributes( | ||
| 204 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
| 205 | ); | ||
| 206 | static HRESULT ConfigureComponents( | ||
| 207 | LPCWSTR pwzPartID, | ||
| 208 | LPCWSTR pwzAppID, | ||
| 209 | CPI_COMPONENT* pCompList, | ||
| 210 | BOOL fCreate, | ||
| 211 | BOOL fProgress | ||
| 212 | ); | ||
| 213 | static HRESULT ConfigureInterfaces( | ||
| 214 | ICatalogCollection* piCompColl, | ||
| 215 | ICatalogObject* piCompObj, | ||
| 216 | CPI_INTERFACE* pIntfList, | ||
| 217 | BOOL fCreate | ||
| 218 | ); | ||
| 219 | static HRESULT ConfigureMethods( | ||
| 220 | ICatalogCollection* piIntfColl, | ||
| 221 | ICatalogObject* piIntfObj, | ||
| 222 | CPI_METHOD* pMethList, | ||
| 223 | BOOL fCreate | ||
| 224 | ); | ||
| 225 | static HRESULT ConfigureRoleAssignments( | ||
| 226 | LPCWSTR pwzCollName, | ||
| 227 | ICatalogCollection* piCompColl, | ||
| 228 | ICatalogObject* piCompObj, | ||
| 229 | CPI_ROLE_ASSIGNMENT* pRoleList, | ||
| 230 | BOOL fCreate | ||
| 231 | ); | ||
| 232 | static HRESULT ReadComponentList( | ||
| 233 | LPWSTR* ppwzData, | ||
| 234 | CPI_COMPONENT** ppCompList | ||
| 235 | ); | ||
| 236 | static HRESULT ReadInterfaceList( | ||
| 237 | LPWSTR* ppwzData, | ||
| 238 | CPI_INTERFACE** ppIntfList | ||
| 239 | ); | ||
| 240 | static HRESULT ReadMethodList( | ||
| 241 | LPWSTR* ppwzData, | ||
| 242 | CPI_METHOD** ppMethList | ||
| 243 | ); | ||
| 244 | static HRESULT ReadRoleAssignmentList( | ||
| 245 | LPWSTR* ppwzData, | ||
| 246 | CPI_ROLE_ASSIGNMENT** ppRoleList | ||
| 247 | ); | ||
| 248 | static void FreeComponentList( | ||
| 249 | CPI_COMPONENT* pList | ||
| 250 | ); | ||
| 251 | static void FreeInterfaceList( | ||
| 252 | CPI_INTERFACE* pList | ||
| 253 | ); | ||
| 254 | static void FreeMethodList( | ||
| 255 | CPI_METHOD* pList | ||
| 256 | ); | ||
| 257 | static void FreeRoleAssignmentList( | ||
| 258 | CPI_ROLE_ASSIGNMENT* pList | ||
| 259 | ); | ||
| 260 | |||
| 261 | |||
| 262 | // variables | ||
| 263 | |||
| 264 | static IDispatch* gpiRegHlp; | ||
| 265 | static IAssemblyCache* gpAssemblyCache; | ||
| 266 | static HMODULE ghMscoree; | ||
| 267 | static HMODULE ghFusion; | ||
| 268 | |||
| 269 | |||
| 270 | // function definitions | ||
| 271 | |||
| 272 | HRESULT CpiConfigureAssemblies( | ||
| 273 | LPWSTR* ppwzData, | ||
| 274 | HANDLE hRollbackFile | ||
| 275 | ) | ||
| 276 | { | ||
| 277 | HRESULT hr = S_OK; | ||
| 278 | |||
| 279 | CPI_ASSEMBLY_ATTRIBUTES attrs; | ||
| 280 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 281 | |||
| 282 | // initialize | ||
| 283 | InitAssemblyExec(); | ||
| 284 | |||
| 285 | // read action text | ||
| 286 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
| 287 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 288 | |||
| 289 | // get count | ||
| 290 | int iCnt = 0; | ||
| 291 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 292 | ExitOnFailure(hr, "Failed to read count"); | ||
| 293 | |||
| 294 | // write count to rollback file | ||
| 295 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
| 296 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
| 297 | |||
| 298 | for (int i = 0; i < iCnt; i++) | ||
| 299 | { | ||
| 300 | // read attributes from CustomActionData | ||
| 301 | hr = ReadAssemblyAttributes(ppwzData, &attrs); | ||
| 302 | ExitOnFailure(hr, "Failed to read assembly attributes"); | ||
| 303 | |||
| 304 | // write key to rollback file | ||
| 305 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
| 306 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
| 307 | |||
| 308 | // action | ||
| 309 | switch (attrs.iActionType) | ||
| 310 | { | ||
| 311 | case atCreate: | ||
| 312 | hr = RegisterAssembly(&attrs); | ||
| 313 | ExitOnFailure(hr, "Failed to register assembly, key: %S", attrs.pwzKey); | ||
| 314 | break; | ||
| 315 | case atRemove: | ||
| 316 | hr = UnregisterAssembly(&attrs); | ||
| 317 | ExitOnFailure(hr, "Failed to unregister assembly, key: %S", attrs.pwzKey); | ||
| 318 | break; | ||
| 319 | default: | ||
| 320 | hr = S_OK; | ||
| 321 | break; | ||
| 322 | } | ||
| 323 | |||
| 324 | if (S_FALSE == hr) | ||
| 325 | ExitFunction(); // aborted by user | ||
| 326 | |||
| 327 | // write completion status to rollback file | ||
| 328 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
| 329 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
| 330 | |||
| 331 | // progress | ||
| 332 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 333 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 334 | } | ||
| 335 | |||
| 336 | hr = S_OK; | ||
| 337 | |||
| 338 | LExit: | ||
| 339 | // clean up | ||
| 340 | FreeAssemblyAttributes(&attrs); | ||
| 341 | |||
| 342 | // uninitialize | ||
| 343 | UninitAssemblyExec(); | ||
| 344 | |||
| 345 | return hr; | ||
| 346 | } | ||
| 347 | |||
| 348 | HRESULT CpiRollbackConfigureAssemblies( | ||
| 349 | LPWSTR* ppwzData, | ||
| 350 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 351 | ) | ||
| 352 | { | ||
| 353 | HRESULT hr = S_OK; | ||
| 354 | |||
| 355 | int iRollbackStatus; | ||
| 356 | |||
| 357 | CPI_ASSEMBLY_ATTRIBUTES attrs; | ||
| 358 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 359 | |||
| 360 | // initialize | ||
| 361 | InitAssemblyExec(); | ||
| 362 | |||
| 363 | // read action text | ||
| 364 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
| 365 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 366 | |||
| 367 | // get count | ||
| 368 | int iCnt = 0; | ||
| 369 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 370 | ExitOnFailure(hr, "Failed to read count"); | ||
| 371 | |||
| 372 | for (int i = 0; i < iCnt; i++) | ||
| 373 | { | ||
| 374 | // read attributes from CustomActionData | ||
| 375 | hr = ReadAssemblyAttributes(ppwzData, &attrs); | ||
| 376 | ExitOnFailure(hr, "Failed to read assembly attributes"); | ||
| 377 | |||
| 378 | // rollback status | ||
| 379 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
| 380 | |||
| 381 | if (S_FALSE == hr) | ||
| 382 | continue; // not found, nothing to rollback | ||
| 383 | |||
| 384 | // action | ||
| 385 | switch (attrs.iActionType) | ||
| 386 | { | ||
| 387 | case atCreate: | ||
| 388 | hr = RegisterAssembly(&attrs); | ||
| 389 | if (FAILED(hr)) | ||
| 390 | WcaLog(LOGMSG_STANDARD, "Failed to register assembly, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 391 | break; | ||
| 392 | case atRemove: | ||
| 393 | hr = UnregisterAssembly(&attrs); | ||
| 394 | if (FAILED(hr)) | ||
| 395 | WcaLog(LOGMSG_STANDARD, "Failed to unregister assembly, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 396 | break; | ||
| 397 | } | ||
| 398 | |||
| 399 | // check rollback status | ||
| 400 | if (0 == iRollbackStatus) | ||
| 401 | continue; // operation did not complete, skip progress | ||
| 402 | |||
| 403 | // progress | ||
| 404 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 405 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 406 | } | ||
| 407 | |||
| 408 | hr = S_OK; | ||
| 409 | |||
| 410 | LExit: | ||
| 411 | // clean up | ||
| 412 | FreeAssemblyAttributes(&attrs); | ||
| 413 | |||
| 414 | // uninitialize | ||
| 415 | UninitAssemblyExec(); | ||
| 416 | |||
| 417 | return hr; | ||
| 418 | } | ||
| 419 | |||
| 420 | HRESULT CpiConfigureRoleAssignments( | ||
| 421 | LPWSTR* ppwzData, | ||
| 422 | HANDLE hRollbackFile | ||
| 423 | ) | ||
| 424 | { | ||
| 425 | HRESULT hr = S_OK; | ||
| 426 | |||
| 427 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES attrs; | ||
| 428 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 429 | |||
| 430 | // read action text | ||
| 431 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
| 432 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 433 | |||
| 434 | // get count | ||
| 435 | int iCnt = 0; | ||
| 436 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 437 | ExitOnFailure(hr, "Failed to read count"); | ||
| 438 | |||
| 439 | // write count to rollback file | ||
| 440 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
| 441 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
| 442 | |||
| 443 | for (int i = 0; i < iCnt; i++) | ||
| 444 | { | ||
| 445 | // read attributes from CustomActionData | ||
| 446 | hr = ReadRoleAssignmentsAttributes(ppwzData, &attrs); | ||
| 447 | ExitOnFailure(hr, "Failed to read role assignments attributes"); | ||
| 448 | |||
| 449 | // write key to rollback file | ||
| 450 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
| 451 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
| 452 | |||
| 453 | // action | ||
| 454 | if (atNoOp != attrs.iActionType) | ||
| 455 | { | ||
| 456 | hr = ConfigureComponents(attrs.pwzPartID, attrs.pwzAppID, attrs.pCompList, atCreate == attrs.iActionType, TRUE); | ||
| 457 | ExitOnFailure(hr, "Failed to configure components"); | ||
| 458 | |||
| 459 | if (S_FALSE == hr) | ||
| 460 | ExitFunction(); // aborted by user | ||
| 461 | } | ||
| 462 | |||
| 463 | // write completion status to rollback file | ||
| 464 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
| 465 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
| 466 | |||
| 467 | // progress | ||
| 468 | hr = WcaProgressMessage(attrs.iActionCost * attrs.iRoleCount, FALSE); | ||
| 469 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 470 | } | ||
| 471 | |||
| 472 | hr = S_OK; | ||
| 473 | |||
| 474 | LExit: | ||
| 475 | // clean up | ||
| 476 | FreeRoleAssignmentsAttributes(&attrs); | ||
| 477 | |||
| 478 | return hr; | ||
| 479 | } | ||
| 480 | |||
| 481 | HRESULT CpiRollbackConfigureRoleAssignments( | ||
| 482 | LPWSTR* ppwzData, | ||
| 483 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 484 | ) | ||
| 485 | { | ||
| 486 | HRESULT hr = S_OK; | ||
| 487 | |||
| 488 | int iRollbackStatus; | ||
| 489 | |||
| 490 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES attrs; | ||
| 491 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 492 | |||
| 493 | // read action text | ||
| 494 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
| 495 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 496 | |||
| 497 | // get count | ||
| 498 | int iCnt = 0; | ||
| 499 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 500 | ExitOnFailure(hr, "Failed to read count"); | ||
| 501 | |||
| 502 | for (int i = 0; i < iCnt; i++) | ||
| 503 | { | ||
| 504 | // read attributes from CustomActionData | ||
| 505 | hr = ReadRoleAssignmentsAttributes(ppwzData, &attrs); | ||
| 506 | ExitOnFailure(hr, "Failed to read role assignments attributes"); | ||
| 507 | |||
| 508 | // rollback status | ||
| 509 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
| 510 | |||
| 511 | if (S_FALSE == hr) | ||
| 512 | continue; // not found, nothing to rollback | ||
| 513 | |||
| 514 | // action | ||
| 515 | if (atNoOp != attrs.iActionType) | ||
| 516 | { | ||
| 517 | hr = ConfigureComponents(attrs.pwzPartID, attrs.pwzAppID, attrs.pCompList, atCreate == attrs.iActionType, TRUE); | ||
| 518 | ExitOnFailure(hr, "Failed to configure components"); | ||
| 519 | |||
| 520 | if (S_FALSE == hr) | ||
| 521 | ExitFunction(); // aborted by user | ||
| 522 | } | ||
| 523 | |||
| 524 | // check rollback status | ||
| 525 | if (0 == iRollbackStatus) | ||
| 526 | continue; // operation did not complete, skip progress | ||
| 527 | |||
| 528 | // progress | ||
| 529 | hr = WcaProgressMessage(attrs.iActionCost * attrs.iRoleCount, FALSE); | ||
| 530 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 531 | } | ||
| 532 | |||
| 533 | hr = S_OK; | ||
| 534 | |||
| 535 | LExit: | ||
| 536 | // clean up | ||
| 537 | FreeRoleAssignmentsAttributes(&attrs); | ||
| 538 | |||
| 539 | return hr; | ||
| 540 | } | ||
| 541 | |||
| 542 | |||
| 543 | // helper function definitions | ||
| 544 | |||
| 545 | static HRESULT RegisterAssembly( | ||
| 546 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 547 | ) | ||
| 548 | { | ||
| 549 | HRESULT hr = S_OK; | ||
| 550 | |||
| 551 | // progress message | ||
| 552 | hr = CpiActionDataMessage(1, (pAttrs->iAttributes & aaPathFromGAC) ? pAttrs->pwzAssemblyName : pAttrs->pwzDllPath); | ||
| 553 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 554 | |||
| 555 | if (S_FALSE == hr) | ||
| 556 | ExitFunction(); // aborted by user | ||
| 557 | |||
| 558 | // log | ||
| 559 | WcaLog(LOGMSG_VERBOSE, "Registering assembly, key: %S", pAttrs->pwzKey); | ||
| 560 | |||
| 561 | // extract path from GAC | ||
| 562 | if (pAttrs->iAttributes & aaPathFromGAC) | ||
| 563 | { | ||
| 564 | hr = GetAssemblyPathFromGAC(pAttrs->pwzAssemblyName, &pAttrs->pwzDllPath); | ||
| 565 | if (S_FALSE == hr) | ||
| 566 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 567 | ExitOnFailure(hr, "Failed to get path for assembly from GAC"); | ||
| 568 | |||
| 569 | // log | ||
| 570 | WcaLog(LOGMSG_VERBOSE, "Assembly path extracted from GAC, key: %S, path: '%S'", pAttrs->pwzKey, pAttrs->pwzDllPath); | ||
| 571 | } | ||
| 572 | |||
| 573 | // .net assembly | ||
| 574 | if (pAttrs->iAttributes & aaDotNetAssembly) | ||
| 575 | { | ||
| 576 | hr = RegisterDotNetAssembly(pAttrs); | ||
| 577 | ExitOnFailure(hr, "Failed to register .NET assembly"); | ||
| 578 | } | ||
| 579 | |||
| 580 | // native assembly | ||
| 581 | else | ||
| 582 | { | ||
| 583 | hr = RegisterNativeAssembly(pAttrs); | ||
| 584 | ExitOnFailure(hr, "Failed to register native assembly"); | ||
| 585 | } | ||
| 586 | |||
| 587 | // configure components | ||
| 588 | if (pAttrs->pCompList) | ||
| 589 | { | ||
| 590 | hr = ConfigureComponents(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pCompList, TRUE, FALSE); | ||
| 591 | ExitOnFailure(hr, "Failed to configure components"); | ||
| 592 | } | ||
| 593 | |||
| 594 | hr = S_OK; | ||
| 595 | |||
| 596 | LExit: | ||
| 597 | return hr; | ||
| 598 | } | ||
| 599 | |||
| 600 | static HRESULT UnregisterAssembly( | ||
| 601 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 602 | ) | ||
| 603 | { | ||
| 604 | HRESULT hr = S_OK; | ||
| 605 | |||
| 606 | long lChanges = 0; | ||
| 607 | |||
| 608 | ICatalogCollection* piColl = NULL; | ||
| 609 | ICatalogObject* piObj = NULL; | ||
| 610 | |||
| 611 | // progress message | ||
| 612 | hr = CpiActionDataMessage(1, (pAttrs->iAttributes & aaPathFromGAC) ? pAttrs->pwzAssemblyName : pAttrs->pwzDllPath); | ||
| 613 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 614 | |||
| 615 | if (S_FALSE == hr) | ||
| 616 | ExitFunction(); // aborted by user | ||
| 617 | |||
| 618 | // log | ||
| 619 | WcaLog(LOGMSG_VERBOSE, "Unregistering assembly, key: %S", pAttrs->pwzKey); | ||
| 620 | |||
| 621 | // extract path from GAC | ||
| 622 | if (pAttrs->iAttributes & aaPathFromGAC) | ||
| 623 | { | ||
| 624 | hr = GetAssemblyPathFromGAC(pAttrs->pwzAssemblyName, &pAttrs->pwzDllPath); | ||
| 625 | ExitOnFailure(hr, "Failed to get path for assembly from GAC"); | ||
| 626 | |||
| 627 | if (S_FALSE == hr) | ||
| 628 | { | ||
| 629 | WcaLog(LOGMSG_VERBOSE, "Unable to locate assembly in GAC, assembly will not be unregistered from COM+, key: %S", pAttrs->pwzKey); | ||
| 630 | ExitFunction1(hr = S_OK); | ||
| 631 | } | ||
| 632 | |||
| 633 | // log | ||
| 634 | WcaLog(LOGMSG_VERBOSE, "Assembly path extracted from GAC, key: %S, path: '%S'", pAttrs->pwzKey, pAttrs->pwzDllPath); | ||
| 635 | } | ||
| 636 | |||
| 637 | // .NET assembly | ||
| 638 | if (pAttrs->iAttributes & aaDotNetAssembly) | ||
| 639 | { | ||
| 640 | if (pAttrs->pwzAppID && *pAttrs->pwzAppID) | ||
| 641 | { | ||
| 642 | // When unregistering a .net assembly using the RegistrationHelper class, and the application is | ||
| 643 | // left empty after all components in the assembly are removed, the RegistrationHelper class also | ||
| 644 | // attempts to remove the application for some reason. However, it does not handle the situation | ||
| 645 | // when the application has its deleteable property set to false, and will simply fail if this is | ||
| 646 | // the case. This is the reason we are clearing the deleatable property of the application here. | ||
| 647 | // | ||
| 648 | // TODO: handle rollbacks | ||
| 649 | |||
| 650 | // get applications collection | ||
| 651 | hr = CpiGetApplicationsCollection(pAttrs->pwzPartID, &piColl); | ||
| 652 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 653 | |||
| 654 | if (S_FALSE == hr) | ||
| 655 | { | ||
| 656 | // applications collection not found | ||
| 657 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve applications collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 658 | ExitFunction1(hr = S_OK); | ||
| 659 | } | ||
| 660 | |||
| 661 | // find application object | ||
| 662 | hr = CpiFindCollectionObjectByStringKey(piColl, pAttrs->pwzAppID, &piObj); | ||
| 663 | ExitOnFailure(hr, "Failed to find application object"); | ||
| 664 | |||
| 665 | if (S_FALSE == hr) | ||
| 666 | { | ||
| 667 | // application not found | ||
| 668 | WcaLog(LOGMSG_VERBOSE, "Unable to find application object, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 669 | ExitFunction1(hr = S_OK); | ||
| 670 | } | ||
| 671 | |||
| 672 | // reset deleteable property | ||
| 673 | hr = CpiResetObjectProperty(piColl, piObj, L"Deleteable"); | ||
| 674 | ExitOnFailure(hr, "Failed to reset deleteable property"); | ||
| 675 | } | ||
| 676 | |||
| 677 | // unregister assembly | ||
| 678 | hr = UnregisterDotNetAssembly(pAttrs); | ||
| 679 | ExitOnFailure(hr, "Failed to unregister .NET assembly"); | ||
| 680 | } | ||
| 681 | |||
| 682 | // native assembly | ||
| 683 | else | ||
| 684 | { | ||
| 685 | // get components collection | ||
| 686 | hr = CpiGetComponentsCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piColl); | ||
| 687 | ExitOnFailure(hr, "Failed to get components collection"); | ||
| 688 | |||
| 689 | if (S_FALSE == hr) | ||
| 690 | { | ||
| 691 | // components collection not found | ||
| 692 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve components collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 693 | ExitFunction1(hr = S_OK); | ||
| 694 | } | ||
| 695 | |||
| 696 | // remove components | ||
| 697 | hr = RemoveComponents(piColl, pAttrs->pCompList); | ||
| 698 | ExitOnFailure(hr, "Failed to get remove components"); | ||
| 699 | |||
| 700 | // save changes | ||
| 701 | hr = piColl->SaveChanges(&lChanges); | ||
| 702 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 703 | CpiLogCatalogErrorInfo(); | ||
| 704 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 705 | } | ||
| 706 | |||
| 707 | hr = S_OK; | ||
| 708 | |||
| 709 | LExit: | ||
| 710 | // clean up | ||
| 711 | ReleaseObject(piColl); | ||
| 712 | ReleaseObject(piObj); | ||
| 713 | |||
| 714 | return hr; | ||
| 715 | } | ||
| 716 | |||
| 717 | static void InitAssemblyExec() | ||
| 718 | { | ||
| 719 | gpiRegHlp = NULL; | ||
| 720 | gpAssemblyCache = NULL; | ||
| 721 | ghMscoree = NULL; | ||
| 722 | ghFusion = NULL; | ||
| 723 | } | ||
| 724 | |||
| 725 | static void UninitAssemblyExec() | ||
| 726 | { | ||
| 727 | ReleaseObject(gpiRegHlp); | ||
| 728 | ReleaseObject(gpAssemblyCache); | ||
| 729 | if (ghFusion) | ||
| 730 | ::FreeLibrary(ghFusion); | ||
| 731 | if (ghMscoree) | ||
| 732 | ::FreeLibrary(ghMscoree); | ||
| 733 | } | ||
| 734 | |||
| 735 | static HRESULT GetRegistrationHelper( | ||
| 736 | IDispatch** ppiRegHlp | ||
| 737 | ) | ||
| 738 | { | ||
| 739 | HRESULT hr = S_OK; | ||
| 740 | |||
| 741 | if (!gpiRegHlp) | ||
| 742 | { | ||
| 743 | // create registration helper object | ||
| 744 | hr = ::CoCreateInstance(CLSID_RegistrationHelper, NULL, CLSCTX_ALL, IID_IDispatch, (void**)&gpiRegHlp); | ||
| 745 | ExitOnFailure(hr, "Failed to create registration helper object"); | ||
| 746 | } | ||
| 747 | |||
| 748 | gpiRegHlp->AddRef(); | ||
| 749 | *ppiRegHlp = gpiRegHlp; | ||
| 750 | |||
| 751 | hr = S_OK; | ||
| 752 | |||
| 753 | LExit: | ||
| 754 | return hr; | ||
| 755 | } | ||
| 756 | |||
| 757 | static HRESULT GetAssemblyCacheObject( | ||
| 758 | IAssemblyCache** ppAssemblyCache | ||
| 759 | ) | ||
| 760 | { | ||
| 761 | HRESULT hr = S_OK; | ||
| 762 | |||
| 763 | if (!gpAssemblyCache) | ||
| 764 | { | ||
| 765 | // mscoree.dll | ||
| 766 | if (!ghMscoree) | ||
| 767 | { | ||
| 768 | // load mscoree.dll | ||
| 769 | ghMscoree = ::LoadLibraryW(L"mscoree.dll"); | ||
| 770 | ExitOnNull(ghMscoree, hr, E_FAIL, "Failed to load mscoree.dll"); | ||
| 771 | } | ||
| 772 | |||
| 773 | // fusion.dll | ||
| 774 | if (!ghFusion) | ||
| 775 | { | ||
| 776 | // get LoadLibraryShim function address | ||
| 777 | LoadLibraryShimFunc pfnLoadLibraryShim = (LoadLibraryShimFunc)::GetProcAddress(ghMscoree, "LoadLibraryShim"); | ||
| 778 | ExitOnNull(pfnLoadLibraryShim, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for LoadLibraryShim() function"); | ||
| 779 | |||
| 780 | // load fusion.dll | ||
| 781 | hr = pfnLoadLibraryShim(L"fusion.dll", NULL, NULL, &ghFusion); | ||
| 782 | ExitOnFailure(hr, "Failed to load fusion.dll"); | ||
| 783 | } | ||
| 784 | |||
| 785 | // get CreateAssemblyCache function address | ||
| 786 | CreateAssemblyCacheFunc pfnCreateAssemblyCache = (CreateAssemblyCacheFunc)::GetProcAddress(ghFusion, "CreateAssemblyCache"); | ||
| 787 | ExitOnNull(pfnCreateAssemblyCache, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for CreateAssemblyCache() function"); | ||
| 788 | |||
| 789 | // create AssemblyCache object | ||
| 790 | hr = pfnCreateAssemblyCache(&gpAssemblyCache, 0); | ||
| 791 | ExitOnFailure(hr, "Failed to create AssemblyCache object"); | ||
| 792 | } | ||
| 793 | |||
| 794 | gpAssemblyCache->AddRef(); | ||
| 795 | *ppAssemblyCache = gpAssemblyCache; | ||
| 796 | |||
| 797 | hr = S_OK; | ||
| 798 | |||
| 799 | LExit: | ||
| 800 | return hr; | ||
| 801 | } | ||
| 802 | |||
| 803 | static HRESULT GetAssemblyPathFromGAC( | ||
| 804 | LPCWSTR pwzAssemblyName, | ||
| 805 | LPWSTR* ppwzAssemblyPath | ||
| 806 | ) | ||
| 807 | { | ||
| 808 | HRESULT hr = S_OK; | ||
| 809 | |||
| 810 | IAssemblyCache* pAssemblyCache = NULL; | ||
| 811 | |||
| 812 | ASSEMBLY_INFO assemblyInfo; | ||
| 813 | WCHAR wzPathBuf[MAX_PATH]; | ||
| 814 | |||
| 815 | ::ZeroMemory(&assemblyInfo, sizeof(ASSEMBLY_INFO)); | ||
| 816 | ::ZeroMemory(wzPathBuf, countof(wzPathBuf)); | ||
| 817 | |||
| 818 | // get AssemblyCache object | ||
| 819 | hr = GetAssemblyCacheObject(&pAssemblyCache); | ||
| 820 | ExitOnFailure(hr, "Failed to get AssemblyCache object"); | ||
| 821 | |||
| 822 | // get assembly info | ||
| 823 | assemblyInfo.cbAssemblyInfo = sizeof(ASSEMBLY_INFO); | ||
| 824 | assemblyInfo.pszCurrentAssemblyPathBuf = wzPathBuf; | ||
| 825 | assemblyInfo.cchBuf = countof(wzPathBuf); | ||
| 826 | |||
| 827 | hr = pAssemblyCache->QueryAssemblyInfo(0, pwzAssemblyName, &assemblyInfo); | ||
| 828 | if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
| 829 | ExitFunction1(hr = S_FALSE); | ||
| 830 | ExitOnFailure(hr, "Failed to get assembly info"); | ||
| 831 | |||
| 832 | // copy assembly path | ||
| 833 | hr = StrAllocString(ppwzAssemblyPath, wzPathBuf, 0); | ||
| 834 | ExitOnFailure(hr, "Failed to copy assembly path"); | ||
| 835 | |||
| 836 | hr = S_OK; | ||
| 837 | |||
| 838 | LExit: | ||
| 839 | // clean up | ||
| 840 | ReleaseObject(pAssemblyCache); | ||
| 841 | |||
| 842 | return hr; | ||
| 843 | } | ||
| 844 | |||
| 845 | static HRESULT RegisterDotNetAssembly( | ||
| 846 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 847 | ) | ||
| 848 | { | ||
| 849 | HRESULT hr = S_OK; | ||
| 850 | |||
| 851 | IDispatch* piRegHlp = NULL; | ||
| 852 | |||
| 853 | DISPID dispid; | ||
| 854 | BSTR bstrMember = NULL; | ||
| 855 | |||
| 856 | long lInstallationFlags = 0; | ||
| 857 | |||
| 858 | VARIANTARG rgvarg[5]; | ||
| 859 | DISPPARAMS dispparams; | ||
| 860 | EXCEPINFO excepInfo; | ||
| 861 | |||
| 862 | BSTR bstrPartName = NULL; | ||
| 863 | BSTR bstrAppName = NULL; | ||
| 864 | BSTR bstrDllPath = NULL; | ||
| 865 | BSTR bstrTlbPath = NULL; | ||
| 866 | |||
| 867 | ::ZeroMemory(rgvarg, sizeof(rgvarg)); | ||
| 868 | ::ZeroMemory(&dispparams, sizeof(dispparams)); | ||
| 869 | ::ZeroMemory(&excepInfo, sizeof(excepInfo)); | ||
| 870 | |||
| 871 | bstrMember = ::SysAllocString(L"InstallAssembly_2"); | ||
| 872 | ExitOnNull(bstrMember, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for method name"); | ||
| 873 | |||
| 874 | // create BSTRs for parameters | ||
| 875 | if (pAttrs->pwzPartID && *pAttrs->pwzPartID) | ||
| 876 | { | ||
| 877 | bstrPartName = ::SysAllocString(pAttrs->pwzPartID); | ||
| 878 | ExitOnNull(bstrPartName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id"); | ||
| 879 | } | ||
| 880 | |||
| 881 | if (pAttrs->pwzAppID && *pAttrs->pwzAppID) | ||
| 882 | { | ||
| 883 | bstrAppName = ::SysAllocString(pAttrs->pwzAppID); | ||
| 884 | ExitOnNull(bstrAppName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id"); | ||
| 885 | } | ||
| 886 | |||
| 887 | bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath); | ||
| 888 | ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path"); | ||
| 889 | |||
| 890 | if (pAttrs->pwzTlbPath && *pAttrs->pwzTlbPath) | ||
| 891 | { | ||
| 892 | bstrTlbPath = ::SysAllocString(pAttrs->pwzTlbPath); | ||
| 893 | ExitOnNull(bstrTlbPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path"); | ||
| 894 | } | ||
| 895 | |||
| 896 | // get registration helper object | ||
| 897 | hr = GetRegistrationHelper(&piRegHlp); | ||
| 898 | ExitOnFailure(hr, "Failed to get registration helper object"); | ||
| 899 | |||
| 900 | // get dispatch id of InstallAssembly() method | ||
| 901 | hr = piRegHlp->GetIDsOfNames(IID_NULL, &bstrMember, 1, LOCALE_USER_DEFAULT, &dispid); | ||
| 902 | ExitOnFailure(hr, "Failed to get dispatch id of InstallAssembly() method"); | ||
| 903 | |||
| 904 | // set installation flags | ||
| 905 | lInstallationFlags = ifExpectExistingTypeLib; | ||
| 906 | |||
| 907 | if (!bstrAppName) | ||
| 908 | lInstallationFlags |= ifFindOrCreateTargetApplication; | ||
| 909 | |||
| 910 | // invoke InstallAssembly() method | ||
| 911 | rgvarg[0].vt = VT_I4; | ||
| 912 | rgvarg[0].lVal = lInstallationFlags; | ||
| 913 | rgvarg[1].vt = VT_BYREF|VT_BSTR; | ||
| 914 | rgvarg[1].pbstrVal = &bstrTlbPath; | ||
| 915 | rgvarg[2].vt = VT_BSTR; | ||
| 916 | rgvarg[2].bstrVal = bstrPartName; | ||
| 917 | rgvarg[3].vt = VT_BYREF|VT_BSTR; | ||
| 918 | rgvarg[3].pbstrVal = &bstrAppName; | ||
| 919 | rgvarg[4].vt = VT_BSTR; | ||
| 920 | rgvarg[4].bstrVal = bstrDllPath; | ||
| 921 | dispparams.rgvarg = rgvarg; | ||
| 922 | dispparams.cArgs = 5; | ||
| 923 | dispparams.cNamedArgs = 0; | ||
| 924 | |||
| 925 | hr = piRegHlp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, NULL, &excepInfo, NULL); | ||
| 926 | if (DISP_E_EXCEPTION == hr) | ||
| 927 | { | ||
| 928 | // log exception information | ||
| 929 | if (!excepInfo.pfnDeferredFillIn || (excepInfo.pfnDeferredFillIn && SUCCEEDED(excepInfo.pfnDeferredFillIn(&excepInfo)))) | ||
| 930 | { | ||
| 931 | WcaLog(LOGMSG_STANDARD, "ExceptionInfo: Code='%hu', Source='%S', Description='%S', HelpFile='%S', HelpContext='%u'", | ||
| 932 | excepInfo.wCode, excepInfo.bstrSource, | ||
| 933 | excepInfo.bstrDescription ? excepInfo.bstrDescription : L"", | ||
| 934 | excepInfo.bstrHelpFile ? excepInfo.bstrHelpFile : L"", | ||
| 935 | excepInfo.dwHelpContext); | ||
| 936 | } | ||
| 937 | } | ||
| 938 | ExitOnFailure(hr, "Failed to invoke RegistrationHelper.InstallAssembly() method"); | ||
| 939 | |||
| 940 | hr = S_OK; | ||
| 941 | |||
| 942 | LExit: | ||
| 943 | // clean up | ||
| 944 | ReleaseObject(piRegHlp); | ||
| 945 | |||
| 946 | ReleaseBSTR(bstrMember); | ||
| 947 | |||
| 948 | ReleaseBSTR(excepInfo.bstrSource); | ||
| 949 | ReleaseBSTR(excepInfo.bstrDescription); | ||
| 950 | ReleaseBSTR(excepInfo.bstrHelpFile); | ||
| 951 | |||
| 952 | ReleaseBSTR(bstrPartName); | ||
| 953 | ReleaseBSTR(bstrAppName); | ||
| 954 | ReleaseBSTR(bstrDllPath); | ||
| 955 | ReleaseBSTR(bstrTlbPath); | ||
| 956 | |||
| 957 | return hr; | ||
| 958 | } | ||
| 959 | |||
| 960 | static HRESULT RegisterNativeAssembly( | ||
| 961 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 962 | ) | ||
| 963 | { | ||
| 964 | HRESULT hr = S_OK; | ||
| 965 | |||
| 966 | ICOMAdminCatalog* piCatalog = NULL; | ||
| 967 | ICOMAdminCatalog2* piCatalog2 = NULL; | ||
| 968 | BSTR bstrGlobPartID = NULL; | ||
| 969 | |||
| 970 | BSTR bstrPartID = NULL; | ||
| 971 | BSTR bstrAppID = NULL; | ||
| 972 | BSTR bstrDllPath = NULL; | ||
| 973 | BSTR bstrTlbPath = NULL; | ||
| 974 | BSTR bstrPSDllPath = NULL; | ||
| 975 | |||
| 976 | // create BSTRs for parameters | ||
| 977 | if (pAttrs->pwzPartID && *pAttrs->pwzPartID) | ||
| 978 | { | ||
| 979 | bstrPartID = ::SysAllocString(pAttrs->pwzPartID); | ||
| 980 | ExitOnNull(bstrPartID, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id"); | ||
| 981 | } | ||
| 982 | |||
| 983 | bstrAppID = ::SysAllocString(pAttrs->pwzAppID); | ||
| 984 | ExitOnNull(bstrAppID, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id"); | ||
| 985 | |||
| 986 | bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath); | ||
| 987 | ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path"); | ||
| 988 | |||
| 989 | bstrTlbPath = ::SysAllocString(pAttrs->pwzTlbPath ? pAttrs->pwzTlbPath : L""); | ||
| 990 | ExitOnNull(bstrTlbPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path"); | ||
| 991 | |||
| 992 | bstrPSDllPath = ::SysAllocString(pAttrs->pwzPSDllPath ? pAttrs->pwzPSDllPath : L""); | ||
| 993 | ExitOnNull(bstrPSDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for tlb path"); | ||
| 994 | |||
| 995 | // get catalog | ||
| 996 | hr = CpiGetAdminCatalog(&piCatalog); | ||
| 997 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
| 998 | |||
| 999 | // get ICOMAdminCatalog2 interface | ||
| 1000 | hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2); | ||
| 1001 | |||
| 1002 | // COM+ 1.5 or later | ||
| 1003 | if (E_NOINTERFACE != hr) | ||
| 1004 | { | ||
| 1005 | ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface"); | ||
| 1006 | |||
| 1007 | // partition id | ||
| 1008 | if (!bstrPartID) | ||
| 1009 | { | ||
| 1010 | // get global partition id | ||
| 1011 | hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID); | ||
| 1012 | ExitOnFailure(hr, "Failed to get global partition id"); | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | // set current partition | ||
| 1016 | hr = piCatalog2->put_CurrentPartition(bstrPartID ? bstrPartID : bstrGlobPartID); | ||
| 1017 | ExitOnFailure(hr, "Failed to set current partition"); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | // COM+ pre 1.5 | ||
| 1021 | else | ||
| 1022 | { | ||
| 1023 | // this version of COM+ does not support partitions, make sure a partition was not specified | ||
| 1024 | if (bstrPartID) | ||
| 1025 | ExitOnFailure(hr = E_FAIL, "Partitions are not supported by this version of COM+"); | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | // install event classes | ||
| 1029 | if (pAttrs->iAttributes & aaEventClass) | ||
| 1030 | { | ||
| 1031 | hr = piCatalog->InstallEventClass(bstrAppID, bstrDllPath, bstrTlbPath, bstrPSDllPath); | ||
| 1032 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 1033 | CpiLogCatalogErrorInfo(); | ||
| 1034 | ExitOnFailure(hr, "Failed to install event classes"); | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | // install components | ||
| 1038 | else | ||
| 1039 | { | ||
| 1040 | hr = piCatalog->InstallComponent(bstrAppID, bstrDllPath, bstrTlbPath, bstrPSDllPath); | ||
| 1041 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 1042 | CpiLogCatalogErrorInfo(); | ||
| 1043 | ExitOnFailure(hr, "Failed to install components"); | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | hr = S_OK; | ||
| 1047 | |||
| 1048 | LExit: | ||
| 1049 | // clean up | ||
| 1050 | ReleaseObject(piCatalog); | ||
| 1051 | ReleaseObject(piCatalog2); | ||
| 1052 | ReleaseBSTR(bstrGlobPartID); | ||
| 1053 | |||
| 1054 | ReleaseBSTR(bstrPartID); | ||
| 1055 | ReleaseBSTR(bstrAppID); | ||
| 1056 | ReleaseBSTR(bstrDllPath); | ||
| 1057 | ReleaseBSTR(bstrTlbPath); | ||
| 1058 | ReleaseBSTR(bstrPSDllPath); | ||
| 1059 | |||
| 1060 | return hr; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | static HRESULT UnregisterDotNetAssembly( | ||
| 1064 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 1065 | ) | ||
| 1066 | { | ||
| 1067 | HRESULT hr = S_OK; | ||
| 1068 | |||
| 1069 | IDispatch* piRegHlp = NULL; | ||
| 1070 | |||
| 1071 | DISPID dispid; | ||
| 1072 | BSTR bstrMember = NULL; | ||
| 1073 | |||
| 1074 | VARIANTARG rgvarg[3]; | ||
| 1075 | DISPPARAMS dispparams; | ||
| 1076 | EXCEPINFO excepInfo; | ||
| 1077 | |||
| 1078 | BSTR bstrPartName = NULL; | ||
| 1079 | BSTR bstrAppName = NULL; | ||
| 1080 | BSTR bstrDllPath = NULL; | ||
| 1081 | |||
| 1082 | ::ZeroMemory(rgvarg, sizeof(rgvarg)); | ||
| 1083 | ::ZeroMemory(&dispparams, sizeof(dispparams)); | ||
| 1084 | ::ZeroMemory(&excepInfo, sizeof(excepInfo)); | ||
| 1085 | |||
| 1086 | bstrMember = ::SysAllocString(L"UninstallAssembly_2"); | ||
| 1087 | ExitOnNull(bstrMember, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for method name"); | ||
| 1088 | |||
| 1089 | // create BSTRs for parameters | ||
| 1090 | if (pAttrs->pwzPartID && *pAttrs->pwzPartID) | ||
| 1091 | { | ||
| 1092 | bstrPartName = ::SysAllocString(pAttrs->pwzPartID); | ||
| 1093 | ExitOnNull(bstrPartName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for partition id"); | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | bstrAppName = ::SysAllocString(pAttrs->pwzAppID); | ||
| 1097 | ExitOnNull(bstrAppName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for application id"); | ||
| 1098 | |||
| 1099 | bstrDllPath = ::SysAllocString(pAttrs->pwzDllPath); | ||
| 1100 | ExitOnNull(bstrDllPath, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for dll path"); | ||
| 1101 | |||
| 1102 | // get registration helper object | ||
| 1103 | hr = GetRegistrationHelper(&piRegHlp); | ||
| 1104 | ExitOnFailure(hr, "Failed to get registration helper object"); | ||
| 1105 | |||
| 1106 | // get dispatch id of UninstallAssembly() method | ||
| 1107 | hr = piRegHlp->GetIDsOfNames(IID_NULL, &bstrMember, 1, LOCALE_USER_DEFAULT, &dispid); | ||
| 1108 | ExitOnFailure(hr, "Failed to get dispatch id of UninstallAssembly() method"); | ||
| 1109 | |||
| 1110 | // invoke UninstallAssembly() method | ||
| 1111 | rgvarg[0].vt = VT_BSTR; | ||
| 1112 | rgvarg[0].bstrVal = bstrPartName; | ||
| 1113 | rgvarg[1].vt = VT_BSTR; | ||
| 1114 | rgvarg[1].bstrVal = bstrAppName; | ||
| 1115 | rgvarg[2].vt = VT_BSTR; | ||
| 1116 | rgvarg[2].bstrVal = bstrDllPath; | ||
| 1117 | dispparams.rgvarg = rgvarg; | ||
| 1118 | dispparams.cArgs = 3; | ||
| 1119 | dispparams.cNamedArgs = 0; | ||
| 1120 | |||
| 1121 | hr = piRegHlp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, NULL, &excepInfo, NULL); | ||
| 1122 | if (DISP_E_EXCEPTION == hr) | ||
| 1123 | { | ||
| 1124 | // log exception information | ||
| 1125 | if (!excepInfo.pfnDeferredFillIn || (excepInfo.pfnDeferredFillIn && SUCCEEDED(excepInfo.pfnDeferredFillIn(&excepInfo)))) | ||
| 1126 | { | ||
| 1127 | WcaLog(LOGMSG_STANDARD, "ExceptionInfo: Code='%hu', Source='%S', Description='%S', HelpFile='%S', HelpContext='%u'", | ||
| 1128 | excepInfo.wCode, excepInfo.bstrSource, | ||
| 1129 | excepInfo.bstrDescription ? excepInfo.bstrDescription : L"", | ||
| 1130 | excepInfo.bstrHelpFile ? excepInfo.bstrHelpFile : L"", | ||
| 1131 | excepInfo.dwHelpContext); | ||
| 1132 | } | ||
| 1133 | } | ||
| 1134 | ExitOnFailure(hr, "Failed to invoke RegistrationHelper.UninstallAssembly() method"); | ||
| 1135 | |||
| 1136 | hr = S_OK; | ||
| 1137 | |||
| 1138 | LExit: | ||
| 1139 | // clean up | ||
| 1140 | ReleaseObject(piRegHlp); | ||
| 1141 | |||
| 1142 | ReleaseBSTR(bstrMember); | ||
| 1143 | |||
| 1144 | ReleaseBSTR(excepInfo.bstrSource); | ||
| 1145 | ReleaseBSTR(excepInfo.bstrDescription); | ||
| 1146 | ReleaseBSTR(excepInfo.bstrHelpFile); | ||
| 1147 | |||
| 1148 | ReleaseBSTR(bstrPartName); | ||
| 1149 | ReleaseBSTR(bstrAppName); | ||
| 1150 | ReleaseBSTR(bstrDllPath); | ||
| 1151 | |||
| 1152 | return hr; | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | static HRESULT RemoveComponents( | ||
| 1156 | ICatalogCollection* piCompColl, | ||
| 1157 | CPI_COMPONENT* pCompList | ||
| 1158 | ) | ||
| 1159 | { | ||
| 1160 | HRESULT hr = S_OK; | ||
| 1161 | |||
| 1162 | for (CPI_COMPONENT* pItm = pCompList; pItm; pItm = pItm->pNext) | ||
| 1163 | { | ||
| 1164 | // remove | ||
| 1165 | hr = CpiRemoveCollectionObject(piCompColl, pItm->wzCLSID, NULL, FALSE); | ||
| 1166 | ExitOnFailure(hr, "Failed to remove component"); | ||
| 1167 | |||
| 1168 | if (S_FALSE == hr) | ||
| 1169 | WcaLog(LOGMSG_VERBOSE, "Component not found, nothing to delete, key: %S", pItm->wzCLSID); | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | hr = S_OK; | ||
| 1173 | |||
| 1174 | LExit: | ||
| 1175 | return hr; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | static HRESULT ReadAssemblyAttributes( | ||
| 1179 | LPWSTR* ppwzData, | ||
| 1180 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 1181 | ) | ||
| 1182 | { | ||
| 1183 | HRESULT hr = S_OK; | ||
| 1184 | |||
| 1185 | // read attributes | ||
| 1186 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
| 1187 | ExitOnFailure(hr, "Failed to read action type"); | ||
| 1188 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
| 1189 | ExitOnFailure(hr, "Failed to read action cost"); | ||
| 1190 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
| 1191 | ExitOnFailure(hr, "Failed to read key"); | ||
| 1192 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAssemblyName); | ||
| 1193 | ExitOnFailure(hr, "Failed to read assembly name"); | ||
| 1194 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzDllPath); | ||
| 1195 | ExitOnFailure(hr, "Failed to read dll path"); | ||
| 1196 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzTlbPath); | ||
| 1197 | ExitOnFailure(hr, "Failed to read tlb path"); | ||
| 1198 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPSDllPath); | ||
| 1199 | ExitOnFailure(hr, "Failed to read proxy-stub dll path"); | ||
| 1200 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iAttributes); | ||
| 1201 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 1202 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
| 1203 | ExitOnFailure(hr, "Failed to read application id"); | ||
| 1204 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
| 1205 | ExitOnFailure(hr, "Failed to read partition id"); | ||
| 1206 | |||
| 1207 | // free existing component list | ||
| 1208 | if (pAttrs->pCompList) | ||
| 1209 | { | ||
| 1210 | FreeComponentList(pAttrs->pCompList); | ||
| 1211 | pAttrs->pCompList = NULL; | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | // read components | ||
| 1215 | hr = ReadComponentList(ppwzData, &pAttrs->pCompList); | ||
| 1216 | ExitOnFailure(hr, "Failed to read components"); | ||
| 1217 | |||
| 1218 | hr = S_OK; | ||
| 1219 | |||
| 1220 | LExit: | ||
| 1221 | return hr; | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | static void FreeAssemblyAttributes( | ||
| 1225 | CPI_ASSEMBLY_ATTRIBUTES* pAttrs | ||
| 1226 | ) | ||
| 1227 | { | ||
| 1228 | ReleaseStr(pAttrs->pwzKey); | ||
| 1229 | ReleaseStr(pAttrs->pwzAssemblyName); | ||
| 1230 | ReleaseStr(pAttrs->pwzDllPath); | ||
| 1231 | ReleaseStr(pAttrs->pwzTlbPath); | ||
| 1232 | ReleaseStr(pAttrs->pwzPSDllPath); | ||
| 1233 | ReleaseStr(pAttrs->pwzAppID); | ||
| 1234 | ReleaseStr(pAttrs->pwzPartID); | ||
| 1235 | |||
| 1236 | if (pAttrs->pCompList) | ||
| 1237 | FreeComponentList(pAttrs->pCompList); | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | static HRESULT ReadRoleAssignmentsAttributes( | ||
| 1241 | LPWSTR* ppwzData, | ||
| 1242 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
| 1243 | ) | ||
| 1244 | { | ||
| 1245 | HRESULT hr = S_OK; | ||
| 1246 | |||
| 1247 | // read attributes | ||
| 1248 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
| 1249 | ExitOnFailure(hr, "Failed to read action type"); | ||
| 1250 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
| 1251 | ExitOnFailure(hr, "Failed to read action cost"); | ||
| 1252 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
| 1253 | ExitOnFailure(hr, "Failed to read key"); | ||
| 1254 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iRoleCount); | ||
| 1255 | ExitOnFailure(hr, "Failed to read role assignments count"); | ||
| 1256 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
| 1257 | ExitOnFailure(hr, "Failed to read application id"); | ||
| 1258 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
| 1259 | ExitOnFailure(hr, "Failed to read partition id"); | ||
| 1260 | |||
| 1261 | // free existing component list | ||
| 1262 | if (pAttrs->pCompList) | ||
| 1263 | { | ||
| 1264 | FreeComponentList(pAttrs->pCompList); | ||
| 1265 | pAttrs->pCompList = NULL; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | // read components | ||
| 1269 | hr = ReadComponentList(ppwzData, &pAttrs->pCompList); | ||
| 1270 | ExitOnFailure(hr, "Failed to read components"); | ||
| 1271 | |||
| 1272 | hr = S_OK; | ||
| 1273 | |||
| 1274 | LExit: | ||
| 1275 | return hr; | ||
| 1276 | } | ||
| 1277 | |||
| 1278 | static void FreeRoleAssignmentsAttributes( | ||
| 1279 | CPI_ROLE_ASSIGNMENTS_ATTRIBUTES* pAttrs | ||
| 1280 | ) | ||
| 1281 | { | ||
| 1282 | ReleaseStr(pAttrs->pwzKey); | ||
| 1283 | ReleaseStr(pAttrs->pwzAppID); | ||
| 1284 | ReleaseStr(pAttrs->pwzPartID); | ||
| 1285 | |||
| 1286 | if (pAttrs->pCompList) | ||
| 1287 | FreeComponentList(pAttrs->pCompList); | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | |||
| 1291 | static HRESULT ConfigureComponents( | ||
| 1292 | LPCWSTR pwzPartID, | ||
| 1293 | LPCWSTR pwzAppID, | ||
| 1294 | CPI_COMPONENT* pCompList, | ||
| 1295 | BOOL fCreate, | ||
| 1296 | BOOL fProgress | ||
| 1297 | ) | ||
| 1298 | { | ||
| 1299 | HRESULT hr = S_OK; | ||
| 1300 | |||
| 1301 | ICatalogCollection* piCompColl = NULL; | ||
| 1302 | ICatalogObject* piCompObj = NULL; | ||
| 1303 | |||
| 1304 | long lChanges = 0; | ||
| 1305 | |||
| 1306 | // get components collection | ||
| 1307 | hr = CpiGetComponentsCollection(pwzPartID, pwzAppID, &piCompColl); | ||
| 1308 | if (S_FALSE == hr) | ||
| 1309 | if (fCreate) | ||
| 1310 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 1311 | else | ||
| 1312 | ExitFunction1(hr = S_OK); | ||
| 1313 | ExitOnFailure(hr, "Failed to get components collection"); | ||
| 1314 | |||
| 1315 | // read components | ||
| 1316 | for (CPI_COMPONENT* pItm = pCompList; pItm; pItm = pItm->pNext) | ||
| 1317 | { | ||
| 1318 | // progress message | ||
| 1319 | if (fProgress) | ||
| 1320 | { | ||
| 1321 | hr = CpiActionDataMessage(1, pItm->wzCLSID); | ||
| 1322 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 1323 | |||
| 1324 | if (S_FALSE == hr) | ||
| 1325 | ExitFunction(); // aborted by user | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | // find component | ||
| 1329 | hr = CpiFindCollectionObjectByStringKey(piCompColl, pItm->wzCLSID, &piCompObj); | ||
| 1330 | if (S_FALSE == hr) | ||
| 1331 | if (fCreate) | ||
| 1332 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 1333 | else | ||
| 1334 | continue; | ||
| 1335 | ExitOnFailure(hr, "Failed to find component object"); | ||
| 1336 | |||
| 1337 | // properties | ||
| 1338 | hr = CpiPutCollectionObjectValues(piCompObj, pItm->pPropertyList); | ||
| 1339 | ExitOnFailure(hr, "Failed to write properties"); | ||
| 1340 | |||
| 1341 | // read roles | ||
| 1342 | if (pItm->pRoleAssignmentList) | ||
| 1343 | { | ||
| 1344 | hr = ConfigureRoleAssignments(L"RolesForComponent", piCompColl, piCompObj, pItm->pRoleAssignmentList, fCreate); | ||
| 1345 | ExitOnFailure(hr, "Failed to read roles"); | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | // read interfaces | ||
| 1349 | if (pItm->pInterfaceList) | ||
| 1350 | { | ||
| 1351 | hr = ConfigureInterfaces(piCompColl, piCompObj, pItm->pInterfaceList, fCreate); | ||
| 1352 | ExitOnFailure(hr, "Failed to read interfaces"); | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | // clean up | ||
| 1356 | ReleaseNullObject(piCompObj); | ||
| 1357 | } | ||
| 1358 | |||
| 1359 | // save changes | ||
| 1360 | hr = piCompColl->SaveChanges(&lChanges); | ||
| 1361 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 1362 | CpiLogCatalogErrorInfo(); | ||
| 1363 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 1364 | |||
| 1365 | hr = S_OK; | ||
| 1366 | |||
| 1367 | LExit: | ||
| 1368 | // clean up | ||
| 1369 | ReleaseObject(piCompColl); | ||
| 1370 | ReleaseObject(piCompObj); | ||
| 1371 | |||
| 1372 | return hr; | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | static HRESULT ConfigureInterfaces( | ||
| 1376 | ICatalogCollection* piCompColl, | ||
| 1377 | ICatalogObject* piCompObj, | ||
| 1378 | CPI_INTERFACE* pIntfList, | ||
| 1379 | BOOL fCreate | ||
| 1380 | ) | ||
| 1381 | { | ||
| 1382 | HRESULT hr = S_OK; | ||
| 1383 | |||
| 1384 | ICatalogCollection* piIntfColl = NULL; | ||
| 1385 | ICatalogObject* piIntfObj = NULL; | ||
| 1386 | |||
| 1387 | long lChanges = 0; | ||
| 1388 | |||
| 1389 | // get interfaces collection | ||
| 1390 | hr = CpiGetInterfacesCollection(piCompColl, piCompObj, &piIntfColl); | ||
| 1391 | if (S_FALSE == hr) | ||
| 1392 | if (fCreate) | ||
| 1393 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 1394 | else | ||
| 1395 | ExitFunction1(hr = S_OK); | ||
| 1396 | ExitOnFailure(hr, "Failed to get interfaces collection"); | ||
| 1397 | |||
| 1398 | // read interfaces | ||
| 1399 | for (CPI_INTERFACE* pItm = pIntfList; pItm; pItm = pItm->pNext) | ||
| 1400 | { | ||
| 1401 | // find interface | ||
| 1402 | hr = CpiFindCollectionObjectByStringKey(piIntfColl, pItm->wzIID, &piIntfObj); | ||
| 1403 | if (S_FALSE == hr) | ||
| 1404 | if (fCreate) | ||
| 1405 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 1406 | else | ||
| 1407 | continue; | ||
| 1408 | ExitOnFailure(hr, "Failed to find interface object"); | ||
| 1409 | |||
| 1410 | // properties | ||
| 1411 | hr = CpiPutCollectionObjectValues(piIntfObj, pItm->pPropertyList); | ||
| 1412 | ExitOnFailure(hr, "Failed to write properties"); | ||
| 1413 | |||
| 1414 | // read roles | ||
| 1415 | if (pItm->pRoleAssignmentList) | ||
| 1416 | { | ||
| 1417 | hr = ConfigureRoleAssignments(L"RolesForInterface", piIntfColl, piIntfObj, pItm->pRoleAssignmentList, fCreate); | ||
| 1418 | ExitOnFailure(hr, "Failed to read roles"); | ||
| 1419 | } | ||
| 1420 | |||
| 1421 | // read methods | ||
| 1422 | if (pItm->pMethodList) | ||
| 1423 | { | ||
| 1424 | hr = ConfigureMethods(piIntfColl, piIntfObj, pItm->pMethodList, fCreate); | ||
| 1425 | ExitOnFailure(hr, "Failed to read methods"); | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | // clean up | ||
| 1429 | ReleaseNullObject(piIntfObj); | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | // save changes | ||
| 1433 | hr = piIntfColl->SaveChanges(&lChanges); | ||
| 1434 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 1435 | CpiLogCatalogErrorInfo(); | ||
| 1436 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 1437 | |||
| 1438 | hr = S_OK; | ||
| 1439 | |||
| 1440 | LExit: | ||
| 1441 | // clean up | ||
| 1442 | ReleaseObject(piIntfColl); | ||
| 1443 | ReleaseObject(piIntfObj); | ||
| 1444 | |||
| 1445 | return hr; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | static HRESULT ConfigureMethods( | ||
| 1449 | ICatalogCollection* piIntfColl, | ||
| 1450 | ICatalogObject* piIntfObj, | ||
| 1451 | CPI_METHOD* pMethList, | ||
| 1452 | BOOL fCreate | ||
| 1453 | ) | ||
| 1454 | { | ||
| 1455 | HRESULT hr = S_OK; | ||
| 1456 | |||
| 1457 | ICatalogCollection* piMethColl = NULL; | ||
| 1458 | ICatalogObject* piMethObj = NULL; | ||
| 1459 | |||
| 1460 | long lChanges = 0; | ||
| 1461 | |||
| 1462 | // get methods collection | ||
| 1463 | hr = CpiGetMethodsCollection(piIntfColl, piIntfObj, &piMethColl); | ||
| 1464 | if (S_FALSE == hr) | ||
| 1465 | if (fCreate) | ||
| 1466 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 1467 | else | ||
| 1468 | ExitFunction1(hr = S_OK); | ||
| 1469 | ExitOnFailure(hr, "Failed to get methods collection"); | ||
| 1470 | |||
| 1471 | // read methods | ||
| 1472 | for (CPI_METHOD* pItm = pMethList; pItm; pItm = pItm->pNext) | ||
| 1473 | { | ||
| 1474 | // find method | ||
| 1475 | if (*pItm->wzIndex) | ||
| 1476 | hr = CpiFindCollectionObjectByIntegerKey(piMethColl, _wtol(pItm->wzIndex), &piMethObj); | ||
| 1477 | else | ||
| 1478 | hr = CpiFindCollectionObjectByName(piMethColl, pItm->wzName, &piMethObj); | ||
| 1479 | |||
| 1480 | if (S_FALSE == hr) | ||
| 1481 | if (fCreate) | ||
| 1482 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 1483 | else | ||
| 1484 | continue; | ||
| 1485 | ExitOnFailure(hr, "Failed to find method object"); | ||
| 1486 | |||
| 1487 | // properties | ||
| 1488 | hr = CpiPutCollectionObjectValues(piMethObj, pItm->pPropertyList); | ||
| 1489 | ExitOnFailure(hr, "Failed to write properties"); | ||
| 1490 | |||
| 1491 | // read roles | ||
| 1492 | if (pItm->pRoleAssignmentList) | ||
| 1493 | { | ||
| 1494 | hr = ConfigureRoleAssignments(L"RolesForMethod", piMethColl, piMethObj, pItm->pRoleAssignmentList, fCreate); | ||
| 1495 | ExitOnFailure(hr, "Failed to read roles"); | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | // clean up | ||
| 1499 | ReleaseNullObject(piMethObj); | ||
| 1500 | } | ||
| 1501 | |||
| 1502 | // save changes | ||
| 1503 | hr = piMethColl->SaveChanges(&lChanges); | ||
| 1504 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 1505 | CpiLogCatalogErrorInfo(); | ||
| 1506 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 1507 | |||
| 1508 | hr = S_OK; | ||
| 1509 | |||
| 1510 | LExit: | ||
| 1511 | // clean up | ||
| 1512 | ReleaseObject(piMethColl); | ||
| 1513 | ReleaseObject(piMethObj); | ||
| 1514 | |||
| 1515 | return hr; | ||
| 1516 | } | ||
| 1517 | |||
| 1518 | static HRESULT ConfigureRoleAssignments( | ||
| 1519 | LPCWSTR pwzCollName, | ||
| 1520 | ICatalogCollection* piCompColl, | ||
| 1521 | ICatalogObject* piCompObj, | ||
| 1522 | CPI_ROLE_ASSIGNMENT* pRoleList, | ||
| 1523 | BOOL fCreate | ||
| 1524 | ) | ||
| 1525 | { | ||
| 1526 | HRESULT hr = S_OK; | ||
| 1527 | |||
| 1528 | ICatalogCollection* piRoleColl = NULL; | ||
| 1529 | ICatalogObject* piRoleObj = NULL; | ||
| 1530 | |||
| 1531 | long lChanges = 0; | ||
| 1532 | |||
| 1533 | // get roles collection | ||
| 1534 | hr = CpiGetCatalogCollection(piCompColl, piCompObj, pwzCollName, &piRoleColl); | ||
| 1535 | if (S_FALSE == hr) | ||
| 1536 | if (fCreate) | ||
| 1537 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 1538 | else | ||
| 1539 | ExitFunction1(hr = S_OK); | ||
| 1540 | ExitOnFailure(hr, "Failed to get role assignments collection"); | ||
| 1541 | |||
| 1542 | // read roles | ||
| 1543 | for (CPI_ROLE_ASSIGNMENT* pItm = pRoleList; pItm; pItm = pItm->pNext) | ||
| 1544 | { | ||
| 1545 | if (fCreate) | ||
| 1546 | { | ||
| 1547 | // find existing role | ||
| 1548 | hr = CpiFindCollectionObjectByName(piRoleColl, pItm->wzRoleName, NULL); | ||
| 1549 | ExitOnFailure(hr, "Failed to find role, key: %S", pItm->wzKey); | ||
| 1550 | |||
| 1551 | if (S_OK == hr) | ||
| 1552 | continue; // role already exists | ||
| 1553 | |||
| 1554 | // add object | ||
| 1555 | hr = CpiAddCollectionObject(piRoleColl, &piRoleObj); | ||
| 1556 | ExitOnFailure(hr, "Failed to add role assignment to collection"); | ||
| 1557 | |||
| 1558 | // role name | ||
| 1559 | hr = CpiPutCollectionObjectValue(piRoleObj, L"Name", pItm->wzRoleName); | ||
| 1560 | ExitOnFailure(hr, "Failed to set role name property, key: %S", pItm->wzKey); | ||
| 1561 | |||
| 1562 | // clean up | ||
| 1563 | ReleaseNullObject(piRoleObj); | ||
| 1564 | } | ||
| 1565 | else | ||
| 1566 | { | ||
| 1567 | // remove role | ||
| 1568 | hr = CpiRemoveCollectionObject(piRoleColl, NULL, pItm->wzRoleName, FALSE); | ||
| 1569 | ExitOnFailure(hr, "Failed to remove role, key: %S", pItm->wzKey); | ||
| 1570 | } | ||
| 1571 | } | ||
| 1572 | |||
| 1573 | // save changes | ||
| 1574 | hr = piRoleColl->SaveChanges(&lChanges); | ||
| 1575 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 1576 | CpiLogCatalogErrorInfo(); | ||
| 1577 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 1578 | |||
| 1579 | hr = S_OK; | ||
| 1580 | |||
| 1581 | LExit: | ||
| 1582 | // clean up | ||
| 1583 | ReleaseObject(piRoleColl); | ||
| 1584 | ReleaseObject(piRoleObj); | ||
| 1585 | |||
| 1586 | return hr; | ||
| 1587 | } | ||
| 1588 | |||
| 1589 | static HRESULT ReadComponentList( | ||
| 1590 | LPWSTR* ppwzData, | ||
| 1591 | CPI_COMPONENT** ppCompList | ||
| 1592 | ) | ||
| 1593 | { | ||
| 1594 | HRESULT hr = S_OK; | ||
| 1595 | |||
| 1596 | LPWSTR pwzData = NULL; | ||
| 1597 | |||
| 1598 | CPI_COMPONENT* pItm = NULL; | ||
| 1599 | |||
| 1600 | int iCnt = 0; | ||
| 1601 | |||
| 1602 | // read count | ||
| 1603 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 1604 | ExitOnFailure(hr, "Failed to read count"); | ||
| 1605 | |||
| 1606 | // read components | ||
| 1607 | for (int i = 0; i < iCnt; i++) | ||
| 1608 | { | ||
| 1609 | pItm = (CPI_COMPONENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_COMPONENT)); | ||
| 1610 | if (!pItm) | ||
| 1611 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 1612 | |||
| 1613 | // read clsid | ||
| 1614 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
| 1615 | ExitOnFailure(hr, "Failed to read clsid"); | ||
| 1616 | StringCchCopyW(pItm->wzCLSID, countof(pItm->wzCLSID), pwzData); | ||
| 1617 | |||
| 1618 | // read properties | ||
| 1619 | hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList); | ||
| 1620 | ExitOnFailure(hr, "Failed to read properties"); | ||
| 1621 | |||
| 1622 | // read role assignments | ||
| 1623 | hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList); | ||
| 1624 | ExitOnFailure(hr, "Failed to read role assignments"); | ||
| 1625 | |||
| 1626 | // read interfaces | ||
| 1627 | hr = ReadInterfaceList(ppwzData, &pItm->pInterfaceList); | ||
| 1628 | ExitOnFailure(hr, "Failed to read interfaces"); | ||
| 1629 | |||
| 1630 | // add to list | ||
| 1631 | if (*ppCompList) | ||
| 1632 | pItm->pNext = *ppCompList; | ||
| 1633 | *ppCompList = pItm; | ||
| 1634 | pItm = NULL; | ||
| 1635 | } | ||
| 1636 | |||
| 1637 | hr = S_OK; | ||
| 1638 | |||
| 1639 | LExit: | ||
| 1640 | // clean up | ||
| 1641 | ReleaseStr(pwzData); | ||
| 1642 | |||
| 1643 | if (pItm) | ||
| 1644 | FreeComponentList(pItm); | ||
| 1645 | |||
| 1646 | return hr; | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | static HRESULT ReadInterfaceList( | ||
| 1650 | LPWSTR* ppwzData, | ||
| 1651 | CPI_INTERFACE** ppIntfList | ||
| 1652 | ) | ||
| 1653 | { | ||
| 1654 | HRESULT hr = S_OK; | ||
| 1655 | |||
| 1656 | LPWSTR pwzData = NULL; | ||
| 1657 | |||
| 1658 | CPI_INTERFACE* pItm = NULL; | ||
| 1659 | |||
| 1660 | int iCnt = 0; | ||
| 1661 | |||
| 1662 | // read count | ||
| 1663 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 1664 | ExitOnFailure(hr, "Failed to read count"); | ||
| 1665 | |||
| 1666 | // read interfaces | ||
| 1667 | for (int i = 0; i < iCnt; i++) | ||
| 1668 | { | ||
| 1669 | pItm = (CPI_INTERFACE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_INTERFACE)); | ||
| 1670 | if (!pItm) | ||
| 1671 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 1672 | |||
| 1673 | // read iid | ||
| 1674 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
| 1675 | ExitOnFailure(hr, "Failed to read iid"); | ||
| 1676 | StringCchCopyW(pItm->wzIID, countof(pItm->wzIID), pwzData); | ||
| 1677 | |||
| 1678 | // read properties | ||
| 1679 | hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList); | ||
| 1680 | ExitOnFailure(hr, "Failed to read properties"); | ||
| 1681 | |||
| 1682 | // read role assignments | ||
| 1683 | hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList); | ||
| 1684 | ExitOnFailure(hr, "Failed to read role assignments"); | ||
| 1685 | |||
| 1686 | // read methods | ||
| 1687 | hr = ReadMethodList(ppwzData, &pItm->pMethodList); | ||
| 1688 | ExitOnFailure(hr, "Failed to read methods"); | ||
| 1689 | |||
| 1690 | // add to list | ||
| 1691 | if (*ppIntfList) | ||
| 1692 | pItm->pNext = *ppIntfList; | ||
| 1693 | *ppIntfList = pItm; | ||
| 1694 | pItm = NULL; | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | hr = S_OK; | ||
| 1698 | |||
| 1699 | LExit: | ||
| 1700 | // clean up | ||
| 1701 | ReleaseStr(pwzData); | ||
| 1702 | |||
| 1703 | if (pItm) | ||
| 1704 | FreeInterfaceList(pItm); | ||
| 1705 | |||
| 1706 | return hr; | ||
| 1707 | } | ||
| 1708 | |||
| 1709 | static HRESULT ReadMethodList( | ||
| 1710 | LPWSTR* ppwzData, | ||
| 1711 | CPI_METHOD** ppMethList | ||
| 1712 | ) | ||
| 1713 | { | ||
| 1714 | HRESULT hr = S_OK; | ||
| 1715 | |||
| 1716 | LPWSTR pwzData = NULL; | ||
| 1717 | |||
| 1718 | CPI_METHOD* pItm = NULL; | ||
| 1719 | |||
| 1720 | int iCnt = 0; | ||
| 1721 | |||
| 1722 | // read count | ||
| 1723 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 1724 | ExitOnFailure(hr, "Failed to read count"); | ||
| 1725 | |||
| 1726 | // read methods | ||
| 1727 | for (int i = 0; i < iCnt; i++) | ||
| 1728 | { | ||
| 1729 | pItm = (CPI_METHOD*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_METHOD)); | ||
| 1730 | if (!pItm) | ||
| 1731 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 1732 | |||
| 1733 | // read index | ||
| 1734 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
| 1735 | ExitOnFailure(hr, "Failed to read index"); | ||
| 1736 | StringCchCopyW(pItm->wzIndex, countof(pItm->wzIndex), pwzData); | ||
| 1737 | |||
| 1738 | // read name | ||
| 1739 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
| 1740 | ExitOnFailure(hr, "Failed to read name"); | ||
| 1741 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
| 1742 | |||
| 1743 | // read properties | ||
| 1744 | hr = CpiReadPropertyList(ppwzData, &pItm->pPropertyList); | ||
| 1745 | ExitOnFailure(hr, "Failed to read properties"); | ||
| 1746 | |||
| 1747 | // read role assignments | ||
| 1748 | hr = ReadRoleAssignmentList(ppwzData, &pItm->pRoleAssignmentList); | ||
| 1749 | ExitOnFailure(hr, "Failed to read role assignments"); | ||
| 1750 | |||
| 1751 | // add to list | ||
| 1752 | if (*ppMethList) | ||
| 1753 | pItm->pNext = *ppMethList; | ||
| 1754 | *ppMethList = pItm; | ||
| 1755 | pItm = NULL; | ||
| 1756 | } | ||
| 1757 | |||
| 1758 | hr = S_OK; | ||
| 1759 | |||
| 1760 | LExit: | ||
| 1761 | // clean up | ||
| 1762 | ReleaseStr(pwzData); | ||
| 1763 | |||
| 1764 | if (pItm) | ||
| 1765 | FreeMethodList(pItm); | ||
| 1766 | |||
| 1767 | return hr; | ||
| 1768 | } | ||
| 1769 | |||
| 1770 | static HRESULT ReadRoleAssignmentList( | ||
| 1771 | LPWSTR* ppwzData, | ||
| 1772 | CPI_ROLE_ASSIGNMENT** ppRoleList | ||
| 1773 | ) | ||
| 1774 | { | ||
| 1775 | HRESULT hr = S_OK; | ||
| 1776 | |||
| 1777 | LPWSTR pwzData = NULL; | ||
| 1778 | |||
| 1779 | CPI_ROLE_ASSIGNMENT* pItm = NULL; | ||
| 1780 | |||
| 1781 | int iCnt = 0; | ||
| 1782 | |||
| 1783 | // read role count | ||
| 1784 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 1785 | ExitOnFailure(hr, "Failed to read role assignments count"); | ||
| 1786 | |||
| 1787 | // read roles | ||
| 1788 | for (int i = 0; i < iCnt; i++) | ||
| 1789 | { | ||
| 1790 | pItm = (CPI_ROLE_ASSIGNMENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLE_ASSIGNMENT)); | ||
| 1791 | if (!pItm) | ||
| 1792 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 1793 | |||
| 1794 | // read key | ||
| 1795 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
| 1796 | ExitOnFailure(hr, "Failed to read key"); | ||
| 1797 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 1798 | |||
| 1799 | // read role name | ||
| 1800 | hr = WcaReadStringFromCaData(ppwzData, &pwzData); | ||
| 1801 | ExitOnFailure(hr, "Failed to read role name"); | ||
| 1802 | StringCchCopyW(pItm->wzRoleName, countof(pItm->wzRoleName), pwzData); | ||
| 1803 | |||
| 1804 | // add to list | ||
| 1805 | if (*ppRoleList) | ||
| 1806 | pItm->pNext = *ppRoleList; | ||
| 1807 | *ppRoleList = pItm; | ||
| 1808 | pItm = NULL; | ||
| 1809 | } | ||
| 1810 | |||
| 1811 | hr = S_OK; | ||
| 1812 | |||
| 1813 | LExit: | ||
| 1814 | // clean up | ||
| 1815 | ReleaseStr(pwzData); | ||
| 1816 | |||
| 1817 | if (pItm) | ||
| 1818 | FreeRoleAssignmentList(pItm); | ||
| 1819 | |||
| 1820 | return hr; | ||
| 1821 | } | ||
| 1822 | |||
| 1823 | static void FreeComponentList( | ||
| 1824 | CPI_COMPONENT* pList | ||
| 1825 | ) | ||
| 1826 | { | ||
| 1827 | while (pList) | ||
| 1828 | { | ||
| 1829 | if (pList->pPropertyList) | ||
| 1830 | CpiFreePropertyList(pList->pPropertyList); | ||
| 1831 | if (pList->pRoleAssignmentList) | ||
| 1832 | FreeRoleAssignmentList(pList->pRoleAssignmentList); | ||
| 1833 | if (pList->pInterfaceList) | ||
| 1834 | FreeInterfaceList(pList->pInterfaceList); | ||
| 1835 | |||
| 1836 | CPI_COMPONENT* pDelete = pList; | ||
| 1837 | pList = pList->pNext; | ||
| 1838 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 1839 | } | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | static void FreeInterfaceList( | ||
| 1843 | CPI_INTERFACE* pList | ||
| 1844 | ) | ||
| 1845 | { | ||
| 1846 | while (pList) | ||
| 1847 | { | ||
| 1848 | if (pList->pPropertyList) | ||
| 1849 | CpiFreePropertyList(pList->pPropertyList); | ||
| 1850 | if (pList->pRoleAssignmentList) | ||
| 1851 | FreeRoleAssignmentList(pList->pRoleAssignmentList); | ||
| 1852 | if (pList->pMethodList) | ||
| 1853 | FreeMethodList(pList->pMethodList); | ||
| 1854 | |||
| 1855 | CPI_INTERFACE* pDelete = pList; | ||
| 1856 | pList = pList->pNext; | ||
| 1857 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 1858 | } | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | static void FreeMethodList( | ||
| 1862 | CPI_METHOD* pList | ||
| 1863 | ) | ||
| 1864 | { | ||
| 1865 | while (pList) | ||
| 1866 | { | ||
| 1867 | if (pList->pPropertyList) | ||
| 1868 | CpiFreePropertyList(pList->pPropertyList); | ||
| 1869 | if (pList->pRoleAssignmentList) | ||
| 1870 | FreeRoleAssignmentList(pList->pRoleAssignmentList); | ||
| 1871 | |||
| 1872 | CPI_METHOD* pDelete = pList; | ||
| 1873 | pList = pList->pNext; | ||
| 1874 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 1875 | } | ||
| 1876 | } | ||
| 1877 | |||
| 1878 | static void FreeRoleAssignmentList( | ||
| 1879 | CPI_ROLE_ASSIGNMENT* pList | ||
| 1880 | ) | ||
| 1881 | { | ||
| 1882 | while (pList) | ||
| 1883 | { | ||
| 1884 | CPI_ROLE_ASSIGNMENT* pDelete = pList; | ||
| 1885 | pList = pList->pNext; | ||
| 1886 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 1887 | } | ||
| 1888 | } | ||
diff --git a/src/ca/cpasmexec.h b/src/ca/cpasmexec.h new file mode 100644 index 00000000..56184c01 --- /dev/null +++ b/src/ca/cpasmexec.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT CpiConfigureAssemblies( | ||
| 6 | LPWSTR* ppwzData, | ||
| 7 | HANDLE hRollbackFile | ||
| 8 | ); | ||
| 9 | HRESULT CpiRollbackConfigureAssemblies( | ||
| 10 | LPWSTR* ppwzData, | ||
| 11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 12 | ); | ||
| 13 | HRESULT CpiConfigureRoleAssignments( | ||
| 14 | LPWSTR* ppwzData, | ||
| 15 | HANDLE hRollbackFile | ||
| 16 | ); | ||
| 17 | HRESULT CpiRollbackConfigureRoleAssignments( | ||
| 18 | LPWSTR* ppwzData, | ||
| 19 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 20 | ); | ||
diff --git a/src/ca/cpasmsched.cpp b/src/ca/cpasmsched.cpp new file mode 100644 index 00000000..97ecff61 --- /dev/null +++ b/src/ca/cpasmsched.cpp | |||
| @@ -0,0 +1,2135 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // sql queries | ||
| 7 | |||
| 8 | LPCWSTR vcsMsiAssemblyNameQuery = | ||
| 9 | L"SELECT `Name`, `Value` FROM `MsiAssemblyName` WHERE `Component_` = ?"; | ||
| 10 | enum eMsiAssemblyNameQuery { manqName = 1, manqValue }; | ||
| 11 | |||
| 12 | LPCWSTR vcsModuleQuery = | ||
| 13 | L"SELECT `ModuleID` FROM `ModuleSignature`"; | ||
| 14 | enum eModuleQuery { mqModule = 1 }; | ||
| 15 | |||
| 16 | LPCWSTR vcsAssemblyQuery = | ||
| 17 | L"SELECT `Assembly`, `Component_`, `Application_`, `AssemblyName`, `DllPath`, `TlbPath`, `PSDllPath`, `Attributes` FROM `ComPlusAssembly`"; | ||
| 18 | enum eAssemblyQuery { aqAssembly = 1, aqComponent, aqApplication, aqAssemblyName, aqDllPath, aqTlbPath, aqPSDllPath, aqAttributes }; | ||
| 19 | |||
| 20 | LPCWSTR vcsComponentQuery = | ||
| 21 | L"SELECT `ComPlusComponent`, `CLSID` FROM `ComPlusComponent` WHERE `Assembly_` = ?"; | ||
| 22 | enum eComponentQuery { cqComponent = 1, cqCLSID }; | ||
| 23 | |||
| 24 | LPCWSTR vcsComponentPropertyQuery = | ||
| 25 | L"SELECT `Name`, `Value` FROM `ComPlusComponentProperty` WHERE `ComPlusComponent_` = ?"; | ||
| 26 | |||
| 27 | LPCWSTR vcsInterfaceQuery = | ||
| 28 | L"SELECT `Interface`, `IID` FROM `ComPlusInterface` WHERE `ComPlusComponent_` = ?"; | ||
| 29 | enum eInterfaceQuery { iqInterface = 1, iqIID }; | ||
| 30 | |||
| 31 | LPCWSTR vcsInterfacePropertyQuery = | ||
| 32 | L"SELECT `Name`, `Value` FROM `ComPlusInterfaceProperty` WHERE `Interface_` = ?"; | ||
| 33 | |||
| 34 | LPCWSTR vcsMethodQuery = | ||
| 35 | L"SELECT `Method`, `Index`, `Name` FROM `ComPlusMethod` WHERE `Interface_` = ?"; | ||
| 36 | enum eMethodQuery { mqMethod = 1, mqIndex, mqName }; | ||
| 37 | |||
| 38 | LPCWSTR vcsMethodPropertyQuery = | ||
| 39 | L"SELECT `Name`, `Value` FROM `ComPlusMethodProperty` WHERE `Method_` = ?"; | ||
| 40 | |||
| 41 | LPCWSTR vcsRoleForComponentQuery = | ||
| 42 | L"SELECT `RoleForComponent`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForComponent` WHERE `ComPlusComponent_` = ?"; | ||
| 43 | LPCWSTR vcsRoleForInterfaceQuery = | ||
| 44 | L"SELECT `RoleForInterface`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForInterface` WHERE `Interface_` = ?"; | ||
| 45 | LPCWSTR vcsRoleForMethodQuery = | ||
| 46 | L"SELECT `RoleForMethod`, `ApplicationRole_`, `Component_` FROM `ComPlusRoleForMethod` WHERE `Method_` = ?"; | ||
| 47 | |||
| 48 | enum eRoleAssignmentQuery { raqKey = 1, raqApplicationRole, raqComponent }; | ||
| 49 | |||
| 50 | LPCWSTR vcsModuleComponentsQuery = | ||
| 51 | L"SELECT `Component`, `ModuleID` FROM `ModuleComponents`"; | ||
| 52 | LPCWSTR vcsModuleDependencyQuery = | ||
| 53 | L"SELECT `ModuleID`, `RequiredID` FROM `ModuleDependency`"; | ||
| 54 | LPCWSTR vcsAssemblyDependencyQuery = | ||
| 55 | L"SELECT `Assembly_`, `RequiredAssembly_` FROM `ComPlusAssemblyDependency`"; | ||
| 56 | |||
| 57 | enum eKeyPairQuery { kpqFirstKey = 1, kpqSecondKey }; | ||
| 58 | |||
| 59 | |||
| 60 | // private structs | ||
| 61 | |||
| 62 | struct CPI_KEY_PAIR | ||
| 63 | { | ||
| 64 | WCHAR wzFirstKey[MAX_DARWIN_KEY + 1]; | ||
| 65 | WCHAR wzSecondKey[MAX_DARWIN_KEY + 1]; | ||
| 66 | |||
| 67 | CPI_KEY_PAIR* pNext; | ||
| 68 | }; | ||
| 69 | |||
| 70 | struct CPI_DEPENDENCY_CHAIN | ||
| 71 | { | ||
| 72 | LPCWSTR pwzKey; | ||
| 73 | |||
| 74 | CPI_DEPENDENCY_CHAIN* pPrev; | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct CPI_MODULE | ||
| 78 | { | ||
| 79 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 80 | |||
| 81 | CPI_MODULE* pPrev; | ||
| 82 | CPI_MODULE* pNext; | ||
| 83 | }; | ||
| 84 | |||
| 85 | struct CPI_MODULE_LIST | ||
| 86 | { | ||
| 87 | CPI_MODULE* pFirst; | ||
| 88 | CPI_MODULE* pLast; | ||
| 89 | }; | ||
| 90 | |||
| 91 | |||
| 92 | // property definitions | ||
| 93 | |||
| 94 | CPI_PROPERTY_DEFINITION pdlComponentProperties[] = | ||
| 95 | { | ||
| 96 | {L"AllowInprocSubscribers", cpptBoolean, 500}, | ||
| 97 | {L"ComponentAccessChecksEnabled", cpptBoolean, 500}, | ||
| 98 | {L"ComponentTransactionTimeout", cpptInteger, 500}, | ||
| 99 | {L"ComponentTransactionTimeoutEnabled", cpptBoolean, 500}, | ||
| 100 | {L"COMTIIntrinsics", cpptBoolean, 500}, | ||
| 101 | {L"ConstructionEnabled", cpptBoolean, 500}, | ||
| 102 | {L"ConstructorString", cpptString, 500}, | ||
| 103 | {L"CreationTimeout", cpptInteger, 500}, | ||
| 104 | {L"Description", cpptString, 500}, | ||
| 105 | {L"EventTrackingEnabled", cpptBoolean, 500}, | ||
| 106 | {L"ExceptionClass", cpptString, 500}, | ||
| 107 | {L"FireInParallel", cpptBoolean, 500}, | ||
| 108 | {L"IISIntrinsics", cpptBoolean, 500}, | ||
| 109 | {L"InitializesServerApplication", cpptBoolean, 500}, | ||
| 110 | {L"IsEnabled", cpptBoolean, 501}, | ||
| 111 | {L"IsPrivateComponent", cpptBoolean, 501}, | ||
| 112 | {L"JustInTimeActivation", cpptBoolean, 500}, | ||
| 113 | {L"LoadBalancingSupported", cpptBoolean, 500}, | ||
| 114 | {L"MaxPoolSize", cpptInteger, 500}, | ||
| 115 | {L"MinPoolSize", cpptInteger, 500}, | ||
| 116 | {L"MultiInterfacePublisherFilterCLSID", cpptString, 500}, | ||
| 117 | {L"MustRunInClientContext", cpptBoolean, 500}, | ||
| 118 | {L"MustRunInDefaultContext", cpptBoolean, 501}, | ||
| 119 | {L"ObjectPoolingEnabled", cpptBoolean, 500}, | ||
| 120 | {L"PublisherID", cpptString, 500}, | ||
| 121 | {L"SoapAssemblyName", cpptString, 502}, | ||
| 122 | {L"SoapTypeName", cpptString, 502}, | ||
| 123 | {L"Synchronization", cpptInteger, 500}, | ||
| 124 | {L"Transaction", cpptInteger, 500}, | ||
| 125 | {L"TxIsolationLevel", cpptInteger, 501}, | ||
| 126 | {NULL, cpptNone, 0} | ||
| 127 | }; | ||
| 128 | |||
| 129 | CPI_PROPERTY_DEFINITION pdlInterfaceProperties[] = | ||
| 130 | { | ||
| 131 | {L"Description", cpptString, 500}, | ||
| 132 | {L"QueuingEnabled", cpptBoolean, 500}, | ||
| 133 | {NULL, cpptNone, 0} | ||
| 134 | }; | ||
| 135 | |||
| 136 | CPI_PROPERTY_DEFINITION pdlMethodProperties[] = | ||
| 137 | { | ||
| 138 | {L"AutoComplete", cpptBoolean, 500}, | ||
| 139 | {L"Description", cpptString, 500}, | ||
| 140 | {NULL, cpptNone, 0} | ||
| 141 | }; | ||
| 142 | |||
| 143 | |||
| 144 | // prototypes for private helper functions | ||
| 145 | |||
| 146 | static HRESULT GetAssemblyName( | ||
| 147 | LPCWSTR pwzComponent, | ||
| 148 | LPWSTR* ppwzAssemblyName | ||
| 149 | ); | ||
| 150 | static HRESULT KeyPairsRead( | ||
| 151 | LPCWSTR pwzQuery, | ||
| 152 | CPI_KEY_PAIR** ppKeyPairList | ||
| 153 | ); | ||
| 154 | static HRESULT ModulesRead( | ||
| 155 | CPI_MODULE_LIST* pModList | ||
| 156 | ); | ||
| 157 | static HRESULT AssembliesRead( | ||
| 158 | CPI_KEY_PAIR* pModCompList, | ||
| 159 | CPI_APPLICATION_LIST* pAppList, | ||
| 160 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 161 | CPI_ASSEMBLY_LIST* pAsmList | ||
| 162 | ); | ||
| 163 | static HRESULT ComponentsRead( | ||
| 164 | LPCWSTR pwzAsmKey, | ||
| 165 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 166 | CPI_ASSEMBLY* pAsm | ||
| 167 | ); | ||
| 168 | static HRESULT InterfacesRead( | ||
| 169 | LPCWSTR pwzCompKey, | ||
| 170 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 171 | CPI_ASSEMBLY* pAsm, | ||
| 172 | CPI_COMPONENT* pComp | ||
| 173 | ); | ||
| 174 | static HRESULT MethodsRead( | ||
| 175 | LPCWSTR pwzIntfKey, | ||
| 176 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 177 | CPI_ASSEMBLY* pAsm, | ||
| 178 | CPI_INTERFACE* pIntf | ||
| 179 | ); | ||
| 180 | static HRESULT RoleAssignmentsRead( | ||
| 181 | LPCWSTR pwzQuery, | ||
| 182 | LPCWSTR pwzKey, | ||
| 183 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 184 | CPI_ROLE_ASSIGNMENT** ppRoleList, | ||
| 185 | int* piInstallCount, | ||
| 186 | int* piUninstallCount | ||
| 187 | ); | ||
| 188 | static HRESULT TopSortModuleList( | ||
| 189 | CPI_KEY_PAIR* pDepList, | ||
| 190 | CPI_MODULE_LIST* pList | ||
| 191 | ); | ||
| 192 | static HRESULT SwapDependentModules( | ||
| 193 | CPI_DEPENDENCY_CHAIN* pdcPrev, | ||
| 194 | CPI_KEY_PAIR* pDepList, | ||
| 195 | CPI_MODULE_LIST* pList, | ||
| 196 | CPI_MODULE* pRoot, | ||
| 197 | CPI_MODULE* pItm | ||
| 198 | ); | ||
| 199 | static HRESULT ModuleFindByKey( | ||
| 200 | CPI_MODULE* pItm, | ||
| 201 | LPCWSTR pwzKey, | ||
| 202 | BOOL fReverse, | ||
| 203 | CPI_MODULE** ppItm | ||
| 204 | ); | ||
| 205 | static void SortAssemblyListByModule( | ||
| 206 | CPI_MODULE_LIST* pModList, | ||
| 207 | CPI_ASSEMBLY_LIST* pAsmList | ||
| 208 | ); | ||
| 209 | static HRESULT TopSortAssemblyList( | ||
| 210 | CPI_KEY_PAIR* pDepList, | ||
| 211 | CPI_ASSEMBLY_LIST* pList | ||
| 212 | ); | ||
| 213 | static HRESULT SwapDependentAssemblies( | ||
| 214 | CPI_DEPENDENCY_CHAIN* pdcPrev, | ||
| 215 | CPI_KEY_PAIR* pDepList, | ||
| 216 | CPI_ASSEMBLY_LIST* pList, | ||
| 217 | CPI_ASSEMBLY* pRoot, | ||
| 218 | CPI_ASSEMBLY* pItm | ||
| 219 | ); | ||
| 220 | static HRESULT AssemblyFindByKey( | ||
| 221 | CPI_ASSEMBLY* pItm, | ||
| 222 | LPCWSTR pwzKey, | ||
| 223 | BOOL fReverse, | ||
| 224 | CPI_ASSEMBLY** ppItm | ||
| 225 | ); | ||
| 226 | static HRESULT AddAssemblyToActionData( | ||
| 227 | CPI_ASSEMBLY* pItm, | ||
| 228 | BOOL fInstall, | ||
| 229 | int iActionType, | ||
| 230 | int iActionCost, | ||
| 231 | LPWSTR* ppwzActionData | ||
| 232 | ); | ||
| 233 | static HRESULT AddRoleAssignmentsToActionData( | ||
| 234 | CPI_ASSEMBLY* pItm, | ||
| 235 | BOOL fInstall, | ||
| 236 | int iActionType, | ||
| 237 | int iActionCost, | ||
| 238 | LPWSTR* ppwzActionData | ||
| 239 | ); | ||
| 240 | static HRESULT AddComponentToActionData( | ||
| 241 | CPI_COMPONENT* pItm, | ||
| 242 | BOOL fInstall, | ||
| 243 | BOOL fProps, | ||
| 244 | BOOL fRoles, | ||
| 245 | LPWSTR* ppwzActionData | ||
| 246 | ); | ||
| 247 | static HRESULT AddInterfaceToActionData( | ||
| 248 | CPI_INTERFACE* pItm, | ||
| 249 | BOOL fInstall, | ||
| 250 | BOOL fProps, | ||
| 251 | BOOL fRoles, | ||
| 252 | LPWSTR* ppwzActionData | ||
| 253 | ); | ||
| 254 | static HRESULT AddMethodToActionData( | ||
| 255 | CPI_METHOD* pItm, | ||
| 256 | BOOL fInstall, | ||
| 257 | BOOL fProps, | ||
| 258 | BOOL fRoles, | ||
| 259 | LPWSTR* ppwzActionData | ||
| 260 | ); | ||
| 261 | static HRESULT AddRolesToActionData( | ||
| 262 | int iRoleInstallCount, | ||
| 263 | int iRoleUninstallCount, | ||
| 264 | CPI_ROLE_ASSIGNMENT* pRoleList, | ||
| 265 | BOOL fInstall, | ||
| 266 | BOOL fRoles, | ||
| 267 | LPWSTR* ppwzActionData | ||
| 268 | ); | ||
| 269 | static HRESULT KeyPairFindByFirstKey( | ||
| 270 | CPI_KEY_PAIR* pList, | ||
| 271 | LPCWSTR pwzKey, | ||
| 272 | CPI_KEY_PAIR** ppItm | ||
| 273 | ); | ||
| 274 | static void AssemblyFree( | ||
| 275 | CPI_ASSEMBLY* pItm | ||
| 276 | ); | ||
| 277 | static void KeyPairsFreeList( | ||
| 278 | CPI_KEY_PAIR* pList | ||
| 279 | ); | ||
| 280 | void ModuleListFree( | ||
| 281 | CPI_MODULE_LIST* pList | ||
| 282 | ); | ||
| 283 | static void ModuleFree( | ||
| 284 | CPI_MODULE* pItm | ||
| 285 | ); | ||
| 286 | static void ComponentsFreeList( | ||
| 287 | CPI_COMPONENT* pList | ||
| 288 | ); | ||
| 289 | static void InterfacesFreeList( | ||
| 290 | CPI_INTERFACE* pList | ||
| 291 | ); | ||
| 292 | static void MethodsFreeList( | ||
| 293 | CPI_METHOD* pList | ||
| 294 | ); | ||
| 295 | static void RoleAssignmentsFreeList( | ||
| 296 | CPI_ROLE_ASSIGNMENT* pList | ||
| 297 | ); | ||
| 298 | |||
| 299 | |||
| 300 | // function definitions | ||
| 301 | |||
| 302 | void CpiAssemblyListFree( | ||
| 303 | CPI_ASSEMBLY_LIST* pList | ||
| 304 | ) | ||
| 305 | { | ||
| 306 | CPI_ASSEMBLY* pItm = pList->pFirst; | ||
| 307 | |||
| 308 | while (pItm) | ||
| 309 | { | ||
| 310 | CPI_ASSEMBLY* pDelete = pItm; | ||
| 311 | pItm = pItm->pNext; | ||
| 312 | AssemblyFree(pDelete); | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | HRESULT CpiAssembliesRead( | ||
| 317 | CPI_APPLICATION_LIST* pAppList, | ||
| 318 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 319 | CPI_ASSEMBLY_LIST* pAsmList | ||
| 320 | ) | ||
| 321 | { | ||
| 322 | HRESULT hr = S_OK; | ||
| 323 | CPI_MODULE_LIST modList; | ||
| 324 | CPI_KEY_PAIR* pModCompList = NULL; | ||
| 325 | CPI_KEY_PAIR* pModDepList = NULL; | ||
| 326 | CPI_KEY_PAIR* pAsmDepList = NULL; | ||
| 327 | |||
| 328 | ::ZeroMemory(&modList, sizeof(CPI_MODULE_LIST)); | ||
| 329 | |||
| 330 | BOOL fModuleSignatureTable = (S_OK == WcaTableExists(L"ModuleSignature")); | ||
| 331 | BOOL fModuleComponentsTable = (S_OK == WcaTableExists(L"ModuleComponents")); | ||
| 332 | BOOL fModuleDependencyTable = (S_OK == WcaTableExists(L"ModuleDependency")); | ||
| 333 | |||
| 334 | // read modules | ||
| 335 | if (fModuleSignatureTable) | ||
| 336 | { | ||
| 337 | hr = ModulesRead(&modList); | ||
| 338 | ExitOnFailure(hr, "Failed to read ModuleSignature table"); | ||
| 339 | } | ||
| 340 | |||
| 341 | // read module components | ||
| 342 | if (fModuleComponentsTable) | ||
| 343 | { | ||
| 344 | hr = KeyPairsRead(vcsModuleComponentsQuery, &pModCompList); | ||
| 345 | ExitOnFailure(hr, "Failed to read ModuleComponents table"); | ||
| 346 | } | ||
| 347 | |||
| 348 | // read module dependencies | ||
| 349 | if (fModuleDependencyTable) | ||
| 350 | { | ||
| 351 | hr = KeyPairsRead(vcsModuleDependencyQuery, &pModDepList); | ||
| 352 | ExitOnFailure(hr, "Failed to read ModuleDependency table"); | ||
| 353 | } | ||
| 354 | |||
| 355 | // read assemblies | ||
| 356 | hr = AssembliesRead(pModCompList, pAppList, pAppRoleList, pAsmList); | ||
| 357 | ExitOnFailure(hr, "Failed to read ComPlusAssembly table"); | ||
| 358 | |||
| 359 | // read assembly dependencies | ||
| 360 | if (CpiTableExists(cptComPlusAssemblyDependency)) | ||
| 361 | { | ||
| 362 | hr = KeyPairsRead(vcsAssemblyDependencyQuery, &pAsmDepList); | ||
| 363 | ExitOnFailure(hr, "Failed to read ComPlusAssemblyDependency table"); | ||
| 364 | } | ||
| 365 | |||
| 366 | // sort modules | ||
| 367 | if (modList.pFirst && pModDepList) | ||
| 368 | { | ||
| 369 | hr = TopSortModuleList(pModDepList, &modList); | ||
| 370 | ExitOnFailure(hr, "Failed to sort modules"); | ||
| 371 | } | ||
| 372 | |||
| 373 | // sort assemblies by module | ||
| 374 | if (pAsmList->pFirst && modList.pFirst && pModDepList) | ||
| 375 | SortAssemblyListByModule(&modList, pAsmList); | ||
| 376 | |||
| 377 | // sort assemblies by dependency | ||
| 378 | if (pAsmList->pFirst && pAsmDepList) | ||
| 379 | { | ||
| 380 | hr = TopSortAssemblyList(pAsmDepList, pAsmList); | ||
| 381 | ExitOnFailure(hr, "Failed to sort assemblies"); | ||
| 382 | } | ||
| 383 | |||
| 384 | hr = S_OK; | ||
| 385 | |||
| 386 | LExit: | ||
| 387 | // clean up | ||
| 388 | ModuleListFree(&modList); | ||
| 389 | if (pModCompList) | ||
| 390 | KeyPairsFreeList(pModCompList); | ||
| 391 | if (pModDepList) | ||
| 392 | KeyPairsFreeList(pModDepList); | ||
| 393 | if (pAsmDepList) | ||
| 394 | KeyPairsFreeList(pAsmDepList); | ||
| 395 | |||
| 396 | return hr; | ||
| 397 | } | ||
| 398 | |||
| 399 | HRESULT CpiAssembliesVerifyInstall( | ||
| 400 | CPI_ASSEMBLY_LIST* pList | ||
| 401 | ) | ||
| 402 | { | ||
| 403 | HRESULT hr = S_OK; | ||
| 404 | |||
| 405 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 406 | { | ||
| 407 | // assemblies that are being installed | ||
| 408 | if (!pItm->fReferencedForInstall && !pItm->iRoleAssignmentsInstallCount && !WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 409 | continue; | ||
| 410 | |||
| 411 | // if the assembly is referensed, it must be installed | ||
| 412 | if ((pItm->fReferencedForInstall || pItm->iRoleAssignmentsInstallCount) && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction)) | ||
| 413 | MessageExitOnFailure(hr = E_FAIL, msierrComPlusAssemblyDependency, "An assembly is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey); | ||
| 414 | } | ||
| 415 | |||
| 416 | hr = S_OK; | ||
| 417 | |||
| 418 | LExit: | ||
| 419 | return hr; | ||
| 420 | } | ||
| 421 | |||
| 422 | HRESULT CpiAssembliesVerifyUninstall( | ||
| 423 | CPI_ASSEMBLY_LIST* pList | ||
| 424 | ) | ||
| 425 | { | ||
| 426 | HRESULT hr = S_OK; | ||
| 427 | |||
| 428 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 429 | { | ||
| 430 | // assemblies that are being uninstalled | ||
| 431 | if (!pItm->fReferencedForUninstall && !pItm->iRoleAssignmentsUninstallCount && (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction) && !WcaIsReInstalling(pItm->isInstalled, pItm->isAction))) | ||
| 432 | continue; | ||
| 433 | |||
| 434 | // if the application is not present, there is no need to remove the components | ||
| 435 | if (pItm->pApplication && pItm->pApplication->fObjectNotFound) | ||
| 436 | { | ||
| 437 | pItm->fIgnore = TRUE; | ||
| 438 | pList->iUninstallCount--; // elements with the fIgnore flag set will not be scheduled for uninstall | ||
| 439 | pList->iRoleUninstallCount--; | ||
| 440 | } | ||
| 441 | } | ||
| 442 | |||
| 443 | hr = S_OK; | ||
| 444 | |||
| 445 | //LExit: | ||
| 446 | return hr; | ||
| 447 | } | ||
| 448 | |||
| 449 | HRESULT CpiAssembliesInstall( | ||
| 450 | CPI_ASSEMBLY_LIST* pList, | ||
| 451 | int iRunMode, | ||
| 452 | LPWSTR* ppwzActionData, | ||
| 453 | int* piProgress | ||
| 454 | ) | ||
| 455 | { | ||
| 456 | HRESULT hr = S_OK; | ||
| 457 | |||
| 458 | int iActionType; | ||
| 459 | int iCount = 0; | ||
| 460 | |||
| 461 | // add action text | ||
| 462 | hr = CpiAddActionTextToActionData(L"RegisterComPlusAssemblies", ppwzActionData); | ||
| 463 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 464 | |||
| 465 | // assembly count | ||
| 466 | switch (iRunMode) | ||
| 467 | { | ||
| 468 | case rmDeferred: | ||
| 469 | iCount = pList->iInstallCount - pList->iCommitCount; | ||
| 470 | break; | ||
| 471 | case rmCommit: | ||
| 472 | iCount = pList->iCommitCount; | ||
| 473 | break; | ||
| 474 | case rmRollback: | ||
| 475 | iCount = pList->iInstallCount; | ||
| 476 | break; | ||
| 477 | } | ||
| 478 | |||
| 479 | // add assembly count to action data | ||
| 480 | hr = WcaWriteIntegerToCaData(iCount, ppwzActionData); | ||
| 481 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 482 | |||
| 483 | // add assemblies to custom action data in forward order | ||
| 484 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 485 | { | ||
| 486 | // assemblies that are being installed, or contains roll assignments to install | ||
| 487 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 488 | continue; | ||
| 489 | |||
| 490 | // assemblies that are being installed must be scheduled during the right type of action | ||
| 491 | BOOL fRunInCommit = 0 != (pItm->iAttributes & aaRunInCommit); | ||
| 492 | if (((rmCommit == iRunMode && !fRunInCommit) || (rmDeferred == iRunMode && fRunInCommit))) | ||
| 493 | continue; | ||
| 494 | |||
| 495 | // action type | ||
| 496 | if (rmRollback == iRunMode) | ||
| 497 | { | ||
| 498 | if (CpiIsInstalled(pItm->isInstalled)) | ||
| 499 | iActionType = atNoOp; | ||
| 500 | else | ||
| 501 | iActionType = atRemove; | ||
| 502 | } | ||
| 503 | else | ||
| 504 | iActionType = atCreate; | ||
| 505 | |||
| 506 | // add to action data | ||
| 507 | hr = AddAssemblyToActionData(pItm, TRUE, iActionType, COST_ASSEMBLY_REGISTER, ppwzActionData); | ||
| 508 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
| 509 | } | ||
| 510 | |||
| 511 | // add progress tics | ||
| 512 | if (piProgress) | ||
| 513 | *piProgress += COST_ASSEMBLY_REGISTER * iCount; | ||
| 514 | |||
| 515 | hr = S_OK; | ||
| 516 | |||
| 517 | LExit: | ||
| 518 | return hr; | ||
| 519 | } | ||
| 520 | |||
| 521 | HRESULT CpiAssembliesUninstall( | ||
| 522 | CPI_ASSEMBLY_LIST* pList, | ||
| 523 | int iRunMode, | ||
| 524 | LPWSTR* ppwzActionData, | ||
| 525 | int* piProgress | ||
| 526 | ) | ||
| 527 | { | ||
| 528 | HRESULT hr = S_OK; | ||
| 529 | |||
| 530 | int iActionType; | ||
| 531 | |||
| 532 | // add action text | ||
| 533 | hr = CpiAddActionTextToActionData(L"UnregisterComPlusAssemblies", ppwzActionData); | ||
| 534 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 535 | |||
| 536 | // add assembly count to action data | ||
| 537 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
| 538 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 539 | |||
| 540 | // add assemblies to custom action data in reverse order | ||
| 541 | for (CPI_ASSEMBLY* pItm = pList->pLast; pItm; pItm = pItm->pPrev) | ||
| 542 | { | ||
| 543 | // assemblies that are being uninstalled | ||
| 544 | if (pItm->fIgnore || (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction) && !WcaIsReInstalling(pItm->isInstalled, pItm->isAction))) | ||
| 545 | continue; | ||
| 546 | |||
| 547 | // action type | ||
| 548 | if (rmRollback == iRunMode) | ||
| 549 | iActionType = atCreate; | ||
| 550 | else | ||
| 551 | iActionType = atRemove; | ||
| 552 | |||
| 553 | // add to action data | ||
| 554 | hr = AddAssemblyToActionData(pItm, FALSE, iActionType, COST_ASSEMBLY_UNREGISTER, ppwzActionData); | ||
| 555 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
| 556 | } | ||
| 557 | |||
| 558 | // add progress tics | ||
| 559 | if (piProgress) | ||
| 560 | *piProgress += COST_ASSEMBLY_UNREGISTER * pList->iUninstallCount; | ||
| 561 | |||
| 562 | hr = S_OK; | ||
| 563 | |||
| 564 | LExit: | ||
| 565 | return hr; | ||
| 566 | } | ||
| 567 | |||
| 568 | HRESULT CpiRoleAssignmentsInstall( | ||
| 569 | CPI_ASSEMBLY_LIST* pList, | ||
| 570 | int iRunMode, | ||
| 571 | LPWSTR* ppwzActionData, | ||
| 572 | int* piProgress | ||
| 573 | ) | ||
| 574 | { | ||
| 575 | HRESULT hr = S_OK; | ||
| 576 | |||
| 577 | int iActionType; | ||
| 578 | int iCount = 0; | ||
| 579 | |||
| 580 | // add action text | ||
| 581 | hr = CpiAddActionTextToActionData(L"AddComPlusRoleAssignments", ppwzActionData); | ||
| 582 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 583 | |||
| 584 | // assembly count | ||
| 585 | switch (iRunMode) | ||
| 586 | { | ||
| 587 | case rmDeferred: | ||
| 588 | iCount = pList->iRoleInstallCount - pList->iRoleCommitCount; | ||
| 589 | break; | ||
| 590 | case rmCommit: | ||
| 591 | iCount = pList->iRoleCommitCount; | ||
| 592 | break; | ||
| 593 | case rmRollback: | ||
| 594 | iCount = pList->iRoleInstallCount; | ||
| 595 | break; | ||
| 596 | } | ||
| 597 | |||
| 598 | // add assembly count to action data | ||
| 599 | hr = WcaWriteIntegerToCaData(iCount, ppwzActionData); | ||
| 600 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 601 | |||
| 602 | // add assemblies to custom action data in forward order | ||
| 603 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 604 | { | ||
| 605 | // assemblies that are being installed, or contains roll assignments to install | ||
| 606 | if (!pItm->iRoleAssignmentsInstallCount) | ||
| 607 | continue; | ||
| 608 | |||
| 609 | // assemblies that are being installed must be scheduled during the right type of action | ||
| 610 | BOOL fRunInCommit = 0 != (pItm->iAttributes & aaRunInCommit); | ||
| 611 | if (((rmCommit == iRunMode && !fRunInCommit) || (rmDeferred == iRunMode && fRunInCommit))) | ||
| 612 | continue; | ||
| 613 | |||
| 614 | // action type | ||
| 615 | if (rmRollback == iRunMode) | ||
| 616 | { | ||
| 617 | if (CpiIsInstalled(pItm->isInstalled)) | ||
| 618 | iActionType = atNoOp; | ||
| 619 | else | ||
| 620 | iActionType = atRemove; | ||
| 621 | } | ||
| 622 | else | ||
| 623 | iActionType = atCreate; | ||
| 624 | |||
| 625 | // add to action data | ||
| 626 | hr = AddRoleAssignmentsToActionData(pItm, TRUE, iActionType, COST_ROLLASSIGNMENT_CREATE, ppwzActionData); | ||
| 627 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
| 628 | |||
| 629 | // add progress tics | ||
| 630 | if (piProgress) | ||
| 631 | *piProgress += COST_ROLLASSIGNMENT_CREATE * pItm->iRoleAssignmentsInstallCount; | ||
| 632 | } | ||
| 633 | |||
| 634 | hr = S_OK; | ||
| 635 | |||
| 636 | LExit: | ||
| 637 | return hr; | ||
| 638 | } | ||
| 639 | |||
| 640 | HRESULT CpiRoleAssignmentsUninstall( | ||
| 641 | CPI_ASSEMBLY_LIST* pList, | ||
| 642 | int iRunMode, | ||
| 643 | LPWSTR* ppwzActionData, | ||
| 644 | int* piProgress | ||
| 645 | ) | ||
| 646 | { | ||
| 647 | HRESULT hr = S_OK; | ||
| 648 | |||
| 649 | int iActionType; | ||
| 650 | |||
| 651 | // add action text | ||
| 652 | hr = CpiAddActionTextToActionData(L"RemoveComPlusRoleAssignments", ppwzActionData); | ||
| 653 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 654 | |||
| 655 | // add assembly count to action data | ||
| 656 | hr = WcaWriteIntegerToCaData(pList->iRoleUninstallCount, ppwzActionData); | ||
| 657 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 658 | |||
| 659 | // add assemblies to custom action data in reverse order | ||
| 660 | for (CPI_ASSEMBLY* pItm = pList->pLast; pItm; pItm = pItm->pPrev) | ||
| 661 | { | ||
| 662 | // assemblies that are being uninstalled | ||
| 663 | if (pItm->fIgnore || !pItm->iRoleAssignmentsUninstallCount) | ||
| 664 | continue; | ||
| 665 | |||
| 666 | // action type | ||
| 667 | if (rmRollback == iRunMode) | ||
| 668 | iActionType = atCreate; | ||
| 669 | else | ||
| 670 | iActionType = atRemove; | ||
| 671 | |||
| 672 | // add to action data | ||
| 673 | hr = AddRoleAssignmentsToActionData(pItm, FALSE, iActionType, COST_ROLLASSIGNMENT_DELETE, ppwzActionData); | ||
| 674 | ExitOnFailure(hr, "Failed to add assembly to custom action data, key: %S", pItm->wzKey); | ||
| 675 | |||
| 676 | // add progress tics | ||
| 677 | if (piProgress) | ||
| 678 | *piProgress += COST_ROLLASSIGNMENT_DELETE * pItm->iRoleAssignmentsUninstallCount; | ||
| 679 | } | ||
| 680 | |||
| 681 | hr = S_OK; | ||
| 682 | |||
| 683 | LExit: | ||
| 684 | return hr; | ||
| 685 | } | ||
| 686 | |||
| 687 | HRESULT CpiGetSubscriptionsCollForComponent( | ||
| 688 | CPI_ASSEMBLY* pAsm, | ||
| 689 | CPI_COMPONENT* pComp, | ||
| 690 | ICatalogCollection** ppiSubsColl | ||
| 691 | ) | ||
| 692 | { | ||
| 693 | HRESULT hr = S_OK; | ||
| 694 | |||
| 695 | ICatalogCollection* piCompColl = NULL; | ||
| 696 | ICatalogObject* piCompObj = NULL; | ||
| 697 | |||
| 698 | // get applications collection | ||
| 699 | if (!pComp->piSubsColl) | ||
| 700 | { | ||
| 701 | // get components collection for application | ||
| 702 | hr = CpiGetComponentsCollForApplication(pAsm->pApplication, &piCompColl); | ||
| 703 | ExitOnFailure(hr, "Failed to get components collection for application"); | ||
| 704 | |||
| 705 | if (S_FALSE == hr) | ||
| 706 | ExitFunction(); // exit with hr = S_FALSE | ||
| 707 | |||
| 708 | // find component object | ||
| 709 | hr = CpiFindCollectionObject(piCompColl, pComp->wzCLSID, NULL, &piCompObj); | ||
| 710 | ExitOnFailure(hr, "Failed to find component object"); | ||
| 711 | |||
| 712 | if (S_FALSE == hr) | ||
| 713 | ExitFunction(); // exit with hr = S_FALSE | ||
| 714 | |||
| 715 | // get roles collection | ||
| 716 | hr = CpiGetCatalogCollection(piCompColl, piCompObj, L"SubscriptionsForComponent", &pComp->piSubsColl); | ||
| 717 | ExitOnFailure(hr, "Failed to get subscriptions collection"); | ||
| 718 | } | ||
| 719 | |||
| 720 | // return value | ||
| 721 | *ppiSubsColl = pComp->piSubsColl; | ||
| 722 | (*ppiSubsColl)->AddRef(); | ||
| 723 | |||
| 724 | hr = S_OK; | ||
| 725 | |||
| 726 | LExit: | ||
| 727 | // clean up | ||
| 728 | ReleaseObject(piCompColl); | ||
| 729 | ReleaseObject(piCompObj); | ||
| 730 | |||
| 731 | return hr; | ||
| 732 | } | ||
| 733 | |||
| 734 | |||
| 735 | // helper function definitions | ||
| 736 | |||
| 737 | static HRESULT GetAssemblyName( | ||
| 738 | LPCWSTR pwzComponent, | ||
| 739 | LPWSTR* ppwzAssemblyName | ||
| 740 | ) | ||
| 741 | { | ||
| 742 | HRESULT hr = S_OK; | ||
| 743 | |||
| 744 | PMSIHANDLE hView, hRecKey, hRec; | ||
| 745 | |||
| 746 | LPWSTR pwzKey = NULL; | ||
| 747 | |||
| 748 | LPWSTR pwzName = NULL; | ||
| 749 | LPWSTR pwzVersion = NULL; | ||
| 750 | LPWSTR pwzCulture = NULL; | ||
| 751 | LPWSTR pwzPublicKeyToken = NULL; | ||
| 752 | |||
| 753 | // create parameter record | ||
| 754 | hRecKey = ::MsiCreateRecord(1); | ||
| 755 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 756 | hr = WcaSetRecordString(hRecKey, 1, pwzComponent); | ||
| 757 | ExitOnFailure(hr, "Failed to set record string"); | ||
| 758 | |||
| 759 | // open view | ||
| 760 | hr = WcaOpenView(vcsMsiAssemblyNameQuery, &hView); | ||
| 761 | ExitOnFailure(hr, "Failed to open view on MsiAssemblyName table"); | ||
| 762 | hr = WcaExecuteView(hView, hRecKey); | ||
| 763 | ExitOnFailure(hr, "Failed to execute view on MsiAssemblyName table"); | ||
| 764 | |||
| 765 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 766 | { | ||
| 767 | // read key | ||
| 768 | hr = WcaGetRecordString(hRec, manqName, &pwzKey); | ||
| 769 | ExitOnFailure(hr, "Failed to get name"); | ||
| 770 | |||
| 771 | // read value | ||
| 772 | if (0 == lstrcmpiW(L"name", pwzKey)) | ||
| 773 | hr = WcaGetRecordString(hRec, manqValue, &pwzName); | ||
| 774 | else if (0 == lstrcmpiW(L"version", pwzKey)) | ||
| 775 | hr = WcaGetRecordString(hRec, manqValue, &pwzVersion); | ||
| 776 | else if (0 == lstrcmpiW(L"culture", pwzKey)) | ||
| 777 | hr = WcaGetRecordString(hRec, manqValue, &pwzCulture); | ||
| 778 | else if (0 == lstrcmpiW(L"publicKeyToken", pwzKey)) | ||
| 779 | hr = WcaGetRecordString(hRec, manqValue, &pwzPublicKeyToken); | ||
| 780 | else | ||
| 781 | { | ||
| 782 | WcaLog(LOGMSG_VERBOSE, "Unknown name in MsiAssemblyName table: %S, %S", pwzComponent, pwzKey); | ||
| 783 | hr = S_OK; | ||
| 784 | } | ||
| 785 | |||
| 786 | ExitOnFailure(hr, "Failed to get value"); | ||
| 787 | } | ||
| 788 | |||
| 789 | if (E_NOMOREITEMS != hr) | ||
| 790 | ExitOnFailure(hr, "Failed to fetch record"); | ||
| 791 | |||
| 792 | // verify | ||
| 793 | if (!(pwzName && *pwzName) || !(pwzVersion && *pwzVersion)) | ||
| 794 | ExitOnFailure(hr = E_FAIL, "Incomplete assembly name"); | ||
| 795 | |||
| 796 | // build name string | ||
| 797 | hr = StrAllocFormatted(ppwzAssemblyName, L"%s, Version=%s, Culture=%s, PublicKeyToken=%s", | ||
| 798 | pwzName, pwzVersion, | ||
| 799 | pwzCulture && *pwzCulture ? pwzCulture : L"Neutral", | ||
| 800 | pwzPublicKeyToken && *pwzPublicKeyToken ? pwzPublicKeyToken : L"null"); | ||
| 801 | ExitOnFailure(hr, "Failed to build assembly name string"); | ||
| 802 | |||
| 803 | hr = S_OK; | ||
| 804 | |||
| 805 | LExit: | ||
| 806 | // clean up | ||
| 807 | ReleaseStr(pwzKey); | ||
| 808 | ReleaseStr(pwzName); | ||
| 809 | ReleaseStr(pwzVersion); | ||
| 810 | ReleaseStr(pwzCulture); | ||
| 811 | ReleaseStr(pwzPublicKeyToken); | ||
| 812 | |||
| 813 | return hr; | ||
| 814 | } | ||
| 815 | |||
| 816 | static HRESULT KeyPairsRead( | ||
| 817 | LPCWSTR pwzQuery, | ||
| 818 | CPI_KEY_PAIR** ppKeyPairList | ||
| 819 | ) | ||
| 820 | { | ||
| 821 | HRESULT hr = S_OK; | ||
| 822 | |||
| 823 | PMSIHANDLE hView, hRec; | ||
| 824 | |||
| 825 | CPI_KEY_PAIR* pItm = NULL; | ||
| 826 | LPWSTR pwzData = NULL; | ||
| 827 | |||
| 828 | // loop through all dependencies | ||
| 829 | hr = WcaOpenExecuteView(pwzQuery, &hView); | ||
| 830 | ExitOnFailure(hr, "Failed to execute view on table"); | ||
| 831 | |||
| 832 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 833 | { | ||
| 834 | // create entry | ||
| 835 | pItm = (CPI_KEY_PAIR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_KEY_PAIR)); | ||
| 836 | if (!pItm) | ||
| 837 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 838 | |||
| 839 | // get key | ||
| 840 | hr = WcaGetRecordString(hRec, kpqFirstKey, &pwzData); | ||
| 841 | ExitOnFailure(hr, "Failed to get first key"); | ||
| 842 | StringCchCopyW(pItm->wzFirstKey, countof(pItm->wzFirstKey), pwzData); | ||
| 843 | |||
| 844 | // get key | ||
| 845 | hr = WcaGetRecordString(hRec, kpqSecondKey, &pwzData); | ||
| 846 | ExitOnFailure(hr, "Failed to get second key"); | ||
| 847 | StringCchCopyW(pItm->wzSecondKey, countof(pItm->wzSecondKey), pwzData); | ||
| 848 | |||
| 849 | // add entry | ||
| 850 | if (*ppKeyPairList) | ||
| 851 | pItm->pNext = *ppKeyPairList; | ||
| 852 | *ppKeyPairList = pItm; | ||
| 853 | pItm = NULL; | ||
| 854 | } | ||
| 855 | |||
| 856 | if (E_NOMOREITEMS == hr) | ||
| 857 | hr = S_OK; | ||
| 858 | |||
| 859 | LExit: | ||
| 860 | // clean up | ||
| 861 | if (pItm) | ||
| 862 | KeyPairsFreeList(pItm); | ||
| 863 | |||
| 864 | ReleaseStr(pwzData); | ||
| 865 | |||
| 866 | return hr; | ||
| 867 | } | ||
| 868 | |||
| 869 | static HRESULT ModulesRead( | ||
| 870 | CPI_MODULE_LIST* pModList | ||
| 871 | ) | ||
| 872 | { | ||
| 873 | HRESULT hr = S_OK; | ||
| 874 | |||
| 875 | PMSIHANDLE hView, hRec; | ||
| 876 | |||
| 877 | CPI_MODULE* pItm = NULL; | ||
| 878 | LPWSTR pwzData = NULL; | ||
| 879 | |||
| 880 | // loop through all modules | ||
| 881 | hr = WcaOpenExecuteView(vcsModuleQuery, &hView); | ||
| 882 | ExitOnFailure(hr, "Failed to execute view on ModuleSignature table"); | ||
| 883 | |||
| 884 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 885 | { | ||
| 886 | // create entry | ||
| 887 | pItm = (CPI_MODULE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_MODULE)); | ||
| 888 | if (!pItm) | ||
| 889 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 890 | |||
| 891 | // get key | ||
| 892 | hr = WcaGetRecordString(hRec, mqModule, &pwzData); | ||
| 893 | ExitOnFailure(hr, "Failed to get key"); | ||
| 894 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 895 | |||
| 896 | // add entry | ||
| 897 | if (pModList->pLast) | ||
| 898 | { | ||
| 899 | pModList->pLast->pNext = pItm; | ||
| 900 | pItm->pPrev = pModList->pLast; | ||
| 901 | } | ||
| 902 | else | ||
| 903 | pModList->pFirst = pItm; | ||
| 904 | pModList->pLast = pItm; | ||
| 905 | pItm = NULL; | ||
| 906 | } | ||
| 907 | |||
| 908 | if (E_NOMOREITEMS == hr) | ||
| 909 | hr = S_OK; | ||
| 910 | |||
| 911 | LExit: | ||
| 912 | // clean up | ||
| 913 | if (pItm) | ||
| 914 | ModuleFree(pItm); | ||
| 915 | |||
| 916 | ReleaseStr(pwzData); | ||
| 917 | |||
| 918 | return hr; | ||
| 919 | } | ||
| 920 | |||
| 921 | static HRESULT AssembliesRead( | ||
| 922 | CPI_KEY_PAIR* pModCompList, | ||
| 923 | CPI_APPLICATION_LIST* pAppList, | ||
| 924 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 925 | CPI_ASSEMBLY_LIST* pAsmList | ||
| 926 | ) | ||
| 927 | { | ||
| 928 | HRESULT hr = S_OK; | ||
| 929 | UINT er = ERROR_SUCCESS; | ||
| 930 | |||
| 931 | PMSIHANDLE hView, hRec; | ||
| 932 | |||
| 933 | CPI_ASSEMBLY* pItm = NULL; | ||
| 934 | CPI_KEY_PAIR* pModComp; | ||
| 935 | LPWSTR pwzData = NULL; | ||
| 936 | LPWSTR pwzComponent = NULL; | ||
| 937 | BOOL fMatchingArchitecture = FALSE; | ||
| 938 | |||
| 939 | // loop through all assemblies | ||
| 940 | hr = WcaOpenExecuteView(vcsAssemblyQuery, &hView); | ||
| 941 | ExitOnFailure(hr, "Failed to execute view on ComPlusAssembly table"); | ||
| 942 | |||
| 943 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 944 | { | ||
| 945 | // get component | ||
| 946 | hr = WcaGetRecordString(hRec, aqComponent, &pwzComponent); | ||
| 947 | ExitOnFailure(hr, "Failed to get component"); | ||
| 948 | |||
| 949 | // check if the component is our processor architecture | ||
| 950 | hr = CpiVerifyComponentArchitecure(pwzComponent, &fMatchingArchitecture); | ||
| 951 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
| 952 | |||
| 953 | if (!fMatchingArchitecture) | ||
| 954 | { | ||
| 955 | continue; // not the same architecture, ignore | ||
| 956 | } | ||
| 957 | |||
| 958 | // create entry | ||
| 959 | pItm = (CPI_ASSEMBLY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ASSEMBLY)); | ||
| 960 | if (!pItm) | ||
| 961 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 962 | |||
| 963 | // get component install state | ||
| 964 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &pItm->isInstalled, &pItm->isAction); | ||
| 965 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
| 966 | |||
| 967 | // get key | ||
| 968 | hr = WcaGetRecordString(hRec, aqAssembly, &pwzData); | ||
| 969 | ExitOnFailure(hr, "Failed to get key"); | ||
| 970 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 971 | |||
| 972 | // get attributes | ||
| 973 | hr = WcaGetRecordInteger(hRec, aqAttributes, &pItm->iAttributes); | ||
| 974 | ExitOnFailure(hr, "Failed to get attributes"); | ||
| 975 | |||
| 976 | // get assembly name | ||
| 977 | hr = WcaGetRecordFormattedString(hRec, aqAssemblyName, &pItm->pwzAssemblyName); | ||
| 978 | ExitOnFailure(hr, "Failed to get assembly name"); | ||
| 979 | |||
| 980 | if (!*pItm->pwzAssemblyName && (pItm->iAttributes & aaPathFromGAC)) | ||
| 981 | { | ||
| 982 | // get assembly name for component | ||
| 983 | hr = GetAssemblyName(pwzComponent, &pItm->pwzAssemblyName); | ||
| 984 | ExitOnFailure(hr, "Failed to get assembly name for component"); | ||
| 985 | } | ||
| 986 | |||
| 987 | // get dll path | ||
| 988 | hr = WcaGetRecordFormattedString(hRec, aqDllPath, &pItm->pwzDllPath); | ||
| 989 | ExitOnFailure(hr, "Failed to get assembly dll path"); | ||
| 990 | |||
| 991 | // get module | ||
| 992 | // TODO: if there is a very large number of components belonging to modules, this search might be slow | ||
| 993 | hr = KeyPairFindByFirstKey(pModCompList, pwzData, &pModComp); | ||
| 994 | |||
| 995 | if (S_OK == hr) | ||
| 996 | StringCchCopyW(pItm->wzModule, countof(pItm->wzModule), pModComp->wzSecondKey); | ||
| 997 | |||
| 998 | // get application | ||
| 999 | hr = WcaGetRecordString(hRec, aqApplication, &pwzData); | ||
| 1000 | ExitOnFailure(hr, "Failed to get application"); | ||
| 1001 | |||
| 1002 | if (pwzData && *pwzData) | ||
| 1003 | { | ||
| 1004 | hr = CpiApplicationFindByKey(pAppList, pwzData, &pItm->pApplication); | ||
| 1005 | if (S_FALSE == hr) | ||
| 1006 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 1007 | ExitOnFailure(hr, "Failed to find application, key: %S", pwzData); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | // get tlb path | ||
| 1011 | hr = WcaGetRecordFormattedString(hRec, aqTlbPath, &pItm->pwzTlbPath); | ||
| 1012 | ExitOnFailure(hr, "Failed to get assembly tlb path"); | ||
| 1013 | |||
| 1014 | // get proxy-stub dll path | ||
| 1015 | hr = WcaGetRecordFormattedString(hRec, aqPSDllPath, &pItm->pwzPSDllPath); | ||
| 1016 | ExitOnFailure(hr, "Failed to get assembly proxy-stub DLL path"); | ||
| 1017 | |||
| 1018 | // read components | ||
| 1019 | if (CpiTableExists(cptComPlusComponent)) | ||
| 1020 | { | ||
| 1021 | hr = ComponentsRead(pItm->wzKey, pAppRoleList, pItm); | ||
| 1022 | ExitOnFailure(hr, "Failed to read components for assembly"); | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | // set references & increment counters | ||
| 1026 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 1027 | { | ||
| 1028 | pAsmList->iInstallCount++; | ||
| 1029 | if (pItm->iAttributes & aaRunInCommit) | ||
| 1030 | pAsmList->iCommitCount++; | ||
| 1031 | } | ||
| 1032 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction) || WcaIsReInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 1033 | pAsmList->iUninstallCount++; | ||
| 1034 | |||
| 1035 | if (pItm->iRoleAssignmentsInstallCount) | ||
| 1036 | { | ||
| 1037 | pAsmList->iRoleInstallCount++; | ||
| 1038 | if (pItm->iAttributes & aaRunInCommit) | ||
| 1039 | pAsmList->iRoleCommitCount++; | ||
| 1040 | } | ||
| 1041 | if (pItm->iRoleAssignmentsUninstallCount) | ||
| 1042 | pAsmList->iRoleUninstallCount++; | ||
| 1043 | |||
| 1044 | if (pItm->pApplication) | ||
| 1045 | { | ||
| 1046 | if (pItm->iRoleAssignmentsInstallCount || WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 1047 | CpiApplicationAddReferenceInstall(pItm->pApplication); | ||
| 1048 | if (pItm->iRoleAssignmentsUninstallCount || WcaIsUninstalling(pItm->isInstalled, pItm->isAction) || WcaIsReInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 1049 | CpiApplicationAddReferenceUninstall(pItm->pApplication); | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | // add entry | ||
| 1053 | if (pAsmList->pLast) | ||
| 1054 | { | ||
| 1055 | pAsmList->pLast->pNext = pItm; | ||
| 1056 | pItm->pPrev = pAsmList->pLast; | ||
| 1057 | } | ||
| 1058 | else | ||
| 1059 | pAsmList->pFirst = pItm; | ||
| 1060 | pAsmList->pLast = pItm; | ||
| 1061 | pItm = NULL; | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | if (E_NOMOREITEMS == hr) | ||
| 1065 | hr = S_OK; | ||
| 1066 | |||
| 1067 | LExit: | ||
| 1068 | // clean up | ||
| 1069 | if (pItm) | ||
| 1070 | AssemblyFree(pItm); | ||
| 1071 | |||
| 1072 | ReleaseStr(pwzData); | ||
| 1073 | ReleaseStr(pwzComponent); | ||
| 1074 | |||
| 1075 | return hr; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | static HRESULT TopSortModuleList( | ||
| 1079 | CPI_KEY_PAIR* pDepList, | ||
| 1080 | CPI_MODULE_LIST* pList | ||
| 1081 | ) | ||
| 1082 | { | ||
| 1083 | HRESULT hr = S_OK; | ||
| 1084 | |||
| 1085 | // top sort list | ||
| 1086 | for (CPI_MODULE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 1087 | { | ||
| 1088 | // append module | ||
| 1089 | hr = SwapDependentModules(NULL, pDepList, pList, pItm, pItm); | ||
| 1090 | ExitOnFailure(hr, "Failed to swap dependent modules"); | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | hr = S_OK; | ||
| 1094 | |||
| 1095 | LExit: | ||
| 1096 | return hr; | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | static HRESULT SwapDependentModules( | ||
| 1100 | CPI_DEPENDENCY_CHAIN* pdcPrev, // list containing the entire dependency chain | ||
| 1101 | CPI_KEY_PAIR* pDepList, // module dependency list | ||
| 1102 | CPI_MODULE_LIST* pList, // module list being sorted | ||
| 1103 | CPI_MODULE* pRoot, // first module in the chain | ||
| 1104 | CPI_MODULE* pItm // current module to test for dependencies | ||
| 1105 | ) | ||
| 1106 | { | ||
| 1107 | HRESULT hr = S_OK; | ||
| 1108 | |||
| 1109 | CPI_MODULE* pDepItm; | ||
| 1110 | |||
| 1111 | // find dependencies | ||
| 1112 | for (CPI_KEY_PAIR* pDep = pDepList; pDep; pDep = pDep->pNext) | ||
| 1113 | { | ||
| 1114 | if (0 == lstrcmpW(pItm->wzKey, pDep->wzFirstKey)) | ||
| 1115 | { | ||
| 1116 | CPI_DEPENDENCY_CHAIN dcItm; | ||
| 1117 | dcItm.pwzKey = pItm->wzKey; | ||
| 1118 | dcItm.pPrev = pdcPrev; | ||
| 1119 | |||
| 1120 | // check for circular dependencies | ||
| 1121 | for (CPI_DEPENDENCY_CHAIN* pdcItm = &dcItm; pdcItm; pdcItm = pdcItm->pPrev) | ||
| 1122 | { | ||
| 1123 | if (0 == lstrcmpW(pdcItm->pwzKey, pDep->wzSecondKey)) | ||
| 1124 | { | ||
| 1125 | // circular dependency found | ||
| 1126 | ExitOnFailure(hr = E_FAIL, "Circular module dependency found, key: %S", pDep->wzSecondKey); | ||
| 1127 | } | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | // make sure the item is not already in the list | ||
| 1131 | hr = ModuleFindByKey(pRoot->pPrev, pDep->wzSecondKey, TRUE, &pDepItm); // find in reverse order | ||
| 1132 | |||
| 1133 | if (S_OK == hr) | ||
| 1134 | continue; // item found, move on | ||
| 1135 | |||
| 1136 | // find item in the list | ||
| 1137 | hr = ModuleFindByKey(pRoot->pNext, pDep->wzSecondKey, FALSE, &pDepItm); // find in forward order | ||
| 1138 | |||
| 1139 | if (S_FALSE == hr) | ||
| 1140 | { | ||
| 1141 | // not found | ||
| 1142 | ExitOnFailure(hr = E_FAIL, "Module dependency not found, key: %S", pDep->wzSecondKey); | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | // if this item in turn has dependencies, they have to be swaped first | ||
| 1146 | hr = SwapDependentModules(&dcItm, pDepList, pList, pRoot, pDepItm); | ||
| 1147 | ExitOnFailure(hr, "Failed to swap dependent module"); | ||
| 1148 | |||
| 1149 | // remove item from its current position | ||
| 1150 | pDepItm->pPrev->pNext = pDepItm->pNext; // pDepItm can never be the first item, no need to check pPrev | ||
| 1151 | if (pDepItm->pNext) | ||
| 1152 | pDepItm->pNext->pPrev = pDepItm->pPrev; | ||
| 1153 | else | ||
| 1154 | { | ||
| 1155 | pList->pLast = pDepItm->pPrev; | ||
| 1156 | pList->pLast->pNext = NULL; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | // insert before the current item | ||
| 1160 | if (pRoot->pPrev) | ||
| 1161 | pRoot->pPrev->pNext = pDepItm; | ||
| 1162 | else | ||
| 1163 | pList->pFirst = pDepItm; | ||
| 1164 | pDepItm->pPrev = pRoot->pPrev; | ||
| 1165 | pRoot->pPrev = pDepItm; | ||
| 1166 | pDepItm->pNext = pRoot; | ||
| 1167 | } | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | hr = S_OK; | ||
| 1171 | |||
| 1172 | LExit: | ||
| 1173 | return hr; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | static HRESULT ModuleFindByKey( | ||
| 1177 | CPI_MODULE* pItm, | ||
| 1178 | LPCWSTR pwzKey, | ||
| 1179 | BOOL fReverse, | ||
| 1180 | CPI_MODULE** ppItm | ||
| 1181 | ) | ||
| 1182 | { | ||
| 1183 | for (; pItm; pItm = fReverse ? pItm->pPrev : pItm->pNext) | ||
| 1184 | { | ||
| 1185 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
| 1186 | { | ||
| 1187 | *ppItm = pItm; | ||
| 1188 | return S_OK; | ||
| 1189 | } | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | return S_FALSE; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | static void SortAssemblyListByModule( | ||
| 1196 | CPI_MODULE_LIST* pModList, | ||
| 1197 | CPI_ASSEMBLY_LIST* pAsmList | ||
| 1198 | ) | ||
| 1199 | { | ||
| 1200 | CPI_ASSEMBLY* pMoved = NULL; // first moved item | ||
| 1201 | |||
| 1202 | // loop modules in reverse order | ||
| 1203 | for (CPI_MODULE* pMod = pModList->pLast; pMod; pMod = pMod->pPrev) | ||
| 1204 | { | ||
| 1205 | // loop assemblies in forward order, starting with the first unmoved item | ||
| 1206 | CPI_ASSEMBLY* pAsm = pMoved ? pMoved->pNext : pAsmList->pFirst; | ||
| 1207 | while (pAsm) | ||
| 1208 | { | ||
| 1209 | CPI_ASSEMBLY* pNext = pAsm->pNext; | ||
| 1210 | |||
| 1211 | // check if assembly belongs to the current module | ||
| 1212 | if (0 == lstrcmpW(pMod->wzKey, pAsm->wzModule)) | ||
| 1213 | { | ||
| 1214 | // if the item is not already first in the list | ||
| 1215 | if (pAsm->pPrev) | ||
| 1216 | { | ||
| 1217 | // remove item from it's current position | ||
| 1218 | pAsm->pPrev->pNext = pAsm->pNext; | ||
| 1219 | if (pAsm->pNext) | ||
| 1220 | pAsm->pNext->pPrev = pAsm->pPrev; | ||
| 1221 | else | ||
| 1222 | pAsmList->pLast = pAsm->pPrev; | ||
| 1223 | |||
| 1224 | // insert item first in the list | ||
| 1225 | pAsmList->pFirst->pPrev = pAsm; | ||
| 1226 | pAsm->pNext = pAsmList->pFirst; | ||
| 1227 | pAsm->pPrev = NULL; | ||
| 1228 | pAsmList->pFirst = pAsm; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | // if we haven't moved any items yet, this is the first moved item | ||
| 1232 | if (!pMoved) | ||
| 1233 | pMoved = pAsm; | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | pAsm = pNext; | ||
| 1237 | } | ||
| 1238 | } | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | static HRESULT TopSortAssemblyList( | ||
| 1242 | CPI_KEY_PAIR* pDepList, | ||
| 1243 | CPI_ASSEMBLY_LIST* pList | ||
| 1244 | ) | ||
| 1245 | { | ||
| 1246 | HRESULT hr = S_OK; | ||
| 1247 | |||
| 1248 | // top sort list | ||
| 1249 | for (CPI_ASSEMBLY* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 1250 | { | ||
| 1251 | // append module | ||
| 1252 | hr = SwapDependentAssemblies(NULL, pDepList, pList, pItm, pItm); | ||
| 1253 | ExitOnFailure(hr, "Failed to swap dependent assemblies"); | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | hr = S_OK; | ||
| 1257 | |||
| 1258 | LExit: | ||
| 1259 | return hr; | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | static HRESULT SwapDependentAssemblies( | ||
| 1263 | CPI_DEPENDENCY_CHAIN* pdcPrev, // list containing the entire dependency chain | ||
| 1264 | CPI_KEY_PAIR* pDepList, // assembly dependency list | ||
| 1265 | CPI_ASSEMBLY_LIST* pList, // assembly list being sorted | ||
| 1266 | CPI_ASSEMBLY* pRoot, // first assembly in the chain | ||
| 1267 | CPI_ASSEMBLY* pItm // current assembly to test for dependencies | ||
| 1268 | ) | ||
| 1269 | { | ||
| 1270 | HRESULT hr = S_OK; | ||
| 1271 | |||
| 1272 | CPI_ASSEMBLY* pDepItm; | ||
| 1273 | |||
| 1274 | // find dependencies | ||
| 1275 | for (CPI_KEY_PAIR* pDep = pDepList; pDep; pDep = pDep->pNext) | ||
| 1276 | { | ||
| 1277 | if (0 == lstrcmpW(pItm->wzKey, pDep->wzFirstKey)) | ||
| 1278 | { | ||
| 1279 | CPI_DEPENDENCY_CHAIN dcItm; | ||
| 1280 | dcItm.pwzKey = pItm->wzKey; | ||
| 1281 | dcItm.pPrev = pdcPrev; | ||
| 1282 | |||
| 1283 | // check for circular dependencies | ||
| 1284 | for (CPI_DEPENDENCY_CHAIN* pdcItm = &dcItm; pdcItm; pdcItm = pdcItm->pPrev) | ||
| 1285 | { | ||
| 1286 | if (0 == lstrcmpW(pdcItm->pwzKey, pDep->wzSecondKey)) | ||
| 1287 | { | ||
| 1288 | // circular dependency found | ||
| 1289 | ExitOnFailure(hr = E_FAIL, "Circular assembly dependency found, key: %S", pDep->wzSecondKey); | ||
| 1290 | } | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | // make sure the item is not already in the list | ||
| 1294 | hr = AssemblyFindByKey(pRoot->pPrev, pDep->wzSecondKey, TRUE, &pDepItm); // find in reverse order | ||
| 1295 | |||
| 1296 | if (S_OK == hr) | ||
| 1297 | continue; // item found, move on | ||
| 1298 | |||
| 1299 | // find item in the list | ||
| 1300 | hr = AssemblyFindByKey(pRoot->pNext, pDep->wzSecondKey, FALSE, &pDepItm); // find in forward order | ||
| 1301 | |||
| 1302 | if (S_FALSE == hr) | ||
| 1303 | { | ||
| 1304 | // not found | ||
| 1305 | ExitOnFailure(hr = E_FAIL, "Assembly dependency not found, key: %S", pDep->wzSecondKey); | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | // if the root item belongs to a module, this item must also belong to the same module | ||
| 1309 | if (*pItm->wzModule) | ||
| 1310 | { | ||
| 1311 | if (0 != lstrcmpW(pDepItm->wzModule, pItm->wzModule)) | ||
| 1312 | ExitOnFailure(hr = E_FAIL, "An assembly dependency can only exist between two assemblies not belonging to modules, or belonging to the same module. assembly: %S, required assembly: %S", pItm->wzKey, pDepItm->wzKey); | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | // if this item in turn has dependencies, they have to be swaped first | ||
| 1316 | hr = SwapDependentAssemblies(&dcItm, pDepList, pList, pRoot, pDepItm); | ||
| 1317 | ExitOnFailure(hr, "Failed to swap dependent assemblies"); | ||
| 1318 | |||
| 1319 | // remove item from its current position | ||
| 1320 | pDepItm->pPrev->pNext = pDepItm->pNext; // pDepItm can never be the first item, no need to check pPrev | ||
| 1321 | if (pDepItm->pNext) | ||
| 1322 | pDepItm->pNext->pPrev = pDepItm->pPrev; | ||
| 1323 | else | ||
| 1324 | { | ||
| 1325 | pList->pLast = pDepItm->pPrev; | ||
| 1326 | pList->pLast->pNext = NULL; | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | // insert before the current item | ||
| 1330 | if (pRoot->pPrev) | ||
| 1331 | pRoot->pPrev->pNext = pDepItm; | ||
| 1332 | else | ||
| 1333 | pList->pFirst = pDepItm; | ||
| 1334 | pDepItm->pPrev = pRoot->pPrev; | ||
| 1335 | pRoot->pPrev = pDepItm; | ||
| 1336 | pDepItm->pNext = pRoot; | ||
| 1337 | } | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | hr = S_OK; | ||
| 1341 | |||
| 1342 | LExit: | ||
| 1343 | return hr; | ||
| 1344 | } | ||
| 1345 | |||
| 1346 | static HRESULT AssemblyFindByKey( | ||
| 1347 | CPI_ASSEMBLY* pItm, | ||
| 1348 | LPCWSTR pwzKey, | ||
| 1349 | BOOL fReverse, | ||
| 1350 | CPI_ASSEMBLY** ppItm | ||
| 1351 | ) | ||
| 1352 | { | ||
| 1353 | for (; pItm; pItm = fReverse ? pItm->pPrev : pItm->pNext) | ||
| 1354 | { | ||
| 1355 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
| 1356 | { | ||
| 1357 | *ppItm = pItm; | ||
| 1358 | return S_OK; | ||
| 1359 | } | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | return S_FALSE; | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | static HRESULT ComponentsRead( | ||
| 1366 | LPCWSTR pwzAsmKey, | ||
| 1367 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 1368 | CPI_ASSEMBLY* pAsm | ||
| 1369 | ) | ||
| 1370 | { | ||
| 1371 | HRESULT hr = S_OK; | ||
| 1372 | PMSIHANDLE hView; | ||
| 1373 | PMSIHANDLE hRec; | ||
| 1374 | PMSIHANDLE hRecKey; | ||
| 1375 | CPI_COMPONENT* pItm = NULL; | ||
| 1376 | LPWSTR pwzData = NULL; | ||
| 1377 | |||
| 1378 | // create parameter record | ||
| 1379 | hRecKey = ::MsiCreateRecord(1); | ||
| 1380 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 1381 | hr = WcaSetRecordString(hRecKey, 1, pwzAsmKey); | ||
| 1382 | ExitOnFailure(hr, "Failed to set record string"); | ||
| 1383 | |||
| 1384 | // open view | ||
| 1385 | hr = WcaOpenView(vcsComponentQuery, &hView); | ||
| 1386 | ExitOnFailure(hr, "Failed to open view on ComPlusComponent table"); | ||
| 1387 | hr = WcaExecuteView(hView, hRecKey); | ||
| 1388 | ExitOnFailure(hr, "Failed to execute view on ComPlusComponent table"); | ||
| 1389 | |||
| 1390 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 1391 | { | ||
| 1392 | // create entry | ||
| 1393 | pItm = (CPI_COMPONENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_COMPONENT)); | ||
| 1394 | if (!pItm) | ||
| 1395 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 1396 | |||
| 1397 | // get key | ||
| 1398 | hr = WcaGetRecordString(hRec, cqComponent, &pwzData); | ||
| 1399 | ExitOnFailure(hr, "Failed to get key"); | ||
| 1400 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 1401 | |||
| 1402 | // get clsid | ||
| 1403 | hr = WcaGetRecordFormattedString(hRec, cqCLSID, &pwzData); | ||
| 1404 | ExitOnFailure(hr, "Failed to get clsid"); | ||
| 1405 | StringCchCopyW(pItm->wzCLSID, countof(pItm->wzCLSID), pwzData); | ||
| 1406 | |||
| 1407 | // read properties | ||
| 1408 | if (CpiTableExists(cptComPlusComponentProperty)) | ||
| 1409 | { | ||
| 1410 | hr = CpiPropertiesRead(vcsComponentPropertyQuery, pItm->wzKey, pdlComponentProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
| 1411 | ExitOnFailure(hr, "Failed to get component properties"); | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | // read roles | ||
| 1415 | if (CpiTableExists(cptComPlusRoleForComponent)) | ||
| 1416 | { | ||
| 1417 | hr = RoleAssignmentsRead(vcsRoleForComponentQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount); | ||
| 1418 | ExitOnFailure(hr, "Failed to get roles for component"); | ||
| 1419 | } | ||
| 1420 | |||
| 1421 | if (pItm->iRoleInstallCount) | ||
| 1422 | pAsm->iRoleAssignmentsInstallCount++; | ||
| 1423 | if (pItm->iRoleUninstallCount) | ||
| 1424 | pAsm->iRoleAssignmentsUninstallCount++; | ||
| 1425 | |||
| 1426 | // read interfaces | ||
| 1427 | if (CpiTableExists(cptComPlusInterface)) | ||
| 1428 | { | ||
| 1429 | hr = InterfacesRead(pItm->wzKey, pAppRoleList, pAsm, pItm); | ||
| 1430 | ExitOnFailure(hr, "Failed to get interfaces for component"); | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | // add entry | ||
| 1434 | pAsm->iComponentCount++; | ||
| 1435 | if (pAsm->pComponents) | ||
| 1436 | pItm->pNext = pAsm->pComponents; | ||
| 1437 | pAsm->pComponents = pItm; | ||
| 1438 | pItm = NULL; | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | if (E_NOMOREITEMS == hr) | ||
| 1442 | hr = S_OK; | ||
| 1443 | |||
| 1444 | LExit: | ||
| 1445 | // clean up | ||
| 1446 | if (pItm) | ||
| 1447 | ComponentsFreeList(pItm); | ||
| 1448 | |||
| 1449 | ReleaseStr(pwzData); | ||
| 1450 | |||
| 1451 | return hr; | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | static HRESULT InterfacesRead( | ||
| 1455 | LPCWSTR pwzCompKey, | ||
| 1456 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 1457 | CPI_ASSEMBLY* pAsm, | ||
| 1458 | CPI_COMPONENT* pComp | ||
| 1459 | ) | ||
| 1460 | { | ||
| 1461 | HRESULT hr = S_OK; | ||
| 1462 | PMSIHANDLE hView; | ||
| 1463 | PMSIHANDLE hRec; | ||
| 1464 | PMSIHANDLE hRecKey; | ||
| 1465 | CPI_INTERFACE* pItm = NULL; | ||
| 1466 | LPWSTR pwzData = NULL; | ||
| 1467 | |||
| 1468 | // create parameter record | ||
| 1469 | hRecKey = ::MsiCreateRecord(1); | ||
| 1470 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 1471 | hr = WcaSetRecordString(hRecKey, 1, pwzCompKey); | ||
| 1472 | ExitOnFailure(hr, "Failed to set record string"); | ||
| 1473 | |||
| 1474 | // open view | ||
| 1475 | hr = WcaOpenView(vcsInterfaceQuery, &hView); | ||
| 1476 | ExitOnFailure(hr, "Failed to open view on ComPlusInterface table"); | ||
| 1477 | hr = WcaExecuteView(hView, hRecKey); | ||
| 1478 | ExitOnFailure(hr, "Failed to execute view on ComPlusInterface table"); | ||
| 1479 | |||
| 1480 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 1481 | { | ||
| 1482 | // create entry | ||
| 1483 | pItm = (CPI_INTERFACE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_INTERFACE)); | ||
| 1484 | if (!pItm) | ||
| 1485 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 1486 | |||
| 1487 | // get key | ||
| 1488 | hr = WcaGetRecordString(hRec, iqInterface, &pwzData); | ||
| 1489 | ExitOnFailure(hr, "Failed to get key"); | ||
| 1490 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 1491 | |||
| 1492 | // get iid | ||
| 1493 | hr = WcaGetRecordFormattedString(hRec, iqIID, &pwzData); | ||
| 1494 | ExitOnFailure(hr, "Failed to get iid"); | ||
| 1495 | StringCchCopyW(pItm->wzIID, countof(pItm->wzIID), pwzData); | ||
| 1496 | |||
| 1497 | // read properties | ||
| 1498 | if (CpiTableExists(cptComPlusInterfaceProperty)) | ||
| 1499 | { | ||
| 1500 | hr = CpiPropertiesRead(vcsInterfacePropertyQuery, pItm->wzKey, pdlInterfaceProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
| 1501 | ExitOnFailure(hr, "Failed to get interface properties"); | ||
| 1502 | } | ||
| 1503 | |||
| 1504 | // read roles | ||
| 1505 | if (CpiTableExists(cptComPlusRoleForInterface)) | ||
| 1506 | { | ||
| 1507 | hr = RoleAssignmentsRead(vcsRoleForInterfaceQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount); | ||
| 1508 | ExitOnFailure(hr, "Failed to get roles for interface"); | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | if (pItm->iRoleInstallCount) | ||
| 1512 | pAsm->iRoleAssignmentsInstallCount++; | ||
| 1513 | if (pItm->iRoleUninstallCount) | ||
| 1514 | pAsm->iRoleAssignmentsUninstallCount++; | ||
| 1515 | |||
| 1516 | // read methods | ||
| 1517 | if (CpiTableExists(cptComPlusMethod)) | ||
| 1518 | { | ||
| 1519 | hr = MethodsRead(pItm->wzKey, pAppRoleList, pAsm, pItm); | ||
| 1520 | ExitOnFailure(hr, "Failed to get methods for interface"); | ||
| 1521 | } | ||
| 1522 | |||
| 1523 | // add entry | ||
| 1524 | pComp->iInterfaceCount++; | ||
| 1525 | if (pComp->pInterfaces) | ||
| 1526 | pItm->pNext = pComp->pInterfaces; | ||
| 1527 | pComp->pInterfaces = pItm; | ||
| 1528 | pItm = NULL; | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | if (E_NOMOREITEMS == hr) | ||
| 1532 | hr = S_OK; | ||
| 1533 | |||
| 1534 | LExit: | ||
| 1535 | // clean up | ||
| 1536 | if (pItm) | ||
| 1537 | InterfacesFreeList(pItm); | ||
| 1538 | |||
| 1539 | ReleaseStr(pwzData); | ||
| 1540 | |||
| 1541 | return hr; | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | static HRESULT MethodsRead( | ||
| 1545 | LPCWSTR pwzIntfKey, | ||
| 1546 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 1547 | CPI_ASSEMBLY* pAsm, | ||
| 1548 | CPI_INTERFACE* pIntf | ||
| 1549 | ) | ||
| 1550 | { | ||
| 1551 | HRESULT hr = S_OK; | ||
| 1552 | PMSIHANDLE hView, hRec, hRecKey; | ||
| 1553 | CPI_METHOD* pItm = NULL; | ||
| 1554 | LPWSTR pwzData = NULL; | ||
| 1555 | |||
| 1556 | // create parameter record | ||
| 1557 | hRecKey = ::MsiCreateRecord(1); | ||
| 1558 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 1559 | hr = WcaSetRecordString(hRecKey, 1, pwzIntfKey); | ||
| 1560 | ExitOnFailure(hr, "Failed to set record string"); | ||
| 1561 | |||
| 1562 | // open view | ||
| 1563 | hr = WcaOpenView(vcsMethodQuery, &hView); | ||
| 1564 | ExitOnFailure(hr, "Failed to open view on ComPlusMethod table"); | ||
| 1565 | hr = WcaExecuteView(hView, hRecKey); | ||
| 1566 | ExitOnFailure(hr, "Failed to execute view on ComPlusMethod table"); | ||
| 1567 | |||
| 1568 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 1569 | { | ||
| 1570 | // create entry | ||
| 1571 | pItm = (CPI_METHOD*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_METHOD)); | ||
| 1572 | if (!pItm) | ||
| 1573 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 1574 | |||
| 1575 | // get key | ||
| 1576 | hr = WcaGetRecordString(hRec, iqInterface, &pwzData); | ||
| 1577 | ExitOnFailure(hr, "Failed to get key"); | ||
| 1578 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 1579 | |||
| 1580 | // get index | ||
| 1581 | hr = WcaGetRecordFormattedString(hRec, mqIndex, &pwzData); | ||
| 1582 | ExitOnFailure(hr, "Failed to get index"); | ||
| 1583 | StringCchCopyW(pItm->wzIndex, countof(pItm->wzIndex), pwzData); | ||
| 1584 | |||
| 1585 | // get name | ||
| 1586 | hr = WcaGetRecordFormattedString(hRec, mqName, &pwzData); | ||
| 1587 | ExitOnFailure(hr, "Failed to get name"); | ||
| 1588 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
| 1589 | |||
| 1590 | // either an index or a name must be provided | ||
| 1591 | if (!*pItm->wzIndex && !*pItm->wzName) | ||
| 1592 | ExitOnFailure(hr = E_FAIL, "A method must have either an index or a name associated, key: %S", pItm->wzKey); | ||
| 1593 | |||
| 1594 | // read properties | ||
| 1595 | if (CpiTableExists(cptComPlusMethodProperty)) | ||
| 1596 | { | ||
| 1597 | hr = CpiPropertiesRead(vcsMethodPropertyQuery, pItm->wzKey, pdlMethodProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
| 1598 | ExitOnFailure(hr, "Failed to get method properties"); | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | // read roles | ||
| 1602 | if (CpiTableExists(cptComPlusRoleForMethod)) | ||
| 1603 | { | ||
| 1604 | hr = RoleAssignmentsRead(vcsRoleForMethodQuery, pItm->wzKey, pAppRoleList, &pItm->pRoles, &pItm->iRoleInstallCount, &pItm->iRoleUninstallCount); | ||
| 1605 | ExitOnFailure(hr, "Failed to get roles for method"); | ||
| 1606 | } | ||
| 1607 | |||
| 1608 | if (pItm->iRoleInstallCount) | ||
| 1609 | pAsm->iRoleAssignmentsInstallCount++; | ||
| 1610 | if (pItm->iRoleUninstallCount) | ||
| 1611 | pAsm->iRoleAssignmentsUninstallCount++; | ||
| 1612 | |||
| 1613 | // add entry | ||
| 1614 | pIntf->iMethodCount++; | ||
| 1615 | if (pIntf->pMethods) | ||
| 1616 | pItm->pNext = pIntf->pMethods; | ||
| 1617 | pIntf->pMethods = pItm; | ||
| 1618 | pItm = NULL; | ||
| 1619 | } | ||
| 1620 | |||
| 1621 | if (E_NOMOREITEMS == hr) | ||
| 1622 | hr = S_OK; | ||
| 1623 | |||
| 1624 | LExit: | ||
| 1625 | // clean up | ||
| 1626 | if (pItm) | ||
| 1627 | MethodsFreeList(pItm); | ||
| 1628 | |||
| 1629 | ReleaseStr(pwzData); | ||
| 1630 | |||
| 1631 | return hr; | ||
| 1632 | } | ||
| 1633 | |||
| 1634 | static HRESULT RoleAssignmentsRead( | ||
| 1635 | LPCWSTR pwzQuery, | ||
| 1636 | LPCWSTR pwzKey, | ||
| 1637 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 1638 | CPI_ROLE_ASSIGNMENT** ppRoleList, | ||
| 1639 | int* piInstallCount, | ||
| 1640 | int* piUninstallCount | ||
| 1641 | ) | ||
| 1642 | { | ||
| 1643 | HRESULT hr = S_OK; | ||
| 1644 | UINT er = ERROR_SUCCESS; | ||
| 1645 | |||
| 1646 | PMSIHANDLE hView, hRec, hRecKey; | ||
| 1647 | |||
| 1648 | CPI_ROLE_ASSIGNMENT* pItm = NULL; | ||
| 1649 | LPWSTR pwzData = NULL; | ||
| 1650 | BOOL fMatchingArchitecture = FALSE; | ||
| 1651 | |||
| 1652 | // create parameter record | ||
| 1653 | hRecKey = ::MsiCreateRecord(1); | ||
| 1654 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 1655 | hr = WcaSetRecordString(hRecKey, 1, pwzKey); | ||
| 1656 | ExitOnFailure(hr, "Failed to set record string"); | ||
| 1657 | |||
| 1658 | // open view | ||
| 1659 | hr = WcaOpenView(pwzQuery, &hView); | ||
| 1660 | ExitOnFailure(hr, "Failed to open view on role assignment table"); | ||
| 1661 | hr = WcaExecuteView(hView, hRecKey); | ||
| 1662 | ExitOnFailure(hr, "Failed to execute view on role assignment table"); | ||
| 1663 | |||
| 1664 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 1665 | { | ||
| 1666 | // get component | ||
| 1667 | hr = WcaGetRecordString(hRec, raqComponent, &pwzData); | ||
| 1668 | ExitOnFailure(hr, "Failed to get assembly component"); | ||
| 1669 | |||
| 1670 | // check if the component is our processor architecture | ||
| 1671 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
| 1672 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
| 1673 | |||
| 1674 | if (!fMatchingArchitecture) | ||
| 1675 | { | ||
| 1676 | continue; // not the same architecture, ignore | ||
| 1677 | } | ||
| 1678 | |||
| 1679 | // create entry | ||
| 1680 | pItm = (CPI_ROLE_ASSIGNMENT*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLE_ASSIGNMENT)); | ||
| 1681 | if (!pItm) | ||
| 1682 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 1683 | |||
| 1684 | // get component install state | ||
| 1685 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
| 1686 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
| 1687 | |||
| 1688 | // get key | ||
| 1689 | hr = WcaGetRecordString(hRec, raqKey, &pwzData); | ||
| 1690 | ExitOnFailure(hr, "Failed to get key"); | ||
| 1691 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 1692 | |||
| 1693 | // get application role | ||
| 1694 | hr = WcaGetRecordString(hRec, raqApplicationRole, &pwzData); | ||
| 1695 | ExitOnFailure(hr, "Failed to get application role"); | ||
| 1696 | |||
| 1697 | hr = CpiApplicationRoleFindByKey(pAppRoleList, pwzData, &pItm->pApplicationRole); | ||
| 1698 | if (S_FALSE == hr) | ||
| 1699 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 1700 | ExitOnFailure(hr, "Failed to find application, key: %S", pwzData); | ||
| 1701 | |||
| 1702 | // set references & increment counters | ||
| 1703 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 1704 | { | ||
| 1705 | CpiApplicationRoleAddReferenceInstall(pItm->pApplicationRole); | ||
| 1706 | ++*piInstallCount; | ||
| 1707 | } | ||
| 1708 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 1709 | { | ||
| 1710 | CpiApplicationRoleAddReferenceUninstall(pItm->pApplicationRole); | ||
| 1711 | ++*piUninstallCount; | ||
| 1712 | } | ||
| 1713 | |||
| 1714 | // add entry | ||
| 1715 | if (*ppRoleList) | ||
| 1716 | pItm->pNext = *ppRoleList; | ||
| 1717 | *ppRoleList = pItm; | ||
| 1718 | pItm = NULL; | ||
| 1719 | } | ||
| 1720 | |||
| 1721 | if (E_NOMOREITEMS == hr) | ||
| 1722 | hr = S_OK; | ||
| 1723 | |||
| 1724 | LExit: | ||
| 1725 | // clean up | ||
| 1726 | if (pItm) | ||
| 1727 | RoleAssignmentsFreeList(pItm); | ||
| 1728 | |||
| 1729 | ReleaseStr(pwzData); | ||
| 1730 | |||
| 1731 | return hr; | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | static HRESULT AddAssemblyToActionData( | ||
| 1735 | CPI_ASSEMBLY* pItm, | ||
| 1736 | BOOL fInstall, | ||
| 1737 | int iActionType, | ||
| 1738 | int iActionCost, | ||
| 1739 | LPWSTR* ppwzActionData | ||
| 1740 | ) | ||
| 1741 | { | ||
| 1742 | HRESULT hr = S_OK; | ||
| 1743 | |||
| 1744 | // add action information to custom action data | ||
| 1745 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
| 1746 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
| 1747 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
| 1748 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
| 1749 | |||
| 1750 | // add assembly information to custom action data | ||
| 1751 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
| 1752 | ExitOnFailure(hr, "Failed to add assembly key to custom action data"); | ||
| 1753 | hr = WcaWriteStringToCaData(pItm->pwzAssemblyName, ppwzActionData); | ||
| 1754 | ExitOnFailure(hr, "Failed to add assembly name to custom action data"); | ||
| 1755 | hr = WcaWriteStringToCaData(pItm->pwzDllPath, ppwzActionData); | ||
| 1756 | ExitOnFailure(hr, "Failed to add assembly dll path to custom action data"); | ||
| 1757 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pwzTlbPath : L"", ppwzActionData); | ||
| 1758 | ExitOnFailure(hr, "Failed to add assembly tlb path to custom action data"); | ||
| 1759 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pwzPSDllPath : L"", ppwzActionData); | ||
| 1760 | ExitOnFailure(hr, "Failed to add assembly proxy-stub dll path to custom action data"); | ||
| 1761 | hr = WcaWriteIntegerToCaData(pItm->iAttributes, ppwzActionData); | ||
| 1762 | ExitOnFailure(hr, "Failed to add assembly attributes to custom action data"); | ||
| 1763 | |||
| 1764 | // add application information to custom action data | ||
| 1765 | hr = WcaWriteStringToCaData(pItm->pApplication ? pItm->pApplication->wzID : L"", ppwzActionData); | ||
| 1766 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
| 1767 | |||
| 1768 | // add partition information to custom action data | ||
| 1769 | LPCWSTR pwzPartID = pItm->pApplication && pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L""; | ||
| 1770 | hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData); | ||
| 1771 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
| 1772 | |||
| 1773 | // add components to custom action data | ||
| 1774 | // | ||
| 1775 | // components are needed acording to the following table: | ||
| 1776 | // | ||
| 1777 | // Native .NET | ||
| 1778 | // -------------------------------------------- | ||
| 1779 | // NoOp | No | No | ||
| 1780 | // Create | Yes | Yes | ||
| 1781 | // Remove | Yes | No | ||
| 1782 | // | ||
| 1783 | int iCompCount = (atCreate == iActionType || (atRemove == iActionType && 0 == (pItm->iAttributes & aaDotNetAssembly))) ? pItm->iComponentCount : 0; | ||
| 1784 | hr = WcaWriteIntegerToCaData(iCompCount, ppwzActionData); | ||
| 1785 | ExitOnFailure(hr, "Failed to add component count to custom action data, key: %S", pItm->wzKey); | ||
| 1786 | |||
| 1787 | if (iCompCount) | ||
| 1788 | { | ||
| 1789 | for (CPI_COMPONENT* pComp = pItm->pComponents; pComp; pComp = pComp->pNext) | ||
| 1790 | { | ||
| 1791 | hr = AddComponentToActionData(pComp, fInstall, atCreate == iActionType, FALSE, ppwzActionData); | ||
| 1792 | ExitOnFailure(hr, "Failed to add component to custom action data, component: %S", pComp->wzKey); | ||
| 1793 | } | ||
| 1794 | } | ||
| 1795 | |||
| 1796 | hr = S_OK; | ||
| 1797 | |||
| 1798 | LExit: | ||
| 1799 | return hr; | ||
| 1800 | } | ||
| 1801 | |||
| 1802 | static HRESULT AddRoleAssignmentsToActionData( | ||
| 1803 | CPI_ASSEMBLY* pItm, | ||
| 1804 | BOOL fInstall, | ||
| 1805 | int iActionType, | ||
| 1806 | int iActionCost, | ||
| 1807 | LPWSTR* ppwzActionData | ||
| 1808 | ) | ||
| 1809 | { | ||
| 1810 | HRESULT hr = S_OK; | ||
| 1811 | |||
| 1812 | // add action information to custom action data | ||
| 1813 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
| 1814 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
| 1815 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
| 1816 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
| 1817 | |||
| 1818 | // add assembly information to custom action data | ||
| 1819 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
| 1820 | ExitOnFailure(hr, "Failed to add assembly key to custom action data"); | ||
| 1821 | hr = WcaWriteIntegerToCaData(fInstall ? pItm->iRoleAssignmentsInstallCount : pItm->iRoleAssignmentsUninstallCount, ppwzActionData); | ||
| 1822 | ExitOnFailure(hr, "Failed to add role assignments count to custom action data"); | ||
| 1823 | |||
| 1824 | // add application information to custom action data | ||
| 1825 | hr = WcaWriteStringToCaData(pItm->pApplication ? pItm->pApplication->wzID : L"", ppwzActionData); | ||
| 1826 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
| 1827 | |||
| 1828 | // add partition information to custom action data | ||
| 1829 | LPCWSTR pwzPartID = pItm->pApplication && pItm->pApplication->pPartition ? pItm->pApplication->pPartition->wzID : L""; | ||
| 1830 | hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData); | ||
| 1831 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
| 1832 | |||
| 1833 | // add components to custom action data | ||
| 1834 | hr = WcaWriteIntegerToCaData(pItm->iComponentCount, ppwzActionData); | ||
| 1835 | ExitOnFailure(hr, "Failed to add component count to custom action data"); | ||
| 1836 | |||
| 1837 | for (CPI_COMPONENT* pComp = pItm->pComponents; pComp; pComp = pComp->pNext) | ||
| 1838 | { | ||
| 1839 | hr = AddComponentToActionData(pComp, fInstall, FALSE, TRUE, ppwzActionData); | ||
| 1840 | ExitOnFailure(hr, "Failed to add component to custom action data, component: %S", pComp->wzKey); | ||
| 1841 | } | ||
| 1842 | |||
| 1843 | hr = S_OK; | ||
| 1844 | |||
| 1845 | LExit: | ||
| 1846 | return hr; | ||
| 1847 | } | ||
| 1848 | |||
| 1849 | static HRESULT AddComponentToActionData( | ||
| 1850 | CPI_COMPONENT* pItm, | ||
| 1851 | BOOL fInstall, | ||
| 1852 | BOOL fProps, | ||
| 1853 | BOOL fRoles, | ||
| 1854 | LPWSTR* ppwzActionData | ||
| 1855 | ) | ||
| 1856 | { | ||
| 1857 | HRESULT hr = S_OK; | ||
| 1858 | |||
| 1859 | // add component information to custom action data | ||
| 1860 | hr = WcaWriteStringToCaData(pItm->wzCLSID, ppwzActionData); | ||
| 1861 | ExitOnFailure(hr, "Failed to add component CLSID to custom action data"); | ||
| 1862 | |||
| 1863 | // add properties to custom action data | ||
| 1864 | hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
| 1865 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
| 1866 | |||
| 1867 | // add roles to custom action data | ||
| 1868 | hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData); | ||
| 1869 | ExitOnFailure(hr, "Failed to add roles to custom action data"); | ||
| 1870 | |||
| 1871 | // add interfaces to custom action data | ||
| 1872 | int iIntfCount = (fProps || fRoles) ? pItm->iInterfaceCount : 0; | ||
| 1873 | hr = WcaWriteIntegerToCaData(iIntfCount, ppwzActionData); | ||
| 1874 | ExitOnFailure(hr, "Failed to add interface count to custom action data"); | ||
| 1875 | |||
| 1876 | if (iIntfCount) | ||
| 1877 | { | ||
| 1878 | for (CPI_INTERFACE* pIntf = pItm->pInterfaces; pIntf; pIntf = pIntf->pNext) | ||
| 1879 | { | ||
| 1880 | hr = AddInterfaceToActionData(pIntf, fInstall, fProps, fRoles, ppwzActionData); | ||
| 1881 | ExitOnFailure(hr, "Failed to add interface custom action data, interface: %S", pIntf->wzKey); | ||
| 1882 | } | ||
| 1883 | } | ||
| 1884 | |||
| 1885 | hr = S_OK; | ||
| 1886 | |||
| 1887 | LExit: | ||
| 1888 | return hr; | ||
| 1889 | } | ||
| 1890 | |||
| 1891 | static HRESULT AddInterfaceToActionData( | ||
| 1892 | CPI_INTERFACE* pItm, | ||
| 1893 | BOOL fInstall, | ||
| 1894 | BOOL fProps, | ||
| 1895 | BOOL fRoles, | ||
| 1896 | LPWSTR* ppwzActionData | ||
| 1897 | ) | ||
| 1898 | { | ||
| 1899 | HRESULT hr = S_OK; | ||
| 1900 | |||
| 1901 | // add interface information to custom action data | ||
| 1902 | hr = WcaWriteStringToCaData(pItm->wzIID, ppwzActionData); | ||
| 1903 | ExitOnFailure(hr, "Failed to add interface IID to custom action data"); | ||
| 1904 | |||
| 1905 | // add properties to custom action data | ||
| 1906 | hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
| 1907 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
| 1908 | |||
| 1909 | // add roles to custom action data | ||
| 1910 | hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData); | ||
| 1911 | ExitOnFailure(hr, "Failed to add roles to custom action data"); | ||
| 1912 | |||
| 1913 | // add methods to custom action data | ||
| 1914 | hr = WcaWriteIntegerToCaData(pItm->iMethodCount, ppwzActionData); | ||
| 1915 | ExitOnFailure(hr, "Failed to add method count to custom action data"); | ||
| 1916 | |||
| 1917 | for (CPI_METHOD* pMeth = pItm->pMethods; pMeth; pMeth = pMeth->pNext) | ||
| 1918 | { | ||
| 1919 | hr = AddMethodToActionData(pMeth, fInstall, fProps, fRoles, ppwzActionData); | ||
| 1920 | ExitOnFailure(hr, "Failed to add method custom action data, method: %S", pMeth->wzKey); | ||
| 1921 | } | ||
| 1922 | |||
| 1923 | hr = S_OK; | ||
| 1924 | |||
| 1925 | LExit: | ||
| 1926 | return hr; | ||
| 1927 | } | ||
| 1928 | |||
| 1929 | static HRESULT AddMethodToActionData( | ||
| 1930 | CPI_METHOD* pItm, | ||
| 1931 | BOOL fInstall, | ||
| 1932 | BOOL fProps, | ||
| 1933 | BOOL fRoles, | ||
| 1934 | LPWSTR* ppwzActionData | ||
| 1935 | ) | ||
| 1936 | { | ||
| 1937 | HRESULT hr = S_OK; | ||
| 1938 | |||
| 1939 | // add interface information to custom action data | ||
| 1940 | hr = WcaWriteStringToCaData(pItm->wzIndex, ppwzActionData); | ||
| 1941 | ExitOnFailure(hr, "Failed to add method index to custom action data"); | ||
| 1942 | |||
| 1943 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
| 1944 | ExitOnFailure(hr, "Failed to add method name to custom action data"); | ||
| 1945 | |||
| 1946 | // add properties to custom action data | ||
| 1947 | hr = CpiAddPropertiesToActionData(fProps ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
| 1948 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
| 1949 | |||
| 1950 | // add roles to custom action data | ||
| 1951 | hr = AddRolesToActionData(pItm->iRoleInstallCount, pItm->iRoleUninstallCount, pItm->pRoles, fInstall, fRoles, ppwzActionData); | ||
| 1952 | ExitOnFailure(hr, "Failed to add roles to custom action data"); | ||
| 1953 | |||
| 1954 | hr = S_OK; | ||
| 1955 | |||
| 1956 | LExit: | ||
| 1957 | return hr; | ||
| 1958 | } | ||
| 1959 | |||
| 1960 | static HRESULT AddRolesToActionData( | ||
| 1961 | int iRoleInstallCount, | ||
| 1962 | int iRoleUninstallCount, | ||
| 1963 | CPI_ROLE_ASSIGNMENT* pRoleList, | ||
| 1964 | BOOL fInstall, | ||
| 1965 | BOOL fRoles, | ||
| 1966 | LPWSTR* ppwzActionData | ||
| 1967 | ) | ||
| 1968 | { | ||
| 1969 | HRESULT hr = S_OK; | ||
| 1970 | |||
| 1971 | int iRoleCount = fRoles ? (fInstall ? iRoleInstallCount : iRoleUninstallCount) : 0; | ||
| 1972 | hr = WcaWriteIntegerToCaData(iRoleCount, ppwzActionData); | ||
| 1973 | ExitOnFailure(hr, "Failed to add role count to custom action data"); | ||
| 1974 | |||
| 1975 | if (iRoleCount) | ||
| 1976 | { | ||
| 1977 | for (CPI_ROLE_ASSIGNMENT* pRole = pRoleList; pRole; pRole = pRole->pNext) | ||
| 1978 | { | ||
| 1979 | // make sure the install state matches the create flag | ||
| 1980 | if (fInstall ? !WcaIsInstalling(pRole->isInstalled, pRole->isAction) : !WcaIsUninstalling(pRole->isInstalled, pRole->isAction)) | ||
| 1981 | continue; | ||
| 1982 | |||
| 1983 | hr = WcaWriteStringToCaData(pRole->pApplicationRole->wzKey, ppwzActionData); | ||
| 1984 | ExitOnFailure(hr, "Failed to add key to custom action data, role: %S", pRole->wzKey); | ||
| 1985 | |||
| 1986 | hr = WcaWriteStringToCaData(pRole->pApplicationRole->wzName, ppwzActionData); | ||
| 1987 | ExitOnFailure(hr, "Failed to add role name to custom action data, role: %S", pRole->wzKey); | ||
| 1988 | } | ||
| 1989 | } | ||
| 1990 | |||
| 1991 | hr = S_OK; | ||
| 1992 | |||
| 1993 | LExit: | ||
| 1994 | return hr; | ||
| 1995 | } | ||
| 1996 | |||
| 1997 | static HRESULT KeyPairFindByFirstKey( | ||
| 1998 | CPI_KEY_PAIR* pList, | ||
| 1999 | LPCWSTR pwzKey, | ||
| 2000 | CPI_KEY_PAIR** ppItm | ||
| 2001 | ) | ||
| 2002 | { | ||
| 2003 | for (; pList; pList = pList->pNext) | ||
| 2004 | { | ||
| 2005 | if (0 == lstrcmpW(pList->wzFirstKey, pwzKey)) | ||
| 2006 | { | ||
| 2007 | *ppItm = pList; | ||
| 2008 | return S_OK; | ||
| 2009 | } | ||
| 2010 | } | ||
| 2011 | |||
| 2012 | return S_FALSE; | ||
| 2013 | } | ||
| 2014 | |||
| 2015 | static void AssemblyFree( | ||
| 2016 | CPI_ASSEMBLY* pItm | ||
| 2017 | ) | ||
| 2018 | { | ||
| 2019 | ReleaseStr(pItm->pwzAssemblyName); | ||
| 2020 | ReleaseStr(pItm->pwzDllPath); | ||
| 2021 | ReleaseStr(pItm->pwzTlbPath); | ||
| 2022 | ReleaseStr(pItm->pwzPSDllPath); | ||
| 2023 | |||
| 2024 | if (pItm->pComponents) | ||
| 2025 | ComponentsFreeList(pItm->pComponents); | ||
| 2026 | |||
| 2027 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
| 2028 | } | ||
| 2029 | |||
| 2030 | static void KeyPairsFreeList( | ||
| 2031 | CPI_KEY_PAIR* pList | ||
| 2032 | ) | ||
| 2033 | { | ||
| 2034 | while (pList) | ||
| 2035 | { | ||
| 2036 | CPI_KEY_PAIR* pDelete = pList; | ||
| 2037 | pList = pList->pNext; | ||
| 2038 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 2039 | } | ||
| 2040 | } | ||
| 2041 | |||
| 2042 | void ModuleListFree( | ||
| 2043 | CPI_MODULE_LIST* pList | ||
| 2044 | ) | ||
| 2045 | { | ||
| 2046 | CPI_MODULE* pItm = pList->pFirst; | ||
| 2047 | |||
| 2048 | while (pItm) | ||
| 2049 | { | ||
| 2050 | CPI_MODULE* pDelete = pItm; | ||
| 2051 | pItm = pItm->pNext; | ||
| 2052 | ModuleFree(pDelete); | ||
| 2053 | } | ||
| 2054 | } | ||
| 2055 | |||
| 2056 | static void ModuleFree( | ||
| 2057 | CPI_MODULE* pItm | ||
| 2058 | ) | ||
| 2059 | { | ||
| 2060 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
| 2061 | } | ||
| 2062 | |||
| 2063 | static void ComponentsFreeList( | ||
| 2064 | CPI_COMPONENT* pList | ||
| 2065 | ) | ||
| 2066 | { | ||
| 2067 | while (pList) | ||
| 2068 | { | ||
| 2069 | if (pList->pProperties) | ||
| 2070 | CpiPropertiesFreeList(pList->pProperties); | ||
| 2071 | |||
| 2072 | if (pList->pRoles) | ||
| 2073 | RoleAssignmentsFreeList(pList->pRoles); | ||
| 2074 | |||
| 2075 | if (pList->pInterfaces) | ||
| 2076 | InterfacesFreeList(pList->pInterfaces); | ||
| 2077 | |||
| 2078 | ReleaseObject(pList->piSubsColl); | ||
| 2079 | |||
| 2080 | CPI_COMPONENT* pDelete = pList; | ||
| 2081 | pList = pList->pNext; | ||
| 2082 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 2083 | } | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | static void InterfacesFreeList( | ||
| 2087 | CPI_INTERFACE* pList | ||
| 2088 | ) | ||
| 2089 | { | ||
| 2090 | while (pList) | ||
| 2091 | { | ||
| 2092 | if (pList->pProperties) | ||
| 2093 | CpiPropertiesFreeList(pList->pProperties); | ||
| 2094 | |||
| 2095 | if (pList->pRoles) | ||
| 2096 | RoleAssignmentsFreeList(pList->pRoles); | ||
| 2097 | |||
| 2098 | if (pList->pMethods) | ||
| 2099 | MethodsFreeList(pList->pMethods); | ||
| 2100 | |||
| 2101 | CPI_INTERFACE* pDelete = pList; | ||
| 2102 | pList = pList->pNext; | ||
| 2103 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 2104 | } | ||
| 2105 | } | ||
| 2106 | |||
| 2107 | static void MethodsFreeList( | ||
| 2108 | CPI_METHOD* pList | ||
| 2109 | ) | ||
| 2110 | { | ||
| 2111 | while (pList) | ||
| 2112 | { | ||
| 2113 | if (pList->pProperties) | ||
| 2114 | CpiPropertiesFreeList(pList->pProperties); | ||
| 2115 | |||
| 2116 | if (pList->pRoles) | ||
| 2117 | RoleAssignmentsFreeList(pList->pRoles); | ||
| 2118 | |||
| 2119 | CPI_METHOD* pDelete = pList; | ||
| 2120 | pList = pList->pNext; | ||
| 2121 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 2122 | } | ||
| 2123 | } | ||
| 2124 | |||
| 2125 | static void RoleAssignmentsFreeList( | ||
| 2126 | CPI_ROLE_ASSIGNMENT* pList | ||
| 2127 | ) | ||
| 2128 | { | ||
| 2129 | while (pList) | ||
| 2130 | { | ||
| 2131 | CPI_ROLE_ASSIGNMENT* pDelete = pList; | ||
| 2132 | pList = pList->pNext; | ||
| 2133 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 2134 | } | ||
| 2135 | } | ||
diff --git a/src/ca/cpasmsched.h b/src/ca/cpasmsched.h new file mode 100644 index 00000000..b5a68d7e --- /dev/null +++ b/src/ca/cpasmsched.h | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | enum eAssemblyAttributes | ||
| 6 | { | ||
| 7 | aaEventClass = (1 << 0), | ||
| 8 | aaDotNetAssembly = (1 << 1), | ||
| 9 | aaPathFromGAC = (1 << 2), | ||
| 10 | aaRunInCommit = (1 << 3) | ||
| 11 | }; | ||
| 12 | |||
| 13 | |||
| 14 | // structs | ||
| 15 | |||
| 16 | struct CPI_ROLE_ASSIGNMENT | ||
| 17 | { | ||
| 18 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 19 | |||
| 20 | INSTALLSTATE isInstalled, isAction; | ||
| 21 | |||
| 22 | CPI_APPLICATION_ROLE* pApplicationRole; | ||
| 23 | |||
| 24 | CPI_ROLE_ASSIGNMENT* pNext; | ||
| 25 | }; | ||
| 26 | |||
| 27 | struct CPI_METHOD | ||
| 28 | { | ||
| 29 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 30 | WCHAR wzIndex[11 + 1]; | ||
| 31 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 32 | |||
| 33 | int iPropertyCount; | ||
| 34 | CPI_PROPERTY* pProperties; | ||
| 35 | |||
| 36 | int iRoleInstallCount; | ||
| 37 | int iRoleUninstallCount; | ||
| 38 | CPI_ROLE_ASSIGNMENT* pRoles; | ||
| 39 | |||
| 40 | CPI_METHOD* pNext; | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct CPI_INTERFACE | ||
| 44 | { | ||
| 45 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 46 | WCHAR wzIID[CPI_MAX_GUID + 1]; | ||
| 47 | |||
| 48 | int iPropertyCount; | ||
| 49 | CPI_PROPERTY* pProperties; | ||
| 50 | |||
| 51 | int iRoleInstallCount; | ||
| 52 | int iRoleUninstallCount; | ||
| 53 | CPI_ROLE_ASSIGNMENT* pRoles; | ||
| 54 | |||
| 55 | int iMethodCount; | ||
| 56 | CPI_METHOD* pMethods; | ||
| 57 | |||
| 58 | CPI_INTERFACE* pNext; | ||
| 59 | }; | ||
| 60 | |||
| 61 | struct CPI_COMPONENT | ||
| 62 | { | ||
| 63 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 64 | WCHAR wzCLSID[CPI_MAX_GUID + 1]; | ||
| 65 | |||
| 66 | int iPropertyCount; | ||
| 67 | CPI_PROPERTY* pProperties; | ||
| 68 | |||
| 69 | int iRoleInstallCount; | ||
| 70 | int iRoleUninstallCount; | ||
| 71 | CPI_ROLE_ASSIGNMENT* pRoles; | ||
| 72 | |||
| 73 | int iInterfaceCount; | ||
| 74 | CPI_INTERFACE* pInterfaces; | ||
| 75 | |||
| 76 | ICatalogCollection* piSubsColl; | ||
| 77 | |||
| 78 | CPI_COMPONENT* pNext; | ||
| 79 | }; | ||
| 80 | |||
| 81 | struct CPI_ASSEMBLY | ||
| 82 | { | ||
| 83 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 84 | WCHAR wzModule[MAX_DARWIN_KEY + 1]; | ||
| 85 | LPWSTR pwzAssemblyName; | ||
| 86 | LPWSTR pwzDllPath; | ||
| 87 | LPWSTR pwzTlbPath; | ||
| 88 | LPWSTR pwzPSDllPath; | ||
| 89 | int iAttributes; | ||
| 90 | |||
| 91 | int iComponentCount; | ||
| 92 | CPI_COMPONENT* pComponents; | ||
| 93 | |||
| 94 | BOOL fReferencedForInstall; | ||
| 95 | BOOL fReferencedForUninstall; | ||
| 96 | BOOL fIgnore; | ||
| 97 | |||
| 98 | int iRoleAssignmentsInstallCount; | ||
| 99 | int iRoleAssignmentsUninstallCount; | ||
| 100 | |||
| 101 | INSTALLSTATE isInstalled, isAction; | ||
| 102 | |||
| 103 | CPI_APPLICATION* pApplication; | ||
| 104 | |||
| 105 | CPI_ASSEMBLY* pPrev; | ||
| 106 | CPI_ASSEMBLY* pNext; | ||
| 107 | }; | ||
| 108 | |||
| 109 | struct CPI_ASSEMBLY_LIST | ||
| 110 | { | ||
| 111 | CPI_ASSEMBLY* pFirst; | ||
| 112 | CPI_ASSEMBLY* pLast; | ||
| 113 | |||
| 114 | int iInstallCount; | ||
| 115 | int iCommitCount; | ||
| 116 | int iUninstallCount; | ||
| 117 | |||
| 118 | int iRoleInstallCount; | ||
| 119 | int iRoleCommitCount; | ||
| 120 | int iRoleUninstallCount; | ||
| 121 | }; | ||
| 122 | |||
| 123 | |||
| 124 | // function prototypes | ||
| 125 | |||
| 126 | void CpiAssemblyListFree( | ||
| 127 | CPI_ASSEMBLY_LIST* pList | ||
| 128 | ); | ||
| 129 | HRESULT CpiAssembliesRead( | ||
| 130 | CPI_APPLICATION_LIST* pAppList, | ||
| 131 | CPI_APPLICATION_ROLE_LIST* pAppRoleList, | ||
| 132 | CPI_ASSEMBLY_LIST* pAsmList | ||
| 133 | ); | ||
| 134 | HRESULT CpiAssembliesVerifyInstall( | ||
| 135 | CPI_ASSEMBLY_LIST* pList | ||
| 136 | ); | ||
| 137 | HRESULT CpiAssembliesVerifyUninstall( | ||
| 138 | CPI_ASSEMBLY_LIST* pList | ||
| 139 | ); | ||
| 140 | HRESULT CpiAssembliesInstall( | ||
| 141 | CPI_ASSEMBLY_LIST* pList, | ||
| 142 | int iRunMode, | ||
| 143 | LPWSTR* ppwzActionData, | ||
| 144 | int* piProgress | ||
| 145 | ); | ||
| 146 | HRESULT CpiAssembliesUninstall( | ||
| 147 | CPI_ASSEMBLY_LIST* pList, | ||
| 148 | int iRunMode, | ||
| 149 | LPWSTR* ppwzActionData, | ||
| 150 | int* piProgress | ||
| 151 | ); | ||
| 152 | HRESULT CpiRoleAssignmentsInstall( | ||
| 153 | CPI_ASSEMBLY_LIST* pList, | ||
| 154 | int iRunMode, | ||
| 155 | LPWSTR* ppwzActionData, | ||
| 156 | int* piProgress | ||
| 157 | ); | ||
| 158 | HRESULT CpiRoleAssignmentsUninstall( | ||
| 159 | CPI_ASSEMBLY_LIST* pList, | ||
| 160 | int iRunMode, | ||
| 161 | LPWSTR* ppwzActionData, | ||
| 162 | int* piProgress | ||
| 163 | ); | ||
| 164 | HRESULT CpiGetSubscriptionsCollForComponent( | ||
| 165 | CPI_ASSEMBLY* pAsm, | ||
| 166 | CPI_COMPONENT* pComp, | ||
| 167 | ICatalogCollection** ppiSubsColl | ||
| 168 | ); | ||
diff --git a/src/ca/cpcost.h b/src/ca/cpcost.h new file mode 100644 index 00000000..7a23e03b --- /dev/null +++ b/src/ca/cpcost.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #define COST_PARTITION_CREATE 10000 | ||
| 6 | #define COST_PARTITION_DELETE 10000 | ||
| 7 | |||
| 8 | #define COST_PARTITION_USER_CREATE 10000 | ||
| 9 | #define COST_PARTITION_USER_DELETE 10000 | ||
| 10 | |||
| 11 | #define COST_USER_IN_PARTITION_ROLE_CREATE 10000 | ||
| 12 | #define COST_USER_IN_PARTITION_ROLE_DELETE 10000 | ||
| 13 | |||
| 14 | #define COST_APPLICATION_CREATE 10000 | ||
| 15 | #define COST_APPLICATION_DELETE 10000 | ||
| 16 | |||
| 17 | #define COST_APPLICATION_ROLE_CREATE 10000 | ||
| 18 | #define COST_APPLICATION_ROLE_DELETE 10000 | ||
| 19 | |||
| 20 | #define COST_USER_IN_APPLICATION_ROLE_CREATE 10000 | ||
| 21 | #define COST_USER_IN_APPLICATION_ROLE_DELETE 10000 | ||
| 22 | |||
| 23 | #define COST_ASSEMBLY_REGISTER 50000 | ||
| 24 | #define COST_ASSEMBLY_UNREGISTER 10000 | ||
| 25 | |||
| 26 | #define COST_ROLLASSIGNMENT_CREATE 10000 | ||
| 27 | #define COST_ROLLASSIGNMENT_DELETE 10000 | ||
| 28 | |||
| 29 | #define COST_SUBSCRIPTION_CREATE 10000 | ||
| 30 | #define COST_SUBSCRIPTION_DELETE 10000 | ||
diff --git a/src/ca/cpexec.cpp b/src/ca/cpexec.cpp new file mode 100644 index 00000000..fa2446d8 --- /dev/null +++ b/src/ca/cpexec.cpp | |||
| @@ -0,0 +1,704 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | /******************************************************************** | ||
| 6 | DllMain - standard entry point for all WiX CustomActions | ||
| 7 | |||
| 8 | ********************************************************************/ | ||
| 9 | extern "C" BOOL WINAPI DllMain( | ||
| 10 | IN HINSTANCE hInst, | ||
| 11 | IN ULONG ulReason, | ||
| 12 | IN LPVOID) | ||
| 13 | { | ||
| 14 | switch(ulReason) | ||
| 15 | { | ||
| 16 | case DLL_PROCESS_ATTACH: | ||
| 17 | WcaGlobalInitialize(hInst); | ||
| 18 | break; | ||
| 19 | |||
| 20 | case DLL_PROCESS_DETACH: | ||
| 21 | WcaGlobalFinalize(); | ||
| 22 | break; | ||
| 23 | } | ||
| 24 | |||
| 25 | return TRUE; | ||
| 26 | } | ||
| 27 | |||
| 28 | /******************************************************************** | ||
| 29 | ComPlusPrepare - CUSTOM ACTION ENTRY POINT | ||
| 30 | |||
| 31 | Input: deferred CustomActionData - ComPlusPrepare | ||
| 32 | ********************************************************************/ | ||
| 33 | extern "C" UINT __stdcall ComPlusPrepare(MSIHANDLE hInstall) | ||
| 34 | { | ||
| 35 | HRESULT hr = S_OK; | ||
| 36 | UINT er = ERROR_SUCCESS; | ||
| 37 | |||
| 38 | LPWSTR pwzCustomActionData = NULL; | ||
| 39 | LPWSTR pwzData = NULL; | ||
| 40 | |||
| 41 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
| 42 | |||
| 43 | // initialize | ||
| 44 | hr = WcaInitialize(hInstall, "ComPlusPrepare"); | ||
| 45 | ExitOnFailure(hr, "Failed to initialize ComPlusPrepare"); | ||
| 46 | |||
| 47 | // get custom action data | ||
| 48 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
| 49 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
| 50 | pwzData = pwzCustomActionData; | ||
| 51 | |||
| 52 | // create rollback file | ||
| 53 | hRollbackFile = ::CreateFileW(pwzData, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
| 54 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
| 55 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to create rollback file, name: %S", pwzData); | ||
| 56 | |||
| 57 | hr = S_OK; | ||
| 58 | |||
| 59 | LExit: | ||
| 60 | // clean up | ||
| 61 | ReleaseStr(pwzCustomActionData); | ||
| 62 | |||
| 63 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
| 64 | ::CloseHandle(hRollbackFile); | ||
| 65 | |||
| 66 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 67 | return WcaFinalize(er); | ||
| 68 | } | ||
| 69 | |||
| 70 | /******************************************************************** | ||
| 71 | ComPlusCleanup - CUSTOM ACTION ENTRY POINT | ||
| 72 | |||
| 73 | Input: deferred CustomActionData - ComPlusCleanup | ||
| 74 | ********************************************************************/ | ||
| 75 | extern "C" UINT __stdcall ComPlusCleanup(MSIHANDLE hInstall) | ||
| 76 | { | ||
| 77 | HRESULT hr = S_OK; | ||
| 78 | UINT er = ERROR_SUCCESS; | ||
| 79 | |||
| 80 | LPWSTR pwzCustomActionData = NULL; | ||
| 81 | LPWSTR pwzData = NULL; | ||
| 82 | |||
| 83 | // initialize | ||
| 84 | hr = WcaInitialize(hInstall, "ComPlusCleanup"); | ||
| 85 | ExitOnFailure(hr, "Failed to initialize ComPlusCleanup"); | ||
| 86 | |||
| 87 | // get custom action data | ||
| 88 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
| 89 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
| 90 | pwzData = pwzCustomActionData; | ||
| 91 | |||
| 92 | // delete rollback file | ||
| 93 | if (!::DeleteFileW(pwzData)) | ||
| 94 | { | ||
| 95 | // error, but not a showstopper | ||
| 96 | hr = HRESULT_FROM_WIN32(::GetLastError()); | ||
| 97 | WcaLog(LOGMSG_STANDARD, "Failed to delete rollback file, hr: 0x%x, name: %S", hr, pwzData); | ||
| 98 | } | ||
| 99 | |||
| 100 | hr = S_OK; | ||
| 101 | |||
| 102 | LExit: | ||
| 103 | // clean up | ||
| 104 | ReleaseStr(pwzCustomActionData); | ||
| 105 | |||
| 106 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 107 | return WcaFinalize(er); | ||
| 108 | } | ||
| 109 | |||
| 110 | /******************************************************************** | ||
| 111 | ComPlusInstallExecute - CUSTOM ACTION ENTRY POINT | ||
| 112 | |||
| 113 | Input: deferred CustomActionData - ComPlusInstallExecute | ||
| 114 | ********************************************************************/ | ||
| 115 | extern "C" UINT __stdcall ComPlusInstallExecute(MSIHANDLE hInstall) | ||
| 116 | { | ||
| 117 | HRESULT hr = S_OK; | ||
| 118 | UINT er = ERROR_SUCCESS; | ||
| 119 | |||
| 120 | LPWSTR pwzCustomActionData = NULL; | ||
| 121 | LPWSTR pwzData = NULL; | ||
| 122 | LPWSTR pwzRollbackFileName = NULL; | ||
| 123 | |||
| 124 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
| 125 | |||
| 126 | BOOL fInitializedCom = FALSE; | ||
| 127 | |||
| 128 | // initialize | ||
| 129 | hr = WcaInitialize(hInstall, "ComPlusInstallExecute"); | ||
| 130 | ExitOnFailure(hr, "Failed to initialize ComPlusInstallExecute"); | ||
| 131 | |||
| 132 | hr = ::CoInitialize(NULL); | ||
| 133 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
| 134 | fInitializedCom = TRUE; | ||
| 135 | |||
| 136 | CpiInitialize(); | ||
| 137 | |||
| 138 | // get custom action data | ||
| 139 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
| 140 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
| 141 | pwzData = pwzCustomActionData; | ||
| 142 | |||
| 143 | // open rollback file | ||
| 144 | hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName); | ||
| 145 | ExitOnFailure(hr, "Failed to read rollback file name"); | ||
| 146 | |||
| 147 | hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
| 148 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
| 149 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName); | ||
| 150 | |||
| 151 | // create partitions | ||
| 152 | hr = CpiConfigurePartitions(&pwzData, hRollbackFile); | ||
| 153 | ExitOnFailure(hr, "Failed to create partitions"); | ||
| 154 | if (S_FALSE == hr) ExitFunction(); | ||
| 155 | |||
| 156 | // create users in partition roles | ||
| 157 | hr = CpiConfigureUsersInPartitionRoles(&pwzData, hRollbackFile); | ||
| 158 | ExitOnFailure(hr, "Failed to create users in partition roles"); | ||
| 159 | if (S_FALSE == hr) ExitFunction(); | ||
| 160 | |||
| 161 | // create partition users | ||
| 162 | hr = CpiConfigurePartitionUsers(&pwzData, hRollbackFile); | ||
| 163 | ExitOnFailure(hr, "Failed to add partition users"); | ||
| 164 | if (S_FALSE == hr) ExitFunction(); | ||
| 165 | |||
| 166 | // create applications | ||
| 167 | hr = CpiConfigureApplications(&pwzData, hRollbackFile); | ||
| 168 | ExitOnFailure(hr, "Failed to create applications"); | ||
| 169 | if (S_FALSE == hr) ExitFunction(); | ||
| 170 | |||
| 171 | // create application roles | ||
| 172 | hr = CpiConfigureApplicationRoles(&pwzData, hRollbackFile); | ||
| 173 | ExitOnFailure(hr, "Failed to create application roles"); | ||
| 174 | if (S_FALSE == hr) ExitFunction(); | ||
| 175 | |||
| 176 | // create users in application roles | ||
| 177 | hr = CpiConfigureUsersInApplicationRoles(&pwzData, hRollbackFile); | ||
| 178 | ExitOnFailure(hr, "Failed to create users in application roles"); | ||
| 179 | if (S_FALSE == hr) ExitFunction(); | ||
| 180 | |||
| 181 | // register assemblies | ||
| 182 | hr = CpiConfigureAssemblies(&pwzData, hRollbackFile); | ||
| 183 | ExitOnFailure(hr, "Failed to register assemblies"); | ||
| 184 | if (S_FALSE == hr) ExitFunction(); | ||
| 185 | |||
| 186 | // create role assignments | ||
| 187 | hr = CpiConfigureRoleAssignments(&pwzData, hRollbackFile); | ||
| 188 | ExitOnFailure(hr, "Failed to create role assignments"); | ||
| 189 | if (S_FALSE == hr) ExitFunction(); | ||
| 190 | |||
| 191 | // create subscriptions | ||
| 192 | hr = CpiConfigureSubscriptions(&pwzData, hRollbackFile); | ||
| 193 | ExitOnFailure(hr, "Failed to create subscriptions"); | ||
| 194 | if (S_FALSE == hr) ExitFunction(); | ||
| 195 | |||
| 196 | hr = S_OK; | ||
| 197 | |||
| 198 | LExit: | ||
| 199 | // clean up | ||
| 200 | ReleaseStr(pwzCustomActionData); | ||
| 201 | ReleaseStr(pwzRollbackFileName); | ||
| 202 | |||
| 203 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
| 204 | ::CloseHandle(hRollbackFile); | ||
| 205 | |||
| 206 | // unitialize | ||
| 207 | CpiFinalize(); | ||
| 208 | |||
| 209 | if (fInitializedCom) | ||
| 210 | ::CoUninitialize(); | ||
| 211 | |||
| 212 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 213 | return WcaFinalize(er); | ||
| 214 | } | ||
| 215 | |||
| 216 | /******************************************************************** | ||
| 217 | ComPlusInstallExecuteCommit - CUSTOM ACTION ENTRY POINT | ||
| 218 | |||
| 219 | Input: deferred CustomActionData - ComPlusInstallExecuteCommit | ||
| 220 | ********************************************************************/ | ||
| 221 | extern "C" UINT __stdcall ComPlusInstallExecuteCommit(MSIHANDLE hInstall) | ||
| 222 | { | ||
| 223 | HRESULT hr = S_OK; | ||
| 224 | UINT er = ERROR_SUCCESS; | ||
| 225 | |||
| 226 | LPWSTR pwzCustomActionData = NULL; | ||
| 227 | LPWSTR pwzData = NULL; | ||
| 228 | LPWSTR pwzRollbackFileName = NULL; | ||
| 229 | |||
| 230 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
| 231 | |||
| 232 | BOOL fInitializedCom = FALSE; | ||
| 233 | |||
| 234 | // initialize | ||
| 235 | hr = WcaInitialize(hInstall, "ComPlusInstallExecuteCommit"); | ||
| 236 | ExitOnFailure(hr, "Failed to initialize ComPlusInstallExecuteCommit"); | ||
| 237 | |||
| 238 | hr = ::CoInitialize(NULL); | ||
| 239 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
| 240 | fInitializedCom = TRUE; | ||
| 241 | |||
| 242 | CpiInitialize(); | ||
| 243 | |||
| 244 | // get custom action data | ||
| 245 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
| 246 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
| 247 | pwzData = pwzCustomActionData; | ||
| 248 | |||
| 249 | // open rollback file | ||
| 250 | hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName); | ||
| 251 | ExitOnFailure(hr, "Failed to read rollback file name"); | ||
| 252 | |||
| 253 | hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
| 254 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
| 255 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName); | ||
| 256 | |||
| 257 | if (INVALID_SET_FILE_POINTER == ::SetFilePointer(hRollbackFile, 0, NULL, FILE_END)) | ||
| 258 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to set file pointer"); | ||
| 259 | |||
| 260 | // register assemblies | ||
| 261 | hr = CpiConfigureAssemblies(&pwzData, hRollbackFile); | ||
| 262 | ExitOnFailure(hr, "Failed to register assemblies"); | ||
| 263 | if (S_FALSE == hr) ExitFunction(); | ||
| 264 | |||
| 265 | // create role assignments | ||
| 266 | hr = CpiConfigureRoleAssignments(&pwzData, hRollbackFile); | ||
| 267 | ExitOnFailure(hr, "Failed to create role assignments"); | ||
| 268 | if (S_FALSE == hr) ExitFunction(); | ||
| 269 | |||
| 270 | // create subscriptions | ||
| 271 | hr = CpiConfigureSubscriptions(&pwzData, hRollbackFile); | ||
| 272 | ExitOnFailure(hr, "Failed to create subscriptions"); | ||
| 273 | if (S_FALSE == hr) ExitFunction(); | ||
| 274 | |||
| 275 | hr = S_OK; | ||
| 276 | |||
| 277 | LExit: | ||
| 278 | // clean up | ||
| 279 | ReleaseStr(pwzCustomActionData); | ||
| 280 | |||
| 281 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
| 282 | ::CloseHandle(hRollbackFile); | ||
| 283 | |||
| 284 | // unitialize | ||
| 285 | CpiFinalize(); | ||
| 286 | |||
| 287 | if (fInitializedCom) | ||
| 288 | ::CoUninitialize(); | ||
| 289 | |||
| 290 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 291 | return WcaFinalize(er); | ||
| 292 | } | ||
| 293 | |||
| 294 | /******************************************************************** | ||
| 295 | ComPlusRollbackInstallExecute - CUSTOM ACTION ENTRY POINT | ||
| 296 | |||
| 297 | Input: deferred CustomActionData - ComPlusRollbackInstallExecute | ||
| 298 | ********************************************************************/ | ||
| 299 | extern "C" UINT __stdcall ComPlusRollbackInstallExecute(MSIHANDLE hInstall) | ||
| 300 | { | ||
| 301 | HRESULT hr = S_OK; | ||
| 302 | UINT er = ERROR_SUCCESS; | ||
| 303 | |||
| 304 | LPWSTR pwzCustomActionData = NULL; | ||
| 305 | LPWSTR pwzData = NULL; | ||
| 306 | LPWSTR pwzRollbackFileName = NULL; | ||
| 307 | |||
| 308 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
| 309 | |||
| 310 | CPI_ROLLBACK_DATA* prdPartitions = NULL; | ||
| 311 | CPI_ROLLBACK_DATA* prdUsersInPartitionRoles = NULL; | ||
| 312 | CPI_ROLLBACK_DATA* prdPartitionUsers = NULL; | ||
| 313 | CPI_ROLLBACK_DATA* prdApplications = NULL; | ||
| 314 | CPI_ROLLBACK_DATA* prdApplicationRoles = NULL; | ||
| 315 | CPI_ROLLBACK_DATA* prdUsersApplicationRoles = NULL; | ||
| 316 | CPI_ROLLBACK_DATA* prdAssemblies = NULL; | ||
| 317 | CPI_ROLLBACK_DATA* prdRoleAssignments = NULL; | ||
| 318 | CPI_ROLLBACK_DATA* prdSubscriptions = NULL; | ||
| 319 | |||
| 320 | BOOL fInitializedCom = FALSE; | ||
| 321 | |||
| 322 | // initialize | ||
| 323 | hr = WcaInitialize(hInstall, "ComPlusRollbackInstallExecute"); | ||
| 324 | ExitOnFailure(hr, "Failed to initialize ComPlusRollbackInstallExecute"); | ||
| 325 | |||
| 326 | hr = ::CoInitialize(NULL); | ||
| 327 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
| 328 | fInitializedCom = TRUE; | ||
| 329 | |||
| 330 | CpiInitialize(); | ||
| 331 | |||
| 332 | // get custom action data | ||
| 333 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
| 334 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
| 335 | pwzData = pwzCustomActionData; | ||
| 336 | |||
| 337 | // open rollback file | ||
| 338 | hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName); | ||
| 339 | ExitOnFailure(hr, "Failed to read rollback file name"); | ||
| 340 | |||
| 341 | hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
| 342 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
| 343 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName); | ||
| 344 | |||
| 345 | // read rollback data (execute) | ||
| 346 | hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitions); | ||
| 347 | ExitOnFailure(hr, "Failed to read partitions rollback data"); | ||
| 348 | hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersInPartitionRoles); | ||
| 349 | ExitOnFailure(hr, "Failed to read users in partition roles rollback data"); | ||
| 350 | hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitionUsers); | ||
| 351 | ExitOnFailure(hr, "Failed to read partition users rollback data"); | ||
| 352 | hr = CpiReadRollbackDataList(hRollbackFile, &prdApplications); | ||
| 353 | ExitOnFailure(hr, "Failed to read applications rollback data"); | ||
| 354 | hr = CpiReadRollbackDataList(hRollbackFile, &prdApplicationRoles); | ||
| 355 | ExitOnFailure(hr, "Failed to read application roles rollback data"); | ||
| 356 | hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersApplicationRoles); | ||
| 357 | ExitOnFailure(hr, "Failed to read users in application roles rollback data"); | ||
| 358 | hr = CpiReadRollbackDataList(hRollbackFile, &prdAssemblies); | ||
| 359 | ExitOnFailure(hr, "Failed to read assemblies rollback data"); | ||
| 360 | hr = CpiReadRollbackDataList(hRollbackFile, &prdRoleAssignments); | ||
| 361 | ExitOnFailure(hr, "Failed to read role assignments rollback data"); | ||
| 362 | hr = CpiReadRollbackDataList(hRollbackFile, &prdSubscriptions); | ||
| 363 | ExitOnFailure(hr, "Failed to read subscription rollback data"); | ||
| 364 | |||
| 365 | // read rollback data (commit) | ||
| 366 | hr = CpiReadRollbackDataList(hRollbackFile, &prdAssemblies); | ||
| 367 | ExitOnFailure(hr, "Failed to read assemblies rollback data (commit)"); | ||
| 368 | hr = CpiReadRollbackDataList(hRollbackFile, &prdRoleAssignments); | ||
| 369 | ExitOnFailure(hr, "Failed to read role assignments rollback data"); | ||
| 370 | hr = CpiReadRollbackDataList(hRollbackFile, &prdSubscriptions); | ||
| 371 | ExitOnFailure(hr, "Failed to read subscription rollback data (commit)"); | ||
| 372 | |||
| 373 | ::CloseHandle(hRollbackFile); | ||
| 374 | hRollbackFile = INVALID_HANDLE_VALUE; | ||
| 375 | |||
| 376 | // rollback create subscriptions | ||
| 377 | hr = CpiRollbackConfigureSubscriptions(&pwzData, prdSubscriptions); | ||
| 378 | ExitOnFailure(hr, "Failed to rollback create subscriptions"); | ||
| 379 | |||
| 380 | // rollback create role assignments | ||
| 381 | hr = CpiRollbackConfigureRoleAssignments(&pwzData, prdRoleAssignments); | ||
| 382 | ExitOnFailure(hr, "Failed to rollback create role assignments"); | ||
| 383 | |||
| 384 | // rollback register assemblies | ||
| 385 | hr = CpiRollbackConfigureAssemblies(&pwzData, prdAssemblies); | ||
| 386 | ExitOnFailure(hr, "Failed to rollback register assemblies"); | ||
| 387 | |||
| 388 | // rollback create users in application roles | ||
| 389 | hr = CpiRollbackConfigureUsersInApplicationRoles(&pwzData, prdUsersApplicationRoles); | ||
| 390 | ExitOnFailure(hr, "Failed to rollback create users in application roles"); | ||
| 391 | |||
| 392 | // rollback create application roles | ||
| 393 | hr = CpiRollbackConfigureApplicationRoles(&pwzData, prdApplicationRoles); | ||
| 394 | ExitOnFailure(hr, "Failed to rollback create application roles"); | ||
| 395 | |||
| 396 | // rollback create applications | ||
| 397 | hr = CpiRollbackConfigureApplications(&pwzData, prdApplications); | ||
| 398 | ExitOnFailure(hr, "Failed to rollback create applications"); | ||
| 399 | |||
| 400 | // rollback create partition users | ||
| 401 | hr = CpiRollbackConfigurePartitionUsers(&pwzData, prdPartitionUsers); | ||
| 402 | ExitOnFailure(hr, "Failed to rollback create partition users"); | ||
| 403 | |||
| 404 | // rollback create users in partition roles | ||
| 405 | hr = CpiRollbackConfigureUsersInPartitionRoles(&pwzData, prdUsersInPartitionRoles); | ||
| 406 | ExitOnFailure(hr, "Failed to rollback create users in partition roles"); | ||
| 407 | |||
| 408 | // rollback create partitions | ||
| 409 | hr = CpiRollbackConfigurePartitions(&pwzData, prdPartitions); | ||
| 410 | ExitOnFailure(hr, "Failed to rollback create partitions"); | ||
| 411 | |||
| 412 | hr = S_OK; | ||
| 413 | |||
| 414 | LExit: | ||
| 415 | // clean up | ||
| 416 | ReleaseStr(pwzCustomActionData); | ||
| 417 | ReleaseStr(pwzRollbackFileName); | ||
| 418 | |||
| 419 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
| 420 | ::CloseHandle(hRollbackFile); | ||
| 421 | |||
| 422 | if (prdPartitions) | ||
| 423 | CpiFreeRollbackDataList(prdPartitions); | ||
| 424 | if (prdUsersInPartitionRoles) | ||
| 425 | CpiFreeRollbackDataList(prdUsersInPartitionRoles); | ||
| 426 | if (prdPartitionUsers) | ||
| 427 | CpiFreeRollbackDataList(prdPartitionUsers); | ||
| 428 | if (prdApplications) | ||
| 429 | CpiFreeRollbackDataList(prdApplications); | ||
| 430 | if (prdApplicationRoles) | ||
| 431 | CpiFreeRollbackDataList(prdApplicationRoles); | ||
| 432 | if (prdUsersApplicationRoles) | ||
| 433 | CpiFreeRollbackDataList(prdUsersApplicationRoles); | ||
| 434 | if (prdAssemblies) | ||
| 435 | CpiFreeRollbackDataList(prdAssemblies); | ||
| 436 | if (prdRoleAssignments) | ||
| 437 | CpiFreeRollbackDataList(prdRoleAssignments); | ||
| 438 | if (prdSubscriptions) | ||
| 439 | CpiFreeRollbackDataList(prdSubscriptions); | ||
| 440 | |||
| 441 | // unitialize | ||
| 442 | CpiFinalize(); | ||
| 443 | |||
| 444 | if (fInitializedCom) | ||
| 445 | ::CoUninitialize(); | ||
| 446 | |||
| 447 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 448 | return WcaFinalize(er); | ||
| 449 | } | ||
| 450 | |||
| 451 | /******************************************************************** | ||
| 452 | ComPlusUninstallExecute - CUSTOM ACTION ENTRY POINT | ||
| 453 | |||
| 454 | Input: deferred CustomActionData - ComPlusUninstallExecute | ||
| 455 | ********************************************************************/ | ||
| 456 | extern "C" UINT __stdcall ComPlusUninstallExecute(MSIHANDLE hInstall) | ||
| 457 | { | ||
| 458 | HRESULT hr = S_OK; | ||
| 459 | UINT er = ERROR_SUCCESS; | ||
| 460 | |||
| 461 | LPWSTR pwzCustomActionData = NULL; | ||
| 462 | LPWSTR pwzData = NULL; | ||
| 463 | LPWSTR pwzRollbackFileName = NULL; | ||
| 464 | |||
| 465 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
| 466 | |||
| 467 | BOOL fInitializedCom = FALSE; | ||
| 468 | |||
| 469 | // initialize | ||
| 470 | hr = WcaInitialize(hInstall, "ComPlusUninstallExecute"); | ||
| 471 | ExitOnFailure(hr, "Failed to initialize ComPlusUninstallExecute"); | ||
| 472 | |||
| 473 | hr = ::CoInitialize(NULL); | ||
| 474 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
| 475 | fInitializedCom = TRUE; | ||
| 476 | |||
| 477 | CpiInitialize(); | ||
| 478 | |||
| 479 | // get custom action data | ||
| 480 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
| 481 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
| 482 | pwzData = pwzCustomActionData; | ||
| 483 | |||
| 484 | // open rollback file | ||
| 485 | hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName); | ||
| 486 | ExitOnFailure(hr, "Failed to read rollback file name"); | ||
| 487 | |||
| 488 | hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
| 489 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
| 490 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName); | ||
| 491 | |||
| 492 | // delete subscriptions | ||
| 493 | hr = CpiConfigureSubscriptions(&pwzData, hRollbackFile); | ||
| 494 | ExitOnFailure(hr, "Failed to delete subscriptions"); | ||
| 495 | if (S_FALSE == hr) ExitFunction(); | ||
| 496 | |||
| 497 | // delete role assignments | ||
| 498 | hr = CpiConfigureRoleAssignments(&pwzData, hRollbackFile); | ||
| 499 | ExitOnFailure(hr, "Failed to delete role assignments"); | ||
| 500 | if (S_FALSE == hr) ExitFunction(); | ||
| 501 | |||
| 502 | // unregister assemblies | ||
| 503 | hr = CpiConfigureAssemblies(&pwzData, hRollbackFile); | ||
| 504 | ExitOnFailure(hr, "Failed to unregister assemblies"); | ||
| 505 | if (S_FALSE == hr) ExitFunction(); | ||
| 506 | |||
| 507 | // remove users in application roles | ||
| 508 | hr = CpiConfigureUsersInApplicationRoles(&pwzData, hRollbackFile); | ||
| 509 | ExitOnFailure(hr, "Failed to delete users in application roles"); | ||
| 510 | if (S_FALSE == hr) ExitFunction(); | ||
| 511 | |||
| 512 | // remove application roles | ||
| 513 | hr = CpiConfigureApplicationRoles(&pwzData, hRollbackFile); | ||
| 514 | ExitOnFailure(hr, "Failed to delete application roles"); | ||
| 515 | if (S_FALSE == hr) ExitFunction(); | ||
| 516 | |||
| 517 | // remove applications | ||
| 518 | hr = CpiConfigureApplications(&pwzData, hRollbackFile); | ||
| 519 | ExitOnFailure(hr, "Failed to remove applications"); | ||
| 520 | if (S_FALSE == hr) ExitFunction(); | ||
| 521 | |||
| 522 | // remove partition users | ||
| 523 | hr = CpiConfigurePartitionUsers(&pwzData, hRollbackFile); | ||
| 524 | ExitOnFailure(hr, "Failed to remove partition users"); | ||
| 525 | if (S_FALSE == hr) ExitFunction(); | ||
| 526 | |||
| 527 | // remove users in partition roles | ||
| 528 | hr = CpiConfigureUsersInPartitionRoles(&pwzData, hRollbackFile); | ||
| 529 | ExitOnFailure(hr, "Failed to delete users in partition roles"); | ||
| 530 | if (S_FALSE == hr) ExitFunction(); | ||
| 531 | |||
| 532 | // remove partitions | ||
| 533 | hr = CpiConfigurePartitions(&pwzData, hRollbackFile); | ||
| 534 | ExitOnFailure(hr, "Failed to delete partitions"); | ||
| 535 | if (S_FALSE == hr) ExitFunction(); | ||
| 536 | |||
| 537 | hr = S_OK; | ||
| 538 | |||
| 539 | LExit: | ||
| 540 | // clean up | ||
| 541 | ReleaseStr(pwzCustomActionData); | ||
| 542 | ReleaseStr(pwzRollbackFileName); | ||
| 543 | |||
| 544 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
| 545 | ::CloseHandle(hRollbackFile); | ||
| 546 | |||
| 547 | // unitialize | ||
| 548 | CpiFinalize(); | ||
| 549 | |||
| 550 | if (fInitializedCom) | ||
| 551 | ::CoUninitialize(); | ||
| 552 | |||
| 553 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 554 | return WcaFinalize(er); | ||
| 555 | } | ||
| 556 | |||
| 557 | /******************************************************************** | ||
| 558 | ComPlusRollbackUninstallExecute - CUSTOM ACTION ENTRY POINT | ||
| 559 | |||
| 560 | Input: deferred CustomActionData - ComPlusRollbackUninstallExecute | ||
| 561 | ********************************************************************/ | ||
| 562 | extern "C" UINT __stdcall ComPlusRollbackUninstallExecute(MSIHANDLE hInstall) | ||
| 563 | { | ||
| 564 | HRESULT hr = S_OK; | ||
| 565 | UINT er = ERROR_SUCCESS; | ||
| 566 | |||
| 567 | LPWSTR pwzCustomActionData = NULL; | ||
| 568 | LPWSTR pwzData = NULL; | ||
| 569 | LPWSTR pwzRollbackFileName = NULL; | ||
| 570 | |||
| 571 | HANDLE hRollbackFile = INVALID_HANDLE_VALUE; | ||
| 572 | |||
| 573 | CPI_ROLLBACK_DATA* prdPartitions = NULL; | ||
| 574 | CPI_ROLLBACK_DATA* prdUsersInPartitionRoles = NULL; | ||
| 575 | CPI_ROLLBACK_DATA* prdPartitionUsers = NULL; | ||
| 576 | CPI_ROLLBACK_DATA* prdApplications = NULL; | ||
| 577 | CPI_ROLLBACK_DATA* prdApplicationRoles = NULL; | ||
| 578 | CPI_ROLLBACK_DATA* prdUsersApplicationRoles = NULL; | ||
| 579 | CPI_ROLLBACK_DATA* prdAssemblies = NULL; | ||
| 580 | CPI_ROLLBACK_DATA* prdRoleAssignments = NULL; | ||
| 581 | CPI_ROLLBACK_DATA* prdSubscriptions = NULL; | ||
| 582 | |||
| 583 | BOOL fInitializedCom = FALSE; | ||
| 584 | |||
| 585 | // initialize | ||
| 586 | hr = WcaInitialize(hInstall, "ComPlusRollbackUninstallExecute"); | ||
| 587 | ExitOnFailure(hr, "Failed to initialize ComPlusRollbackUninstallExecute"); | ||
| 588 | |||
| 589 | hr = ::CoInitialize(NULL); | ||
| 590 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
| 591 | fInitializedCom = TRUE; | ||
| 592 | |||
| 593 | CpiInitialize(); | ||
| 594 | |||
| 595 | // get custom action data | ||
| 596 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
| 597 | ExitOnFailure(hr, "Failed to get CustomActionData"); | ||
| 598 | pwzData = pwzCustomActionData; | ||
| 599 | |||
| 600 | // open rollback file | ||
| 601 | hr = WcaReadStringFromCaData(&pwzData, &pwzRollbackFileName); | ||
| 602 | ExitOnFailure(hr, "Failed to read rollback file name"); | ||
| 603 | |||
| 604 | hRollbackFile = ::CreateFileW(pwzRollbackFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL); | ||
| 605 | if (INVALID_HANDLE_VALUE == hRollbackFile) | ||
| 606 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to open rollback file, name: %S", pwzRollbackFileName); | ||
| 607 | |||
| 608 | // read rollback data | ||
| 609 | hr = CpiReadRollbackDataList(hRollbackFile, &prdSubscriptions); | ||
| 610 | ExitOnFailure(hr, "Failed to read subscription rollback data"); | ||
| 611 | hr = CpiReadRollbackDataList(hRollbackFile, &prdRoleAssignments); | ||
| 612 | ExitOnFailure(hr, "Failed to read role assignments rollback data"); | ||
| 613 | hr = CpiReadRollbackDataList(hRollbackFile, &prdAssemblies); | ||
| 614 | ExitOnFailure(hr, "Failed to read assemblies rollback data"); | ||
| 615 | hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersApplicationRoles); | ||
| 616 | ExitOnFailure(hr, "Failed to read users in application roles rollback data"); | ||
| 617 | hr = CpiReadRollbackDataList(hRollbackFile, &prdApplicationRoles); | ||
| 618 | ExitOnFailure(hr, "Failed to read application roles rollback data"); | ||
| 619 | hr = CpiReadRollbackDataList(hRollbackFile, &prdApplications); | ||
| 620 | ExitOnFailure(hr, "Failed to read applications rollback data"); | ||
| 621 | hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitionUsers); | ||
| 622 | ExitOnFailure(hr, "Failed to read partition users rollback data"); | ||
| 623 | hr = CpiReadRollbackDataList(hRollbackFile, &prdUsersInPartitionRoles); | ||
| 624 | ExitOnFailure(hr, "Failed to read users in partition roles rollback data"); | ||
| 625 | hr = CpiReadRollbackDataList(hRollbackFile, &prdPartitions); | ||
| 626 | ExitOnFailure(hr, "Failed to read partitions rollback data"); | ||
| 627 | |||
| 628 | ::CloseHandle(hRollbackFile); | ||
| 629 | hRollbackFile = INVALID_HANDLE_VALUE; | ||
| 630 | |||
| 631 | // rollback remove partitions | ||
| 632 | hr = CpiRollbackConfigurePartitions(&pwzData, prdPartitions); | ||
| 633 | ExitOnFailure(hr, "Failed to rollback delete partitions"); | ||
| 634 | |||
| 635 | // rollback remove users in partition roles | ||
| 636 | hr = CpiRollbackConfigureUsersInPartitionRoles(&pwzData, prdUsersInPartitionRoles); | ||
| 637 | ExitOnFailure(hr, "Failed to rollback delete users in partition roles"); | ||
| 638 | |||
| 639 | // rollback remove partition users | ||
| 640 | hr = CpiRollbackConfigurePartitionUsers(&pwzData, prdPartitionUsers); | ||
| 641 | ExitOnFailure(hr, "Failed to rollback delete partition users"); | ||
| 642 | |||
| 643 | // rollback remove applications | ||
| 644 | hr = CpiRollbackConfigureApplications(&pwzData, prdApplications); | ||
| 645 | ExitOnFailure(hr, "Failed to rollback delete applications"); | ||
| 646 | |||
| 647 | // rollback remove application roles | ||
| 648 | hr = CpiRollbackConfigureApplicationRoles(&pwzData, prdApplicationRoles); | ||
| 649 | ExitOnFailure(hr, "Failed to rollback delete application roles"); | ||
| 650 | |||
| 651 | // rollback remove users in application roles | ||
| 652 | hr = CpiRollbackConfigureUsersInApplicationRoles(&pwzData, prdUsersApplicationRoles); | ||
| 653 | ExitOnFailure(hr, "Failed to rollback delete users in application roles"); | ||
| 654 | |||
| 655 | // rollback unregister assemblies | ||
| 656 | hr = CpiRollbackConfigureAssemblies(&pwzData, prdAssemblies); | ||
| 657 | ExitOnFailure(hr, "Failed to rollback unregister assemblies"); | ||
| 658 | |||
| 659 | // rollback delete role assignments | ||
| 660 | hr = CpiRollbackConfigureRoleAssignments(&pwzData, prdAssemblies); | ||
| 661 | ExitOnFailure(hr, "Failed to rollback delete role assignments"); | ||
| 662 | |||
| 663 | // rollback delete subscriptions | ||
| 664 | hr = CpiRollbackConfigureSubscriptions(&pwzData, prdSubscriptions); | ||
| 665 | ExitOnFailure(hr, "Failed to rollback delete subscriptions"); | ||
| 666 | |||
| 667 | hr = S_OK; | ||
| 668 | |||
| 669 | LExit: | ||
| 670 | // clean up | ||
| 671 | ReleaseStr(pwzCustomActionData); | ||
| 672 | ReleaseStr(pwzRollbackFileName); | ||
| 673 | |||
| 674 | if (INVALID_HANDLE_VALUE != hRollbackFile) | ||
| 675 | ::CloseHandle(hRollbackFile); | ||
| 676 | |||
| 677 | if (prdPartitions) | ||
| 678 | CpiFreeRollbackDataList(prdPartitions); | ||
| 679 | if (prdUsersInPartitionRoles) | ||
| 680 | CpiFreeRollbackDataList(prdUsersInPartitionRoles); | ||
| 681 | if (prdPartitionUsers) | ||
| 682 | CpiFreeRollbackDataList(prdPartitionUsers); | ||
| 683 | if (prdApplications) | ||
| 684 | CpiFreeRollbackDataList(prdApplications); | ||
| 685 | if (prdApplicationRoles) | ||
| 686 | CpiFreeRollbackDataList(prdApplicationRoles); | ||
| 687 | if (prdUsersApplicationRoles) | ||
| 688 | CpiFreeRollbackDataList(prdUsersApplicationRoles); | ||
| 689 | if (prdAssemblies) | ||
| 690 | CpiFreeRollbackDataList(prdAssemblies); | ||
| 691 | if (prdRoleAssignments) | ||
| 692 | CpiFreeRollbackDataList(prdRoleAssignments); | ||
| 693 | if (prdSubscriptions) | ||
| 694 | CpiFreeRollbackDataList(prdSubscriptions); | ||
| 695 | |||
| 696 | // unitialize | ||
| 697 | CpiFinalize(); | ||
| 698 | |||
| 699 | if (fInitializedCom) | ||
| 700 | ::CoUninitialize(); | ||
| 701 | |||
| 702 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 703 | return WcaFinalize(er); | ||
| 704 | } | ||
diff --git a/src/ca/cpexec.def b/src/ca/cpexec.def new file mode 100644 index 00000000..1dad15c2 --- /dev/null +++ b/src/ca/cpexec.def | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | ; Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | |||
| 4 | EXPORTS | ||
| 5 | ComPlusPrepare | ||
| 6 | ComPlusCleanup | ||
| 7 | ComPlusInstallExecute | ||
| 8 | ComPlusInstallExecuteCommit | ||
| 9 | ComPlusRollbackInstallExecute | ||
| 10 | ComPlusUninstallExecute | ||
| 11 | ComPlusRollbackUninstallExecute | ||
diff --git a/src/ca/cppartexec.cpp b/src/ca/cppartexec.cpp new file mode 100644 index 00000000..d8c30c6a --- /dev/null +++ b/src/ca/cppartexec.cpp | |||
| @@ -0,0 +1,690 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // private structs | ||
| 7 | |||
| 8 | struct CPI_PARTITION_ATTRIBUTES | ||
| 9 | { | ||
| 10 | int iActionType; | ||
| 11 | int iActionCost; | ||
| 12 | LPWSTR pwzKey; | ||
| 13 | LPWSTR pwzID; | ||
| 14 | LPWSTR pwzName; | ||
| 15 | CPI_PROPERTY* pPropList; | ||
| 16 | }; | ||
| 17 | |||
| 18 | struct CPI_PARTITION_USER_ATTRIBUTES | ||
| 19 | { | ||
| 20 | int iActionType; | ||
| 21 | int iActionCost; | ||
| 22 | LPWSTR pwzKey; | ||
| 23 | LPWSTR pwzAccount; | ||
| 24 | LPWSTR pwzPartID; | ||
| 25 | }; | ||
| 26 | |||
| 27 | |||
| 28 | // prototypes for private helper functions | ||
| 29 | |||
| 30 | static HRESULT ReadPartitionAttributes( | ||
| 31 | LPWSTR* ppwzData, | ||
| 32 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
| 33 | ); | ||
| 34 | static void FreePartitionAttributes( | ||
| 35 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
| 36 | ); | ||
| 37 | static HRESULT CreatePartition( | ||
| 38 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
| 39 | ); | ||
| 40 | static HRESULT RemovePartition( | ||
| 41 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
| 42 | ); | ||
| 43 | static HRESULT ReadPartitionUserAttributes( | ||
| 44 | LPWSTR* ppwzData, | ||
| 45 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
| 46 | ); | ||
| 47 | static void FreePartitionUserAttributes( | ||
| 48 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
| 49 | ); | ||
| 50 | static HRESULT CreatePartitionUser( | ||
| 51 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
| 52 | ); | ||
| 53 | static HRESULT RemovePartitionUser( | ||
| 54 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
| 55 | ); | ||
| 56 | |||
| 57 | |||
| 58 | // function definitions | ||
| 59 | |||
| 60 | HRESULT CpiConfigurePartitions( | ||
| 61 | LPWSTR* ppwzData, | ||
| 62 | HANDLE hRollbackFile | ||
| 63 | ) | ||
| 64 | { | ||
| 65 | HRESULT hr = S_OK; | ||
| 66 | |||
| 67 | CPI_PARTITION_ATTRIBUTES attrs; | ||
| 68 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 69 | |||
| 70 | // read action text | ||
| 71 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
| 72 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 73 | |||
| 74 | // ger partition count | ||
| 75 | int iCnt = 0; | ||
| 76 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 77 | ExitOnFailure(hr, "Failed to read count"); | ||
| 78 | |||
| 79 | // write count to rollback file | ||
| 80 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
| 81 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
| 82 | |||
| 83 | for (int i = 0; i < iCnt; i++) | ||
| 84 | { | ||
| 85 | // read partition attributes from CustomActionData | ||
| 86 | hr = ReadPartitionAttributes(ppwzData, &attrs); | ||
| 87 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 88 | |||
| 89 | // progress message | ||
| 90 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
| 91 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 92 | |||
| 93 | if (S_FALSE == hr) | ||
| 94 | ExitFunction(); | ||
| 95 | |||
| 96 | // write key to rollback file | ||
| 97 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
| 98 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
| 99 | |||
| 100 | // action | ||
| 101 | switch (attrs.iActionType) | ||
| 102 | { | ||
| 103 | case atCreate: | ||
| 104 | hr = CreatePartition(&attrs); | ||
| 105 | ExitOnFailure(hr, "Failed to create partition, key: %S", attrs.pwzKey); | ||
| 106 | break; | ||
| 107 | case atRemove: | ||
| 108 | hr = RemovePartition(&attrs); | ||
| 109 | ExitOnFailure(hr, "Failed to remove partition, key: %S", attrs.pwzKey); | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | |||
| 113 | // write completion status to rollback file | ||
| 114 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
| 115 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
| 116 | |||
| 117 | // progress | ||
| 118 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 119 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 120 | } | ||
| 121 | |||
| 122 | hr = S_OK; | ||
| 123 | |||
| 124 | LExit: | ||
| 125 | // clean up | ||
| 126 | FreePartitionAttributes(&attrs); | ||
| 127 | |||
| 128 | return hr; | ||
| 129 | } | ||
| 130 | |||
| 131 | HRESULT CpiRollbackConfigurePartitions( | ||
| 132 | LPWSTR* ppwzData, | ||
| 133 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 134 | ) | ||
| 135 | { | ||
| 136 | HRESULT hr = S_OK; | ||
| 137 | |||
| 138 | int iRollbackStatus; | ||
| 139 | |||
| 140 | CPI_PARTITION_ATTRIBUTES attrs; | ||
| 141 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 142 | |||
| 143 | // read action text | ||
| 144 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
| 145 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 146 | |||
| 147 | // get count | ||
| 148 | int iCnt = 0; | ||
| 149 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 150 | ExitOnFailure(hr, "Failed to read count"); | ||
| 151 | |||
| 152 | for (int i = 0; i < iCnt; i++) | ||
| 153 | { | ||
| 154 | // read partition attributes from CustomActionData | ||
| 155 | hr = ReadPartitionAttributes(ppwzData, &attrs); | ||
| 156 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 157 | |||
| 158 | // rollback status | ||
| 159 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
| 160 | |||
| 161 | if (S_FALSE == hr) | ||
| 162 | continue; // not found, nothing to rollback | ||
| 163 | |||
| 164 | // progress message | ||
| 165 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
| 166 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 167 | |||
| 168 | if (S_FALSE == hr) | ||
| 169 | ExitFunction(); | ||
| 170 | |||
| 171 | // action | ||
| 172 | switch (attrs.iActionType) | ||
| 173 | { | ||
| 174 | case atCreate: | ||
| 175 | hr = CreatePartition(&attrs); | ||
| 176 | if (FAILED(hr)) | ||
| 177 | WcaLog(LOGMSG_STANDARD, "Failed to create partition, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 178 | break; | ||
| 179 | case atRemove: | ||
| 180 | hr = RemovePartition(&attrs); | ||
| 181 | if (FAILED(hr)) | ||
| 182 | WcaLog(LOGMSG_STANDARD, "Failed to remove partition, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | |||
| 186 | // check rollback status | ||
| 187 | if (0 == iRollbackStatus) | ||
| 188 | continue; // operation did not complete, skip progress | ||
| 189 | |||
| 190 | // progress | ||
| 191 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 192 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 193 | } | ||
| 194 | |||
| 195 | hr = S_OK; | ||
| 196 | |||
| 197 | LExit: | ||
| 198 | // clean up | ||
| 199 | FreePartitionAttributes(&attrs); | ||
| 200 | |||
| 201 | return hr; | ||
| 202 | } | ||
| 203 | |||
| 204 | HRESULT CpiConfigurePartitionUsers( | ||
| 205 | LPWSTR* ppwzData, | ||
| 206 | HANDLE hRollbackFile | ||
| 207 | ) | ||
| 208 | { | ||
| 209 | HRESULT hr = S_OK; | ||
| 210 | |||
| 211 | CPI_PARTITION_USER_ATTRIBUTES attrs; | ||
| 212 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 213 | |||
| 214 | // read action text | ||
| 215 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
| 216 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 217 | |||
| 218 | // ger partition count | ||
| 219 | int iCnt = 0; | ||
| 220 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 221 | ExitOnFailure(hr, "Failed to read count"); | ||
| 222 | |||
| 223 | // write count to rollback file | ||
| 224 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
| 225 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
| 226 | |||
| 227 | for (int i = 0; i < iCnt; i++) | ||
| 228 | { | ||
| 229 | // read partition attributes from CustomActionData | ||
| 230 | hr = ReadPartitionUserAttributes(ppwzData, &attrs); | ||
| 231 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 232 | |||
| 233 | // progress message | ||
| 234 | hr = CpiActionDataMessage(1, attrs.pwzAccount); | ||
| 235 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 236 | |||
| 237 | if (S_FALSE == hr) | ||
| 238 | ExitFunction(); | ||
| 239 | |||
| 240 | // write key to rollback file | ||
| 241 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
| 242 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
| 243 | |||
| 244 | // action | ||
| 245 | switch (attrs.iActionType) | ||
| 246 | { | ||
| 247 | case atCreate: | ||
| 248 | hr = CreatePartitionUser(&attrs); | ||
| 249 | ExitOnFailure(hr, "Failed to create partition user, key: %S", attrs.pwzKey); | ||
| 250 | break; | ||
| 251 | case atRemove: | ||
| 252 | hr = RemovePartitionUser(&attrs); | ||
| 253 | ExitOnFailure(hr, "Failed to remove partition user, key: %S", attrs.pwzKey); | ||
| 254 | break; | ||
| 255 | } | ||
| 256 | |||
| 257 | // write completion status to rollback file | ||
| 258 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
| 259 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
| 260 | |||
| 261 | // progress | ||
| 262 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 263 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 264 | } | ||
| 265 | |||
| 266 | hr = S_OK; | ||
| 267 | |||
| 268 | LExit: | ||
| 269 | // clean up | ||
| 270 | FreePartitionUserAttributes(&attrs); | ||
| 271 | |||
| 272 | return hr; | ||
| 273 | } | ||
| 274 | |||
| 275 | HRESULT CpiRollbackConfigurePartitionUsers( | ||
| 276 | LPWSTR* ppwzData, | ||
| 277 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 278 | ) | ||
| 279 | { | ||
| 280 | HRESULT hr = S_OK; | ||
| 281 | |||
| 282 | int iRollbackStatus; | ||
| 283 | |||
| 284 | CPI_PARTITION_USER_ATTRIBUTES attrs; | ||
| 285 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 286 | |||
| 287 | // read action text | ||
| 288 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
| 289 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 290 | |||
| 291 | // get count | ||
| 292 | int iCnt = 0; | ||
| 293 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 294 | ExitOnFailure(hr, "Failed to read count"); | ||
| 295 | |||
| 296 | for (int i = 0; i < iCnt; i++) | ||
| 297 | { | ||
| 298 | // read partition attributes from CustomActionData | ||
| 299 | hr = ReadPartitionUserAttributes(ppwzData, &attrs); | ||
| 300 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 301 | |||
| 302 | // rollback status | ||
| 303 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
| 304 | |||
| 305 | if (S_FALSE == hr) | ||
| 306 | continue; // not found, nothing to rollback | ||
| 307 | |||
| 308 | // progress message | ||
| 309 | hr = CpiActionDataMessage(1, attrs.pwzAccount); | ||
| 310 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 311 | |||
| 312 | if (S_FALSE == hr) | ||
| 313 | ExitFunction(); | ||
| 314 | |||
| 315 | // action | ||
| 316 | switch (attrs.iActionType) | ||
| 317 | { | ||
| 318 | case atCreate: | ||
| 319 | hr = CreatePartitionUser(&attrs); | ||
| 320 | ExitOnFailure(hr, "Failed to create partition user, key: %S", attrs.pwzKey); | ||
| 321 | break; | ||
| 322 | case atRemove: | ||
| 323 | hr = RemovePartitionUser(&attrs); | ||
| 324 | ExitOnFailure(hr, "Failed to remove partition user, key: %S", attrs.pwzKey); | ||
| 325 | break; | ||
| 326 | } | ||
| 327 | |||
| 328 | // check rollback status | ||
| 329 | if (0 == iRollbackStatus) | ||
| 330 | continue; // operation did not complete, skip progress | ||
| 331 | |||
| 332 | // progress | ||
| 333 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 334 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 335 | } | ||
| 336 | |||
| 337 | hr = S_OK; | ||
| 338 | |||
| 339 | LExit: | ||
| 340 | // clean up | ||
| 341 | FreePartitionUserAttributes(&attrs); | ||
| 342 | |||
| 343 | return hr; | ||
| 344 | } | ||
| 345 | |||
| 346 | |||
| 347 | // helper function definitions | ||
| 348 | |||
| 349 | static HRESULT ReadPartitionAttributes( | ||
| 350 | LPWSTR* ppwzData, | ||
| 351 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
| 352 | ) | ||
| 353 | { | ||
| 354 | HRESULT hr = S_OK; | ||
| 355 | |||
| 356 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
| 357 | ExitOnFailure(hr, "Failed to read action type"); | ||
| 358 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
| 359 | ExitOnFailure(hr, "Failed to read action cost"); | ||
| 360 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
| 361 | ExitOnFailure(hr, "Failed to read key"); | ||
| 362 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzID); | ||
| 363 | ExitOnFailure(hr, "Failed to read id"); | ||
| 364 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName); | ||
| 365 | ExitOnFailure(hr, "Failed to read name"); | ||
| 366 | hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList); | ||
| 367 | ExitOnFailure(hr, "Failed to read properties"); | ||
| 368 | |||
| 369 | hr = S_OK; | ||
| 370 | |||
| 371 | LExit: | ||
| 372 | return hr; | ||
| 373 | } | ||
| 374 | |||
| 375 | static void FreePartitionAttributes( | ||
| 376 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
| 377 | ) | ||
| 378 | { | ||
| 379 | ReleaseStr(pAttrs->pwzKey); | ||
| 380 | ReleaseStr(pAttrs->pwzID); | ||
| 381 | ReleaseStr(pAttrs->pwzName); | ||
| 382 | |||
| 383 | if (pAttrs->pPropList) | ||
| 384 | CpiFreePropertyList(pAttrs->pPropList); | ||
| 385 | } | ||
| 386 | |||
| 387 | static HRESULT CreatePartition( | ||
| 388 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
| 389 | ) | ||
| 390 | { | ||
| 391 | HRESULT hr = S_OK; | ||
| 392 | |||
| 393 | ICatalogCollection* piPartColl = NULL; | ||
| 394 | ICatalogObject* piPartObj = NULL; | ||
| 395 | |||
| 396 | long lChanges = 0; | ||
| 397 | |||
| 398 | // log | ||
| 399 | WcaLog(LOGMSG_VERBOSE, "Creating partition, key: %S", pAttrs->pwzKey); | ||
| 400 | |||
| 401 | // get partitions collection | ||
| 402 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
| 403 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
| 404 | |||
| 405 | // check if partition exists | ||
| 406 | hr = CpiFindCollectionObjectByStringKey(piPartColl, pAttrs->pwzID, &piPartObj); | ||
| 407 | ExitOnFailure(hr, "Failed to find partition"); | ||
| 408 | |||
| 409 | if (S_FALSE == hr) | ||
| 410 | { | ||
| 411 | // create partition | ||
| 412 | hr = CpiAddCollectionObject(piPartColl, &piPartObj); | ||
| 413 | ExitOnFailure(hr, "Failed to add partition to collection"); | ||
| 414 | |||
| 415 | hr = CpiPutCollectionObjectValue(piPartObj, L"ID", pAttrs->pwzID); | ||
| 416 | ExitOnFailure(hr, "Failed to set partition id property"); | ||
| 417 | |||
| 418 | hr = CpiPutCollectionObjectValue(piPartObj, L"Name", pAttrs->pwzName); | ||
| 419 | ExitOnFailure(hr, "Failed to set partition name property"); | ||
| 420 | } | ||
| 421 | |||
| 422 | // properties | ||
| 423 | hr = CpiPutCollectionObjectValues(piPartObj, pAttrs->pPropList); | ||
| 424 | ExitOnFailure(hr, "Failed to write properties"); | ||
| 425 | |||
| 426 | // save changes | ||
| 427 | hr = piPartColl->SaveChanges(&lChanges); | ||
| 428 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 429 | CpiLogCatalogErrorInfo(); | ||
| 430 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 431 | |||
| 432 | // log | ||
| 433 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 434 | |||
| 435 | hr = S_OK; | ||
| 436 | |||
| 437 | LExit: | ||
| 438 | // clean up | ||
| 439 | ReleaseObject(piPartColl); | ||
| 440 | ReleaseObject(piPartObj); | ||
| 441 | |||
| 442 | return hr; | ||
| 443 | } | ||
| 444 | |||
| 445 | static HRESULT RemovePartition( | ||
| 446 | CPI_PARTITION_ATTRIBUTES* pAttrs | ||
| 447 | ) | ||
| 448 | { | ||
| 449 | HRESULT hr = S_OK; | ||
| 450 | |||
| 451 | ICatalogCollection* piPartColl = NULL; | ||
| 452 | |||
| 453 | long lChanges = 0; | ||
| 454 | |||
| 455 | // log | ||
| 456 | WcaLog(LOGMSG_VERBOSE, "Removing partition, key: %S", pAttrs->pwzKey); | ||
| 457 | |||
| 458 | // get partitions collection | ||
| 459 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
| 460 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
| 461 | |||
| 462 | // remove | ||
| 463 | hr = CpiRemoveCollectionObject(piPartColl, pAttrs->pwzID, NULL, TRUE); | ||
| 464 | ExitOnFailure(hr, "Failed to remove partition"); | ||
| 465 | |||
| 466 | if (S_FALSE == hr) | ||
| 467 | { | ||
| 468 | // partition not found | ||
| 469 | WcaLog(LOGMSG_VERBOSE, "Partition not found, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 470 | ExitFunction1(hr = S_OK); | ||
| 471 | } | ||
| 472 | |||
| 473 | // save changes | ||
| 474 | hr = piPartColl->SaveChanges(&lChanges); | ||
| 475 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 476 | CpiLogCatalogErrorInfo(); | ||
| 477 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 478 | |||
| 479 | // log | ||
| 480 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 481 | |||
| 482 | hr = S_OK; | ||
| 483 | |||
| 484 | LExit: | ||
| 485 | // clean up | ||
| 486 | ReleaseObject(piPartColl); | ||
| 487 | |||
| 488 | return hr; | ||
| 489 | } | ||
| 490 | |||
| 491 | static HRESULT ReadPartitionUserAttributes( | ||
| 492 | LPWSTR* ppwzData, | ||
| 493 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
| 494 | ) | ||
| 495 | { | ||
| 496 | HRESULT hr = S_OK; | ||
| 497 | |||
| 498 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
| 499 | ExitOnFailure(hr, "Failed to read action type"); | ||
| 500 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
| 501 | ExitOnFailure(hr, "Failed to read action cost"); | ||
| 502 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
| 503 | ExitOnFailure(hr, "Failed to read key"); | ||
| 504 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount); | ||
| 505 | ExitOnFailure(hr, "Failed to read account name"); | ||
| 506 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
| 507 | ExitOnFailure(hr, "Failed to read partition id"); | ||
| 508 | |||
| 509 | hr = S_OK; | ||
| 510 | |||
| 511 | LExit: | ||
| 512 | return hr; | ||
| 513 | } | ||
| 514 | |||
| 515 | static void FreePartitionUserAttributes( | ||
| 516 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
| 517 | ) | ||
| 518 | { | ||
| 519 | ReleaseStr(pAttrs->pwzKey); | ||
| 520 | ReleaseStr(pAttrs->pwzAccount); | ||
| 521 | ReleaseStr(pAttrs->pwzPartID); | ||
| 522 | } | ||
| 523 | |||
| 524 | static HRESULT CreatePartitionUser( | ||
| 525 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
| 526 | ) | ||
| 527 | { | ||
| 528 | HRESULT hr = S_OK; | ||
| 529 | UINT er = ERROR_SUCCESS; | ||
| 530 | |||
| 531 | ICatalogCollection* piUserColl = NULL; | ||
| 532 | ICatalogObject* piUserObj = NULL; | ||
| 533 | |||
| 534 | PSID pSid = NULL; | ||
| 535 | long lChanges = 0; | ||
| 536 | |||
| 537 | // log | ||
| 538 | WcaLog(LOGMSG_VERBOSE, "Setting default partition for user, key: %S", pAttrs->pwzKey); | ||
| 539 | |||
| 540 | // get partition users collection | ||
| 541 | hr = CpiGetPartitionUsersCollection(&piUserColl); | ||
| 542 | ExitOnFailure(hr, "Failed to get partition users collection"); | ||
| 543 | |||
| 544 | // get SID for account | ||
| 545 | do { | ||
| 546 | er = ERROR_SUCCESS; | ||
| 547 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
| 548 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
| 549 | { | ||
| 550 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
| 551 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 552 | switch (er) | ||
| 553 | { | ||
| 554 | case IDABORT: | ||
| 555 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
| 556 | case IDRETRY: | ||
| 557 | break; | ||
| 558 | case IDIGNORE: | ||
| 559 | default: | ||
| 560 | ExitFunction1(hr = S_OK); | ||
| 561 | } | ||
| 562 | } | ||
| 563 | else | ||
| 564 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
| 565 | } while (IDRETRY == er); | ||
| 566 | |||
| 567 | // remove any existing entry | ||
| 568 | hr = CpiRemoveUserCollectionObject(piUserColl, pSid); | ||
| 569 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
| 570 | { | ||
| 571 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
| 572 | hr = S_FALSE; | ||
| 573 | } | ||
| 574 | else | ||
| 575 | ExitOnFailure(hr, "Failed to remove user"); | ||
| 576 | |||
| 577 | if (S_OK == hr) | ||
| 578 | WcaLog(LOGMSG_VERBOSE, "Existing default partition for user was removed, key: %S", pAttrs->pwzKey); | ||
| 579 | |||
| 580 | // add partition user | ||
| 581 | hr = CpiAddCollectionObject(piUserColl, &piUserObj); | ||
| 582 | ExitOnFailure(hr, "Failed to add partition to collection"); | ||
| 583 | |||
| 584 | hr = CpiPutCollectionObjectValue(piUserObj, L"AccountName", pAttrs->pwzAccount); | ||
| 585 | ExitOnFailure(hr, "Failed to set account name property"); | ||
| 586 | |||
| 587 | hr = CpiPutCollectionObjectValue(piUserObj, L"DefaultPartitionID", pAttrs->pwzPartID); | ||
| 588 | ExitOnFailure(hr, "Failed to set default partition id property"); | ||
| 589 | |||
| 590 | // save changes | ||
| 591 | hr = piUserColl->SaveChanges(&lChanges); | ||
| 592 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 593 | CpiLogCatalogErrorInfo(); | ||
| 594 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 595 | |||
| 596 | // log | ||
| 597 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 598 | |||
| 599 | hr = S_OK; | ||
| 600 | |||
| 601 | LExit: | ||
| 602 | // clean up | ||
| 603 | ReleaseObject(piUserColl); | ||
| 604 | ReleaseObject(piUserObj); | ||
| 605 | |||
| 606 | if (pSid) | ||
| 607 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
| 608 | |||
| 609 | return hr; | ||
| 610 | } | ||
| 611 | |||
| 612 | static HRESULT RemovePartitionUser( | ||
| 613 | CPI_PARTITION_USER_ATTRIBUTES* pAttrs | ||
| 614 | ) | ||
| 615 | { | ||
| 616 | HRESULT hr = S_OK; | ||
| 617 | UINT er = ERROR_SUCCESS; | ||
| 618 | |||
| 619 | ICatalogCollection* piUserColl = NULL; | ||
| 620 | |||
| 621 | PSID pSid = NULL; | ||
| 622 | long lChanges = 0; | ||
| 623 | |||
| 624 | // log | ||
| 625 | WcaLog(LOGMSG_VERBOSE, "Removing default partition for user, key: %S", pAttrs->pwzKey); | ||
| 626 | |||
| 627 | // get partition users collection | ||
| 628 | hr = CpiGetPartitionUsersCollection(&piUserColl); | ||
| 629 | ExitOnFailure(hr, "Failed to get partition users collection"); | ||
| 630 | |||
| 631 | // get SID for account | ||
| 632 | do { | ||
| 633 | er = ERROR_SUCCESS; | ||
| 634 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
| 635 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
| 636 | { | ||
| 637 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
| 638 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 639 | switch (er) | ||
| 640 | { | ||
| 641 | case IDABORT: | ||
| 642 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
| 643 | case IDRETRY: | ||
| 644 | break; | ||
| 645 | case IDIGNORE: | ||
| 646 | default: | ||
| 647 | ExitFunction1(hr = S_OK); | ||
| 648 | } | ||
| 649 | } | ||
| 650 | else | ||
| 651 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
| 652 | } while (IDRETRY == er); | ||
| 653 | |||
| 654 | // remove | ||
| 655 | hr = CpiRemoveUserCollectionObject(piUserColl, pSid); | ||
| 656 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
| 657 | { | ||
| 658 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
| 659 | hr = S_FALSE; | ||
| 660 | } | ||
| 661 | else | ||
| 662 | ExitOnFailure(hr, "Failed to remove user"); | ||
| 663 | |||
| 664 | if (S_FALSE == hr) | ||
| 665 | { | ||
| 666 | // user not found | ||
| 667 | WcaLog(LOGMSG_VERBOSE, "Default partition for user not found, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 668 | ExitFunction1(hr = S_OK); | ||
| 669 | } | ||
| 670 | |||
| 671 | // save changes | ||
| 672 | hr = piUserColl->SaveChanges(&lChanges); | ||
| 673 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 674 | CpiLogCatalogErrorInfo(); | ||
| 675 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 676 | |||
| 677 | // log | ||
| 678 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 679 | |||
| 680 | hr = S_OK; | ||
| 681 | |||
| 682 | LExit: | ||
| 683 | // clean up | ||
| 684 | ReleaseObject(piUserColl); | ||
| 685 | |||
| 686 | if (pSid) | ||
| 687 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
| 688 | |||
| 689 | return hr; | ||
| 690 | } | ||
diff --git a/src/ca/cppartexec.h b/src/ca/cppartexec.h new file mode 100644 index 00000000..132a9f5a --- /dev/null +++ b/src/ca/cppartexec.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT CpiConfigurePartitions( | ||
| 6 | LPWSTR* ppwzData, | ||
| 7 | HANDLE hRollbackFile | ||
| 8 | ); | ||
| 9 | HRESULT CpiRollbackConfigurePartitions( | ||
| 10 | LPWSTR* ppwzData, | ||
| 11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 12 | ); | ||
| 13 | HRESULT CpiConfigurePartitionUsers( | ||
| 14 | LPWSTR* ppwzData, | ||
| 15 | HANDLE hRollbackFile | ||
| 16 | ); | ||
| 17 | HRESULT CpiRollbackConfigurePartitionUsers( | ||
| 18 | LPWSTR* ppwzData, | ||
| 19 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 20 | ); | ||
diff --git a/src/ca/cppartroleexec.cpp b/src/ca/cppartroleexec.cpp new file mode 100644 index 00000000..4a503c79 --- /dev/null +++ b/src/ca/cppartroleexec.cpp | |||
| @@ -0,0 +1,397 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // private structs | ||
| 7 | |||
| 8 | struct CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES | ||
| 9 | { | ||
| 10 | int iActionType; | ||
| 11 | int iActionCost; | ||
| 12 | LPWSTR pwzKey; | ||
| 13 | LPWSTR pwzRoleName; | ||
| 14 | LPWSTR pwzAccount; | ||
| 15 | LPWSTR pwzPartID; | ||
| 16 | }; | ||
| 17 | |||
| 18 | |||
| 19 | // prototypes for private helper functions | ||
| 20 | |||
| 21 | static HRESULT ReadUserInPartitionRoleAttributes( | ||
| 22 | LPWSTR* ppwzData, | ||
| 23 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
| 24 | ); | ||
| 25 | static void FreeUserInPartitionRoleAttributes( | ||
| 26 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
| 27 | ); | ||
| 28 | static HRESULT CreateUserInPartitionRole( | ||
| 29 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
| 30 | ); | ||
| 31 | static HRESULT RemoveUserInPartitionRole( | ||
| 32 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
| 33 | ); | ||
| 34 | |||
| 35 | |||
| 36 | // function definitions | ||
| 37 | |||
| 38 | HRESULT CpiConfigureUsersInPartitionRoles( | ||
| 39 | LPWSTR* ppwzData, | ||
| 40 | HANDLE hRollbackFile | ||
| 41 | ) | ||
| 42 | { | ||
| 43 | HRESULT hr = S_OK; | ||
| 44 | |||
| 45 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES attrs; | ||
| 46 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 47 | |||
| 48 | // read action text | ||
| 49 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
| 50 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 51 | |||
| 52 | // ger count | ||
| 53 | int iCnt = 0; | ||
| 54 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 55 | ExitOnFailure(hr, "Failed to read count"); | ||
| 56 | |||
| 57 | // write count to rollback file | ||
| 58 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
| 59 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
| 60 | |||
| 61 | for (int i = 0; i < iCnt; i++) | ||
| 62 | { | ||
| 63 | // read attributes from CustomActionData | ||
| 64 | hr = ReadUserInPartitionRoleAttributes(ppwzData, &attrs); | ||
| 65 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 66 | |||
| 67 | // progress message | ||
| 68 | hr = CpiActionDataMessage(1, attrs.pwzRoleName); | ||
| 69 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 70 | |||
| 71 | if (S_FALSE == hr) | ||
| 72 | ExitFunction(); | ||
| 73 | |||
| 74 | // write key to rollback file | ||
| 75 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
| 76 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
| 77 | |||
| 78 | // action | ||
| 79 | switch (attrs.iActionType) | ||
| 80 | { | ||
| 81 | case atCreate: | ||
| 82 | hr = CreateUserInPartitionRole(&attrs); | ||
| 83 | ExitOnFailure(hr, "Failed to add user to partition role, key: %S", attrs.pwzKey); | ||
| 84 | break; | ||
| 85 | case atRemove: | ||
| 86 | hr = RemoveUserInPartitionRole(&attrs); | ||
| 87 | ExitOnFailure(hr, "Failed to remove user from partition role, key: %S", attrs.pwzKey); | ||
| 88 | break; | ||
| 89 | } | ||
| 90 | |||
| 91 | // write completion status to rollback file | ||
| 92 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
| 93 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
| 94 | |||
| 95 | // progress | ||
| 96 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 97 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 98 | } | ||
| 99 | |||
| 100 | hr = S_OK; | ||
| 101 | |||
| 102 | LExit: | ||
| 103 | // clean up | ||
| 104 | FreeUserInPartitionRoleAttributes(&attrs); | ||
| 105 | |||
| 106 | return hr; | ||
| 107 | } | ||
| 108 | |||
| 109 | HRESULT CpiRollbackConfigureUsersInPartitionRoles( | ||
| 110 | LPWSTR* ppwzData, | ||
| 111 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 112 | ) | ||
| 113 | { | ||
| 114 | HRESULT hr = S_OK; | ||
| 115 | |||
| 116 | int iRollbackStatus; | ||
| 117 | |||
| 118 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES attrs; | ||
| 119 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 120 | |||
| 121 | // read action text | ||
| 122 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
| 123 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 124 | |||
| 125 | // get count | ||
| 126 | int iCnt = 0; | ||
| 127 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 128 | ExitOnFailure(hr, "Failed to read count"); | ||
| 129 | |||
| 130 | for (int i = 0; i < iCnt; i++) | ||
| 131 | { | ||
| 132 | // read attributes from CustomActionData | ||
| 133 | hr = ReadUserInPartitionRoleAttributes(ppwzData, &attrs); | ||
| 134 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 135 | |||
| 136 | // rollback status | ||
| 137 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
| 138 | |||
| 139 | if (S_FALSE == hr) | ||
| 140 | continue; // not found, nothing to rollback | ||
| 141 | |||
| 142 | // progress message | ||
| 143 | hr = CpiActionDataMessage(1, attrs.pwzRoleName); | ||
| 144 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 145 | |||
| 146 | if (S_FALSE == hr) | ||
| 147 | ExitFunction(); | ||
| 148 | |||
| 149 | // action | ||
| 150 | switch (attrs.iActionType) | ||
| 151 | { | ||
| 152 | case atCreate: | ||
| 153 | hr = CreateUserInPartitionRole(&attrs); | ||
| 154 | if (FAILED(hr)) | ||
| 155 | WcaLog(LOGMSG_STANDARD, "Failed to add user to partition role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 156 | break; | ||
| 157 | case atRemove: | ||
| 158 | hr = RemoveUserInPartitionRole(&attrs); | ||
| 159 | if (FAILED(hr)) | ||
| 160 | WcaLog(LOGMSG_STANDARD, "Failed to remove user from partition role, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | |||
| 164 | // check rollback status | ||
| 165 | if (0 == iRollbackStatus) | ||
| 166 | continue; // operation did not complete, skip progress | ||
| 167 | |||
| 168 | // progress | ||
| 169 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 170 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 171 | } | ||
| 172 | |||
| 173 | hr = S_OK; | ||
| 174 | |||
| 175 | LExit: | ||
| 176 | // clean up | ||
| 177 | FreeUserInPartitionRoleAttributes(&attrs); | ||
| 178 | |||
| 179 | return hr; | ||
| 180 | } | ||
| 181 | |||
| 182 | |||
| 183 | // helper function definitions | ||
| 184 | |||
| 185 | static HRESULT ReadUserInPartitionRoleAttributes( | ||
| 186 | LPWSTR* ppwzData, | ||
| 187 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
| 188 | ) | ||
| 189 | { | ||
| 190 | HRESULT hr = S_OK; | ||
| 191 | |||
| 192 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
| 193 | ExitOnFailure(hr, "Failed to read action type"); | ||
| 194 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
| 195 | ExitOnFailure(hr, "Failed to read action cost"); | ||
| 196 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
| 197 | ExitOnFailure(hr, "Failed to read key"); | ||
| 198 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzRoleName); | ||
| 199 | ExitOnFailure(hr, "Failed to read role name"); | ||
| 200 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAccount); | ||
| 201 | ExitOnFailure(hr, "Failed to read account name"); | ||
| 202 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
| 203 | ExitOnFailure(hr, "Failed to read partition id"); | ||
| 204 | |||
| 205 | hr = S_OK; | ||
| 206 | |||
| 207 | LExit: | ||
| 208 | return hr; | ||
| 209 | } | ||
| 210 | |||
| 211 | static void FreeUserInPartitionRoleAttributes( | ||
| 212 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
| 213 | ) | ||
| 214 | { | ||
| 215 | ReleaseStr(pAttrs->pwzKey); | ||
| 216 | ReleaseStr(pAttrs->pwzRoleName); | ||
| 217 | ReleaseStr(pAttrs->pwzAccount); | ||
| 218 | ReleaseStr(pAttrs->pwzPartID); | ||
| 219 | } | ||
| 220 | |||
| 221 | static HRESULT CreateUserInPartitionRole( | ||
| 222 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
| 223 | ) | ||
| 224 | { | ||
| 225 | HRESULT hr = S_OK; | ||
| 226 | UINT er = ERROR_SUCCESS; | ||
| 227 | |||
| 228 | ICatalogCollection* piUsrInRoleColl = NULL; | ||
| 229 | ICatalogObject* piUsrInRoleObj = NULL; | ||
| 230 | |||
| 231 | PSID pSid = NULL; | ||
| 232 | long lChanges = 0; | ||
| 233 | |||
| 234 | // log | ||
| 235 | WcaLog(LOGMSG_VERBOSE, "Adding user to partition role, key: %S", pAttrs->pwzKey); | ||
| 236 | |||
| 237 | // get users in partition role collection | ||
| 238 | hr = CpiGetUsersInPartitionRoleCollection(pAttrs->pwzPartID, pAttrs->pwzRoleName, &piUsrInRoleColl); | ||
| 239 | if (S_FALSE == hr) | ||
| 240 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 241 | ExitOnFailure(hr, "Failed to get users in partition role collection"); | ||
| 242 | |||
| 243 | // get SID for account | ||
| 244 | do { | ||
| 245 | er = ERROR_SUCCESS; | ||
| 246 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
| 247 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
| 248 | { | ||
| 249 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
| 250 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 251 | switch (er) | ||
| 252 | { | ||
| 253 | case IDABORT: | ||
| 254 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
| 255 | case IDRETRY: | ||
| 256 | break; | ||
| 257 | case IDIGNORE: | ||
| 258 | default: | ||
| 259 | ExitFunction1(hr = S_OK); | ||
| 260 | } | ||
| 261 | } | ||
| 262 | else | ||
| 263 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
| 264 | } while (IDRETRY == er); | ||
| 265 | |||
| 266 | // find any existing entry | ||
| 267 | hr = CpiFindUserCollectionObject(piUsrInRoleColl, pSid, NULL); | ||
| 268 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
| 269 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
| 270 | else | ||
| 271 | ExitOnFailure(hr, "Failed to find user in partition role"); | ||
| 272 | |||
| 273 | if (S_OK == hr) | ||
| 274 | { | ||
| 275 | WcaLog(LOGMSG_VERBOSE, "User already assigned to partition role, key: %S", pAttrs->pwzKey); | ||
| 276 | ExitFunction(); // exit with hr = S_OK | ||
| 277 | } | ||
| 278 | |||
| 279 | // convert SID back to account name | ||
| 280 | hr = CpiSidToAccountName(pSid, &pAttrs->pwzAccount); | ||
| 281 | ExitOnFailure(hr, "Failed to convert SID to account name"); | ||
| 282 | |||
| 283 | // add user | ||
| 284 | hr = CpiAddCollectionObject(piUsrInRoleColl, &piUsrInRoleObj); | ||
| 285 | ExitOnFailure(hr, "Failed to add user in role to collection"); | ||
| 286 | |||
| 287 | hr = CpiPutCollectionObjectValue(piUsrInRoleObj, L"User", pAttrs->pwzAccount); | ||
| 288 | ExitOnFailure(hr, "Failed to set role name property"); | ||
| 289 | |||
| 290 | // save changes | ||
| 291 | hr = piUsrInRoleColl->SaveChanges(&lChanges); | ||
| 292 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 293 | CpiLogCatalogErrorInfo(); | ||
| 294 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 295 | |||
| 296 | // log | ||
| 297 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 298 | |||
| 299 | hr = S_OK; | ||
| 300 | |||
| 301 | LExit: | ||
| 302 | // clean up | ||
| 303 | ReleaseObject(piUsrInRoleColl); | ||
| 304 | ReleaseObject(piUsrInRoleObj); | ||
| 305 | |||
| 306 | if (pSid) | ||
| 307 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
| 308 | |||
| 309 | return hr; | ||
| 310 | } | ||
| 311 | |||
| 312 | static HRESULT RemoveUserInPartitionRole( | ||
| 313 | CPI_USER_IN_PARTITION_ROLE_ATTRIBUTES* pAttrs | ||
| 314 | ) | ||
| 315 | { | ||
| 316 | HRESULT hr = S_OK; | ||
| 317 | UINT er = ERROR_SUCCESS; | ||
| 318 | |||
| 319 | ICatalogCollection* piUsrInRoleColl = NULL; | ||
| 320 | |||
| 321 | PSID pSid = NULL; | ||
| 322 | long lChanges = 0; | ||
| 323 | |||
| 324 | // log | ||
| 325 | WcaLog(LOGMSG_VERBOSE, "Removing user from partition role, key: %S", pAttrs->pwzKey); | ||
| 326 | |||
| 327 | // get users in partition role collection | ||
| 328 | hr = CpiGetUsersInPartitionRoleCollection(pAttrs->pwzPartID, pAttrs->pwzRoleName, &piUsrInRoleColl); | ||
| 329 | ExitOnFailure(hr, "Failed to get users in partition role collection"); | ||
| 330 | |||
| 331 | if (S_FALSE == hr) | ||
| 332 | { | ||
| 333 | // users in role collection not found | ||
| 334 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve users in partition role collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 335 | ExitFunction1(hr = S_OK); | ||
| 336 | } | ||
| 337 | |||
| 338 | // get SID for account | ||
| 339 | do { | ||
| 340 | er = ERROR_SUCCESS; | ||
| 341 | hr = CpiAccountNameToSid(pAttrs->pwzAccount, &pSid); | ||
| 342 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr && !::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
| 343 | { | ||
| 344 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pAttrs->pwzAccount); | ||
| 345 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 346 | switch (er) | ||
| 347 | { | ||
| 348 | case IDABORT: | ||
| 349 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
| 350 | case IDRETRY: | ||
| 351 | break; | ||
| 352 | case IDIGNORE: | ||
| 353 | default: | ||
| 354 | ExitFunction1(hr = S_OK); | ||
| 355 | } | ||
| 356 | } | ||
| 357 | else | ||
| 358 | ExitOnFailure(hr, "Failed to get SID for account"); | ||
| 359 | } while (IDRETRY == er); | ||
| 360 | |||
| 361 | // remove | ||
| 362 | hr = CpiRemoveUserCollectionObject(piUsrInRoleColl, pSid); | ||
| 363 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr || HRESULT_FROM_WIN32(ERROR_SOME_NOT_MAPPED) == hr) | ||
| 364 | { | ||
| 365 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account names, hr: 0x%x", hr); | ||
| 366 | hr = S_FALSE; | ||
| 367 | } | ||
| 368 | else | ||
| 369 | ExitOnFailure(hr, "Failed to remove user"); | ||
| 370 | |||
| 371 | if (S_FALSE == hr) | ||
| 372 | { | ||
| 373 | // role not found | ||
| 374 | WcaLog(LOGMSG_VERBOSE, "User not found for partition role, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 375 | ExitFunction1(hr = S_OK); | ||
| 376 | } | ||
| 377 | |||
| 378 | // save changes | ||
| 379 | hr = piUsrInRoleColl->SaveChanges(&lChanges); | ||
| 380 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 381 | CpiLogCatalogErrorInfo(); | ||
| 382 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 383 | |||
| 384 | // log | ||
| 385 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 386 | |||
| 387 | hr = S_OK; | ||
| 388 | |||
| 389 | LExit: | ||
| 390 | // clean up | ||
| 391 | ReleaseObject(piUsrInRoleColl); | ||
| 392 | |||
| 393 | if (pSid) | ||
| 394 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
| 395 | |||
| 396 | return hr; | ||
| 397 | } | ||
diff --git a/src/ca/cppartroleexec.h b/src/ca/cppartroleexec.h new file mode 100644 index 00000000..0ec47dad --- /dev/null +++ b/src/ca/cppartroleexec.h | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT CpiConfigureUsersInPartitionRoles( | ||
| 6 | LPWSTR* ppwzData, | ||
| 7 | HANDLE hRollbackFile | ||
| 8 | ); | ||
| 9 | HRESULT CpiRollbackConfigureUsersInPartitionRoles( | ||
| 10 | LPWSTR* ppwzData, | ||
| 11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 12 | ); | ||
diff --git a/src/ca/cppartrolesched.cpp b/src/ca/cppartrolesched.cpp new file mode 100644 index 00000000..a988f8e3 --- /dev/null +++ b/src/ca/cppartrolesched.cpp | |||
| @@ -0,0 +1,421 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // sql queries | ||
| 7 | |||
| 8 | LPCWSTR vcsPartitionRoleQuery = | ||
| 9 | L"SELECT `PartitionRole`, `Partition_`, `Component_`, `Name` FROM `ComPlusPartitionRole`"; | ||
| 10 | enum ePartitionRoleQuery { prqPartitionRole = 1, prqPartition, prqComponent, prqName }; | ||
| 11 | |||
| 12 | LPCWSTR vcsUserInPartitionRoleQuery = | ||
| 13 | L"SELECT `UserInPartitionRole`, `PartitionRole_`, `ComPlusUserInPartitionRole`.`Component_`, `Domain`, `Name` FROM `ComPlusUserInPartitionRole`, `User` WHERE `User_` = `User`"; | ||
| 14 | LPCWSTR vcsGroupInPartitionRoleQuery = | ||
| 15 | L"SELECT `GroupInPartitionRole`, `PartitionRole_`, `ComPlusGroupInPartitionRole`.`Component_`, `Domain`, `Name` FROM `ComPlusGroupInPartitionRole`, `Group` WHERE `Group_` = `Group`"; | ||
| 16 | enum eTrusteeInPartitionRoleQuery { tiprqUserInPartitionRole = 1, tiprqPartitionRole, tiprqComponent, tiprqDomain, tiprqName }; | ||
| 17 | |||
| 18 | |||
| 19 | // prototypes for private helper functions | ||
| 20 | |||
| 21 | static HRESULT TrusteesInPartitionRolesRead( | ||
| 22 | LPCWSTR pwzQuery, | ||
| 23 | CPI_PARTITION_ROLE_LIST* pPartRoleList, | ||
| 24 | CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList | ||
| 25 | ); | ||
| 26 | static void FreePartitionRole( | ||
| 27 | CPI_PARTITION_ROLE* pItm | ||
| 28 | ); | ||
| 29 | static void FreeUserInPartitionRole( | ||
| 30 | CPI_USER_IN_PARTITION_ROLE* pItm | ||
| 31 | ); | ||
| 32 | static HRESULT AddUserInPartitionRoleToActionData( | ||
| 33 | CPI_USER_IN_PARTITION_ROLE* pItm, | ||
| 34 | int iActionType, | ||
| 35 | int iActionCost, | ||
| 36 | LPWSTR* ppwzActionData | ||
| 37 | ); | ||
| 38 | |||
| 39 | |||
| 40 | // function definitions | ||
| 41 | |||
| 42 | void CpiPartitionRoleListFree( | ||
| 43 | CPI_PARTITION_ROLE_LIST* pList | ||
| 44 | ) | ||
| 45 | { | ||
| 46 | CPI_PARTITION_ROLE* pItm = pList->pFirst; | ||
| 47 | |||
| 48 | while (pItm) | ||
| 49 | { | ||
| 50 | CPI_PARTITION_ROLE* pDelete = pItm; | ||
| 51 | pItm = pItm->pNext; | ||
| 52 | FreePartitionRole(pDelete); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | HRESULT CpiPartitionRolesRead( | ||
| 57 | CPI_PARTITION_LIST* pPartList, | ||
| 58 | CPI_PARTITION_ROLE_LIST* pPartRoleList | ||
| 59 | ) | ||
| 60 | { | ||
| 61 | HRESULT hr = S_OK; | ||
| 62 | PMSIHANDLE hView, hRec; | ||
| 63 | CPI_PARTITION_ROLE* pItm = NULL; | ||
| 64 | LPWSTR pwzData = NULL; | ||
| 65 | |||
| 66 | // loop through all application roles | ||
| 67 | hr = WcaOpenExecuteView(vcsPartitionRoleQuery, &hView); | ||
| 68 | ExitOnFailure(hr, "Failed to execute view on ComPlusPartitionRole table"); | ||
| 69 | |||
| 70 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 71 | { | ||
| 72 | // create entry | ||
| 73 | pItm = (CPI_PARTITION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION_ROLE)); | ||
| 74 | if (!pItm) | ||
| 75 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 76 | |||
| 77 | // get key | ||
| 78 | hr = WcaGetRecordString(hRec, prqPartitionRole, &pwzData); | ||
| 79 | ExitOnFailure(hr, "Failed to get key"); | ||
| 80 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 81 | |||
| 82 | // get partition | ||
| 83 | hr = WcaGetRecordString(hRec, prqPartition, &pwzData); | ||
| 84 | ExitOnFailure(hr, "Failed to get application"); | ||
| 85 | |||
| 86 | hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition); | ||
| 87 | if (S_FALSE == hr) | ||
| 88 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 89 | ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData); | ||
| 90 | |||
| 91 | // get name | ||
| 92 | hr = WcaGetRecordFormattedString(hRec, prqName, &pwzData); | ||
| 93 | ExitOnFailure(hr, "Failed to get name"); | ||
| 94 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
| 95 | |||
| 96 | // add entry | ||
| 97 | if (pPartRoleList->pFirst) | ||
| 98 | pItm->pNext = pPartRoleList->pFirst; | ||
| 99 | pPartRoleList->pFirst = pItm; | ||
| 100 | pItm = NULL; | ||
| 101 | } | ||
| 102 | |||
| 103 | if (E_NOMOREITEMS == hr) | ||
| 104 | hr = S_OK; | ||
| 105 | |||
| 106 | LExit: | ||
| 107 | // clean up | ||
| 108 | if (pItm) | ||
| 109 | FreePartitionRole(pItm); | ||
| 110 | |||
| 111 | ReleaseStr(pwzData); | ||
| 112 | |||
| 113 | return hr; | ||
| 114 | } | ||
| 115 | |||
| 116 | HRESULT CpiPartitionRoleFindByKey( | ||
| 117 | CPI_PARTITION_ROLE_LIST* pList, | ||
| 118 | LPCWSTR pwzKey, | ||
| 119 | CPI_PARTITION_ROLE** ppPartRole | ||
| 120 | ) | ||
| 121 | { | ||
| 122 | for (CPI_PARTITION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 123 | { | ||
| 124 | if (0 == lstrcmpW(pItm->wzKey, pwzKey)) | ||
| 125 | { | ||
| 126 | *ppPartRole = pItm; | ||
| 127 | return S_OK; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | return E_FAIL; | ||
| 132 | } | ||
| 133 | |||
| 134 | void CpiUserInPartitionRoleListFree( | ||
| 135 | CPI_USER_IN_PARTITION_ROLE_LIST* pList | ||
| 136 | ) | ||
| 137 | { | ||
| 138 | CPI_USER_IN_PARTITION_ROLE* pItm = pList->pFirst; | ||
| 139 | |||
| 140 | while (pItm) | ||
| 141 | { | ||
| 142 | CPI_USER_IN_PARTITION_ROLE* pDelete = pItm; | ||
| 143 | pItm = pItm->pNext; | ||
| 144 | FreeUserInPartitionRole(pDelete); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | HRESULT CpiUsersInPartitionRolesRead( | ||
| 149 | CPI_PARTITION_ROLE_LIST* pPartRoleList, | ||
| 150 | CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList | ||
| 151 | ) | ||
| 152 | { | ||
| 153 | HRESULT hr = S_OK; | ||
| 154 | |||
| 155 | // read users in partition roles | ||
| 156 | if (CpiTableExists(cptComPlusUserInPartitionRole)) | ||
| 157 | { | ||
| 158 | hr = TrusteesInPartitionRolesRead(vcsUserInPartitionRoleQuery, pPartRoleList, pUsrInPartRoleList); | ||
| 159 | ExitOnFailure(hr, "Failed to read users in partition roles"); | ||
| 160 | } | ||
| 161 | |||
| 162 | // read groups in partition roles | ||
| 163 | if (CpiTableExists(cptComPlusGroupInPartitionRole)) | ||
| 164 | { | ||
| 165 | hr = TrusteesInPartitionRolesRead(vcsGroupInPartitionRoleQuery, pPartRoleList, pUsrInPartRoleList); | ||
| 166 | ExitOnFailure(hr, "Failed to read groups in partition roles"); | ||
| 167 | } | ||
| 168 | |||
| 169 | hr = S_OK; | ||
| 170 | |||
| 171 | LExit: | ||
| 172 | return hr; | ||
| 173 | } | ||
| 174 | |||
| 175 | HRESULT CpiUsersInPartitionRolesInstall( | ||
| 176 | CPI_USER_IN_PARTITION_ROLE_LIST* pList, | ||
| 177 | int iRunMode, | ||
| 178 | LPWSTR* ppwzActionData, | ||
| 179 | int* piProgress | ||
| 180 | ) | ||
| 181 | { | ||
| 182 | HRESULT hr = S_OK; | ||
| 183 | |||
| 184 | int iActionType; | ||
| 185 | |||
| 186 | // add action text | ||
| 187 | hr = CpiAddActionTextToActionData(L"AddUsersToComPlusPartitionRoles", ppwzActionData); | ||
| 188 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 189 | |||
| 190 | // add count to action data | ||
| 191 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
| 192 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 193 | |||
| 194 | // add roles to custom action data | ||
| 195 | for (CPI_USER_IN_PARTITION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 196 | { | ||
| 197 | // roles that are being installed only | ||
| 198 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 199 | continue; | ||
| 200 | |||
| 201 | // action type | ||
| 202 | if (rmRollback == iRunMode) | ||
| 203 | { | ||
| 204 | if (CpiIsInstalled(pItm->isInstalled)) | ||
| 205 | iActionType = atNoOp; | ||
| 206 | else | ||
| 207 | iActionType = atRemove; | ||
| 208 | } | ||
| 209 | else | ||
| 210 | iActionType = atCreate; | ||
| 211 | |||
| 212 | // add to action data | ||
| 213 | hr = AddUserInPartitionRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_CREATE, ppwzActionData); | ||
| 214 | ExitOnFailure(hr, "Failed to add user in partition role to custom action data, key: %S", pItm->wzKey); | ||
| 215 | } | ||
| 216 | |||
| 217 | // add progress tics | ||
| 218 | if (piProgress) | ||
| 219 | *piProgress += COST_USER_IN_APPLICATION_ROLE_CREATE * pList->iInstallCount; | ||
| 220 | |||
| 221 | hr = S_OK; | ||
| 222 | |||
| 223 | LExit: | ||
| 224 | return hr; | ||
| 225 | } | ||
| 226 | |||
| 227 | HRESULT CpiUsersInPartitionRolesUninstall( | ||
| 228 | CPI_USER_IN_PARTITION_ROLE_LIST* pList, | ||
| 229 | int iRunMode, | ||
| 230 | LPWSTR* ppwzActionData, | ||
| 231 | int* piProgress | ||
| 232 | ) | ||
| 233 | { | ||
| 234 | HRESULT hr = S_OK; | ||
| 235 | |||
| 236 | int iActionType; | ||
| 237 | |||
| 238 | // add action text | ||
| 239 | hr = CpiAddActionTextToActionData(L"RemoveUsersFromComPlusPartRoles", ppwzActionData); | ||
| 240 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 241 | |||
| 242 | // add count to action data | ||
| 243 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
| 244 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 245 | |||
| 246 | // add roles to custom action data | ||
| 247 | for (CPI_USER_IN_PARTITION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 248 | { | ||
| 249 | // roles that are being uninstalled only | ||
| 250 | if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 251 | continue; | ||
| 252 | |||
| 253 | // action type | ||
| 254 | if (rmRollback == iRunMode) | ||
| 255 | iActionType = atCreate; | ||
| 256 | else | ||
| 257 | iActionType = atRemove; | ||
| 258 | |||
| 259 | // add to action data | ||
| 260 | hr = AddUserInPartitionRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_DELETE, ppwzActionData); | ||
| 261 | ExitOnFailure(hr, "Failed to add user in partition role to custom action data, key: %S", pItm->wzKey); | ||
| 262 | } | ||
| 263 | |||
| 264 | // add progress tics | ||
| 265 | if (piProgress) | ||
| 266 | *piProgress += COST_USER_IN_APPLICATION_ROLE_DELETE * pList->iUninstallCount; | ||
| 267 | |||
| 268 | hr = S_OK; | ||
| 269 | |||
| 270 | LExit: | ||
| 271 | return hr; | ||
| 272 | } | ||
| 273 | |||
| 274 | |||
| 275 | // helper function definitions | ||
| 276 | |||
| 277 | static HRESULT TrusteesInPartitionRolesRead( | ||
| 278 | LPCWSTR pwzQuery, | ||
| 279 | CPI_PARTITION_ROLE_LIST* pPartRoleList, | ||
| 280 | CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList | ||
| 281 | ) | ||
| 282 | { | ||
| 283 | HRESULT hr = S_OK; | ||
| 284 | UINT er = ERROR_SUCCESS; | ||
| 285 | |||
| 286 | PMSIHANDLE hView, hRec; | ||
| 287 | |||
| 288 | CPI_USER_IN_PARTITION_ROLE* pItm = NULL; | ||
| 289 | LPWSTR pwzData = NULL; | ||
| 290 | LPWSTR pwzDomain = NULL; | ||
| 291 | LPWSTR pwzName = NULL; | ||
| 292 | BOOL fMatchingArchitecture = FALSE; | ||
| 293 | |||
| 294 | // loop through all application roles | ||
| 295 | hr = WcaOpenExecuteView(pwzQuery, &hView); | ||
| 296 | ExitOnFailure(hr, "Failed to execute view on table"); | ||
| 297 | |||
| 298 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 299 | { | ||
| 300 | // get component | ||
| 301 | hr = WcaGetRecordString(hRec, tiprqComponent, &pwzData); | ||
| 302 | ExitOnFailure(hr, "Failed to get component"); | ||
| 303 | |||
| 304 | // check if the component is our processor architecture | ||
| 305 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
| 306 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
| 307 | |||
| 308 | if (!fMatchingArchitecture) | ||
| 309 | { | ||
| 310 | continue; // not the same architecture, ignore | ||
| 311 | } | ||
| 312 | |||
| 313 | // create entry | ||
| 314 | pItm = (CPI_USER_IN_PARTITION_ROLE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_USER_IN_PARTITION_ROLE)); | ||
| 315 | if (!pItm) | ||
| 316 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 317 | |||
| 318 | // get component install state | ||
| 319 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
| 320 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
| 321 | |||
| 322 | // get key | ||
| 323 | hr = WcaGetRecordString(hRec, tiprqUserInPartitionRole, &pwzData); | ||
| 324 | ExitOnFailure(hr, "Failed to get key"); | ||
| 325 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 326 | |||
| 327 | // get partition role | ||
| 328 | hr = WcaGetRecordString(hRec, tiprqPartitionRole, &pwzData); | ||
| 329 | ExitOnFailure(hr, "Failed to get partition role"); | ||
| 330 | |||
| 331 | hr = CpiPartitionRoleFindByKey(pPartRoleList, pwzData, &pItm->pPartitionRole); | ||
| 332 | ExitOnFailure(hr, "Failed to find partition role, key: %S", pwzData); | ||
| 333 | |||
| 334 | // get user domain | ||
| 335 | hr = WcaGetRecordFormattedString(hRec, tiprqDomain, &pwzDomain); | ||
| 336 | ExitOnFailure(hr, "Failed to get domain"); | ||
| 337 | |||
| 338 | // get user name | ||
| 339 | hr = WcaGetRecordFormattedString(hRec, tiprqName, &pwzName); | ||
| 340 | ExitOnFailure(hr, "Failed to get name"); | ||
| 341 | |||
| 342 | // build account name | ||
| 343 | hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount); | ||
| 344 | ExitOnFailure(hr, "Failed to build account name"); | ||
| 345 | |||
| 346 | // increment counters | ||
| 347 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 348 | pUsrInPartRoleList->iInstallCount++; | ||
| 349 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 350 | pUsrInPartRoleList->iUninstallCount++; | ||
| 351 | |||
| 352 | // add entry | ||
| 353 | if (pUsrInPartRoleList->pFirst) | ||
| 354 | pItm->pNext = pUsrInPartRoleList->pFirst; | ||
| 355 | pUsrInPartRoleList->pFirst = pItm; | ||
| 356 | pItm = NULL; | ||
| 357 | } | ||
| 358 | |||
| 359 | if (E_NOMOREITEMS == hr) | ||
| 360 | hr = S_OK; | ||
| 361 | |||
| 362 | LExit: | ||
| 363 | // clean up | ||
| 364 | if (pItm) | ||
| 365 | FreeUserInPartitionRole(pItm); | ||
| 366 | |||
| 367 | ReleaseStr(pwzData); | ||
| 368 | ReleaseStr(pwzDomain); | ||
| 369 | ReleaseStr(pwzName); | ||
| 370 | |||
| 371 | return hr; | ||
| 372 | } | ||
| 373 | |||
| 374 | static void FreePartitionRole( | ||
| 375 | CPI_PARTITION_ROLE* pItm | ||
| 376 | ) | ||
| 377 | { | ||
| 378 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
| 379 | } | ||
| 380 | |||
| 381 | static void FreeUserInPartitionRole( | ||
| 382 | CPI_USER_IN_PARTITION_ROLE* pItm | ||
| 383 | ) | ||
| 384 | { | ||
| 385 | ReleaseStr(pItm->pwzAccount); | ||
| 386 | |||
| 387 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
| 388 | } | ||
| 389 | |||
| 390 | static HRESULT AddUserInPartitionRoleToActionData( | ||
| 391 | CPI_USER_IN_PARTITION_ROLE* pItm, | ||
| 392 | int iActionType, | ||
| 393 | int iActionCost, | ||
| 394 | LPWSTR* ppwzActionData | ||
| 395 | ) | ||
| 396 | { | ||
| 397 | HRESULT hr = S_OK; | ||
| 398 | |||
| 399 | // add action information to custom action data | ||
| 400 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
| 401 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
| 402 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
| 403 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
| 404 | |||
| 405 | // add application role information to custom action data | ||
| 406 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
| 407 | ExitOnFailure(hr, "Failed to add key to custom action data"); | ||
| 408 | hr = WcaWriteStringToCaData(pItm->pPartitionRole->wzName, ppwzActionData); | ||
| 409 | ExitOnFailure(hr, "Failed to add role name to custom action data"); | ||
| 410 | hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData); | ||
| 411 | ExitOnFailure(hr, "Failed to add user account to custom action data"); | ||
| 412 | |||
| 413 | // add partition information to custom action data | ||
| 414 | hr = WcaWriteStringToCaData(pItm->pPartitionRole->pPartition->wzID, ppwzActionData); | ||
| 415 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
| 416 | |||
| 417 | hr = S_OK; | ||
| 418 | |||
| 419 | LExit: | ||
| 420 | return hr; | ||
| 421 | } | ||
diff --git a/src/ca/cppartrolesched.h b/src/ca/cppartrolesched.h new file mode 100644 index 00000000..ff1275d9 --- /dev/null +++ b/src/ca/cppartrolesched.h | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | struct CPI_PARTITION_ROLE | ||
| 6 | { | ||
| 7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 8 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 9 | |||
| 10 | CPI_PARTITION* pPartition; | ||
| 11 | |||
| 12 | ICatalogCollection* piUsersColl; | ||
| 13 | |||
| 14 | CPI_PARTITION_ROLE* pNext; | ||
| 15 | }; | ||
| 16 | |||
| 17 | struct CPI_PARTITION_ROLE_LIST | ||
| 18 | { | ||
| 19 | CPI_PARTITION_ROLE* pFirst; | ||
| 20 | }; | ||
| 21 | |||
| 22 | struct CPI_USER_IN_PARTITION_ROLE | ||
| 23 | { | ||
| 24 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 25 | LPWSTR pwzAccount; | ||
| 26 | |||
| 27 | INSTALLSTATE isInstalled, isAction; | ||
| 28 | |||
| 29 | CPI_PARTITION_ROLE* pPartitionRole; | ||
| 30 | |||
| 31 | CPI_USER_IN_PARTITION_ROLE* pNext; | ||
| 32 | }; | ||
| 33 | |||
| 34 | struct CPI_USER_IN_PARTITION_ROLE_LIST | ||
| 35 | { | ||
| 36 | CPI_USER_IN_PARTITION_ROLE* pFirst; | ||
| 37 | |||
| 38 | int iInstallCount; | ||
| 39 | int iUninstallCount; | ||
| 40 | }; | ||
| 41 | |||
| 42 | |||
| 43 | // function prototypes | ||
| 44 | |||
| 45 | void CpiPartitionRoleListFree( | ||
| 46 | CPI_PARTITION_ROLE_LIST* pList | ||
| 47 | ); | ||
| 48 | HRESULT CpiPartitionRolesRead( | ||
| 49 | CPI_PARTITION_LIST* pPartList, | ||
| 50 | CPI_PARTITION_ROLE_LIST* pPartRoleList | ||
| 51 | ); | ||
| 52 | HRESULT CpiPartitionRoleFindByKey( | ||
| 53 | CPI_PARTITION_ROLE_LIST* pList, | ||
| 54 | LPCWSTR pwzKey, | ||
| 55 | CPI_PARTITION_ROLE** ppPartRole | ||
| 56 | ); | ||
| 57 | |||
| 58 | void CpiUserInPartitionRoleListFree( | ||
| 59 | CPI_USER_IN_PARTITION_ROLE_LIST* pList | ||
| 60 | ); | ||
| 61 | HRESULT CpiUsersInPartitionRolesRead( | ||
| 62 | CPI_PARTITION_ROLE_LIST* pPartRoleList, | ||
| 63 | CPI_USER_IN_PARTITION_ROLE_LIST* pUsrInPartRoleList | ||
| 64 | ); | ||
| 65 | HRESULT CpiUsersInPartitionRolesInstall( | ||
| 66 | CPI_USER_IN_PARTITION_ROLE_LIST* pList, | ||
| 67 | int iRunMode, | ||
| 68 | LPWSTR* ppwzActionData, | ||
| 69 | int* piProgress | ||
| 70 | ); | ||
| 71 | HRESULT CpiUsersInPartitionRolesUninstall( | ||
| 72 | CPI_USER_IN_PARTITION_ROLE_LIST* pList, | ||
| 73 | int iRunMode, | ||
| 74 | LPWSTR* ppwzActionData, | ||
| 75 | int* piProgress | ||
| 76 | ); | ||
diff --git a/src/ca/cppartsched.cpp b/src/ca/cppartsched.cpp new file mode 100644 index 00000000..6643a50b --- /dev/null +++ b/src/ca/cppartsched.cpp | |||
| @@ -0,0 +1,912 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // sql queries | ||
| 7 | |||
| 8 | LPCWSTR vcsPartitionQuery = | ||
| 9 | L"SELECT `Partition`, `Component_`, `Id`, `Name` FROM `ComPlusPartition`"; | ||
| 10 | enum ePartitionQuery { pqPartition = 1, pqComponent, pqID, pqName }; | ||
| 11 | |||
| 12 | LPCWSTR vcsPartitionPropertyQuery = | ||
| 13 | L"SELECT `Name`, `Value` FROM `ComPlusPartitionProperty` WHERE `Partition_` = ?"; | ||
| 14 | |||
| 15 | LPCWSTR vcsPartitionUserQuery = | ||
| 16 | L"SELECT `PartitionUser`, `Partition_`, `ComPlusPartitionUser`.`Component_`, `Domain`, `Name` FROM `ComPlusPartitionUser`, `User` WHERE `User_` = `User`"; | ||
| 17 | enum ePartitionUserQuery { puqPartitionUser = 1, puqPartition, puqComponent, puqDomain, puqName }; | ||
| 18 | |||
| 19 | |||
| 20 | // property definitions | ||
| 21 | |||
| 22 | CPI_PROPERTY_DEFINITION pdlPartitionProperties[] = | ||
| 23 | { | ||
| 24 | {L"Changeable", cpptBoolean, 502}, | ||
| 25 | {L"Deleteable", cpptBoolean, 502}, | ||
| 26 | {L"Description", cpptString, 502}, | ||
| 27 | {NULL, cpptNone, 0} | ||
| 28 | }; | ||
| 29 | |||
| 30 | |||
| 31 | // prototypes for private helper functions | ||
| 32 | |||
| 33 | static void FreePartition( | ||
| 34 | CPI_PARTITION* pItm | ||
| 35 | ); | ||
| 36 | static void FreePartitionUser( | ||
| 37 | CPI_PARTITION_USER* pItm | ||
| 38 | ); | ||
| 39 | static HRESULT AddPartitionToActionData( | ||
| 40 | CPI_PARTITION* pItm, | ||
| 41 | int iActionType, | ||
| 42 | int iActionCost, | ||
| 43 | LPWSTR* ppwzActionData | ||
| 44 | ); | ||
| 45 | static HRESULT AddPartitionUserToActionData( | ||
| 46 | CPI_PARTITION_USER* pItm, | ||
| 47 | int iActionType, | ||
| 48 | int iActionCost, | ||
| 49 | LPWSTR* ppwzActionData | ||
| 50 | ); | ||
| 51 | |||
| 52 | |||
| 53 | // function definitions | ||
| 54 | |||
| 55 | void CpiPartitionListFree( | ||
| 56 | CPI_PARTITION_LIST* pList | ||
| 57 | ) | ||
| 58 | { | ||
| 59 | CPI_PARTITION* pItm = pList->pFirst; | ||
| 60 | |||
| 61 | while (pItm) | ||
| 62 | { | ||
| 63 | CPI_PARTITION* pDelete = pItm; | ||
| 64 | pItm = pItm->pNext; | ||
| 65 | FreePartition(pDelete); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | HRESULT CpiPartitionsRead( | ||
| 70 | CPI_PARTITION_LIST* pPartList | ||
| 71 | ) | ||
| 72 | { | ||
| 73 | HRESULT hr = S_OK; | ||
| 74 | UINT er = ERROR_SUCCESS; | ||
| 75 | |||
| 76 | PMSIHANDLE hView, hRec; | ||
| 77 | |||
| 78 | CPI_PARTITION* pItm = NULL; | ||
| 79 | LPWSTR pwzData = NULL; | ||
| 80 | BOOL fMatchingArchitecture = FALSE; | ||
| 81 | |||
| 82 | // loop through all partitions | ||
| 83 | hr = WcaOpenExecuteView(vcsPartitionQuery, &hView); | ||
| 84 | ExitOnFailure(hr, "Failed to execute view on ComPlusPartition table"); | ||
| 85 | |||
| 86 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 87 | { | ||
| 88 | // get component | ||
| 89 | hr = WcaGetRecordString(hRec, pqComponent, &pwzData); | ||
| 90 | ExitOnFailure(hr, "Failed to get component"); | ||
| 91 | |||
| 92 | // check if the component is our processor architecture | ||
| 93 | if (pwzData && *pwzData) | ||
| 94 | { | ||
| 95 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
| 96 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
| 97 | |||
| 98 | if (!fMatchingArchitecture) | ||
| 99 | { | ||
| 100 | continue; // not the same architecture, ignore | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | // create entry | ||
| 105 | pItm = (CPI_PARTITION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION)); | ||
| 106 | if (!pItm) | ||
| 107 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 108 | |||
| 109 | // get component install state | ||
| 110 | if (pwzData && *pwzData) | ||
| 111 | { | ||
| 112 | pItm->fHasComponent = TRUE; | ||
| 113 | |||
| 114 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
| 115 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
| 116 | } | ||
| 117 | |||
| 118 | // get key | ||
| 119 | hr = WcaGetRecordString(hRec, pqPartition, &pwzData); | ||
| 120 | ExitOnFailure(hr, "Failed to get key"); | ||
| 121 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 122 | |||
| 123 | // get id | ||
| 124 | hr = WcaGetRecordFormattedString(hRec, pqID, &pwzData); | ||
| 125 | ExitOnFailure(hr, "Failed to get id"); | ||
| 126 | |||
| 127 | if (pwzData && *pwzData) | ||
| 128 | { | ||
| 129 | hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID)); | ||
| 130 | ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData); | ||
| 131 | } | ||
| 132 | |||
| 133 | // get name | ||
| 134 | hr = WcaGetRecordFormattedString(hRec, pqName, &pwzData); | ||
| 135 | ExitOnFailure(hr, "Failed to get name"); | ||
| 136 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
| 137 | |||
| 138 | // if partition is a locater, either an id or a name must be provided | ||
| 139 | if (!pItm->fHasComponent && !*pItm->wzID && !*pItm->wzName) | ||
| 140 | ExitOnFailure(hr = E_FAIL, "A partition locater must have either an id or a name associated, key: %S", pItm->wzKey); | ||
| 141 | |||
| 142 | // if partition is not a locater, an name must be provided | ||
| 143 | if (pItm->fHasComponent && !*pItm->wzName) | ||
| 144 | ExitOnFailure(hr = E_FAIL, "A partition must have a name associated, key: %S", pItm->wzKey); | ||
| 145 | |||
| 146 | // get properties | ||
| 147 | if (CpiTableExists(cptComPlusPartitionProperty) && pItm->fHasComponent) | ||
| 148 | { | ||
| 149 | hr = CpiPropertiesRead(vcsPartitionPropertyQuery, pItm->wzKey, pdlPartitionProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
| 150 | ExitOnFailure(hr, "Failed to get properties"); | ||
| 151 | } | ||
| 152 | |||
| 153 | // increment counters | ||
| 154 | if (pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 155 | pPartList->iInstallCount++; | ||
| 156 | if (pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 157 | pPartList->iUninstallCount++; | ||
| 158 | |||
| 159 | // add entry | ||
| 160 | if (pPartList->pFirst) | ||
| 161 | pItm->pNext = pPartList->pFirst; | ||
| 162 | pPartList->pFirst = pItm; | ||
| 163 | pItm = NULL; | ||
| 164 | } | ||
| 165 | |||
| 166 | if (E_NOMOREITEMS == hr) | ||
| 167 | hr = S_OK; | ||
| 168 | |||
| 169 | LExit: | ||
| 170 | // clean up | ||
| 171 | if (pItm) | ||
| 172 | FreePartition(pItm); | ||
| 173 | |||
| 174 | ReleaseStr(pwzData); | ||
| 175 | |||
| 176 | return hr; | ||
| 177 | } | ||
| 178 | |||
| 179 | HRESULT CpiPartitionsVerifyInstall( | ||
| 180 | CPI_PARTITION_LIST* pList | ||
| 181 | ) | ||
| 182 | { | ||
| 183 | HRESULT hr = S_OK; | ||
| 184 | UINT er = ERROR_SUCCESS; | ||
| 185 | |||
| 186 | ICatalogCollection* piPartColl = NULL; | ||
| 187 | ICatalogObject* piPartObj = NULL; | ||
| 188 | |||
| 189 | for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 190 | { | ||
| 191 | // referenced locaters or partitions that are being installed | ||
| 192 | if (!pItm->fReferencedForInstall && !(pItm->fHasComponent && WcaIsInstalling(pItm->isInstalled, pItm->isAction))) | ||
| 193 | continue; | ||
| 194 | |||
| 195 | // if the partition is referensed and is not a locater, it must be installed | ||
| 196 | if (pItm->fReferencedForInstall && pItm->fHasComponent && !CpiWillBeInstalled(pItm->isInstalled, pItm->isAction)) | ||
| 197 | MessageExitOnFailure(hr = E_FAIL, msierrComPlusPartitionDependency, "A partition is used by another entity being installed, but is not installed itself, key: %S", pItm->wzKey); | ||
| 198 | |||
| 199 | // get partitions collection | ||
| 200 | if (!piPartColl) | ||
| 201 | { | ||
| 202 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
| 203 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
| 204 | } | ||
| 205 | |||
| 206 | // partition is supposed to exist | ||
| 207 | if (!pItm->fHasComponent || CpiIsInstalled(pItm->isInstalled)) | ||
| 208 | { | ||
| 209 | // get collection object for partition | ||
| 210 | hr = CpiFindCollectionObject(piPartColl, pItm->wzID, *pItm->wzID ? NULL : pItm->wzName, &piPartObj); | ||
| 211 | ExitOnFailure(hr, "Failed to find collection object for partition"); | ||
| 212 | |||
| 213 | // if the partition was found | ||
| 214 | if (S_OK == hr) | ||
| 215 | { | ||
| 216 | // if we don't have an id, copy id from object | ||
| 217 | if (!*pItm->wzID) | ||
| 218 | { | ||
| 219 | hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID)); | ||
| 220 | ExitOnFailure(hr, "Failed to get id"); | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | // if the partition was not found | ||
| 225 | else | ||
| 226 | { | ||
| 227 | // if the application is a locater, this is an error | ||
| 228 | if (!pItm->fHasComponent) | ||
| 229 | MessageExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), msierrComPlusPartitionNotFound, "A partition required by this installation was not found, key: %S", pItm->wzKey); | ||
| 230 | |||
| 231 | // create a new id if one is missing | ||
| 232 | if (!*pItm->wzID) | ||
| 233 | { | ||
| 234 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
| 235 | ExitOnFailure(hr, "Failed to create id"); | ||
| 236 | } | ||
| 237 | } | ||
| 238 | } | ||
| 239 | |||
| 240 | // partition is supposed to be created | ||
| 241 | else | ||
| 242 | { | ||
| 243 | // check for conflicts | ||
| 244 | do { | ||
| 245 | if (*pItm->wzID) | ||
| 246 | { | ||
| 247 | // find partitions with conflicting id | ||
| 248 | hr = CpiFindCollectionObject(piPartColl, pItm->wzID, NULL, &piPartObj); | ||
| 249 | ExitOnFailure(hr, "Failed to find collection object for partition"); | ||
| 250 | |||
| 251 | if (S_FALSE == hr) | ||
| 252 | { | ||
| 253 | // find partitions with conflicting name | ||
| 254 | hr = CpiFindCollectionObject(piPartColl, NULL, pItm->wzName, &piPartObj); | ||
| 255 | ExitOnFailure(hr, "Failed to find collection object for partition"); | ||
| 256 | |||
| 257 | if (S_OK == hr) | ||
| 258 | // "A partition with a conflictiong name exists. retry cancel" | ||
| 259 | er = WcaErrorMessage(msierrComPlusPartitionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0); | ||
| 260 | else | ||
| 261 | break; // no conflicting entry found, break loop | ||
| 262 | } | ||
| 263 | else | ||
| 264 | // "A partition with a conflicting id exists. abort retry ignore" | ||
| 265 | er = WcaErrorMessage(msierrComPlusPartitionIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 266 | } | ||
| 267 | else | ||
| 268 | { | ||
| 269 | // find partitions with conflicting name | ||
| 270 | hr = CpiFindCollectionObject(piPartColl, NULL, pItm->wzName, &piPartObj); | ||
| 271 | ExitOnFailure(hr, "Failed to find collection object for partition"); | ||
| 272 | |||
| 273 | if (S_OK == hr) | ||
| 274 | // "A partition with a conflictiong name exists. abort retry ignore" | ||
| 275 | er = WcaErrorMessage(msierrComPlusPartitionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 276 | else | ||
| 277 | break; // no conflicting entry found, break loop | ||
| 278 | } | ||
| 279 | |||
| 280 | switch (er) | ||
| 281 | { | ||
| 282 | case IDCANCEL: | ||
| 283 | case IDABORT: | ||
| 284 | ExitOnFailure(hr = E_FAIL, "A partition with a conflictiong name or id exists, key: %S", pItm->wzKey); | ||
| 285 | break; | ||
| 286 | case IDRETRY: | ||
| 287 | break; | ||
| 288 | case IDIGNORE: | ||
| 289 | default: | ||
| 290 | // if we don't have an id, copy id from object | ||
| 291 | if (!*pItm->wzID) | ||
| 292 | { | ||
| 293 | hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID)); | ||
| 294 | ExitOnFailure(hr, "Failed to get id"); | ||
| 295 | } | ||
| 296 | hr = S_FALSE; // indicate that this is not a conflict | ||
| 297 | } | ||
| 298 | } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts | ||
| 299 | |||
| 300 | // create a new id if one is missing | ||
| 301 | if (!*pItm->wzID) | ||
| 302 | { | ||
| 303 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
| 304 | ExitOnFailure(hr, "Failed to create id"); | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | // clean up | ||
| 309 | ReleaseNullObject(piPartObj); | ||
| 310 | } | ||
| 311 | |||
| 312 | hr = S_OK; | ||
| 313 | |||
| 314 | LExit: | ||
| 315 | // clean up | ||
| 316 | ReleaseObject(piPartColl); | ||
| 317 | ReleaseObject(piPartObj); | ||
| 318 | |||
| 319 | return hr; | ||
| 320 | } | ||
| 321 | |||
| 322 | HRESULT CpiPartitionsVerifyUninstall( | ||
| 323 | CPI_PARTITION_LIST* pList | ||
| 324 | ) | ||
| 325 | { | ||
| 326 | HRESULT hr = S_OK; | ||
| 327 | ICatalogCollection* piPartColl = NULL; | ||
| 328 | ICatalogObject* piPartObj = NULL; | ||
| 329 | |||
| 330 | for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 331 | { | ||
| 332 | // referenced locaters or partitions that are being uninstalled | ||
| 333 | if (!pItm->fReferencedForUninstall && !(pItm->fHasComponent && WcaIsUninstalling(pItm->isInstalled, pItm->isAction))) | ||
| 334 | continue; | ||
| 335 | |||
| 336 | // get partitions collection | ||
| 337 | if (!piPartColl) | ||
| 338 | { | ||
| 339 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
| 340 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
| 341 | } | ||
| 342 | |||
| 343 | // get collection object for partition | ||
| 344 | hr = CpiFindCollectionObject(piPartColl, pItm->wzID, *pItm->wzID ? NULL : pItm->wzName, &piPartObj); | ||
| 345 | ExitOnFailure(hr, "Failed to find collection object for partition"); | ||
| 346 | |||
| 347 | // if the partition was found | ||
| 348 | if (S_OK == hr) | ||
| 349 | { | ||
| 350 | // if we don't have an id, copy id from object | ||
| 351 | if (!*pItm->wzID) | ||
| 352 | { | ||
| 353 | hr = CpiGetKeyForObject(piPartObj, pItm->wzID, countof(pItm->wzID)); | ||
| 354 | ExitOnFailure(hr, "Failed to get id"); | ||
| 355 | } | ||
| 356 | } | ||
| 357 | |||
| 358 | // if the partition was not found | ||
| 359 | else | ||
| 360 | { | ||
| 361 | pItm->fObjectNotFound = TRUE; | ||
| 362 | if (pItm->fHasComponent) | ||
| 363 | pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall | ||
| 364 | } | ||
| 365 | |||
| 366 | // clean up | ||
| 367 | ReleaseNullObject(piPartObj); | ||
| 368 | } | ||
| 369 | |||
| 370 | hr = S_OK; | ||
| 371 | |||
| 372 | LExit: | ||
| 373 | // clean up | ||
| 374 | ReleaseObject(piPartColl); | ||
| 375 | ReleaseObject(piPartObj); | ||
| 376 | |||
| 377 | return hr; | ||
| 378 | } | ||
| 379 | |||
| 380 | void CpiPartitionAddReferenceInstall( | ||
| 381 | CPI_PARTITION* pItm | ||
| 382 | ) | ||
| 383 | { | ||
| 384 | pItm->fReferencedForInstall = TRUE; | ||
| 385 | } | ||
| 386 | |||
| 387 | void CpiPartitionAddReferenceUninstall( | ||
| 388 | CPI_PARTITION* pItm | ||
| 389 | ) | ||
| 390 | { | ||
| 391 | pItm->fReferencedForUninstall = TRUE; | ||
| 392 | } | ||
| 393 | |||
| 394 | HRESULT CpiPartitionsInstall( | ||
| 395 | CPI_PARTITION_LIST* pList, | ||
| 396 | int iRunMode, | ||
| 397 | LPWSTR* ppwzActionData, | ||
| 398 | int* piProgress | ||
| 399 | ) | ||
| 400 | { | ||
| 401 | HRESULT hr = S_OK; | ||
| 402 | |||
| 403 | int iActionType; | ||
| 404 | |||
| 405 | // add action text | ||
| 406 | hr = CpiAddActionTextToActionData(L"CreateComPlusPartitions", ppwzActionData); | ||
| 407 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 408 | |||
| 409 | // add partition count to action data | ||
| 410 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
| 411 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 412 | |||
| 413 | // add applications to custom action data | ||
| 414 | for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 415 | { | ||
| 416 | // partitions that are being installed only | ||
| 417 | if (!pItm->fHasComponent || !WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 418 | continue; | ||
| 419 | |||
| 420 | // action type | ||
| 421 | if (rmRollback == iRunMode) | ||
| 422 | { | ||
| 423 | if (CpiIsInstalled(pItm->isInstalled)) | ||
| 424 | iActionType = atNoOp; | ||
| 425 | else | ||
| 426 | iActionType = atRemove; | ||
| 427 | } | ||
| 428 | else | ||
| 429 | iActionType = atCreate; | ||
| 430 | |||
| 431 | // add to action data | ||
| 432 | hr = AddPartitionToActionData(pItm, iActionType, COST_PARTITION_CREATE, ppwzActionData); | ||
| 433 | ExitOnFailure(hr, "Failed to add partition to custom action data, key: %S", pItm->wzKey); | ||
| 434 | } | ||
| 435 | |||
| 436 | // add progress tics | ||
| 437 | if (piProgress) | ||
| 438 | *piProgress += COST_PARTITION_CREATE * pList->iInstallCount; | ||
| 439 | |||
| 440 | hr = S_OK; | ||
| 441 | |||
| 442 | LExit: | ||
| 443 | return hr; | ||
| 444 | } | ||
| 445 | |||
| 446 | HRESULT CpiPartitionsUninstall( | ||
| 447 | CPI_PARTITION_LIST* pList, | ||
| 448 | int iRunMode, | ||
| 449 | LPWSTR* ppwzActionData, | ||
| 450 | int* piProgress | ||
| 451 | ) | ||
| 452 | { | ||
| 453 | HRESULT hr = S_OK; | ||
| 454 | |||
| 455 | int iActionType; | ||
| 456 | |||
| 457 | // add action text | ||
| 458 | hr = CpiAddActionTextToActionData(L"RemoveComPlusPartitions", ppwzActionData); | ||
| 459 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 460 | |||
| 461 | // add partition count to action data | ||
| 462 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
| 463 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 464 | |||
| 465 | // add partitions to custom action data | ||
| 466 | for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 467 | { | ||
| 468 | // partitions that are being uninstalled only | ||
| 469 | if (!pItm->fHasComponent || pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 470 | continue; | ||
| 471 | |||
| 472 | // action type | ||
| 473 | if (rmRollback == iRunMode) | ||
| 474 | iActionType = atCreate; | ||
| 475 | else | ||
| 476 | iActionType = atRemove; | ||
| 477 | |||
| 478 | // add to action data | ||
| 479 | hr = AddPartitionToActionData(pItm, iActionType, COST_PARTITION_DELETE, ppwzActionData); | ||
| 480 | ExitOnFailure(hr, "Failed to add partition to custom action data, key:", pItm->wzKey); | ||
| 481 | } | ||
| 482 | |||
| 483 | // add progress tics | ||
| 484 | if (piProgress) | ||
| 485 | *piProgress += COST_PARTITION_DELETE * pList->iUninstallCount; | ||
| 486 | |||
| 487 | hr = S_OK; | ||
| 488 | |||
| 489 | LExit: | ||
| 490 | return hr; | ||
| 491 | } | ||
| 492 | |||
| 493 | HRESULT CpiPartitionFindByKey( | ||
| 494 | CPI_PARTITION_LIST* pList, | ||
| 495 | LPCWSTR wzKey, | ||
| 496 | CPI_PARTITION** ppItm | ||
| 497 | ) | ||
| 498 | { | ||
| 499 | for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 500 | { | ||
| 501 | if (0 == lstrcmpW(pItm->wzKey, wzKey)) | ||
| 502 | { | ||
| 503 | *ppItm = pItm; | ||
| 504 | return S_OK; | ||
| 505 | } | ||
| 506 | } | ||
| 507 | |||
| 508 | return S_FALSE; | ||
| 509 | } | ||
| 510 | |||
| 511 | HRESULT CpiGetApplicationsCollForPartition( | ||
| 512 | CPI_PARTITION* pPart, | ||
| 513 | ICatalogCollection** ppiAppColl | ||
| 514 | ) | ||
| 515 | { | ||
| 516 | HRESULT hr = S_OK; | ||
| 517 | |||
| 518 | ICatalogCollection* piPartColl = NULL; | ||
| 519 | ICatalogObject* piPartObj = NULL; | ||
| 520 | |||
| 521 | // if a previous attempt to locate the collection object failed | ||
| 522 | if (pPart->fObjectNotFound) | ||
| 523 | ExitFunction1(hr = S_FALSE); | ||
| 524 | |||
| 525 | // get applications collection | ||
| 526 | if (!pPart->piApplicationsColl) | ||
| 527 | { | ||
| 528 | // get partitions collection from catalog | ||
| 529 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
| 530 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
| 531 | |||
| 532 | // find application object | ||
| 533 | hr = CpiFindCollectionObject(piPartColl, pPart->wzID, *pPart->wzID ? NULL : pPart->wzName, &piPartObj); | ||
| 534 | ExitOnFailure(hr, "Failed to find partition object"); | ||
| 535 | |||
| 536 | if (S_FALSE == hr) | ||
| 537 | { | ||
| 538 | pPart->fObjectNotFound = TRUE; | ||
| 539 | ExitFunction(); // exit with hr = S_FALSE | ||
| 540 | } | ||
| 541 | |||
| 542 | // get roles collection | ||
| 543 | hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"Applications", &pPart->piApplicationsColl); | ||
| 544 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 545 | } | ||
| 546 | |||
| 547 | // return value | ||
| 548 | *ppiAppColl = pPart->piApplicationsColl; | ||
| 549 | (*ppiAppColl)->AddRef(); | ||
| 550 | |||
| 551 | hr = S_OK; | ||
| 552 | |||
| 553 | LExit: | ||
| 554 | // clean up | ||
| 555 | ReleaseObject(piPartColl); | ||
| 556 | ReleaseObject(piPartObj); | ||
| 557 | |||
| 558 | return hr; | ||
| 559 | } | ||
| 560 | |||
| 561 | HRESULT CpiGetRolesCollForPartition( | ||
| 562 | CPI_PARTITION* pPart, | ||
| 563 | ICatalogCollection** ppiRolesColl | ||
| 564 | ) | ||
| 565 | { | ||
| 566 | HRESULT hr = S_OK; | ||
| 567 | |||
| 568 | ICatalogCollection* piPartColl = NULL; | ||
| 569 | ICatalogObject* piPartObj = NULL; | ||
| 570 | |||
| 571 | // if a previous attempt to locate the collection object failed | ||
| 572 | if (pPart->fObjectNotFound) | ||
| 573 | ExitFunction1(hr = S_FALSE); | ||
| 574 | |||
| 575 | // get applications collection | ||
| 576 | if (!pPart->piRolesColl) | ||
| 577 | { | ||
| 578 | // get partitions collection from catalog | ||
| 579 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
| 580 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
| 581 | |||
| 582 | // find partition object | ||
| 583 | hr = CpiFindCollectionObject(piPartColl, pPart->wzID, *pPart->wzID ? NULL : pPart->wzName, &piPartObj); | ||
| 584 | ExitOnFailure(hr, "Failed to find partition object"); | ||
| 585 | |||
| 586 | if (S_FALSE == hr) | ||
| 587 | ExitFunction(); // exit with hr = S_FALSE | ||
| 588 | |||
| 589 | // get roles collection | ||
| 590 | hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"RolesForPartition", &pPart->piRolesColl); | ||
| 591 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
| 592 | } | ||
| 593 | |||
| 594 | // return value | ||
| 595 | *ppiRolesColl = pPart->piRolesColl; | ||
| 596 | (*ppiRolesColl)->AddRef(); | ||
| 597 | |||
| 598 | hr = S_OK; | ||
| 599 | |||
| 600 | LExit: | ||
| 601 | // clean up | ||
| 602 | ReleaseObject(piPartColl); | ||
| 603 | ReleaseObject(piPartObj); | ||
| 604 | |||
| 605 | return hr; | ||
| 606 | } | ||
| 607 | |||
| 608 | void CpiPartitionUserListFree( | ||
| 609 | CPI_PARTITION_USER_LIST* pList | ||
| 610 | ) | ||
| 611 | { | ||
| 612 | CPI_PARTITION_USER* pItm = pList->pFirst; | ||
| 613 | |||
| 614 | while (pItm) | ||
| 615 | { | ||
| 616 | CPI_PARTITION_USER* pDelete = pItm; | ||
| 617 | pItm = pItm->pNext; | ||
| 618 | FreePartitionUser(pDelete); | ||
| 619 | } | ||
| 620 | } | ||
| 621 | |||
| 622 | HRESULT CpiPartitionUsersRead( | ||
| 623 | CPI_PARTITION_LIST* pPartList, | ||
| 624 | CPI_PARTITION_USER_LIST* pPartUsrList | ||
| 625 | ) | ||
| 626 | { | ||
| 627 | HRESULT hr = S_OK; | ||
| 628 | UINT er = ERROR_SUCCESS; | ||
| 629 | |||
| 630 | PMSIHANDLE hView, hRec; | ||
| 631 | |||
| 632 | CPI_PARTITION_USER* pItm = NULL; | ||
| 633 | LPWSTR pwzData = NULL; | ||
| 634 | LPWSTR pwzDomain = NULL; | ||
| 635 | LPWSTR pwzName = NULL; | ||
| 636 | BOOL fMatchingArchitecture = FALSE; | ||
| 637 | |||
| 638 | // loop through all partition users | ||
| 639 | hr = WcaOpenExecuteView(vcsPartitionUserQuery, &hView); | ||
| 640 | ExitOnFailure(hr, "Failed to execute view on ComPlusPartitionUser table"); | ||
| 641 | |||
| 642 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 643 | { | ||
| 644 | // get component | ||
| 645 | hr = WcaGetRecordString(hRec, puqComponent, &pwzData); | ||
| 646 | ExitOnFailure(hr, "Failed to get component"); | ||
| 647 | |||
| 648 | // check if the component is our processor architecture | ||
| 649 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
| 650 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
| 651 | |||
| 652 | if (!fMatchingArchitecture) | ||
| 653 | { | ||
| 654 | continue; // not the same architecture, ignore | ||
| 655 | } | ||
| 656 | |||
| 657 | // create entry | ||
| 658 | pItm = (CPI_PARTITION_USER*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PARTITION_USER)); | ||
| 659 | if (!pItm) | ||
| 660 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 661 | |||
| 662 | // get component install state | ||
| 663 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
| 664 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
| 665 | |||
| 666 | // get key | ||
| 667 | hr = WcaGetRecordString(hRec, puqPartitionUser, &pwzData); | ||
| 668 | ExitOnFailure(hr, "Failed to get key"); | ||
| 669 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 670 | |||
| 671 | // get partition | ||
| 672 | hr = WcaGetRecordString(hRec, puqPartition, &pwzData); | ||
| 673 | ExitOnFailure(hr, "Failed to get partition"); | ||
| 674 | |||
| 675 | hr = CpiPartitionFindByKey(pPartList, pwzData, &pItm->pPartition); | ||
| 676 | if (S_FALSE == hr) | ||
| 677 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 678 | ExitOnFailure(hr, "Failed to find partition, key: %S", pwzData); | ||
| 679 | |||
| 680 | // get user domain | ||
| 681 | hr = WcaGetRecordFormattedString(hRec, puqDomain, &pwzDomain); | ||
| 682 | ExitOnFailure(hr, "Failed to get user domain"); | ||
| 683 | |||
| 684 | // get user name | ||
| 685 | hr = WcaGetRecordFormattedString(hRec, puqName, &pwzName); | ||
| 686 | ExitOnFailure(hr, "Failed to get user name"); | ||
| 687 | |||
| 688 | // build account name | ||
| 689 | hr = CpiBuildAccountName(pwzDomain, pwzName, &pItm->pwzAccount); | ||
| 690 | ExitOnFailure(hr, "Failed to build account name"); | ||
| 691 | |||
| 692 | // set references & increment counters | ||
| 693 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 694 | { | ||
| 695 | pItm->pPartition->fReferencedForInstall = TRUE; | ||
| 696 | pPartUsrList->iInstallCount++; | ||
| 697 | } | ||
| 698 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 699 | { | ||
| 700 | pItm->pPartition->fReferencedForUninstall = TRUE; | ||
| 701 | pPartUsrList->iUninstallCount++; | ||
| 702 | } | ||
| 703 | |||
| 704 | // add entry | ||
| 705 | if (pPartUsrList->pFirst) | ||
| 706 | pItm->pNext = pPartUsrList->pFirst; | ||
| 707 | pPartUsrList->pFirst = pItm; | ||
| 708 | pItm = NULL; | ||
| 709 | } | ||
| 710 | |||
| 711 | if (E_NOMOREITEMS == hr) | ||
| 712 | hr = S_OK; | ||
| 713 | |||
| 714 | LExit: | ||
| 715 | // clean up | ||
| 716 | if (pItm) | ||
| 717 | FreePartitionUser(pItm); | ||
| 718 | |||
| 719 | ReleaseStr(pwzData); | ||
| 720 | ReleaseStr(pwzDomain); | ||
| 721 | ReleaseStr(pwzName); | ||
| 722 | |||
| 723 | return hr; | ||
| 724 | } | ||
| 725 | |||
| 726 | HRESULT CpiPartitionUsersInstall( | ||
| 727 | CPI_PARTITION_USER_LIST* pList, | ||
| 728 | int iRunMode, | ||
| 729 | LPWSTR* ppwzActionData, | ||
| 730 | int* piProgress | ||
| 731 | ) | ||
| 732 | { | ||
| 733 | HRESULT hr = S_OK; | ||
| 734 | |||
| 735 | int iActionType; | ||
| 736 | |||
| 737 | // add action text | ||
| 738 | hr = CpiAddActionTextToActionData(L"AddComPlusPartitionUsers", ppwzActionData); | ||
| 739 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 740 | |||
| 741 | // add partition count to action data | ||
| 742 | hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); | ||
| 743 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 744 | |||
| 745 | // add applications to custom action data | ||
| 746 | for (CPI_PARTITION_USER* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 747 | { | ||
| 748 | // partitions that are being installed only | ||
| 749 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 750 | continue; | ||
| 751 | |||
| 752 | // action type | ||
| 753 | if (rmRollback == iRunMode) | ||
| 754 | { | ||
| 755 | if (CpiIsInstalled(pItm->isInstalled)) | ||
| 756 | iActionType = atNoOp; | ||
| 757 | else | ||
| 758 | iActionType = atRemove; | ||
| 759 | } | ||
| 760 | else | ||
| 761 | iActionType = atCreate; | ||
| 762 | |||
| 763 | // add to action data | ||
| 764 | hr = AddPartitionUserToActionData(pItm, iActionType, COST_PARTITION_USER_CREATE, ppwzActionData); | ||
| 765 | ExitOnFailure(hr, "Failed to add partition user to custom action data, key: %S", pItm->wzKey); | ||
| 766 | } | ||
| 767 | |||
| 768 | // add progress tics | ||
| 769 | if (piProgress) | ||
| 770 | *piProgress += COST_PARTITION_USER_CREATE * pList->iInstallCount; | ||
| 771 | |||
| 772 | hr = S_OK; | ||
| 773 | |||
| 774 | LExit: | ||
| 775 | return hr; | ||
| 776 | } | ||
| 777 | |||
| 778 | HRESULT CpiPartitionUsersUninstall( | ||
| 779 | CPI_PARTITION_USER_LIST* pList, | ||
| 780 | int iRunMode, | ||
| 781 | LPWSTR* ppwzActionData, | ||
| 782 | int* piProgress | ||
| 783 | ) | ||
| 784 | { | ||
| 785 | HRESULT hr = S_OK; | ||
| 786 | |||
| 787 | int iActionType; | ||
| 788 | |||
| 789 | // add action text | ||
| 790 | hr = CpiAddActionTextToActionData(L"RemoveComPlusPartitionUsers", ppwzActionData); | ||
| 791 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 792 | |||
| 793 | // add partition count to action data | ||
| 794 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
| 795 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 796 | |||
| 797 | // add partitions to custom action data | ||
| 798 | for (CPI_PARTITION_USER* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 799 | { | ||
| 800 | // partitions that are being uninstalled only | ||
| 801 | if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 802 | continue; | ||
| 803 | |||
| 804 | // action type | ||
| 805 | if (rmRollback == iRunMode) | ||
| 806 | iActionType = atCreate; | ||
| 807 | else | ||
| 808 | iActionType = atRemove; | ||
| 809 | |||
| 810 | // add to action data | ||
| 811 | hr = AddPartitionUserToActionData(pItm, iActionType, COST_PARTITION_USER_DELETE, ppwzActionData); | ||
| 812 | ExitOnFailure(hr, "Failed to add partition user to custom action data, key: %S", pItm->wzKey); | ||
| 813 | } | ||
| 814 | |||
| 815 | // add progress tics | ||
| 816 | if (piProgress) | ||
| 817 | *piProgress += COST_PARTITION_USER_DELETE * pList->iUninstallCount; | ||
| 818 | |||
| 819 | hr = S_OK; | ||
| 820 | |||
| 821 | LExit: | ||
| 822 | return hr; | ||
| 823 | } | ||
| 824 | |||
| 825 | |||
| 826 | // helper function definitions | ||
| 827 | |||
| 828 | static void FreePartition( | ||
| 829 | CPI_PARTITION* pItm | ||
| 830 | ) | ||
| 831 | { | ||
| 832 | if (pItm->pProperties) | ||
| 833 | CpiPropertiesFreeList(pItm->pProperties); | ||
| 834 | |||
| 835 | ReleaseObject(pItm->piApplicationsColl); | ||
| 836 | ReleaseObject(pItm->piRolesColl); | ||
| 837 | |||
| 838 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
| 839 | } | ||
| 840 | |||
| 841 | static void FreePartitionUser( | ||
| 842 | CPI_PARTITION_USER* pItm | ||
| 843 | ) | ||
| 844 | { | ||
| 845 | ReleaseStr(pItm->pwzAccount); | ||
| 846 | |||
| 847 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
| 848 | } | ||
| 849 | |||
| 850 | static HRESULT AddPartitionToActionData( | ||
| 851 | CPI_PARTITION* pItm, | ||
| 852 | int iActionType, | ||
| 853 | int iActionCost, | ||
| 854 | LPWSTR* ppwzActionData | ||
| 855 | ) | ||
| 856 | { | ||
| 857 | HRESULT hr = S_OK; | ||
| 858 | |||
| 859 | // add action information to custom action data | ||
| 860 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
| 861 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
| 862 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
| 863 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
| 864 | |||
| 865 | // add partition information to custom action data | ||
| 866 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
| 867 | ExitOnFailure(hr, "Failed to add partition key to custom action data"); | ||
| 868 | hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData); | ||
| 869 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
| 870 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
| 871 | ExitOnFailure(hr, "Failed to add partition name to custom action data"); | ||
| 872 | |||
| 873 | // add properties to custom action data | ||
| 874 | hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
| 875 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
| 876 | |||
| 877 | hr = S_OK; | ||
| 878 | |||
| 879 | LExit: | ||
| 880 | return hr; | ||
| 881 | } | ||
| 882 | |||
| 883 | static HRESULT AddPartitionUserToActionData( | ||
| 884 | CPI_PARTITION_USER* pItm, | ||
| 885 | int iActionType, | ||
| 886 | int iActionCost, | ||
| 887 | LPWSTR* ppwzActionData | ||
| 888 | ) | ||
| 889 | { | ||
| 890 | HRESULT hr = S_OK; | ||
| 891 | |||
| 892 | // add action information to custom action data | ||
| 893 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
| 894 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
| 895 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
| 896 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
| 897 | |||
| 898 | // add partition user information to custom action data | ||
| 899 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
| 900 | ExitOnFailure(hr, "Failed to add partition user key to custom action data"); | ||
| 901 | hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData); | ||
| 902 | ExitOnFailure(hr, "Failed to add user account to custom action data"); | ||
| 903 | |||
| 904 | // add partition information to custom action data | ||
| 905 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pPartition->wzID : L"", ppwzActionData); | ||
| 906 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
| 907 | |||
| 908 | hr = S_OK; | ||
| 909 | |||
| 910 | LExit: | ||
| 911 | return hr; | ||
| 912 | } | ||
diff --git a/src/ca/cppartsched.h b/src/ca/cppartsched.h new file mode 100644 index 00000000..55085912 --- /dev/null +++ b/src/ca/cppartsched.h | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | struct CPI_PARTITION | ||
| 6 | { | ||
| 7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 8 | WCHAR wzID[CPI_MAX_GUID + 1]; | ||
| 9 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 10 | |||
| 11 | int iPropertyCount; | ||
| 12 | CPI_PROPERTY* pProperties; | ||
| 13 | |||
| 14 | BOOL fHasComponent; | ||
| 15 | BOOL fReferencedForInstall; | ||
| 16 | BOOL fReferencedForUninstall; | ||
| 17 | BOOL fObjectNotFound; | ||
| 18 | |||
| 19 | INSTALLSTATE isInstalled, isAction; | ||
| 20 | |||
| 21 | ICatalogCollection* piApplicationsColl; | ||
| 22 | ICatalogCollection* piRolesColl; | ||
| 23 | |||
| 24 | CPI_PARTITION* pNext; | ||
| 25 | }; | ||
| 26 | |||
| 27 | struct CPI_PARTITION_LIST | ||
| 28 | { | ||
| 29 | CPI_PARTITION* pFirst; | ||
| 30 | |||
| 31 | int iInstallCount; | ||
| 32 | int iUninstallCount; | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct CPI_PARTITION_USER | ||
| 36 | { | ||
| 37 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 38 | LPWSTR pwzAccount; | ||
| 39 | |||
| 40 | BOOL fNoFind; | ||
| 41 | |||
| 42 | INSTALLSTATE isInstalled, isAction; | ||
| 43 | |||
| 44 | CPI_PARTITION* pPartition; | ||
| 45 | |||
| 46 | CPI_PARTITION_USER* pNext; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct CPI_PARTITION_USER_LIST | ||
| 50 | { | ||
| 51 | CPI_PARTITION_USER* pFirst; | ||
| 52 | |||
| 53 | int iInstallCount; | ||
| 54 | int iUninstallCount; | ||
| 55 | }; | ||
| 56 | |||
| 57 | |||
| 58 | // function prototypes | ||
| 59 | |||
| 60 | void CpiPartitionListFree( | ||
| 61 | CPI_PARTITION_LIST* pList | ||
| 62 | ); | ||
| 63 | HRESULT CpiPartitionsRead( | ||
| 64 | CPI_PARTITION_LIST* pPartList | ||
| 65 | ); | ||
| 66 | HRESULT CpiPartitionsVerifyInstall( | ||
| 67 | CPI_PARTITION_LIST* pList | ||
| 68 | ); | ||
| 69 | HRESULT CpiPartitionsVerifyUninstall( | ||
| 70 | CPI_PARTITION_LIST* pList | ||
| 71 | ); | ||
| 72 | void CpiPartitionAddReferenceInstall( | ||
| 73 | CPI_PARTITION* pItm | ||
| 74 | ); | ||
| 75 | void CpiPartitionAddReferenceUninstall( | ||
| 76 | CPI_PARTITION* pItm | ||
| 77 | ); | ||
| 78 | HRESULT CpiPartitionsInstall( | ||
| 79 | CPI_PARTITION_LIST* pList, | ||
| 80 | int iRunMode, | ||
| 81 | LPWSTR* ppwzActionData, | ||
| 82 | int* piProgress | ||
| 83 | ); | ||
| 84 | HRESULT CpiPartitionsUninstall( | ||
| 85 | CPI_PARTITION_LIST* pList, | ||
| 86 | int iRunMode, | ||
| 87 | LPWSTR* ppwzActionData, | ||
| 88 | int* piProgress | ||
| 89 | ); | ||
| 90 | HRESULT CpiPartitionFindByKey( | ||
| 91 | CPI_PARTITION_LIST* pList, | ||
| 92 | LPCWSTR wzKey, | ||
| 93 | CPI_PARTITION** ppItm | ||
| 94 | ); | ||
| 95 | HRESULT CpiGetApplicationsCollForPartition( | ||
| 96 | CPI_PARTITION* pPart, | ||
| 97 | ICatalogCollection** ppiAppColl | ||
| 98 | ); | ||
| 99 | HRESULT CpiGetPartitionUsersCollection( | ||
| 100 | CPI_PARTITION* pPart, | ||
| 101 | ICatalogCollection** ppiPartUsrColl | ||
| 102 | ); | ||
| 103 | HRESULT CpiGetRolesCollForPartition( | ||
| 104 | CPI_PARTITION* pPart, | ||
| 105 | ICatalogCollection** ppiRolesColl | ||
| 106 | ); | ||
| 107 | void CpiPartitionUserListFree( | ||
| 108 | CPI_PARTITION_USER_LIST* pList | ||
| 109 | ); | ||
| 110 | HRESULT CpiPartitionUsersRead( | ||
| 111 | CPI_PARTITION_LIST* pPartList, | ||
| 112 | CPI_PARTITION_USER_LIST* pPartUsrList | ||
| 113 | ); | ||
| 114 | HRESULT CpiPartitionUsersInstall( | ||
| 115 | CPI_PARTITION_USER_LIST* pList, | ||
| 116 | int iRunMode, | ||
| 117 | LPWSTR* ppwzActionData, | ||
| 118 | int* piProgress | ||
| 119 | ); | ||
| 120 | HRESULT CpiPartitionUsersUninstall( | ||
| 121 | CPI_PARTITION_USER_LIST* pList, | ||
| 122 | int iRunMode, | ||
| 123 | LPWSTR* ppwzActionData, | ||
| 124 | int* piProgress | ||
| 125 | ); | ||
diff --git a/src/ca/cpsched.cpp b/src/ca/cpsched.cpp new file mode 100644 index 00000000..ac0dda59 --- /dev/null +++ b/src/ca/cpsched.cpp | |||
| @@ -0,0 +1,590 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | #ifdef _WIN64 | ||
| 7 | #define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare_64" | ||
| 8 | #define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare_64" | ||
| 9 | #define CP_COMPLUSROLLBACKINSTALLEXECUTE L"ComPlusRollbackInstallExecute_64" | ||
| 10 | #define CP_COMPLUSINSTALLEXECUTE L"ComPlusInstallExecute_64" | ||
| 11 | #define CP_COMPLUSINSTALLEXECUTECOMMIT L"ComPlusInstallExecuteCommit_64" | ||
| 12 | #define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit_64" | ||
| 13 | #define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare_64" | ||
| 14 | #define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare_64" | ||
| 15 | #define CP_COMPLUSROLLBACKUNINSTALLEXECUTE L"ComPlusRollbackUninstallExecute_64" | ||
| 16 | #define CP_COMPLUSUNINSTALLEXECUTE L"ComPlusUninstallExecute_64" | ||
| 17 | #define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit_64" | ||
| 18 | #else | ||
| 19 | #define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare" | ||
| 20 | #define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare" | ||
| 21 | #define CP_COMPLUSROLLBACKINSTALLEXECUTE L"ComPlusRollbackInstallExecute" | ||
| 22 | #define CP_COMPLUSINSTALLEXECUTE L"ComPlusInstallExecute" | ||
| 23 | #define CP_COMPLUSINSTALLEXECUTECOMMIT L"ComPlusInstallExecuteCommit" | ||
| 24 | #define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit" | ||
| 25 | #define CP_COMPLUSROLLBACKINSTALLPREPARE L"ComPlusRollbackInstallPrepare" | ||
| 26 | #define CP_COMPLUSINSTALLPREPARE L"ComPlusInstallPrepare" | ||
| 27 | #define CP_COMPLUSROLLBACKUNINSTALLEXECUTE L"ComPlusRollbackUninstallExecute" | ||
| 28 | #define CP_COMPLUSUNINSTALLEXECUTE L"ComPlusUninstallExecute" | ||
| 29 | #define CP_COMPLUSINSTALLCOMMIT L"ComPlusInstallCommit" | ||
| 30 | #endif | ||
| 31 | |||
| 32 | |||
| 33 | /******************************************************************** | ||
| 34 | DllMain - standard entry point for all WiX CustomActions | ||
| 35 | |||
| 36 | ********************************************************************/ | ||
| 37 | extern "C" BOOL WINAPI DllMain( | ||
| 38 | IN HINSTANCE hInst, | ||
| 39 | IN ULONG ulReason, | ||
| 40 | IN LPVOID) | ||
| 41 | { | ||
| 42 | switch(ulReason) | ||
| 43 | { | ||
| 44 | case DLL_PROCESS_ATTACH: | ||
| 45 | WcaGlobalInitialize(hInst); | ||
| 46 | break; | ||
| 47 | |||
| 48 | case DLL_PROCESS_DETACH: | ||
| 49 | WcaGlobalFinalize(); | ||
| 50 | break; | ||
| 51 | } | ||
| 52 | |||
| 53 | return TRUE; | ||
| 54 | } | ||
| 55 | |||
| 56 | /******************************************************************** | ||
| 57 | ConfigureComPlusInstall - CUSTOM ACTION ENTRY POINT for installing COM+ components | ||
| 58 | |||
| 59 | ********************************************************************/ | ||
| 60 | extern "C" UINT __stdcall ConfigureComPlusInstall(MSIHANDLE hInstall) | ||
| 61 | { | ||
| 62 | HRESULT hr = S_OK; | ||
| 63 | UINT er = ERROR_SUCCESS; | ||
| 64 | |||
| 65 | BOOL fInitializedCom = FALSE; | ||
| 66 | |||
| 67 | ICOMAdminCatalog* piCatalog = NULL; | ||
| 68 | |||
| 69 | CPI_PARTITION_LIST partList; | ||
| 70 | CPI_PARTITION_ROLE_LIST partRoleList; | ||
| 71 | CPI_USER_IN_PARTITION_ROLE_LIST usrInPartRoleList; | ||
| 72 | CPI_PARTITION_USER_LIST partUsrList; | ||
| 73 | CPI_APPLICATION_LIST appList; | ||
| 74 | CPI_APPLICATION_ROLE_LIST appRoleList; | ||
| 75 | CPI_USER_IN_APPLICATION_ROLE_LIST usrInAppRoleList; | ||
| 76 | CPI_ASSEMBLY_LIST asmList; | ||
| 77 | CPI_SUBSCRIPTION_LIST subList; | ||
| 78 | |||
| 79 | LPWSTR pwzRollbackFileName = NULL; | ||
| 80 | LPWSTR pwzActionData = NULL; | ||
| 81 | LPWSTR pwzRollbackActionData = NULL; | ||
| 82 | LPWSTR pwzCommitActionData = NULL; | ||
| 83 | |||
| 84 | int iVersionNT = 0; | ||
| 85 | int iProgress = 0; | ||
| 86 | int iCommitProgress = 0; | ||
| 87 | |||
| 88 | ::ZeroMemory(&partList, sizeof(CPI_PARTITION_LIST)); | ||
| 89 | ::ZeroMemory(&partRoleList, sizeof(CPI_PARTITION_ROLE_LIST)); | ||
| 90 | ::ZeroMemory(&usrInPartRoleList, sizeof(CPI_USER_IN_PARTITION_ROLE_LIST)); | ||
| 91 | ::ZeroMemory(&partUsrList, sizeof(CPI_PARTITION_USER_LIST)); | ||
| 92 | ::ZeroMemory(&appList, sizeof(CPI_APPLICATION_LIST)); | ||
| 93 | ::ZeroMemory(&appRoleList, sizeof(CPI_APPLICATION_ROLE_LIST)); | ||
| 94 | ::ZeroMemory(&usrInAppRoleList, sizeof(CPI_USER_IN_APPLICATION_ROLE_LIST)); | ||
| 95 | ::ZeroMemory(&asmList, sizeof(CPI_ASSEMBLY_LIST)); | ||
| 96 | ::ZeroMemory(&subList, sizeof(CPI_SUBSCRIPTION_LIST)); | ||
| 97 | |||
| 98 | // initialize | ||
| 99 | hr = WcaInitialize(hInstall, "ConfigureComPlusInstall"); | ||
| 100 | ExitOnFailure(hr, "Failed to initialize"); | ||
| 101 | |||
| 102 | hr = ::CoInitialize(NULL); | ||
| 103 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
| 104 | fInitializedCom = TRUE; | ||
| 105 | |||
| 106 | CpiInitialize(); | ||
| 107 | |||
| 108 | // check for the prerequsite tables | ||
| 109 | if (!CpiTableExists(cptComPlusPartition) && !CpiTableExists(cptComPlusApplication) && !CpiTableExists(cptComPlusAssembly)) | ||
| 110 | { | ||
| 111 | WcaLog(LOGMSG_VERBOSE, "skipping install COM+ CustomAction, no ComPlusPartition, ComPlusApplication or ComPlusAssembly table present"); | ||
| 112 | ExitFunction1(hr = S_FALSE); | ||
| 113 | } | ||
| 114 | |||
| 115 | // make sure we can access the COM+ admin catalog | ||
| 116 | do { | ||
| 117 | hr = CpiGetAdminCatalog(&piCatalog); | ||
| 118 | if (FAILED(hr)) | ||
| 119 | { | ||
| 120 | WcaLog(LOGMSG_STANDARD, "Failed to get COM+ admin catalog"); | ||
| 121 | er = WcaErrorMessage(msierrComPlusCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 122 | switch (er) | ||
| 123 | { | ||
| 124 | case IDABORT: | ||
| 125 | ExitFunction(); // exit with hr from CpiGetAdminCatalog() to kick off a rollback | ||
| 126 | case IDRETRY: | ||
| 127 | hr = S_FALSE; | ||
| 128 | break; | ||
| 129 | case IDIGNORE: | ||
| 130 | default: | ||
| 131 | ExitFunction1(hr = S_OK); // pretend everything is okay and bail | ||
| 132 | } | ||
| 133 | } | ||
| 134 | } while (S_FALSE == hr); | ||
| 135 | |||
| 136 | // get NT version | ||
| 137 | hr = WcaGetIntProperty(L"VersionNT", &iVersionNT); | ||
| 138 | ExitOnFailure(hr, "Failed to get VersionNT property"); | ||
| 139 | |||
| 140 | // read elements | ||
| 141 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartition)) | ||
| 142 | { | ||
| 143 | hr = CpiPartitionsRead(&partList); | ||
| 144 | MessageExitOnFailure(hr, msierrComPlusPartitionReadFailed, "Failed to read ComPlusPartitions table"); | ||
| 145 | } | ||
| 146 | |||
| 147 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionRole)) | ||
| 148 | { | ||
| 149 | hr = CpiPartitionRolesRead(&partList, &partRoleList); | ||
| 150 | MessageExitOnFailure(hr, msierrComPlusPartitionRoleReadFailed, "Failed to read ComPlusPartitionRole table"); | ||
| 151 | } | ||
| 152 | |||
| 153 | if (502 <= iVersionNT && (CpiTableExists(cptComPlusUserInPartitionRole) || CpiTableExists(cptComPlusGroupInPartitionRole))) | ||
| 154 | { | ||
| 155 | hr = CpiUsersInPartitionRolesRead(&partRoleList, &usrInPartRoleList); | ||
| 156 | MessageExitOnFailure(hr, msierrComPlusUserInPartitionRoleReadFailed, "Failed to read ComPlusUserInPartitionRole table"); | ||
| 157 | } | ||
| 158 | |||
| 159 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionUser)) | ||
| 160 | { | ||
| 161 | hr = CpiPartitionUsersRead(&partList, &partUsrList); | ||
| 162 | MessageExitOnFailure(hr, msierrComPlusPartitionUserReadFailed, "Failed to read ComPlusPartitionUser table"); | ||
| 163 | } | ||
| 164 | |||
| 165 | if (CpiTableExists(cptComPlusApplication)) | ||
| 166 | { | ||
| 167 | hr = CpiApplicationsRead(&partList, &appList); | ||
| 168 | MessageExitOnFailure(hr, msierrComPlusApplicationReadFailed, "Failed to read ComPlusApplication table"); | ||
| 169 | } | ||
| 170 | |||
| 171 | if (CpiTableExists(cptComPlusApplicationRole)) | ||
| 172 | { | ||
| 173 | hr = CpiApplicationRolesRead(&appList, &appRoleList); | ||
| 174 | MessageExitOnFailure(hr, msierrComPlusApplicationRoleReadFailed, "Failed to read ComPlusApplicationRole table"); | ||
| 175 | } | ||
| 176 | |||
| 177 | if (CpiTableExists(cptComPlusUserInApplicationRole) || CpiTableExists(cptComPlusGroupInApplicationRole)) | ||
| 178 | { | ||
| 179 | hr = CpiUsersInApplicationRolesRead(&appRoleList, &usrInAppRoleList); | ||
| 180 | MessageExitOnFailure(hr, msierrComPlusUserInApplicationRoleReadFailed, "Failed to read ComPlusUserInApplicationRole table"); | ||
| 181 | } | ||
| 182 | |||
| 183 | if (CpiTableExists(cptComPlusAssembly)) | ||
| 184 | { | ||
| 185 | hr = CpiAssembliesRead(&appList, &appRoleList, &asmList); | ||
| 186 | MessageExitOnFailure(hr, msierrComPlusAssembliesReadFailed, "Failed to read ComPlusAssembly table"); | ||
| 187 | } | ||
| 188 | |||
| 189 | if (CpiTableExists(cptComPlusSubscription)) | ||
| 190 | { | ||
| 191 | hr = CpiSubscriptionsRead(&asmList, &subList); | ||
| 192 | MessageExitOnFailure(hr, msierrComPlusSubscriptionReadFailed, "Failed to read ComPlusSubscription table"); | ||
| 193 | } | ||
| 194 | |||
| 195 | // verify elements | ||
| 196 | hr = CpiPartitionsVerifyInstall(&partList); | ||
| 197 | ExitOnFailure(hr, "Failed to verify partitions"); | ||
| 198 | |||
| 199 | hr = CpiApplicationsVerifyInstall(&appList); | ||
| 200 | ExitOnFailure(hr, "Failed to verify applications"); | ||
| 201 | |||
| 202 | hr = CpiApplicationRolesVerifyInstall(&appRoleList); | ||
| 203 | ExitOnFailure(hr, "Failed to verify application roles"); | ||
| 204 | |||
| 205 | hr = CpiAssembliesVerifyInstall(&asmList); | ||
| 206 | ExitOnFailure(hr, "Failed to verify assemblies"); | ||
| 207 | |||
| 208 | if (subList.iInstallCount) | ||
| 209 | { | ||
| 210 | hr = CpiSubscriptionsVerifyInstall(&subList); | ||
| 211 | ExitOnFailure(hr, "Failed to verify subscriptions"); | ||
| 212 | } | ||
| 213 | |||
| 214 | // schedule | ||
| 215 | if (partList.iInstallCount || appList.iInstallCount || usrInAppRoleList.iInstallCount || | ||
| 216 | appRoleList.iInstallCount || asmList.iInstallCount || asmList.iRoleInstallCount || subList.iInstallCount) | ||
| 217 | { | ||
| 218 | // create rollback file name | ||
| 219 | hr = CpiGetTempFileName(&pwzRollbackFileName); | ||
| 220 | ExitOnFailure(hr, "Failed to get rollback file name"); | ||
| 221 | |||
| 222 | // schedule rollback prepare custom action | ||
| 223 | hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKINSTALLPREPARE, pwzRollbackFileName, 0); | ||
| 224 | ExitOnFailure(hr, "Failed to schedule ComPlusRollbackInstallPrepare"); | ||
| 225 | |||
| 226 | // schedule prepare custom action | ||
| 227 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLPREPARE, pwzRollbackFileName, 0); | ||
| 228 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallPrepare"); | ||
| 229 | |||
| 230 | // schedule rollback custom action | ||
| 231 | hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzRollbackActionData); | ||
| 232 | ExitOnFailure(hr, "Failed to add rollback file name to rollback custom action data"); | ||
| 233 | |||
| 234 | hr = CpiSubscriptionsInstall(&subList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 235 | ExitOnFailure(hr, "Failed to install subscriptions"); | ||
| 236 | hr = CpiRoleAssignmentsInstall(&asmList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 237 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
| 238 | hr = CpiAssembliesInstall(&asmList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 239 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
| 240 | hr = CpiUsersInApplicationRolesInstall(&usrInAppRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 241 | ExitOnFailure(hr, "Failed to install users in application roles"); | ||
| 242 | hr = CpiApplicationRolesInstall(&appRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 243 | ExitOnFailure(hr, "Failed to install application roles"); | ||
| 244 | hr = CpiApplicationsInstall(&appList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 245 | ExitOnFailure(hr, "Failed to install applications"); | ||
| 246 | hr = CpiPartitionUsersInstall(&partUsrList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 247 | ExitOnFailure(hr, "Failed to install partition users"); | ||
| 248 | hr = CpiUsersInPartitionRolesInstall(&usrInPartRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 249 | ExitOnFailure(hr, "Failed to install users in partition roles"); | ||
| 250 | hr = CpiPartitionsInstall(&partList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 251 | ExitOnFailure(hr, "Failed to install partitions"); | ||
| 252 | |||
| 253 | hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKINSTALLEXECUTE, pwzRollbackActionData, 0); | ||
| 254 | ExitOnFailure(hr, "Failed to schedule ComPlusRollbackInstallExecute"); | ||
| 255 | |||
| 256 | // schedule install custom action | ||
| 257 | hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzActionData); | ||
| 258 | ExitOnFailure(hr, "Failed to add rollback file name to custom action data"); | ||
| 259 | |||
| 260 | hr = CpiPartitionsInstall(&partList, rmDeferred, &pwzActionData, &iProgress); | ||
| 261 | ExitOnFailure(hr, "Failed to install partitions"); | ||
| 262 | hr = CpiUsersInPartitionRolesInstall(&usrInPartRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
| 263 | ExitOnFailure(hr, "Failed to install users in partition roles"); | ||
| 264 | hr = CpiPartitionUsersInstall(&partUsrList, rmDeferred, &pwzActionData, &iProgress); | ||
| 265 | ExitOnFailure(hr, "Failed to install partition users"); | ||
| 266 | hr = CpiApplicationsInstall(&appList, rmDeferred, &pwzActionData, &iProgress); | ||
| 267 | ExitOnFailure(hr, "Failed to install applications"); | ||
| 268 | hr = CpiApplicationRolesInstall(&appRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
| 269 | ExitOnFailure(hr, "Failed to install application roles"); | ||
| 270 | hr = CpiUsersInApplicationRolesInstall(&usrInAppRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
| 271 | ExitOnFailure(hr, "Failed to install users in application roles"); | ||
| 272 | hr = CpiAssembliesInstall(&asmList, rmDeferred, &pwzActionData, &iProgress); | ||
| 273 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
| 274 | hr = CpiRoleAssignmentsInstall(&asmList, rmDeferred, &pwzActionData, &iProgress); | ||
| 275 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
| 276 | hr = CpiSubscriptionsInstall(&subList, rmDeferred, &pwzActionData, &iProgress); | ||
| 277 | ExitOnFailure(hr, "Failed to install subscriptions"); | ||
| 278 | |||
| 279 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLEXECUTE, pwzActionData, iProgress); | ||
| 280 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallExecute"); | ||
| 281 | |||
| 282 | // schedule install commit custom action | ||
| 283 | hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzCommitActionData); | ||
| 284 | ExitOnFailure(hr, "Failed to add rollback file name to commit custom action data"); | ||
| 285 | |||
| 286 | hr = CpiAssembliesInstall(&asmList, rmCommit, &pwzCommitActionData, &iCommitProgress); | ||
| 287 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
| 288 | hr = CpiRoleAssignmentsInstall(&asmList, rmCommit, &pwzCommitActionData, &iCommitProgress); | ||
| 289 | ExitOnFailure(hr, "Failed to install assemblies"); | ||
| 290 | hr = CpiSubscriptionsInstall(&subList, rmCommit, &pwzCommitActionData, &iCommitProgress); | ||
| 291 | ExitOnFailure(hr, "Failed to install subscriptions"); | ||
| 292 | |||
| 293 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLEXECUTECOMMIT, pwzCommitActionData, iCommitProgress); | ||
| 294 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallExecuteCommit"); | ||
| 295 | |||
| 296 | // schedule commit custom action | ||
| 297 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLCOMMIT, pwzRollbackFileName, 0); | ||
| 298 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallCommit"); | ||
| 299 | } | ||
| 300 | |||
| 301 | hr = S_OK; | ||
| 302 | |||
| 303 | LExit: | ||
| 304 | // clean up | ||
| 305 | ReleaseObject(piCatalog); | ||
| 306 | |||
| 307 | ReleaseStr(pwzRollbackFileName); | ||
| 308 | ReleaseStr(pwzActionData); | ||
| 309 | ReleaseStr(pwzRollbackActionData); | ||
| 310 | ReleaseStr(pwzCommitActionData); | ||
| 311 | |||
| 312 | CpiPartitionListFree(&partList); | ||
| 313 | CpiPartitionRoleListFree(&partRoleList); | ||
| 314 | CpiUserInPartitionRoleListFree(&usrInPartRoleList); | ||
| 315 | CpiPartitionUserListFree(&partUsrList); | ||
| 316 | CpiApplicationListFree(&appList); | ||
| 317 | CpiApplicationRoleListFree(&appRoleList); | ||
| 318 | CpiUserInApplicationRoleListFree(&usrInAppRoleList); | ||
| 319 | CpiAssemblyListFree(&asmList); | ||
| 320 | CpiSubscriptionListFree(&subList); | ||
| 321 | |||
| 322 | // unitialize | ||
| 323 | CpiFinalize(); | ||
| 324 | |||
| 325 | if (fInitializedCom) | ||
| 326 | ::CoUninitialize(); | ||
| 327 | |||
| 328 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 329 | return WcaFinalize(er); | ||
| 330 | } | ||
| 331 | |||
| 332 | |||
| 333 | /******************************************************************** | ||
| 334 | ConfigureComPlusUninstall - CUSTOM ACTION ENTRY POINT for uninstalling COM+ components | ||
| 335 | |||
| 336 | ********************************************************************/ | ||
| 337 | extern "C" UINT __stdcall ConfigureComPlusUninstall(MSIHANDLE hInstall) | ||
| 338 | { | ||
| 339 | HRESULT hr = S_OK; | ||
| 340 | UINT er = ERROR_SUCCESS; | ||
| 341 | |||
| 342 | BOOL fInitializedCom = FALSE; | ||
| 343 | |||
| 344 | ICOMAdminCatalog* piCatalog = NULL; | ||
| 345 | |||
| 346 | CPI_PARTITION_LIST partList; | ||
| 347 | CPI_PARTITION_ROLE_LIST partRoleList; | ||
| 348 | CPI_USER_IN_PARTITION_ROLE_LIST usrInPartRoleList; | ||
| 349 | CPI_PARTITION_USER_LIST partUsrList; | ||
| 350 | CPI_APPLICATION_LIST appList; | ||
| 351 | CPI_APPLICATION_ROLE_LIST appRoleList; | ||
| 352 | CPI_USER_IN_APPLICATION_ROLE_LIST usrInAppRoleList; | ||
| 353 | CPI_ASSEMBLY_LIST asmList; | ||
| 354 | CPI_SUBSCRIPTION_LIST subList; | ||
| 355 | |||
| 356 | LPWSTR pwzRollbackFileName = NULL; | ||
| 357 | LPWSTR pwzActionData = NULL; | ||
| 358 | LPWSTR pwzRollbackActionData = NULL; | ||
| 359 | |||
| 360 | int iVersionNT = 0; | ||
| 361 | int iProgress = 0; | ||
| 362 | |||
| 363 | ::ZeroMemory(&partList, sizeof(CPI_PARTITION_LIST)); | ||
| 364 | ::ZeroMemory(&partRoleList, sizeof(CPI_PARTITION_ROLE_LIST)); | ||
| 365 | ::ZeroMemory(&usrInPartRoleList, sizeof(CPI_USER_IN_PARTITION_ROLE_LIST)); | ||
| 366 | ::ZeroMemory(&partUsrList, sizeof(CPI_PARTITION_USER_LIST)); | ||
| 367 | ::ZeroMemory(&appList, sizeof(CPI_APPLICATION_LIST)); | ||
| 368 | ::ZeroMemory(&appRoleList, sizeof(CPI_APPLICATION_ROLE_LIST)); | ||
| 369 | ::ZeroMemory(&usrInAppRoleList, sizeof(CPI_USER_IN_APPLICATION_ROLE_LIST)); | ||
| 370 | ::ZeroMemory(&asmList, sizeof(CPI_ASSEMBLY_LIST)); | ||
| 371 | ::ZeroMemory(&subList, sizeof(CPI_SUBSCRIPTION_LIST)); | ||
| 372 | |||
| 373 | // initialize | ||
| 374 | hr = WcaInitialize(hInstall, "ConfigureComPlusUninstall"); | ||
| 375 | ExitOnFailure(hr, "Failed to initialize"); | ||
| 376 | |||
| 377 | hr = ::CoInitialize(NULL); | ||
| 378 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
| 379 | fInitializedCom = TRUE; | ||
| 380 | |||
| 381 | CpiInitialize(); | ||
| 382 | |||
| 383 | // check for the prerequsite tables | ||
| 384 | if (!CpiTableExists(cptComPlusPartition) && !CpiTableExists(cptComPlusApplication) && !CpiTableExists(cptComPlusAssembly)) | ||
| 385 | { | ||
| 386 | WcaLog(LOGMSG_VERBOSE, "skipping uninstall COM+ CustomAction, no ComPlusPartition, ComPlusApplication or ComPlusAssembly table present"); | ||
| 387 | ExitFunction1(hr = S_FALSE); | ||
| 388 | } | ||
| 389 | |||
| 390 | // make sure we can access the COM+ admin catalog | ||
| 391 | do { | ||
| 392 | hr = CpiGetAdminCatalog(&piCatalog); | ||
| 393 | if (FAILED(hr)) | ||
| 394 | { | ||
| 395 | WcaLog(LOGMSG_STANDARD, "Failed to get COM+ admin catalog"); | ||
| 396 | er = WcaErrorMessage(msierrComPlusCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 397 | switch (er) | ||
| 398 | { | ||
| 399 | case IDABORT: | ||
| 400 | ExitFunction(); // exit with hr from CpiGetAdminCatalog() to kick off a rollback | ||
| 401 | case IDRETRY: | ||
| 402 | hr = S_FALSE; | ||
| 403 | break; | ||
| 404 | case IDIGNORE: | ||
| 405 | default: | ||
| 406 | ExitFunction1(hr = S_OK); // pretend everything is okay and bail | ||
| 407 | } | ||
| 408 | } | ||
| 409 | } while (S_FALSE == hr); | ||
| 410 | |||
| 411 | // get NT version | ||
| 412 | hr = WcaGetIntProperty(L"VersionNT", &iVersionNT); | ||
| 413 | ExitOnFailure(hr, "Failed to get VersionNT property"); | ||
| 414 | |||
| 415 | // read elements | ||
| 416 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartition)) | ||
| 417 | { | ||
| 418 | hr = CpiPartitionsRead(&partList); | ||
| 419 | MessageExitOnFailure(hr, msierrComPlusPartitionReadFailed, "Failed to read ComPlusPartitions table"); | ||
| 420 | } | ||
| 421 | |||
| 422 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionRole)) | ||
| 423 | { | ||
| 424 | hr = CpiPartitionRolesRead(&partList, &partRoleList); | ||
| 425 | MessageExitOnFailure(hr, msierrComPlusPartitionRoleReadFailed, "Failed to read ComPlusPartitionRole table"); | ||
| 426 | } | ||
| 427 | |||
| 428 | if (502 <= iVersionNT && (CpiTableExists(cptComPlusUserInPartitionRole) || CpiTableExists(cptComPlusGroupInPartitionRole))) | ||
| 429 | { | ||
| 430 | hr = CpiUsersInPartitionRolesRead(&partRoleList, &usrInPartRoleList); | ||
| 431 | MessageExitOnFailure(hr, msierrComPlusUserInPartitionRoleReadFailed, "Failed to read ComPlusUserInPartitionRole table"); | ||
| 432 | } | ||
| 433 | |||
| 434 | if (502 <= iVersionNT && CpiTableExists(cptComPlusPartitionUser)) | ||
| 435 | { | ||
| 436 | hr = CpiPartitionUsersRead(&partList, &partUsrList); | ||
| 437 | MessageExitOnFailure(hr, msierrComPlusPartitionUserReadFailed, "Failed to read ComPlusPartitionUser table"); | ||
| 438 | } | ||
| 439 | |||
| 440 | if (CpiTableExists(cptComPlusApplication)) | ||
| 441 | { | ||
| 442 | hr = CpiApplicationsRead(&partList, &appList); | ||
| 443 | MessageExitOnFailure(hr, msierrComPlusApplicationReadFailed, "Failed to read ComPlusApplication table"); | ||
| 444 | } | ||
| 445 | |||
| 446 | if (CpiTableExists(cptComPlusApplicationRole)) | ||
| 447 | { | ||
| 448 | hr = CpiApplicationRolesRead(&appList, &appRoleList); | ||
| 449 | MessageExitOnFailure(hr, msierrComPlusApplicationRoleReadFailed, "Failed to read ComPlusApplicationRole table"); | ||
| 450 | } | ||
| 451 | |||
| 452 | if (CpiTableExists(cptComPlusUserInApplicationRole) || CpiTableExists(cptComPlusGroupInApplicationRole)) | ||
| 453 | { | ||
| 454 | hr = CpiUsersInApplicationRolesRead(&appRoleList, &usrInAppRoleList); | ||
| 455 | MessageExitOnFailure(hr, msierrComPlusUserInApplicationRoleReadFailed, "Failed to read ComPlusUserInApplicationRole table"); | ||
| 456 | } | ||
| 457 | |||
| 458 | if (CpiTableExists(cptComPlusAssembly)) | ||
| 459 | { | ||
| 460 | hr = CpiAssembliesRead(&appList, &appRoleList, &asmList); | ||
| 461 | MessageExitOnFailure(hr, msierrComPlusAssembliesReadFailed, "Failed to read ComPlusAssembly table"); | ||
| 462 | } | ||
| 463 | |||
| 464 | if (CpiTableExists(cptComPlusSubscription)) | ||
| 465 | { | ||
| 466 | hr = CpiSubscriptionsRead(&asmList, &subList); | ||
| 467 | MessageExitOnFailure(hr, msierrComPlusSubscriptionReadFailed, "Failed to read ComPlusSubscription table"); | ||
| 468 | } | ||
| 469 | |||
| 470 | // verify elements | ||
| 471 | hr = CpiPartitionsVerifyUninstall(&partList); | ||
| 472 | ExitOnFailure(hr, "Failed to verify partitions"); | ||
| 473 | |||
| 474 | hr = CpiApplicationsVerifyUninstall(&appList); | ||
| 475 | ExitOnFailure(hr, "Failed to verify applications"); | ||
| 476 | |||
| 477 | hr = CpiApplicationRolesVerifyUninstall(&appRoleList); | ||
| 478 | ExitOnFailure(hr, "Failed to verify application roles"); | ||
| 479 | |||
| 480 | hr = CpiAssembliesVerifyUninstall(&asmList); | ||
| 481 | ExitOnFailure(hr, "Failed to verify assemblies"); | ||
| 482 | |||
| 483 | if (subList.iUninstallCount) | ||
| 484 | { | ||
| 485 | hr = CpiSubscriptionsVerifyUninstall(&subList); | ||
| 486 | ExitOnFailure(hr, "Failed to verify subscriptions"); | ||
| 487 | } | ||
| 488 | |||
| 489 | // schedule | ||
| 490 | if (partList.iUninstallCount || appList.iUninstallCount || appRoleList.iUninstallCount || | ||
| 491 | usrInAppRoleList.iUninstallCount || asmList.iUninstallCount || asmList.iRoleUninstallCount || subList.iUninstallCount) | ||
| 492 | { | ||
| 493 | // create rollback file name | ||
| 494 | hr = CpiGetTempFileName(&pwzRollbackFileName); | ||
| 495 | ExitOnFailure(hr, "Failed to get rollback file name"); | ||
| 496 | |||
| 497 | // schedule rollback prepare custom action | ||
| 498 | hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKINSTALLPREPARE, pwzRollbackFileName, 0); | ||
| 499 | ExitOnFailure(hr, "Failed to schedule ComPlusRollbackInstallPrepare"); | ||
| 500 | |||
| 501 | // schedule prepare custom action | ||
| 502 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLPREPARE, pwzRollbackFileName, 0); | ||
| 503 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallPrepare"); | ||
| 504 | |||
| 505 | // schedule rollback custom action | ||
| 506 | hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzRollbackActionData); | ||
| 507 | ExitOnFailure(hr, "Failed to add rollback file name to rollback custom action data"); | ||
| 508 | |||
| 509 | hr = CpiPartitionsUninstall(&partList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 510 | ExitOnFailure(hr, "Failed to uninstall partitions"); | ||
| 511 | hr = CpiUsersInPartitionRolesUninstall(&usrInPartRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 512 | ExitOnFailure(hr, "Failed to uninstall users in partition roles"); | ||
| 513 | hr = CpiPartitionUsersUninstall(&partUsrList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 514 | ExitOnFailure(hr, "Failed to uninstall partition users"); | ||
| 515 | hr = CpiApplicationsUninstall(&appList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 516 | ExitOnFailure(hr, "Failed to uninstall applications"); | ||
| 517 | hr = CpiApplicationRolesUninstall(&appRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 518 | ExitOnFailure(hr, "Failed to uninstall application roles"); | ||
| 519 | hr = CpiUsersInApplicationRolesUninstall(&usrInAppRoleList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 520 | ExitOnFailure(hr, "Failed to uninstall users in application roles"); | ||
| 521 | hr = CpiAssembliesUninstall(&asmList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 522 | ExitOnFailure(hr, "Failed to uninstall assemblies"); | ||
| 523 | hr = CpiRoleAssignmentsUninstall(&asmList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 524 | ExitOnFailure(hr, "Failed to uninstall assemblies"); | ||
| 525 | hr = CpiSubscriptionsUninstall(&subList, rmRollback, &pwzRollbackActionData, NULL); | ||
| 526 | ExitOnFailure(hr, "Failed to uninstall subscriptions"); | ||
| 527 | |||
| 528 | hr = WcaDoDeferredAction(CP_COMPLUSROLLBACKUNINSTALLEXECUTE, pwzRollbackActionData, 0); | ||
| 529 | ExitOnFailure(hr, "Failed to schedule ComPlusRollbackUninstallExecute"); | ||
| 530 | |||
| 531 | // schedule install custom action | ||
| 532 | hr = WcaWriteStringToCaData(pwzRollbackFileName, &pwzActionData); | ||
| 533 | ExitOnFailure(hr, "Failed to add rollback file name to custom action data"); | ||
| 534 | |||
| 535 | hr = CpiSubscriptionsUninstall(&subList, rmDeferred, &pwzActionData, &iProgress); | ||
| 536 | ExitOnFailure(hr, "Failed to uninstall subscriptions"); | ||
| 537 | hr = CpiRoleAssignmentsUninstall(&asmList, rmDeferred, &pwzActionData, &iProgress); | ||
| 538 | ExitOnFailure(hr, "Failed to uninstall assemblies"); | ||
| 539 | hr = CpiAssembliesUninstall(&asmList, rmDeferred, &pwzActionData, &iProgress); | ||
| 540 | ExitOnFailure(hr, "Failed to uninstall assemblies"); | ||
| 541 | hr = CpiUsersInApplicationRolesUninstall(&usrInAppRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
| 542 | ExitOnFailure(hr, "Failed to uninstall users in application roles"); | ||
| 543 | hr = CpiApplicationRolesUninstall(&appRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
| 544 | ExitOnFailure(hr, "Failed to uninstall application roles"); | ||
| 545 | hr = CpiApplicationsUninstall(&appList, rmDeferred, &pwzActionData, &iProgress); | ||
| 546 | ExitOnFailure(hr, "Failed to uninstall applications"); | ||
| 547 | hr = CpiPartitionUsersUninstall(&partUsrList, rmDeferred, &pwzActionData, &iProgress); | ||
| 548 | ExitOnFailure(hr, "Failed to uninstall partition users"); | ||
| 549 | hr = CpiUsersInPartitionRolesUninstall(&usrInPartRoleList, rmDeferred, &pwzActionData, &iProgress); | ||
| 550 | ExitOnFailure(hr, "Failed to uninstall users in partition roles"); | ||
| 551 | hr = CpiPartitionsUninstall(&partList, rmDeferred, &pwzActionData, &iProgress); | ||
| 552 | ExitOnFailure(hr, "Failed to uninstall partitions"); | ||
| 553 | |||
| 554 | hr = WcaDoDeferredAction(CP_COMPLUSUNINSTALLEXECUTE, pwzActionData, iProgress); | ||
| 555 | ExitOnFailure(hr, "Failed to schedule ComPlusUninstallExecute"); | ||
| 556 | |||
| 557 | // schedule commit custom action | ||
| 558 | hr = WcaDoDeferredAction(CP_COMPLUSINSTALLCOMMIT, pwzRollbackFileName, 0); | ||
| 559 | ExitOnFailure(hr, "Failed to schedule ComPlusInstallCommit"); | ||
| 560 | } | ||
| 561 | |||
| 562 | hr = S_OK; | ||
| 563 | |||
| 564 | LExit: | ||
| 565 | // clean up | ||
| 566 | ReleaseObject(piCatalog); | ||
| 567 | |||
| 568 | ReleaseStr(pwzRollbackFileName); | ||
| 569 | ReleaseStr(pwzActionData); | ||
| 570 | ReleaseStr(pwzRollbackActionData); | ||
| 571 | |||
| 572 | CpiPartitionListFree(&partList); | ||
| 573 | CpiPartitionRoleListFree(&partRoleList); | ||
| 574 | CpiUserInPartitionRoleListFree(&usrInPartRoleList); | ||
| 575 | CpiPartitionUserListFree(&partUsrList); | ||
| 576 | CpiApplicationListFree(&appList); | ||
| 577 | CpiApplicationRoleListFree(&appRoleList); | ||
| 578 | CpiUserInApplicationRoleListFree(&usrInAppRoleList); | ||
| 579 | CpiAssemblyListFree(&asmList); | ||
| 580 | CpiSubscriptionListFree(&subList); | ||
| 581 | |||
| 582 | // unitialize | ||
| 583 | CpiFinalize(); | ||
| 584 | |||
| 585 | if (fInitializedCom) | ||
| 586 | ::CoUninitialize(); | ||
| 587 | |||
| 588 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
| 589 | return WcaFinalize(er); | ||
| 590 | } | ||
diff --git a/src/ca/cpsubsexec.cpp b/src/ca/cpsubsexec.cpp new file mode 100644 index 00000000..bbcf9853 --- /dev/null +++ b/src/ca/cpsubsexec.cpp | |||
| @@ -0,0 +1,411 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // private structs | ||
| 7 | |||
| 8 | struct CPI_SUBSCRIPTION_ATTRIBUTES | ||
| 9 | { | ||
| 10 | int iActionType; | ||
| 11 | int iActionCost; | ||
| 12 | LPWSTR pwzKey; | ||
| 13 | LPWSTR pwzID; | ||
| 14 | LPWSTR pwzName; | ||
| 15 | LPWSTR pwzEventCLSID; | ||
| 16 | LPWSTR pwzPublisherID; | ||
| 17 | LPWSTR pwzCompCLSID; | ||
| 18 | LPWSTR pwzAppID; | ||
| 19 | LPWSTR pwzPartID; | ||
| 20 | CPI_PROPERTY* pPropList; | ||
| 21 | }; | ||
| 22 | |||
| 23 | |||
| 24 | // prototypes for private helper functions | ||
| 25 | |||
| 26 | static HRESULT ReadSubscriptionAttributes( | ||
| 27 | LPWSTR* ppwzData, | ||
| 28 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
| 29 | ); | ||
| 30 | static void FreeSubscriptionAttributes( | ||
| 31 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
| 32 | ); | ||
| 33 | static HRESULT CreateSubscription( | ||
| 34 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
| 35 | ); | ||
| 36 | static HRESULT RemoveSubscription( | ||
| 37 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
| 38 | ); | ||
| 39 | |||
| 40 | |||
| 41 | // function definitions | ||
| 42 | |||
| 43 | HRESULT CpiConfigureSubscriptions( | ||
| 44 | LPWSTR* ppwzData, | ||
| 45 | HANDLE hRollbackFile | ||
| 46 | ) | ||
| 47 | { | ||
| 48 | HRESULT hr = S_OK; | ||
| 49 | |||
| 50 | CPI_SUBSCRIPTION_ATTRIBUTES attrs; | ||
| 51 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 52 | |||
| 53 | // read action text | ||
| 54 | hr = CpiActionStartMessage(ppwzData, FALSE); | ||
| 55 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 56 | |||
| 57 | // ger count | ||
| 58 | int iCnt = 0; | ||
| 59 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 60 | ExitOnFailure(hr, "Failed to read count"); | ||
| 61 | |||
| 62 | // write count to rollback file | ||
| 63 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, iCnt); | ||
| 64 | ExitOnFailure(hr, "Failed to write count to rollback file"); | ||
| 65 | |||
| 66 | for (int i = 0; i < iCnt; i++) | ||
| 67 | { | ||
| 68 | // read attributes from CustomActionData | ||
| 69 | hr = ReadSubscriptionAttributes(ppwzData, &attrs); | ||
| 70 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 71 | |||
| 72 | // progress message | ||
| 73 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
| 74 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 75 | |||
| 76 | if (S_FALSE == hr) | ||
| 77 | ExitFunction(); | ||
| 78 | |||
| 79 | // write key to rollback file | ||
| 80 | hr = CpiWriteKeyToRollbackFile(hRollbackFile, attrs.pwzKey); | ||
| 81 | ExitOnFailure(hr, "Failed to write key to rollback file"); | ||
| 82 | |||
| 83 | // action | ||
| 84 | switch (attrs.iActionType) | ||
| 85 | { | ||
| 86 | case atCreate: | ||
| 87 | hr = CreateSubscription(&attrs); | ||
| 88 | ExitOnFailure(hr, "Failed to create subscription, key: %S", attrs.pwzKey); | ||
| 89 | break; | ||
| 90 | case atRemove: | ||
| 91 | hr = RemoveSubscription(&attrs); | ||
| 92 | ExitOnFailure(hr, "Failed to remove subscription, key: %S", attrs.pwzKey); | ||
| 93 | break; | ||
| 94 | } | ||
| 95 | |||
| 96 | // write completion status to rollback file | ||
| 97 | hr = CpiWriteIntegerToRollbackFile(hRollbackFile, 1); | ||
| 98 | ExitOnFailure(hr, "Failed to write completion status to rollback file"); | ||
| 99 | |||
| 100 | // progress | ||
| 101 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 102 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 103 | } | ||
| 104 | |||
| 105 | hr = S_OK; | ||
| 106 | |||
| 107 | LExit: | ||
| 108 | // clean up | ||
| 109 | FreeSubscriptionAttributes(&attrs); | ||
| 110 | |||
| 111 | return hr; | ||
| 112 | } | ||
| 113 | |||
| 114 | HRESULT CpiRollbackConfigureSubscriptions( | ||
| 115 | LPWSTR* ppwzData, | ||
| 116 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 117 | ) | ||
| 118 | { | ||
| 119 | HRESULT hr = S_OK; | ||
| 120 | |||
| 121 | int iRollbackStatus; | ||
| 122 | |||
| 123 | CPI_SUBSCRIPTION_ATTRIBUTES attrs; | ||
| 124 | ::ZeroMemory(&attrs, sizeof(attrs)); | ||
| 125 | |||
| 126 | // read action text | ||
| 127 | hr = CpiActionStartMessage(ppwzData, NULL == pRollbackDataList); | ||
| 128 | ExitOnFailure(hr, "Failed to send action start message"); | ||
| 129 | |||
| 130 | // ger count | ||
| 131 | int iCnt = 0; | ||
| 132 | hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); | ||
| 133 | ExitOnFailure(hr, "Failed to read count"); | ||
| 134 | |||
| 135 | for (int i = 0; i < iCnt; i++) | ||
| 136 | { | ||
| 137 | // read attributes from CustomActionData | ||
| 138 | hr = ReadSubscriptionAttributes(ppwzData, &attrs); | ||
| 139 | ExitOnFailure(hr, "Failed to read attributes"); | ||
| 140 | |||
| 141 | // rollback status | ||
| 142 | hr = CpiFindRollbackStatus(pRollbackDataList, attrs.pwzKey, &iRollbackStatus); | ||
| 143 | |||
| 144 | if (S_FALSE == hr) | ||
| 145 | continue; // not found, nothing to rollback | ||
| 146 | |||
| 147 | // progress message | ||
| 148 | hr = CpiActionDataMessage(1, attrs.pwzName); | ||
| 149 | ExitOnFailure(hr, "Failed to send progress messages"); | ||
| 150 | |||
| 151 | if (S_FALSE == hr) | ||
| 152 | ExitFunction(); | ||
| 153 | |||
| 154 | // action | ||
| 155 | switch (attrs.iActionType) | ||
| 156 | { | ||
| 157 | case atCreate: | ||
| 158 | hr = CreateSubscription(&attrs); | ||
| 159 | if (FAILED(hr)) | ||
| 160 | WcaLog(LOGMSG_STANDARD, "Failed to create subscription, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 161 | break; | ||
| 162 | case atRemove: | ||
| 163 | hr = RemoveSubscription(&attrs); | ||
| 164 | if (FAILED(hr)) | ||
| 165 | WcaLog(LOGMSG_STANDARD, "Failed to remove subscription, hr: 0x%x, key: %S", hr, attrs.pwzKey); | ||
| 166 | break; | ||
| 167 | } | ||
| 168 | |||
| 169 | // check rollback status | ||
| 170 | if (0 == iRollbackStatus) | ||
| 171 | continue; // operation did not complete, skip progress | ||
| 172 | |||
| 173 | // progress | ||
| 174 | hr = WcaProgressMessage(attrs.iActionCost, FALSE); | ||
| 175 | ExitOnFailure(hr, "Failed to update progress"); | ||
| 176 | } | ||
| 177 | |||
| 178 | hr = S_OK; | ||
| 179 | |||
| 180 | LExit: | ||
| 181 | // clean up | ||
| 182 | FreeSubscriptionAttributes(&attrs); | ||
| 183 | |||
| 184 | return hr; | ||
| 185 | } | ||
| 186 | |||
| 187 | |||
| 188 | // helper function definitions | ||
| 189 | |||
| 190 | static HRESULT ReadSubscriptionAttributes( | ||
| 191 | LPWSTR* ppwzData, | ||
| 192 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
| 193 | ) | ||
| 194 | { | ||
| 195 | HRESULT hr = S_OK; | ||
| 196 | |||
| 197 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionType); | ||
| 198 | ExitOnFailure(hr, "Failed to read action type"); | ||
| 199 | hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iActionCost); | ||
| 200 | ExitOnFailure(hr, "Failed to read action cost"); | ||
| 201 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey); | ||
| 202 | ExitOnFailure(hr, "Failed to read key"); | ||
| 203 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzID); | ||
| 204 | ExitOnFailure(hr, "Failed to read id"); | ||
| 205 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName); | ||
| 206 | ExitOnFailure(hr, "Failed to read name"); | ||
| 207 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzEventCLSID); | ||
| 208 | ExitOnFailure(hr, "Failed to read event clsid"); | ||
| 209 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPublisherID); | ||
| 210 | ExitOnFailure(hr, "Failed to read publisher id"); | ||
| 211 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzCompCLSID); | ||
| 212 | ExitOnFailure(hr, "Failed to read component clsid"); | ||
| 213 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzAppID); | ||
| 214 | ExitOnFailure(hr, "Failed to read application id"); | ||
| 215 | hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPartID); | ||
| 216 | ExitOnFailure(hr, "Failed to read partition id"); | ||
| 217 | |||
| 218 | hr = CpiReadPropertyList(ppwzData, &pAttrs->pPropList); | ||
| 219 | ExitOnFailure(hr, "Failed to read properties"); | ||
| 220 | |||
| 221 | hr = S_OK; | ||
| 222 | |||
| 223 | LExit: | ||
| 224 | return hr; | ||
| 225 | } | ||
| 226 | |||
| 227 | static void FreeSubscriptionAttributes( | ||
| 228 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
| 229 | ) | ||
| 230 | { | ||
| 231 | ReleaseStr(pAttrs->pwzKey); | ||
| 232 | ReleaseStr(pAttrs->pwzID); | ||
| 233 | ReleaseStr(pAttrs->pwzName); | ||
| 234 | ReleaseStr(pAttrs->pwzEventCLSID); | ||
| 235 | ReleaseStr(pAttrs->pwzPublisherID); | ||
| 236 | ReleaseStr(pAttrs->pwzCompCLSID); | ||
| 237 | ReleaseStr(pAttrs->pwzAppID); | ||
| 238 | ReleaseStr(pAttrs->pwzPartID); | ||
| 239 | |||
| 240 | if (pAttrs->pPropList) | ||
| 241 | CpiFreePropertyList(pAttrs->pPropList); | ||
| 242 | } | ||
| 243 | |||
| 244 | static HRESULT CreateSubscription( | ||
| 245 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
| 246 | ) | ||
| 247 | { | ||
| 248 | HRESULT hr = S_OK; | ||
| 249 | UINT er = ERROR_SUCCESS; | ||
| 250 | |||
| 251 | ICatalogCollection* piSubsColl = NULL; | ||
| 252 | ICatalogObject* piSubsObj = NULL; | ||
| 253 | |||
| 254 | PSID pSid = NULL; | ||
| 255 | long lChanges = 0; | ||
| 256 | |||
| 257 | // log | ||
| 258 | WcaLog(LOGMSG_VERBOSE, "Creating subscription, key: %S", pAttrs->pwzKey); | ||
| 259 | |||
| 260 | // get subscriptions collection | ||
| 261 | hr = CpiGetSubscriptionsCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzCompCLSID, &piSubsColl); | ||
| 262 | if (S_FALSE == hr) | ||
| 263 | hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | ||
| 264 | ExitOnFailure(hr, "Failed to get subscriptions collection"); | ||
| 265 | |||
| 266 | // check if subscription exists | ||
| 267 | hr = CpiFindCollectionObjectByStringKey(piSubsColl, pAttrs->pwzID, &piSubsObj); | ||
| 268 | ExitOnFailure(hr, "Failed to find subscription"); | ||
| 269 | |||
| 270 | if (S_FALSE == hr) | ||
| 271 | { | ||
| 272 | // create subscription | ||
| 273 | hr = CpiAddCollectionObject(piSubsColl, &piSubsObj); | ||
| 274 | ExitOnFailure(hr, "Failed to add subscription to collection"); | ||
| 275 | |||
| 276 | hr = CpiPutCollectionObjectValue(piSubsObj, L"ID", pAttrs->pwzID); | ||
| 277 | ExitOnFailure(hr, "Failed to set subscription id property"); | ||
| 278 | |||
| 279 | hr = CpiPutCollectionObjectValue(piSubsObj, L"Name", pAttrs->pwzName); | ||
| 280 | ExitOnFailure(hr, "Failed to set subscription name property"); | ||
| 281 | |||
| 282 | if (pAttrs->pwzEventCLSID && *pAttrs->pwzEventCLSID) | ||
| 283 | { | ||
| 284 | hr = CpiPutCollectionObjectValue(piSubsObj, L"EventCLSID", pAttrs->pwzEventCLSID); | ||
| 285 | ExitOnFailure(hr, "Failed to set role event clsid property"); | ||
| 286 | } | ||
| 287 | |||
| 288 | if (pAttrs->pwzPublisherID && *pAttrs->pwzPublisherID) | ||
| 289 | { | ||
| 290 | hr = CpiPutCollectionObjectValue(piSubsObj, L"PublisherID", pAttrs->pwzPublisherID); | ||
| 291 | ExitOnFailure(hr, "Failed to set role publisher id property"); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | // properties | ||
| 296 | for (CPI_PROPERTY* pItm = pAttrs->pPropList; pItm; pItm = pItm->pNext) | ||
| 297 | { | ||
| 298 | // UserName property | ||
| 299 | if (0 == lstrcmpW(pItm->wzName, L"UserName")) | ||
| 300 | { | ||
| 301 | // get SID for account | ||
| 302 | do { | ||
| 303 | er = ERROR_SUCCESS; | ||
| 304 | hr = CpiAccountNameToSid(pItm->pwzValue, &pSid); | ||
| 305 | if (!::MsiGetMode(WcaGetInstallHandle(), MSIRUNMODE_ROLLBACK)) | ||
| 306 | { | ||
| 307 | if (HRESULT_FROM_WIN32(ERROR_NONE_MAPPED) == hr) | ||
| 308 | { | ||
| 309 | WcaLog(LOGMSG_STANDARD, "Failed to lookup account name, hr: 0x%x, account: '%S'", hr, pItm->pwzValue); | ||
| 310 | er = WcaErrorMessage(msierrComPlusFailedLookupNames, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 311 | switch (er) | ||
| 312 | { | ||
| 313 | case IDABORT: | ||
| 314 | ExitFunction(); // exit with error code from CpiAccountNameToSid() | ||
| 315 | case IDRETRY: | ||
| 316 | break; | ||
| 317 | case IDIGNORE: | ||
| 318 | default: | ||
| 319 | hr = S_FALSE; | ||
| 320 | } | ||
| 321 | } | ||
| 322 | else | ||
| 323 | ExitOnFailure(hr, "Failed to get SID for account, account: '%S'", pItm->pwzValue); | ||
| 324 | } | ||
| 325 | else if (FAILED(hr)) | ||
| 326 | { | ||
| 327 | WcaLog(LOGMSG_STANDARD, "Failed to get SID for account, hr: 0x%x, account: '%S'", hr, pItm->pwzValue); | ||
| 328 | hr = S_FALSE; | ||
| 329 | } | ||
| 330 | } while (IDRETRY == er); | ||
| 331 | |||
| 332 | if (S_FALSE == hr) | ||
| 333 | continue; | ||
| 334 | |||
| 335 | // convert SID back to account name | ||
| 336 | hr = CpiSidToAccountName(pSid, &pItm->pwzValue); | ||
| 337 | ExitOnFailure(hr, "Failed to convert SID to account name"); | ||
| 338 | } | ||
| 339 | |||
| 340 | // set property | ||
| 341 | hr = CpiPutCollectionObjectValue(piSubsObj, pItm->wzName, pItm->pwzValue); | ||
| 342 | ExitOnFailure(hr, "Failed to set object property value, name: %S", pItm->wzName); | ||
| 343 | } | ||
| 344 | |||
| 345 | // save changes | ||
| 346 | hr = piSubsColl->SaveChanges(&lChanges); | ||
| 347 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 348 | CpiLogCatalogErrorInfo(); | ||
| 349 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 350 | |||
| 351 | // log | ||
| 352 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 353 | |||
| 354 | hr = S_OK; | ||
| 355 | |||
| 356 | LExit: | ||
| 357 | // clean up | ||
| 358 | ReleaseObject(piSubsColl); | ||
| 359 | ReleaseObject(piSubsObj); | ||
| 360 | |||
| 361 | if (pSid) | ||
| 362 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
| 363 | |||
| 364 | return hr; | ||
| 365 | } | ||
| 366 | |||
| 367 | static HRESULT RemoveSubscription( | ||
| 368 | CPI_SUBSCRIPTION_ATTRIBUTES* pAttrs | ||
| 369 | ) | ||
| 370 | { | ||
| 371 | HRESULT hr = S_OK; | ||
| 372 | |||
| 373 | ICatalogCollection* piSubsColl = NULL; | ||
| 374 | |||
| 375 | long lChanges = 0; | ||
| 376 | |||
| 377 | // log | ||
| 378 | WcaLog(LOGMSG_VERBOSE, "Removing subscription, key: %S", pAttrs->pwzKey); | ||
| 379 | |||
| 380 | // get subscriptions collection | ||
| 381 | hr = CpiGetSubscriptionsCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, pAttrs->pwzCompCLSID, &piSubsColl); | ||
| 382 | ExitOnFailure(hr, "Failed to get subscriptions collection"); | ||
| 383 | |||
| 384 | if (S_FALSE == hr) | ||
| 385 | { | ||
| 386 | // subscription not found | ||
| 387 | WcaLog(LOGMSG_VERBOSE, "Unable to retrieve subscriptions collection, nothing to delete, key: %S", pAttrs->pwzKey); | ||
| 388 | ExitFunction1(hr = S_OK); | ||
| 389 | } | ||
| 390 | |||
| 391 | // remove | ||
| 392 | hr = CpiRemoveCollectionObject(piSubsColl, pAttrs->pwzID, NULL, FALSE); | ||
| 393 | ExitOnFailure(hr, "Failed to remove subscriptions"); | ||
| 394 | |||
| 395 | // save changes | ||
| 396 | hr = piSubsColl->SaveChanges(&lChanges); | ||
| 397 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 398 | CpiLogCatalogErrorInfo(); | ||
| 399 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 400 | |||
| 401 | // log | ||
| 402 | WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); | ||
| 403 | |||
| 404 | hr = S_OK; | ||
| 405 | |||
| 406 | LExit: | ||
| 407 | // clean up | ||
| 408 | ReleaseObject(piSubsColl); | ||
| 409 | |||
| 410 | return hr; | ||
| 411 | } | ||
diff --git a/src/ca/cpsubsexec.h b/src/ca/cpsubsexec.h new file mode 100644 index 00000000..2f4d3c75 --- /dev/null +++ b/src/ca/cpsubsexec.h | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | HRESULT CpiConfigureSubscriptions( | ||
| 6 | LPWSTR* ppwzData, | ||
| 7 | HANDLE hRollbackFile | ||
| 8 | ); | ||
| 9 | HRESULT CpiRollbackConfigureSubscriptions( | ||
| 10 | LPWSTR* ppwzData, | ||
| 11 | CPI_ROLLBACK_DATA* pRollbackDataList | ||
| 12 | ); | ||
diff --git a/src/ca/cpsubssched.cpp b/src/ca/cpsubssched.cpp new file mode 100644 index 00000000..73fd4f6d --- /dev/null +++ b/src/ca/cpsubssched.cpp | |||
| @@ -0,0 +1,606 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // sql queries | ||
| 7 | |||
| 8 | LPCWSTR vcsSubscriptionQuery = | ||
| 9 | L"SELECT `Subscription`, `ComPlusComponent_`, `Component_`, `Id`, `Name`, `EventCLSID`, `PublisherID` FROM `ComPlusSubscription`"; | ||
| 10 | enum eSubscriptionQuery { sqSubscription = 1, sqComPlusComponent, sqComponent, sqID, sqName, sqEventCLSID, sqPublisherID }; | ||
| 11 | |||
| 12 | LPCWSTR vcsSubscriptionPropertyQuery = | ||
| 13 | L"SELECT `Name`, `Value` FROM `ComPlusSubscriptionProperty` WHERE `Subscription_` = ?"; | ||
| 14 | |||
| 15 | |||
| 16 | // property definitions | ||
| 17 | |||
| 18 | CPI_PROPERTY_DEFINITION pdlSubscriptionProperties[] = | ||
| 19 | { | ||
| 20 | {L"Description", cpptString, 500}, | ||
| 21 | {L"Enabled", cpptBoolean, 500}, | ||
| 22 | {L"EventClassPartitionID", cpptString, 502}, | ||
| 23 | {L"FilterCriteria", cpptString, 500}, | ||
| 24 | {L"InterfaceID", cpptString, 500}, | ||
| 25 | {L"MachineName", cpptString, 500}, | ||
| 26 | {L"MethodName", cpptString, 500}, | ||
| 27 | {L"PerUser", cpptBoolean, 500}, | ||
| 28 | {L"Queued", cpptBoolean, 500}, | ||
| 29 | {L"SubscriberMoniker", cpptString, 500}, | ||
| 30 | {L"UserName", cpptUser, 500}, | ||
| 31 | {NULL, cpptNone, 0} | ||
| 32 | }; | ||
| 33 | |||
| 34 | |||
| 35 | // prototypes for private helper functions | ||
| 36 | |||
| 37 | static void FreeSubscription( | ||
| 38 | CPI_SUBSCRIPTION* pItm | ||
| 39 | ); | ||
| 40 | static HRESULT FindObjectForSubscription( | ||
| 41 | CPI_SUBSCRIPTION* pItm, | ||
| 42 | BOOL fFindId, | ||
| 43 | BOOL fFindName, | ||
| 44 | ICatalogObject** ppiSubsObj | ||
| 45 | ); | ||
| 46 | static HRESULT AddSubscriptionToActionData( | ||
| 47 | CPI_SUBSCRIPTION* pItm, | ||
| 48 | int iActionType, | ||
| 49 | int iActionCost, | ||
| 50 | LPWSTR* ppwzActionData | ||
| 51 | ); | ||
| 52 | static HRESULT ComponentFindByKey( | ||
| 53 | CPI_ASSEMBLY_LIST* pAsmList, | ||
| 54 | LPCWSTR pwzKey, | ||
| 55 | CPI_ASSEMBLY** ppAsmItm, | ||
| 56 | CPI_COMPONENT** ppCompItm | ||
| 57 | ); | ||
| 58 | |||
| 59 | |||
| 60 | // function definitions | ||
| 61 | |||
| 62 | void CpiSubscriptionListFree( | ||
| 63 | CPI_SUBSCRIPTION_LIST* pList | ||
| 64 | ) | ||
| 65 | { | ||
| 66 | CPI_SUBSCRIPTION* pItm = pList->pFirst; | ||
| 67 | |||
| 68 | while (pItm) | ||
| 69 | { | ||
| 70 | CPI_SUBSCRIPTION* pDelete = pItm; | ||
| 71 | pItm = pItm->pNext; | ||
| 72 | FreeSubscription(pDelete); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | HRESULT CpiSubscriptionsRead( | ||
| 77 | CPI_ASSEMBLY_LIST* pAsmList, | ||
| 78 | CPI_SUBSCRIPTION_LIST* pSubList | ||
| 79 | ) | ||
| 80 | { | ||
| 81 | HRESULT hr = S_OK; | ||
| 82 | UINT er = ERROR_SUCCESS; | ||
| 83 | |||
| 84 | PMSIHANDLE hView, hRec; | ||
| 85 | |||
| 86 | CPI_SUBSCRIPTION* pItm = NULL; | ||
| 87 | LPWSTR pwzData = NULL; | ||
| 88 | BOOL fMatchingArchitecture = FALSE; | ||
| 89 | |||
| 90 | // loop through all applications | ||
| 91 | hr = WcaOpenExecuteView(vcsSubscriptionQuery, &hView); | ||
| 92 | ExitOnFailure(hr, "Failed to execute view on ComPlusSubscription table"); | ||
| 93 | |||
| 94 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 95 | { | ||
| 96 | // get component | ||
| 97 | hr = WcaGetRecordString(hRec, sqComponent, &pwzData); | ||
| 98 | ExitOnFailure(hr, "Failed to get component"); | ||
| 99 | |||
| 100 | // check if the component is our processor architecture | ||
| 101 | hr = CpiVerifyComponentArchitecure(pwzData, &fMatchingArchitecture); | ||
| 102 | ExitOnFailure(hr, "Failed to get component architecture."); | ||
| 103 | |||
| 104 | if (!fMatchingArchitecture) | ||
| 105 | { | ||
| 106 | continue; // not the same architecture, ignore | ||
| 107 | } | ||
| 108 | |||
| 109 | // create entry | ||
| 110 | pItm = (CPI_SUBSCRIPTION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_SUBSCRIPTION)); | ||
| 111 | if (!pItm) | ||
| 112 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 113 | |||
| 114 | // get component install state | ||
| 115 | er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction); | ||
| 116 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state"); | ||
| 117 | |||
| 118 | // get key | ||
| 119 | hr = WcaGetRecordString(hRec, sqSubscription, &pwzData); | ||
| 120 | ExitOnFailure(hr, "Failed to get key"); | ||
| 121 | StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData); | ||
| 122 | |||
| 123 | // get com+ component | ||
| 124 | hr = WcaGetRecordString(hRec, sqComPlusComponent, &pwzData); | ||
| 125 | ExitOnFailure(hr, "Failed to get COM+ component"); | ||
| 126 | |||
| 127 | hr = ComponentFindByKey(pAsmList, pwzData, &pItm->pAssembly, &pItm->pComponent); | ||
| 128 | |||
| 129 | if (S_FALSE == hr) | ||
| 130 | { | ||
| 131 | // component not found | ||
| 132 | ExitOnFailure(hr = E_FAIL, "Failed to find component, key: %S", pwzData); | ||
| 133 | } | ||
| 134 | |||
| 135 | // get id | ||
| 136 | hr = WcaGetRecordFormattedString(hRec, sqID, &pwzData); | ||
| 137 | ExitOnFailure(hr, "Failed to get id"); | ||
| 138 | |||
| 139 | if (pwzData && *pwzData) | ||
| 140 | { | ||
| 141 | hr = PcaGuidToRegFormat(pwzData, pItm->wzID, countof(pItm->wzID)); | ||
| 142 | ExitOnFailure(hr, "Failed to parse id guid value, key: %S, value: '%S'", pItm->wzKey, pwzData); | ||
| 143 | } | ||
| 144 | |||
| 145 | // get name | ||
| 146 | hr = WcaGetRecordFormattedString(hRec, sqName, &pwzData); | ||
| 147 | ExitOnFailure(hr, "Failed to get name"); | ||
| 148 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
| 149 | |||
| 150 | // get event clsid | ||
| 151 | hr = WcaGetRecordFormattedString(hRec, sqEventCLSID, &pwzData); | ||
| 152 | ExitOnFailure(hr, "Failed to get event clsid"); | ||
| 153 | StringCchCopyW(pItm->wzEventCLSID, countof(pItm->wzEventCLSID), pwzData); | ||
| 154 | |||
| 155 | // get publisher id | ||
| 156 | hr = WcaGetRecordFormattedString(hRec, sqPublisherID, &pwzData); | ||
| 157 | ExitOnFailure(hr, "Failed to get publisher id"); | ||
| 158 | StringCchCopyW(pItm->wzPublisherID, countof(pItm->wzPublisherID), pwzData); | ||
| 159 | |||
| 160 | // get properties | ||
| 161 | if (CpiTableExists(cptComPlusSubscriptionProperty)) | ||
| 162 | { | ||
| 163 | hr = CpiPropertiesRead(vcsSubscriptionPropertyQuery, pItm->wzKey, pdlSubscriptionProperties, &pItm->pProperties, &pItm->iPropertyCount); | ||
| 164 | ExitOnFailure(hr, "Failed to get subscription properties"); | ||
| 165 | } | ||
| 166 | |||
| 167 | // set references & increment counters | ||
| 168 | if (WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 169 | { | ||
| 170 | CpiApplicationAddReferenceInstall(pItm->pAssembly->pApplication); | ||
| 171 | pItm->pAssembly->fReferencedForInstall = TRUE; | ||
| 172 | pSubList->iInstallCount++; | ||
| 173 | if (pItm->pAssembly->iAttributes & aaRunInCommit) | ||
| 174 | pSubList->iCommitCount++; | ||
| 175 | } | ||
| 176 | if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 177 | { | ||
| 178 | CpiApplicationAddReferenceUninstall(pItm->pAssembly->pApplication); | ||
| 179 | pItm->pAssembly->fReferencedForUninstall = TRUE; | ||
| 180 | pSubList->iUninstallCount++; | ||
| 181 | } | ||
| 182 | |||
| 183 | // add entry | ||
| 184 | if (pSubList->pFirst) | ||
| 185 | pItm->pNext = pSubList->pFirst; | ||
| 186 | pSubList->pFirst = pItm; | ||
| 187 | pItm = NULL; | ||
| 188 | } | ||
| 189 | |||
| 190 | if (E_NOMOREITEMS == hr) | ||
| 191 | hr = S_OK; | ||
| 192 | |||
| 193 | LExit: | ||
| 194 | // clean up | ||
| 195 | if (pItm) | ||
| 196 | FreeSubscription(pItm); | ||
| 197 | |||
| 198 | ReleaseStr(pwzData); | ||
| 199 | |||
| 200 | return hr; | ||
| 201 | } | ||
| 202 | |||
| 203 | HRESULT CpiSubscriptionsVerifyInstall( | ||
| 204 | CPI_SUBSCRIPTION_LIST* pList | ||
| 205 | ) | ||
| 206 | { | ||
| 207 | HRESULT hr = S_OK; | ||
| 208 | UINT er = ERROR_SUCCESS; | ||
| 209 | |||
| 210 | ICatalogObject* piSubsObj = NULL; | ||
| 211 | |||
| 212 | for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 213 | { | ||
| 214 | // subscriptions that are being installed | ||
| 215 | if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 216 | continue; | ||
| 217 | |||
| 218 | // subscription is supposed to exist | ||
| 219 | if (CpiIsInstalled(pItm->isInstalled)) | ||
| 220 | { | ||
| 221 | // if we don't have an id | ||
| 222 | if (!*pItm->wzID) | ||
| 223 | { | ||
| 224 | // find subscriptions with conflicting name | ||
| 225 | hr = FindObjectForSubscription(pItm, FALSE, TRUE, &piSubsObj); | ||
| 226 | ExitOnFailure(hr, "Failed to find collection object for subscription"); | ||
| 227 | |||
| 228 | // if the subscription was found | ||
| 229 | if (S_OK == hr) | ||
| 230 | { | ||
| 231 | // get id from subscription object | ||
| 232 | hr = CpiGetKeyForObject(piSubsObj, pItm->wzID, countof(pItm->wzID)); | ||
| 233 | ExitOnFailure(hr, "Failed to get id"); | ||
| 234 | } | ||
| 235 | |||
| 236 | // if the subscription was not found | ||
| 237 | else | ||
| 238 | { | ||
| 239 | // create a new id | ||
| 240 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
| 241 | ExitOnFailure(hr, "Failed to create id"); | ||
| 242 | } | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | // subscription is supposed to be created | ||
| 247 | else | ||
| 248 | { | ||
| 249 | // check for conflicts | ||
| 250 | do { | ||
| 251 | if (*pItm->wzID) | ||
| 252 | { | ||
| 253 | // find subscriptions with conflicting id | ||
| 254 | hr = FindObjectForSubscription(pItm, TRUE, FALSE, &piSubsObj); | ||
| 255 | ExitOnFailure(hr, "Failed to find collection object for subscription"); | ||
| 256 | |||
| 257 | if (S_FALSE == hr) | ||
| 258 | { | ||
| 259 | // find subscriptions with conflicting name | ||
| 260 | hr = FindObjectForSubscription(pItm, FALSE, TRUE, &piSubsObj); | ||
| 261 | ExitOnFailure(hr, "Failed to find collection object for subscription"); | ||
| 262 | |||
| 263 | if (S_OK == hr) | ||
| 264 | // "A subscription with a conflictiong name exists. retry cancel" | ||
| 265 | er = WcaErrorMessage(msierrComPlusSubscriptionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_RETRYCANCEL, 0); | ||
| 266 | else | ||
| 267 | break; // no conflicting entry found, break loop | ||
| 268 | } | ||
| 269 | else | ||
| 270 | // "A subscription with a conflicting id exists. abort retry ignore" | ||
| 271 | er = WcaErrorMessage(msierrComPlusSubscriptionIdConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 272 | } | ||
| 273 | else | ||
| 274 | { | ||
| 275 | // find subscriptions with conflicting name | ||
| 276 | hr = FindObjectForSubscription(pItm, FALSE, TRUE, &piSubsObj); | ||
| 277 | ExitOnFailure(hr, "Failed to find collection object for subscription"); | ||
| 278 | |||
| 279 | if (S_OK == hr) | ||
| 280 | // "A subscription with a conflictiong name exists. abort retry ignore" | ||
| 281 | er = WcaErrorMessage(msierrComPlusSubscriptionNameConflict, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
| 282 | else | ||
| 283 | break; // no conflicting entry found, break loop | ||
| 284 | } | ||
| 285 | |||
| 286 | switch (er) | ||
| 287 | { | ||
| 288 | case IDCANCEL: | ||
| 289 | case IDABORT: | ||
| 290 | ExitOnFailure(hr = E_FAIL, "A subscription with a conflictiong name or id exists, key: %S", pItm->wzKey); | ||
| 291 | break; | ||
| 292 | case IDRETRY: | ||
| 293 | break; | ||
| 294 | case IDIGNORE: | ||
| 295 | default: | ||
| 296 | // if we don't have an id, copy id from object | ||
| 297 | if (!*pItm->wzID) | ||
| 298 | { | ||
| 299 | hr = CpiGetKeyForObject(piSubsObj, pItm->wzID, countof(pItm->wzID)); | ||
| 300 | ExitOnFailure(hr, "Failed to get id"); | ||
| 301 | } | ||
| 302 | hr = S_FALSE; // indicate that this is not a conflict | ||
| 303 | } | ||
| 304 | } while (S_OK == hr); // hr = S_FALSE if we don't have any conflicts | ||
| 305 | |||
| 306 | // create a new id if one is missing | ||
| 307 | if (!*pItm->wzID) | ||
| 308 | { | ||
| 309 | hr = CpiCreateId(pItm->wzID, countof(pItm->wzID)); | ||
| 310 | ExitOnFailure(hr, "Failed to create id"); | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | // clean up | ||
| 315 | ReleaseNullObject(piSubsObj); | ||
| 316 | } | ||
| 317 | |||
| 318 | hr = S_OK; | ||
| 319 | |||
| 320 | LExit: | ||
| 321 | // clean up | ||
| 322 | ReleaseObject(piSubsObj); | ||
| 323 | |||
| 324 | return hr; | ||
| 325 | } | ||
| 326 | |||
| 327 | HRESULT CpiSubscriptionsVerifyUninstall( | ||
| 328 | CPI_SUBSCRIPTION_LIST* pList | ||
| 329 | ) | ||
| 330 | { | ||
| 331 | HRESULT hr = S_OK; | ||
| 332 | ICatalogObject* piSubsObj = NULL; | ||
| 333 | |||
| 334 | for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 335 | { | ||
| 336 | // subscriptions that are being installed | ||
| 337 | if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 338 | continue; | ||
| 339 | |||
| 340 | // find subscriptions with conflicting name | ||
| 341 | hr = FindObjectForSubscription(pItm, 0 != *pItm->wzID, 0 == *pItm->wzID, &piSubsObj); | ||
| 342 | ExitOnFailure(hr, "Failed to find collection object for subscription"); | ||
| 343 | |||
| 344 | // if the subscription was found | ||
| 345 | if (S_OK == hr) | ||
| 346 | { | ||
| 347 | // if we don't have an id, copy id from object | ||
| 348 | if (!*pItm->wzID) | ||
| 349 | { | ||
| 350 | hr = CpiGetKeyForObject(piSubsObj, pItm->wzID, countof(pItm->wzID)); | ||
| 351 | ExitOnFailure(hr, "Failed to get id"); | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | // if the subscription was not found | ||
| 356 | else | ||
| 357 | { | ||
| 358 | pItm->fObjectNotFound = TRUE; | ||
| 359 | pList->iUninstallCount--; // elements with the fObjectNotFound flag set will not be scheduled for uninstall | ||
| 360 | } | ||
| 361 | |||
| 362 | // clean up | ||
| 363 | ReleaseNullObject(piSubsObj); | ||
| 364 | } | ||
| 365 | |||
| 366 | hr = S_OK; | ||
| 367 | |||
| 368 | LExit: | ||
| 369 | // clean up | ||
| 370 | ReleaseObject(piSubsObj); | ||
| 371 | |||
| 372 | return hr; | ||
| 373 | } | ||
| 374 | |||
| 375 | HRESULT CpiSubscriptionsInstall( | ||
| 376 | CPI_SUBSCRIPTION_LIST* pList, | ||
| 377 | int iRunMode, | ||
| 378 | LPWSTR* ppwzActionData, | ||
| 379 | int* piProgress | ||
| 380 | ) | ||
| 381 | { | ||
| 382 | HRESULT hr = S_OK; | ||
| 383 | |||
| 384 | int iActionType; | ||
| 385 | int iCount = 0; | ||
| 386 | |||
| 387 | // add action text | ||
| 388 | hr = CpiAddActionTextToActionData(L"CreateSubscrComPlusComponents", ppwzActionData); | ||
| 389 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 390 | |||
| 391 | // subscription count | ||
| 392 | switch (iRunMode) | ||
| 393 | { | ||
| 394 | case rmDeferred: | ||
| 395 | iCount = pList->iInstallCount - pList->iCommitCount; | ||
| 396 | break; | ||
| 397 | case rmCommit: | ||
| 398 | iCount = pList->iCommitCount; | ||
| 399 | break; | ||
| 400 | case rmRollback: | ||
| 401 | iCount = pList->iInstallCount; | ||
| 402 | break; | ||
| 403 | } | ||
| 404 | |||
| 405 | // add subscription count to action data | ||
| 406 | hr = WcaWriteIntegerToCaData(iCount, ppwzActionData); | ||
| 407 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 408 | |||
| 409 | // add assemblies to custom action data in forward order | ||
| 410 | for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 411 | { | ||
| 412 | // roles that are being installed only | ||
| 413 | if ((rmCommit == iRunMode && !(pItm->pAssembly->iAttributes & aaRunInCommit)) || | ||
| 414 | (rmDeferred == iRunMode && (pItm->pAssembly->iAttributes & aaRunInCommit)) || | ||
| 415 | !WcaIsInstalling(pItm->isInstalled, pItm->isAction)) | ||
| 416 | continue; | ||
| 417 | |||
| 418 | // action type | ||
| 419 | if (rmRollback == iRunMode) | ||
| 420 | { | ||
| 421 | if (CpiIsInstalled(pItm->isInstalled)) | ||
| 422 | iActionType = atNoOp; | ||
| 423 | else | ||
| 424 | iActionType = atRemove; | ||
| 425 | } | ||
| 426 | else | ||
| 427 | iActionType = atCreate; | ||
| 428 | |||
| 429 | // add to action data | ||
| 430 | hr = AddSubscriptionToActionData(pItm, iActionType, COST_SUBSCRIPTION_CREATE, ppwzActionData); | ||
| 431 | ExitOnFailure(hr, "Failed to add subscription to custom action data, key: %S", pItm->wzKey); | ||
| 432 | } | ||
| 433 | |||
| 434 | // add progress tics | ||
| 435 | if (piProgress) | ||
| 436 | *piProgress += COST_SUBSCRIPTION_CREATE * pList->iInstallCount; | ||
| 437 | |||
| 438 | hr = S_OK; | ||
| 439 | |||
| 440 | LExit: | ||
| 441 | return hr; | ||
| 442 | } | ||
| 443 | |||
| 444 | HRESULT CpiSubscriptionsUninstall( | ||
| 445 | CPI_SUBSCRIPTION_LIST* pList, | ||
| 446 | int iRunMode, | ||
| 447 | LPWSTR* ppwzActionData, | ||
| 448 | int* piProgress | ||
| 449 | ) | ||
| 450 | { | ||
| 451 | HRESULT hr = S_OK; | ||
| 452 | |||
| 453 | int iActionType; | ||
| 454 | |||
| 455 | // add action text | ||
| 456 | hr = CpiAddActionTextToActionData(L"RemoveSubscrComPlusComponents", ppwzActionData); | ||
| 457 | ExitOnFailure(hr, "Failed to add action text to custom action data"); | ||
| 458 | |||
| 459 | // add subscription count to action data | ||
| 460 | hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); | ||
| 461 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 462 | |||
| 463 | // add assemblies to custom action data in reverse order | ||
| 464 | for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) | ||
| 465 | { | ||
| 466 | // roles that are being uninstalled only | ||
| 467 | if (pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) | ||
| 468 | continue; | ||
| 469 | |||
| 470 | // action type | ||
| 471 | if (rmRollback == iRunMode) | ||
| 472 | iActionType = atCreate; | ||
| 473 | else | ||
| 474 | iActionType = atRemove; | ||
| 475 | |||
| 476 | // add to action data | ||
| 477 | hr = AddSubscriptionToActionData(pItm, iActionType, COST_SUBSCRIPTION_DELETE, ppwzActionData); | ||
| 478 | ExitOnFailure(hr, "Failed to add subscription to custom action data, key: %S", pItm->wzKey); | ||
| 479 | } | ||
| 480 | |||
| 481 | // add progress tics | ||
| 482 | if (piProgress) | ||
| 483 | *piProgress += COST_SUBSCRIPTION_DELETE * pList->iUninstallCount; | ||
| 484 | |||
| 485 | hr = S_OK; | ||
| 486 | |||
| 487 | LExit: | ||
| 488 | return hr; | ||
| 489 | } | ||
| 490 | |||
| 491 | |||
| 492 | // helper function definitions | ||
| 493 | |||
| 494 | static void FreeSubscription( | ||
| 495 | CPI_SUBSCRIPTION* pItm | ||
| 496 | ) | ||
| 497 | { | ||
| 498 | if (pItm->pProperties) | ||
| 499 | CpiPropertiesFreeList(pItm->pProperties); | ||
| 500 | |||
| 501 | ::HeapFree(::GetProcessHeap(), 0, pItm); | ||
| 502 | } | ||
| 503 | |||
| 504 | static HRESULT FindObjectForSubscription( | ||
| 505 | CPI_SUBSCRIPTION* pItm, | ||
| 506 | BOOL fFindId, | ||
| 507 | BOOL fFindName, | ||
| 508 | ICatalogObject** ppiSubsObj | ||
| 509 | ) | ||
| 510 | { | ||
| 511 | HRESULT hr = S_OK; | ||
| 512 | |||
| 513 | ICatalogCollection* piSubsColl = NULL; | ||
| 514 | |||
| 515 | // get applications collection | ||
| 516 | hr = CpiGetSubscriptionsCollForComponent(pItm->pAssembly, pItm->pComponent, &piSubsColl); | ||
| 517 | ExitOnFailure(hr, "Failed to get collection"); | ||
| 518 | |||
| 519 | if (S_FALSE == hr) | ||
| 520 | ExitFunction(); // exit with hr = S_FALSE | ||
| 521 | |||
| 522 | // find application object | ||
| 523 | hr = CpiFindCollectionObject(piSubsColl, fFindId ? pItm->wzID : NULL, fFindName ? pItm->wzName : NULL, ppiSubsObj); | ||
| 524 | ExitOnFailure(hr, "Failed to find object"); | ||
| 525 | |||
| 526 | // exit with hr from CpiFindCollectionObject() | ||
| 527 | |||
| 528 | LExit: | ||
| 529 | // clean up | ||
| 530 | ReleaseObject(piSubsColl); | ||
| 531 | |||
| 532 | return hr; | ||
| 533 | } | ||
| 534 | |||
| 535 | static HRESULT AddSubscriptionToActionData( | ||
| 536 | CPI_SUBSCRIPTION* pItm, | ||
| 537 | int iActionType, | ||
| 538 | int iActionCost, | ||
| 539 | LPWSTR* ppwzActionData | ||
| 540 | ) | ||
| 541 | { | ||
| 542 | HRESULT hr = S_OK; | ||
| 543 | |||
| 544 | // add action information to custom action data | ||
| 545 | hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); | ||
| 546 | ExitOnFailure(hr, "Failed to add action type to custom action data"); | ||
| 547 | hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); | ||
| 548 | ExitOnFailure(hr, "Failed to add action cost to custom action data"); | ||
| 549 | |||
| 550 | // add application role information to custom action data | ||
| 551 | hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); | ||
| 552 | ExitOnFailure(hr, "Failed to add subscription key to custom action data"); | ||
| 553 | hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData); | ||
| 554 | ExitOnFailure(hr, "Failed to add subscription id to custom action data"); | ||
| 555 | hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); | ||
| 556 | ExitOnFailure(hr, "Failed to add subscription name to custom action data"); | ||
| 557 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->wzEventCLSID : L"", ppwzActionData); | ||
| 558 | ExitOnFailure(hr, "Failed to add assembly tlb path to custom action data"); | ||
| 559 | hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->wzPublisherID : L"", ppwzActionData); | ||
| 560 | ExitOnFailure(hr, "Failed to add assembly proxy-stub dll path to custom action data"); | ||
| 561 | |||
| 562 | // add component information to custom action data | ||
| 563 | hr = WcaWriteStringToCaData(pItm->pComponent->wzCLSID, ppwzActionData); | ||
| 564 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
| 565 | |||
| 566 | // add application information to custom action data | ||
| 567 | hr = WcaWriteStringToCaData(pItm->pAssembly->pApplication->wzID, ppwzActionData); | ||
| 568 | ExitOnFailure(hr, "Failed to add application id to custom action data"); | ||
| 569 | |||
| 570 | // add partition information to custom action data | ||
| 571 | LPCWSTR pwzPartID = pItm->pAssembly->pApplication->pPartition ? pItm->pAssembly->pApplication->pPartition->wzID : L""; | ||
| 572 | hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData); | ||
| 573 | ExitOnFailure(hr, "Failed to add partition id to custom action data"); | ||
| 574 | |||
| 575 | // add properties to custom action data | ||
| 576 | hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); | ||
| 577 | ExitOnFailure(hr, "Failed to add properties to custom action data"); | ||
| 578 | |||
| 579 | hr = S_OK; | ||
| 580 | |||
| 581 | LExit: | ||
| 582 | return hr; | ||
| 583 | } | ||
| 584 | |||
| 585 | static HRESULT ComponentFindByKey( | ||
| 586 | CPI_ASSEMBLY_LIST* pAsmList, | ||
| 587 | LPCWSTR pwzKey, | ||
| 588 | CPI_ASSEMBLY** ppAsmItm, | ||
| 589 | CPI_COMPONENT** ppCompItm | ||
| 590 | ) | ||
| 591 | { | ||
| 592 | for (CPI_ASSEMBLY* pAsmItm = pAsmList->pFirst; pAsmItm; pAsmItm = pAsmItm->pNext) | ||
| 593 | { | ||
| 594 | for (CPI_COMPONENT* pCompItm = pAsmItm->pComponents; pCompItm; pCompItm = pCompItm->pNext) | ||
| 595 | { | ||
| 596 | if (0 == lstrcmpW(pCompItm->wzKey, pwzKey)) | ||
| 597 | { | ||
| 598 | *ppAsmItm = pAsmItm; | ||
| 599 | *ppCompItm = pCompItm; | ||
| 600 | return S_OK; | ||
| 601 | } | ||
| 602 | } | ||
| 603 | } | ||
| 604 | |||
| 605 | return S_FALSE; | ||
| 606 | } | ||
diff --git a/src/ca/cpsubssched.h b/src/ca/cpsubssched.h new file mode 100644 index 00000000..3fc18478 --- /dev/null +++ b/src/ca/cpsubssched.h | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | struct CPI_SUBSCRIPTION | ||
| 6 | { | ||
| 7 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 8 | WCHAR wzID[CPI_MAX_GUID + 1]; | ||
| 9 | WCHAR wzName[MAX_DARWIN_COLUMN + 1]; | ||
| 10 | WCHAR wzEventCLSID[CPI_MAX_GUID + 1]; | ||
| 11 | WCHAR wzPublisherID[CPI_MAX_GUID + 1]; | ||
| 12 | |||
| 13 | BOOL fObjectNotFound; | ||
| 14 | |||
| 15 | int iPropertyCount; | ||
| 16 | CPI_PROPERTY* pProperties; | ||
| 17 | |||
| 18 | INSTALLSTATE isInstalled, isAction; | ||
| 19 | |||
| 20 | CPI_ASSEMBLY* pAssembly; | ||
| 21 | CPI_COMPONENT* pComponent; | ||
| 22 | |||
| 23 | CPI_SUBSCRIPTION* pNext; | ||
| 24 | }; | ||
| 25 | |||
| 26 | struct CPI_SUBSCRIPTION_LIST | ||
| 27 | { | ||
| 28 | CPI_SUBSCRIPTION* pFirst; | ||
| 29 | |||
| 30 | int iInstallCount; | ||
| 31 | int iCommitCount; | ||
| 32 | int iUninstallCount; | ||
| 33 | }; | ||
| 34 | |||
| 35 | |||
| 36 | // function prototypes | ||
| 37 | |||
| 38 | void CpiSubscriptionListFree( | ||
| 39 | CPI_SUBSCRIPTION_LIST* pList | ||
| 40 | ); | ||
| 41 | HRESULT CpiSubscriptionsRead( | ||
| 42 | CPI_ASSEMBLY_LIST* pAsmList, | ||
| 43 | CPI_SUBSCRIPTION_LIST* pSubList | ||
| 44 | ); | ||
| 45 | HRESULT CpiSubscriptionsVerifyInstall( | ||
| 46 | CPI_SUBSCRIPTION_LIST* pList | ||
| 47 | ); | ||
| 48 | HRESULT CpiSubscriptionsVerifyUninstall( | ||
| 49 | CPI_SUBSCRIPTION_LIST* pList | ||
| 50 | ); | ||
| 51 | HRESULT CpiSubscriptionsInstall( | ||
| 52 | CPI_SUBSCRIPTION_LIST* pList, | ||
| 53 | int iRunMode, | ||
| 54 | LPWSTR* ppwzActionData, | ||
| 55 | int* piProgress | ||
| 56 | ); | ||
| 57 | HRESULT CpiSubscriptionsUninstall( | ||
| 58 | CPI_SUBSCRIPTION_LIST* pList, | ||
| 59 | int iRunMode, | ||
| 60 | LPWSTR* ppwzActionData, | ||
| 61 | int* piProgress | ||
| 62 | ); | ||
diff --git a/src/ca/cputilexec.cpp b/src/ca/cputilexec.cpp new file mode 100644 index 00000000..e081678b --- /dev/null +++ b/src/ca/cputilexec.cpp | |||
| @@ -0,0 +1,1881 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // private structs | ||
| 7 | |||
| 8 | struct CPI_WELLKNOWN_SID | ||
| 9 | { | ||
| 10 | LPCWSTR pwzName; | ||
| 11 | SID_IDENTIFIER_AUTHORITY iaIdentifierAuthority; | ||
| 12 | BYTE nSubAuthorityCount; | ||
| 13 | DWORD dwSubAuthority[8]; | ||
| 14 | }; | ||
| 15 | |||
| 16 | |||
| 17 | // well known SIDs | ||
| 18 | |||
| 19 | CPI_WELLKNOWN_SID wsWellKnownSids[] = { | ||
| 20 | {L"\\Everyone", SECURITY_WORLD_SID_AUTHORITY, 1, {SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
| 21 | {L"\\Administrators", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0}}, | ||
| 22 | {L"\\LocalSystem", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
| 23 | {L"\\LocalService", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
| 24 | {L"\\NetworkService", SECURITY_NT_AUTHORITY, 1, {SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
| 25 | {L"\\AuthenticatedUser", SECURITY_NT_AUTHORITY, 1, {SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
| 26 | {L"\\Guests", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS, 0, 0, 0, 0, 0, 0}}, | ||
| 27 | {L"\\Users", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0}}, | ||
| 28 | {L"\\CREATOR OWNER", SECURITY_NT_AUTHORITY, 1, {SECURITY_CREATOR_OWNER_RID, 0, 0, 0, 0, 0, 0, 0}}, | ||
| 29 | {NULL, SECURITY_NULL_SID_AUTHORITY, 0, {0, 0, 0, 0, 0, 0, 0, 0}} | ||
| 30 | }; | ||
| 31 | |||
| 32 | |||
| 33 | // prototypes for private helper functions | ||
| 34 | |||
| 35 | static HRESULT FindUserCollectionObjectIndex( | ||
| 36 | ICatalogCollection* piColl, | ||
| 37 | PSID pSid, | ||
| 38 | int* pi | ||
| 39 | ); | ||
| 40 | static HRESULT CreateSidFromDomainRidPair( | ||
| 41 | PSID pDomainSid, | ||
| 42 | DWORD dwRid, | ||
| 43 | PSID* ppSid | ||
| 44 | ); | ||
| 45 | static HRESULT InitLsaUnicodeString( | ||
| 46 | PLSA_UNICODE_STRING plusStr, | ||
| 47 | LPCWSTR pwzStr, | ||
| 48 | DWORD dwLen | ||
| 49 | ); | ||
| 50 | static void FreeLsaUnicodeString( | ||
| 51 | PLSA_UNICODE_STRING plusStr | ||
| 52 | ); | ||
| 53 | static HRESULT WriteFileAll( | ||
| 54 | HANDLE hFile, | ||
| 55 | PBYTE pbBuffer, | ||
| 56 | DWORD dwBufferLength | ||
| 57 | ); | ||
| 58 | static HRESULT ReadFileAll( | ||
| 59 | HANDLE hFile, | ||
| 60 | PBYTE pbBuffer, | ||
| 61 | DWORD dwBufferLength | ||
| 62 | ); | ||
| 63 | |||
| 64 | |||
| 65 | // variables | ||
| 66 | |||
| 67 | static ICOMAdminCatalog* gpiCatalog; | ||
| 68 | |||
| 69 | |||
| 70 | // function definitions | ||
| 71 | |||
| 72 | void CpiInitialize() | ||
| 73 | { | ||
| 74 | // collections | ||
| 75 | gpiCatalog = NULL; | ||
| 76 | } | ||
| 77 | |||
| 78 | void CpiFinalize() | ||
| 79 | { | ||
| 80 | // collections | ||
| 81 | ReleaseObject(gpiCatalog); | ||
| 82 | } | ||
| 83 | |||
| 84 | HRESULT CpiActionStartMessage( | ||
| 85 | LPWSTR* ppwzActionData, | ||
| 86 | BOOL fSuppress | ||
| 87 | ) | ||
| 88 | { | ||
| 89 | HRESULT hr = S_OK; | ||
| 90 | UINT er = ERROR_SUCCESS; | ||
| 91 | |||
| 92 | PMSIHANDLE hRec; | ||
| 93 | |||
| 94 | LPWSTR pwzData = NULL; | ||
| 95 | |||
| 96 | // create record | ||
| 97 | hRec = ::MsiCreateRecord(3); | ||
| 98 | ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 99 | |||
| 100 | // action name | ||
| 101 | hr = WcaReadStringFromCaData(ppwzActionData, &pwzData); | ||
| 102 | ExitOnFailure(hr, "Failed to action name"); | ||
| 103 | |||
| 104 | er = ::MsiRecordSetStringW(hRec, 1, pwzData); | ||
| 105 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set action name"); | ||
| 106 | |||
| 107 | // description | ||
| 108 | hr = WcaReadStringFromCaData(ppwzActionData, &pwzData); | ||
| 109 | ExitOnFailure(hr, "Failed to description"); | ||
| 110 | |||
| 111 | er = ::MsiRecordSetStringW(hRec, 2, pwzData); | ||
| 112 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set description"); | ||
| 113 | |||
| 114 | // template | ||
| 115 | hr = WcaReadStringFromCaData(ppwzActionData, &pwzData); | ||
| 116 | ExitOnFailure(hr, "Failed to template"); | ||
| 117 | |||
| 118 | er = ::MsiRecordSetStringW(hRec, 3, pwzData); | ||
| 119 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set template"); | ||
| 120 | |||
| 121 | // message | ||
| 122 | if (!fSuppress) | ||
| 123 | { | ||
| 124 | er = WcaProcessMessage(INSTALLMESSAGE_ACTIONSTART, hRec); | ||
| 125 | if (0 == er || IDOK == er || IDYES == er) | ||
| 126 | { | ||
| 127 | hr = S_OK; | ||
| 128 | } | ||
| 129 | else if (IDABORT == er || IDCANCEL == er) | ||
| 130 | { | ||
| 131 | WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit | ||
| 132 | hr = S_FALSE; | ||
| 133 | } | ||
| 134 | else | ||
| 135 | hr = E_UNEXPECTED; | ||
| 136 | } | ||
| 137 | |||
| 138 | LExit: | ||
| 139 | // clean up | ||
| 140 | ReleaseStr(pwzData); | ||
| 141 | |||
| 142 | return hr; | ||
| 143 | } | ||
| 144 | |||
| 145 | HRESULT CpiActionDataMessage( | ||
| 146 | DWORD cArgs, | ||
| 147 | ... | ||
| 148 | ) | ||
| 149 | { | ||
| 150 | HRESULT hr = S_OK; | ||
| 151 | UINT er = ERROR_SUCCESS; | ||
| 152 | |||
| 153 | PMSIHANDLE hRec; | ||
| 154 | va_list args; | ||
| 155 | |||
| 156 | // record | ||
| 157 | hRec = ::MsiCreateRecord(cArgs); | ||
| 158 | ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 159 | |||
| 160 | va_start(args, cArgs); | ||
| 161 | for (DWORD i = 1; i <= cArgs; i++) | ||
| 162 | { | ||
| 163 | LPCWSTR pwzArg = va_arg(args, WCHAR*); | ||
| 164 | if (pwzArg && *pwzArg) | ||
| 165 | { | ||
| 166 | er = ::MsiRecordSetStringW(hRec, i, pwzArg); | ||
| 167 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set record field string"); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | va_end(args); | ||
| 171 | |||
| 172 | // message | ||
| 173 | er = WcaProcessMessage(INSTALLMESSAGE_ACTIONDATA, hRec); | ||
| 174 | if (0 == er || IDOK == er || IDYES == er) | ||
| 175 | { | ||
| 176 | hr = S_OK; | ||
| 177 | } | ||
| 178 | else if (IDABORT == er || IDCANCEL == er) | ||
| 179 | { | ||
| 180 | WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit | ||
| 181 | hr = S_FALSE; | ||
| 182 | } | ||
| 183 | else | ||
| 184 | hr = E_UNEXPECTED; | ||
| 185 | |||
| 186 | LExit: | ||
| 187 | return hr; | ||
| 188 | } | ||
| 189 | |||
| 190 | HRESULT CpiGetAdminCatalog( | ||
| 191 | ICOMAdminCatalog** ppiCatalog | ||
| 192 | ) | ||
| 193 | { | ||
| 194 | HRESULT hr = S_OK; | ||
| 195 | |||
| 196 | if (!gpiCatalog) | ||
| 197 | { | ||
| 198 | // get collection | ||
| 199 | hr = ::CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_ALL, IID_ICOMAdminCatalog, (void**)&gpiCatalog); | ||
| 200 | ExitOnFailure(hr, "Failed to create COM+ admin catalog object"); | ||
| 201 | } | ||
| 202 | |||
| 203 | // return value | ||
| 204 | gpiCatalog->AddRef(); | ||
| 205 | *ppiCatalog = gpiCatalog; | ||
| 206 | |||
| 207 | hr = S_OK; | ||
| 208 | |||
| 209 | LExit: | ||
| 210 | return hr; | ||
| 211 | } | ||
| 212 | |||
| 213 | HRESULT CpiLogCatalogErrorInfo() | ||
| 214 | { | ||
| 215 | HRESULT hr = S_OK; | ||
| 216 | |||
| 217 | ICOMAdminCatalog* piCatalog = NULL; | ||
| 218 | ICatalogCollection* piErrColl = NULL; | ||
| 219 | IDispatch* piDisp = NULL; | ||
| 220 | ICatalogObject* piObj = NULL; | ||
| 221 | |||
| 222 | LPWSTR pwzName = NULL; | ||
| 223 | LPWSTR pwzErrorCode = NULL; | ||
| 224 | LPWSTR pwzMajorRef = NULL; | ||
| 225 | LPWSTR pwzMinorRef = NULL; | ||
| 226 | |||
| 227 | // get catalog | ||
| 228 | hr = CpiGetAdminCatalog(&piCatalog); | ||
| 229 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
| 230 | |||
| 231 | // get error info collection | ||
| 232 | hr = CpiGetCatalogCollection(L"ErrorInfo", &piErrColl); | ||
| 233 | ExitOnFailure(hr, "Failed to get error info collection"); | ||
| 234 | |||
| 235 | // loop objects | ||
| 236 | long lCnt; | ||
| 237 | hr = piErrColl->get_Count(&lCnt); | ||
| 238 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
| 239 | |||
| 240 | for (long i = 0; i < lCnt; i++) | ||
| 241 | { | ||
| 242 | // get ICatalogObject interface | ||
| 243 | hr = piErrColl->get_Item(i, &piDisp); | ||
| 244 | ExitOnFailure(hr, "Failed to get item from partitions collection"); | ||
| 245 | |||
| 246 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
| 247 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
| 248 | |||
| 249 | // get properties | ||
| 250 | hr = CpiGetCollectionObjectValue(piObj, L"Name", &pwzName); | ||
| 251 | ExitOnFailure(hr, "Failed to get name"); | ||
| 252 | hr = CpiGetCollectionObjectValue(piObj, L"ErrorCode", &pwzErrorCode); | ||
| 253 | ExitOnFailure(hr, "Failed to get error code"); | ||
| 254 | hr = CpiGetCollectionObjectValue(piObj, L"MajorRef", &pwzMajorRef); | ||
| 255 | ExitOnFailure(hr, "Failed to get major ref"); | ||
| 256 | hr = CpiGetCollectionObjectValue(piObj, L"MinorRef", &pwzMinorRef); | ||
| 257 | ExitOnFailure(hr, "Failed to get minor ref"); | ||
| 258 | |||
| 259 | // write to log | ||
| 260 | WcaLog(LOGMSG_STANDARD, "ErrorInfo: Name='%S', ErrorCode='%S', MajorRef='%S', MinorRef='%S'", | ||
| 261 | pwzName, pwzErrorCode, pwzMajorRef, pwzMinorRef); | ||
| 262 | |||
| 263 | // clean up | ||
| 264 | ReleaseNullObject(piDisp); | ||
| 265 | ReleaseNullObject(piObj); | ||
| 266 | } | ||
| 267 | |||
| 268 | hr = S_OK; | ||
| 269 | |||
| 270 | LExit: | ||
| 271 | // clean up | ||
| 272 | ReleaseObject(piCatalog); | ||
| 273 | ReleaseObject(piErrColl); | ||
| 274 | ReleaseObject(piDisp); | ||
| 275 | ReleaseObject(piObj); | ||
| 276 | |||
| 277 | ReleaseStr(pwzName); | ||
| 278 | ReleaseStr(pwzErrorCode); | ||
| 279 | ReleaseStr(pwzMajorRef); | ||
| 280 | ReleaseStr(pwzMinorRef); | ||
| 281 | |||
| 282 | return hr; | ||
| 283 | } | ||
| 284 | |||
| 285 | HRESULT CpiGetCatalogCollection( | ||
| 286 | LPCWSTR pwzName, | ||
| 287 | ICatalogCollection** ppiColl | ||
| 288 | ) | ||
| 289 | { | ||
| 290 | HRESULT hr = S_OK; | ||
| 291 | |||
| 292 | ICOMAdminCatalog* piCatalog = NULL; | ||
| 293 | IDispatch* piDisp = NULL; | ||
| 294 | |||
| 295 | BSTR bstrName = NULL; | ||
| 296 | |||
| 297 | // copy name string | ||
| 298 | bstrName = ::SysAllocString(pwzName); | ||
| 299 | ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name"); | ||
| 300 | |||
| 301 | // get catalog | ||
| 302 | hr = CpiGetAdminCatalog(&piCatalog); | ||
| 303 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
| 304 | |||
| 305 | // get collecton from catalog | ||
| 306 | hr = piCatalog->GetCollection(bstrName, &piDisp); | ||
| 307 | ExitOnFailure(hr, "Failed to get collection"); | ||
| 308 | |||
| 309 | hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl); | ||
| 310 | ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface"); | ||
| 311 | |||
| 312 | // populate collection | ||
| 313 | hr = (*ppiColl)->Populate(); | ||
| 314 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 315 | CpiLogCatalogErrorInfo(); | ||
| 316 | ExitOnFailure(hr, "Failed to populate collection"); | ||
| 317 | |||
| 318 | hr = S_OK; | ||
| 319 | |||
| 320 | LExit: | ||
| 321 | // clean up | ||
| 322 | ReleaseObject(piCatalog); | ||
| 323 | ReleaseObject(piDisp); | ||
| 324 | ReleaseBSTR(bstrName); | ||
| 325 | |||
| 326 | return hr; | ||
| 327 | } | ||
| 328 | |||
| 329 | HRESULT CpiGetCatalogCollection( | ||
| 330 | ICatalogCollection* piColl, | ||
| 331 | ICatalogObject* piObj, | ||
| 332 | LPCWSTR pwzName, | ||
| 333 | ICatalogCollection** ppiColl | ||
| 334 | ) | ||
| 335 | { | ||
| 336 | HRESULT hr = S_OK; | ||
| 337 | |||
| 338 | ICOMAdminCatalog* piCatalog = NULL; | ||
| 339 | IDispatch* piDisp = NULL; | ||
| 340 | |||
| 341 | BSTR bstrName = NULL; | ||
| 342 | |||
| 343 | VARIANT vtKey; | ||
| 344 | ::VariantInit(&vtKey); | ||
| 345 | |||
| 346 | // copy name string | ||
| 347 | bstrName = ::SysAllocString(pwzName); | ||
| 348 | ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name"); | ||
| 349 | |||
| 350 | // get catalog | ||
| 351 | hr = CpiGetAdminCatalog(&piCatalog); | ||
| 352 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
| 353 | |||
| 354 | // get key | ||
| 355 | hr = piObj->get_Key(&vtKey); | ||
| 356 | ExitOnFailure(hr, "Failed to get object key"); | ||
| 357 | |||
| 358 | // get collecton from catalog | ||
| 359 | hr = piColl->GetCollection(bstrName, vtKey, &piDisp); | ||
| 360 | ExitOnFailure(hr, "Failed to get collection"); | ||
| 361 | |||
| 362 | hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl); | ||
| 363 | ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface"); | ||
| 364 | |||
| 365 | // populate collection | ||
| 366 | hr = (*ppiColl)->Populate(); | ||
| 367 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 368 | CpiLogCatalogErrorInfo(); | ||
| 369 | ExitOnFailure(hr, "Failed to populate collection"); | ||
| 370 | |||
| 371 | hr = S_OK; | ||
| 372 | |||
| 373 | LExit: | ||
| 374 | // clean up | ||
| 375 | ReleaseObject(piCatalog); | ||
| 376 | ReleaseObject(piDisp); | ||
| 377 | ReleaseBSTR(bstrName); | ||
| 378 | ::VariantClear(&vtKey); | ||
| 379 | |||
| 380 | return hr; | ||
| 381 | } | ||
| 382 | |||
| 383 | HRESULT CpiAddCollectionObject( | ||
| 384 | ICatalogCollection* piColl, | ||
| 385 | ICatalogObject** ppiObj | ||
| 386 | ) | ||
| 387 | { | ||
| 388 | HRESULT hr = S_OK; | ||
| 389 | |||
| 390 | IDispatch* piDisp = NULL; | ||
| 391 | |||
| 392 | hr = piColl->Add(&piDisp); | ||
| 393 | ExitOnFailure(hr, "Failed to add object to collection"); | ||
| 394 | |||
| 395 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)ppiObj); | ||
| 396 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
| 397 | |||
| 398 | hr = S_OK; | ||
| 399 | |||
| 400 | LExit: | ||
| 401 | // clean up | ||
| 402 | ReleaseObject(piDisp); | ||
| 403 | |||
| 404 | return hr; | ||
| 405 | } | ||
| 406 | |||
| 407 | HRESULT CpiPutCollectionObjectValue( | ||
| 408 | ICatalogObject* piObj, | ||
| 409 | LPCWSTR pwzPropName, | ||
| 410 | LPCWSTR pwzValue | ||
| 411 | ) | ||
| 412 | { | ||
| 413 | HRESULT hr = S_OK; | ||
| 414 | |||
| 415 | BSTR bstrPropName = NULL; | ||
| 416 | |||
| 417 | VARIANT vtVal; | ||
| 418 | ::VariantInit(&vtVal); | ||
| 419 | |||
| 420 | // allocate property name string | ||
| 421 | bstrPropName = ::SysAllocString(pwzPropName); | ||
| 422 | ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate property name string"); | ||
| 423 | |||
| 424 | // prepare value variant | ||
| 425 | vtVal.vt = VT_BSTR; | ||
| 426 | vtVal.bstrVal = ::SysAllocString(pwzValue); | ||
| 427 | ExitOnNull(vtVal.bstrVal, hr, E_OUTOFMEMORY, "Failed to allocate property value string"); | ||
| 428 | |||
| 429 | // put value | ||
| 430 | hr = piObj->put_Value(bstrPropName, vtVal); | ||
| 431 | ExitOnFailure(hr, "Failed to put property value"); | ||
| 432 | |||
| 433 | hr = S_OK; | ||
| 434 | |||
| 435 | LExit: | ||
| 436 | // clean up | ||
| 437 | ReleaseBSTR(bstrPropName); | ||
| 438 | ::VariantClear(&vtVal); | ||
| 439 | |||
| 440 | return hr; | ||
| 441 | } | ||
| 442 | |||
| 443 | HRESULT CpiPutCollectionObjectValues( | ||
| 444 | ICatalogObject* piObj, | ||
| 445 | CPI_PROPERTY* pPropList | ||
| 446 | ) | ||
| 447 | { | ||
| 448 | HRESULT hr = S_OK; | ||
| 449 | |||
| 450 | for (CPI_PROPERTY* pItm = pPropList; pItm; pItm = pItm->pNext) | ||
| 451 | { | ||
| 452 | // set property | ||
| 453 | hr = CpiPutCollectionObjectValue(piObj, pItm->wzName, pItm->pwzValue); | ||
| 454 | ExitOnFailure(hr, "Failed to set object property value, name: %S", pItm->wzName); | ||
| 455 | } | ||
| 456 | |||
| 457 | hr = S_OK; | ||
| 458 | |||
| 459 | LExit: | ||
| 460 | return hr; | ||
| 461 | } | ||
| 462 | |||
| 463 | HRESULT CpiGetCollectionObjectValue( | ||
| 464 | ICatalogObject* piObj, | ||
| 465 | LPCWSTR szPropName, | ||
| 466 | LPWSTR* ppwzValue | ||
| 467 | ) | ||
| 468 | { | ||
| 469 | HRESULT hr = S_OK; | ||
| 470 | |||
| 471 | BSTR bstrPropName = NULL; | ||
| 472 | |||
| 473 | VARIANT vtVal; | ||
| 474 | ::VariantInit(&vtVal); | ||
| 475 | |||
| 476 | // allocate property name string | ||
| 477 | bstrPropName = ::SysAllocString(szPropName); | ||
| 478 | ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate property name string"); | ||
| 479 | |||
| 480 | // get value | ||
| 481 | hr = piObj->get_Value(bstrPropName, &vtVal); | ||
| 482 | ExitOnFailure(hr, "Failed to get property value"); | ||
| 483 | |||
| 484 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
| 485 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 486 | |||
| 487 | hr = StrAllocString(ppwzValue, vtVal.bstrVal, ::SysStringLen(vtVal.bstrVal)); | ||
| 488 | ExitOnFailure(hr, "Failed to allocate memory for value string"); | ||
| 489 | |||
| 490 | hr = S_OK; | ||
| 491 | |||
| 492 | LExit: | ||
| 493 | // clean up | ||
| 494 | ReleaseBSTR(bstrPropName); | ||
| 495 | ::VariantClear(&vtVal); | ||
| 496 | |||
| 497 | return hr; | ||
| 498 | } | ||
| 499 | |||
| 500 | HRESULT CpiResetObjectProperty( | ||
| 501 | ICatalogCollection* piColl, | ||
| 502 | ICatalogObject* piObj, | ||
| 503 | LPCWSTR pwzPropName | ||
| 504 | ) | ||
| 505 | { | ||
| 506 | HRESULT hr = S_OK; | ||
| 507 | |||
| 508 | BSTR bstrPropName = NULL; | ||
| 509 | |||
| 510 | long lChanges = 0; | ||
| 511 | |||
| 512 | VARIANT vtVal; | ||
| 513 | ::VariantInit(&vtVal); | ||
| 514 | |||
| 515 | // allocate property name string | ||
| 516 | bstrPropName = ::SysAllocString(pwzPropName); | ||
| 517 | ExitOnNull(bstrPropName, hr, E_OUTOFMEMORY, "Failed to allocate deleteable property name string"); | ||
| 518 | |||
| 519 | // get value | ||
| 520 | hr = piObj->get_Value(bstrPropName, &vtVal); | ||
| 521 | ExitOnFailure(hr, "Failed to get deleteable property value"); | ||
| 522 | |||
| 523 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BOOL); | ||
| 524 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 525 | |||
| 526 | // if the deleteable property is set | ||
| 527 | if (VARIANT_FALSE == vtVal.boolVal) | ||
| 528 | { | ||
| 529 | // clear property | ||
| 530 | vtVal.boolVal = VARIANT_TRUE; | ||
| 531 | |||
| 532 | hr = piObj->put_Value(bstrPropName, vtVal); | ||
| 533 | ExitOnFailure(hr, "Failed to get property value"); | ||
| 534 | |||
| 535 | // save changes | ||
| 536 | hr = piColl->SaveChanges(&lChanges); | ||
| 537 | if (COMADMIN_E_OBJECTERRORS == hr) | ||
| 538 | CpiLogCatalogErrorInfo(); | ||
| 539 | ExitOnFailure(hr, "Failed to save changes"); | ||
| 540 | } | ||
| 541 | |||
| 542 | hr = S_OK; | ||
| 543 | |||
| 544 | LExit: | ||
| 545 | // clean up | ||
| 546 | ReleaseBSTR(bstrPropName); | ||
| 547 | ::VariantClear(&vtVal); | ||
| 548 | |||
| 549 | return hr; | ||
| 550 | } | ||
| 551 | |||
| 552 | HRESULT CpiRemoveCollectionObject( | ||
| 553 | ICatalogCollection* piColl, | ||
| 554 | LPCWSTR pwzID, | ||
| 555 | LPCWSTR pwzName, | ||
| 556 | BOOL fResetDeleteable | ||
| 557 | ) | ||
| 558 | { | ||
| 559 | HRESULT hr = S_OK; | ||
| 560 | |||
| 561 | IDispatch* piDisp = NULL; | ||
| 562 | ICatalogObject* piObj = NULL; | ||
| 563 | |||
| 564 | BOOL fMatch = FALSE; | ||
| 565 | |||
| 566 | VARIANT vtVal; | ||
| 567 | ::VariantInit(&vtVal); | ||
| 568 | |||
| 569 | long lCnt; | ||
| 570 | hr = piColl->get_Count(&lCnt); | ||
| 571 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
| 572 | |||
| 573 | for (long i = 0; i < lCnt; i++) | ||
| 574 | { | ||
| 575 | // get ICatalogObject interface | ||
| 576 | hr = piColl->get_Item(i, &piDisp); | ||
| 577 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
| 578 | |||
| 579 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
| 580 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
| 581 | |||
| 582 | // compare id | ||
| 583 | if (pwzID && *pwzID) | ||
| 584 | { | ||
| 585 | hr = piObj->get_Key(&vtVal); | ||
| 586 | ExitOnFailure(hr, "Failed to get key"); | ||
| 587 | |||
| 588 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
| 589 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 590 | |||
| 591 | if (0 == lstrcmpiW(vtVal.bstrVal, pwzID)) | ||
| 592 | fMatch = TRUE; | ||
| 593 | |||
| 594 | ::VariantClear(&vtVal); | ||
| 595 | } | ||
| 596 | |||
| 597 | // compare name | ||
| 598 | if (pwzName && *pwzName) | ||
| 599 | { | ||
| 600 | hr = piObj->get_Name(&vtVal); | ||
| 601 | ExitOnFailure(hr, "Failed to get name"); | ||
| 602 | |||
| 603 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
| 604 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 605 | |||
| 606 | if (0 == lstrcmpW(vtVal.bstrVal, pwzName)) | ||
| 607 | fMatch = TRUE; | ||
| 608 | |||
| 609 | ::VariantClear(&vtVal); | ||
| 610 | } | ||
| 611 | |||
| 612 | // if it's a match, remove it | ||
| 613 | if (fMatch) | ||
| 614 | { | ||
| 615 | if (fResetDeleteable) | ||
| 616 | { | ||
| 617 | // reset deleteable property, if set | ||
| 618 | hr = CpiResetObjectProperty(piColl, piObj, L"Deleteable"); | ||
| 619 | ExitOnFailure(hr, "Failed to reset deleteable property"); | ||
| 620 | } | ||
| 621 | |||
| 622 | hr = piColl->Remove(i); | ||
| 623 | ExitOnFailure(hr, "Failed to remove item from collection"); | ||
| 624 | break; | ||
| 625 | } | ||
| 626 | |||
| 627 | // release interface pointers | ||
| 628 | ReleaseNullObject(piDisp); | ||
| 629 | ReleaseNullObject(piObj); | ||
| 630 | } | ||
| 631 | |||
| 632 | hr = S_OK; | ||
| 633 | |||
| 634 | LExit: | ||
| 635 | // clean up | ||
| 636 | ReleaseObject(piDisp); | ||
| 637 | ReleaseObject(piObj); | ||
| 638 | |||
| 639 | ::VariantClear(&vtVal); | ||
| 640 | |||
| 641 | return hr; | ||
| 642 | } | ||
| 643 | |||
| 644 | HRESULT CpiRemoveUserCollectionObject( | ||
| 645 | ICatalogCollection* piColl, | ||
| 646 | PSID pSid | ||
| 647 | ) | ||
| 648 | { | ||
| 649 | HRESULT hr = S_OK; | ||
| 650 | |||
| 651 | int i = 0; | ||
| 652 | |||
| 653 | // find index | ||
| 654 | hr = FindUserCollectionObjectIndex(piColl, pSid, &i); | ||
| 655 | ExitOnFailure(hr, "Failed to find user collection index"); | ||
| 656 | |||
| 657 | if (S_FALSE == hr) | ||
| 658 | ExitFunction(); // not found, exit with hr = S_FALSE | ||
| 659 | |||
| 660 | // remove object | ||
| 661 | hr = piColl->Remove(i); | ||
| 662 | ExitOnFailure(hr, "Failed to remove object from collection"); | ||
| 663 | |||
| 664 | hr = S_OK; | ||
| 665 | |||
| 666 | LExit: | ||
| 667 | return hr; | ||
| 668 | } | ||
| 669 | |||
| 670 | HRESULT CpiFindCollectionObjectByStringKey( | ||
| 671 | ICatalogCollection* piColl, | ||
| 672 | LPCWSTR pwzKey, | ||
| 673 | ICatalogObject** ppiObj | ||
| 674 | ) | ||
| 675 | { | ||
| 676 | HRESULT hr = S_OK; | ||
| 677 | |||
| 678 | IDispatch* piDisp = NULL; | ||
| 679 | ICatalogObject* piObj = NULL; | ||
| 680 | |||
| 681 | VARIANT vtVal; | ||
| 682 | ::VariantInit(&vtVal); | ||
| 683 | |||
| 684 | long lCnt; | ||
| 685 | hr = piColl->get_Count(&lCnt); | ||
| 686 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
| 687 | |||
| 688 | for (long i = 0; i < lCnt; i++) | ||
| 689 | { | ||
| 690 | // get ICatalogObject interface | ||
| 691 | hr = piColl->get_Item(i, &piDisp); | ||
| 692 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
| 693 | |||
| 694 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
| 695 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
| 696 | |||
| 697 | // compare key | ||
| 698 | hr = piObj->get_Key(&vtVal); | ||
| 699 | ExitOnFailure(hr, "Failed to get key"); | ||
| 700 | |||
| 701 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
| 702 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 703 | |||
| 704 | if (0 == lstrcmpiW(vtVal.bstrVal, pwzKey)) | ||
| 705 | { | ||
| 706 | if (ppiObj) | ||
| 707 | { | ||
| 708 | *ppiObj = piObj; | ||
| 709 | piObj = NULL; | ||
| 710 | } | ||
| 711 | ExitFunction1(hr = S_OK); | ||
| 712 | } | ||
| 713 | |||
| 714 | // clean up | ||
| 715 | ReleaseNullObject(piDisp); | ||
| 716 | ReleaseNullObject(piObj); | ||
| 717 | |||
| 718 | ::VariantClear(&vtVal); | ||
| 719 | } | ||
| 720 | |||
| 721 | hr = S_FALSE; | ||
| 722 | |||
| 723 | LExit: | ||
| 724 | // clean up | ||
| 725 | ReleaseObject(piDisp); | ||
| 726 | ReleaseObject(piObj); | ||
| 727 | |||
| 728 | ::VariantClear(&vtVal); | ||
| 729 | |||
| 730 | return hr; | ||
| 731 | } | ||
| 732 | |||
| 733 | HRESULT CpiFindCollectionObjectByIntegerKey( | ||
| 734 | ICatalogCollection* piColl, | ||
| 735 | long lKey, | ||
| 736 | ICatalogObject** ppiObj | ||
| 737 | ) | ||
| 738 | { | ||
| 739 | HRESULT hr = S_OK; | ||
| 740 | |||
| 741 | IDispatch* piDisp = NULL; | ||
| 742 | ICatalogObject* piObj = NULL; | ||
| 743 | |||
| 744 | VARIANT vtVal; | ||
| 745 | ::VariantInit(&vtVal); | ||
| 746 | |||
| 747 | long lCnt; | ||
| 748 | hr = piColl->get_Count(&lCnt); | ||
| 749 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
| 750 | |||
| 751 | for (long i = 0; i < lCnt; i++) | ||
| 752 | { | ||
| 753 | // get ICatalogObject interface | ||
| 754 | hr = piColl->get_Item(i, &piDisp); | ||
| 755 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
| 756 | |||
| 757 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
| 758 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
| 759 | |||
| 760 | // compare key | ||
| 761 | hr = piObj->get_Key(&vtVal); | ||
| 762 | ExitOnFailure(hr, "Failed to get key"); | ||
| 763 | |||
| 764 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_I4); | ||
| 765 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 766 | |||
| 767 | if (vtVal.lVal == lKey) | ||
| 768 | { | ||
| 769 | if (ppiObj) | ||
| 770 | { | ||
| 771 | *ppiObj = piObj; | ||
| 772 | piObj = NULL; | ||
| 773 | } | ||
| 774 | ExitFunction1(hr = S_OK); | ||
| 775 | } | ||
| 776 | |||
| 777 | // clean up | ||
| 778 | ReleaseNullObject(piDisp); | ||
| 779 | ReleaseNullObject(piObj); | ||
| 780 | |||
| 781 | ::VariantClear(&vtVal); | ||
| 782 | } | ||
| 783 | |||
| 784 | hr = S_FALSE; | ||
| 785 | |||
| 786 | LExit: | ||
| 787 | // clean up | ||
| 788 | ReleaseObject(piDisp); | ||
| 789 | ReleaseObject(piObj); | ||
| 790 | |||
| 791 | ::VariantClear(&vtVal); | ||
| 792 | |||
| 793 | return hr; | ||
| 794 | } | ||
| 795 | |||
| 796 | HRESULT CpiFindCollectionObjectByName( | ||
| 797 | ICatalogCollection* piColl, | ||
| 798 | LPCWSTR pwzName, | ||
| 799 | ICatalogObject** ppiObj | ||
| 800 | ) | ||
| 801 | { | ||
| 802 | HRESULT hr = S_OK; | ||
| 803 | |||
| 804 | IDispatch* piDisp = NULL; | ||
| 805 | ICatalogObject* piObj = NULL; | ||
| 806 | |||
| 807 | VARIANT vtVal; | ||
| 808 | ::VariantInit(&vtVal); | ||
| 809 | |||
| 810 | long lCnt; | ||
| 811 | hr = piColl->get_Count(&lCnt); | ||
| 812 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
| 813 | |||
| 814 | for (long i = 0; i < lCnt; i++) | ||
| 815 | { | ||
| 816 | // get ICatalogObject interface | ||
| 817 | hr = piColl->get_Item(i, &piDisp); | ||
| 818 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
| 819 | |||
| 820 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
| 821 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
| 822 | |||
| 823 | // compare key | ||
| 824 | hr = piObj->get_Name(&vtVal); | ||
| 825 | ExitOnFailure(hr, "Failed to get key"); | ||
| 826 | |||
| 827 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
| 828 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 829 | |||
| 830 | if (0 == lstrcmpW(vtVal.bstrVal, pwzName)) | ||
| 831 | { | ||
| 832 | if (ppiObj) | ||
| 833 | { | ||
| 834 | *ppiObj = piObj; | ||
| 835 | piObj = NULL; | ||
| 836 | } | ||
| 837 | ExitFunction1(hr = S_OK); | ||
| 838 | } | ||
| 839 | |||
| 840 | // clean up | ||
| 841 | ReleaseNullObject(piDisp); | ||
| 842 | ReleaseNullObject(piObj); | ||
| 843 | |||
| 844 | ::VariantClear(&vtVal); | ||
| 845 | } | ||
| 846 | |||
| 847 | hr = S_FALSE; | ||
| 848 | |||
| 849 | LExit: | ||
| 850 | // clean up | ||
| 851 | ReleaseObject(piDisp); | ||
| 852 | ReleaseObject(piObj); | ||
| 853 | |||
| 854 | ::VariantClear(&vtVal); | ||
| 855 | |||
| 856 | return hr; | ||
| 857 | } | ||
| 858 | |||
| 859 | HRESULT CpiFindUserCollectionObject( | ||
| 860 | ICatalogCollection* piColl, | ||
| 861 | PSID pSid, | ||
| 862 | ICatalogObject** ppiObj | ||
| 863 | ) | ||
| 864 | { | ||
| 865 | HRESULT hr = S_OK; | ||
| 866 | |||
| 867 | int i = 0; | ||
| 868 | |||
| 869 | IDispatch* piDisp = NULL; | ||
| 870 | |||
| 871 | // find index | ||
| 872 | hr = FindUserCollectionObjectIndex(piColl, pSid, &i); | ||
| 873 | ExitOnFailure(hr, "Failed to find user collection index"); | ||
| 874 | |||
| 875 | if (S_FALSE == hr) | ||
| 876 | ExitFunction(); // not found, exit with hr = S_FALSE | ||
| 877 | |||
| 878 | // get object | ||
| 879 | if (ppiObj) | ||
| 880 | { | ||
| 881 | hr = piColl->get_Item(i, &piDisp); | ||
| 882 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
| 883 | |||
| 884 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)ppiObj); | ||
| 885 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
| 886 | } | ||
| 887 | |||
| 888 | hr = S_OK; | ||
| 889 | |||
| 890 | LExit: | ||
| 891 | // clean up | ||
| 892 | ReleaseObject(piDisp); | ||
| 893 | |||
| 894 | return hr; | ||
| 895 | } | ||
| 896 | |||
| 897 | HRESULT CpiGetPartitionsCollection( | ||
| 898 | ICatalogCollection** ppiPartColl | ||
| 899 | ) | ||
| 900 | { | ||
| 901 | HRESULT hr = S_OK; | ||
| 902 | |||
| 903 | // get collection | ||
| 904 | hr = CpiGetCatalogCollection(L"Partitions", ppiPartColl); | ||
| 905 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
| 906 | |||
| 907 | hr = S_OK; | ||
| 908 | |||
| 909 | LExit: | ||
| 910 | return hr; | ||
| 911 | } | ||
| 912 | |||
| 913 | HRESULT CpiGetPartitionRolesCollection( | ||
| 914 | LPCWSTR pwzPartID, | ||
| 915 | ICatalogCollection** ppiRolesColl | ||
| 916 | ) | ||
| 917 | { | ||
| 918 | HRESULT hr = S_OK; | ||
| 919 | |||
| 920 | ICatalogCollection* piPartColl = NULL; | ||
| 921 | ICatalogObject* piPartObj = NULL; | ||
| 922 | |||
| 923 | // get partitions collection | ||
| 924 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
| 925 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
| 926 | |||
| 927 | if (S_FALSE == hr) | ||
| 928 | ExitFunction(); // partitions collection not found, exit with hr = S_FALSE | ||
| 929 | |||
| 930 | // find object | ||
| 931 | hr = CpiFindCollectionObjectByStringKey(piPartColl, pwzPartID, &piPartObj); | ||
| 932 | ExitOnFailure(hr, "Failed to find collection object"); | ||
| 933 | |||
| 934 | if (S_FALSE == hr) | ||
| 935 | ExitFunction(); // partition not found, exit with hr = S_FALSE | ||
| 936 | |||
| 937 | // get roles collection | ||
| 938 | hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"RolesForPartition", ppiRolesColl); | ||
| 939 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
| 940 | |||
| 941 | hr = S_OK; | ||
| 942 | |||
| 943 | LExit: | ||
| 944 | // clean up | ||
| 945 | ReleaseObject(piPartColl); | ||
| 946 | ReleaseObject(piPartObj); | ||
| 947 | |||
| 948 | return hr; | ||
| 949 | } | ||
| 950 | |||
| 951 | HRESULT CpiGetUsersInPartitionRoleCollection( | ||
| 952 | LPCWSTR pwzPartID, | ||
| 953 | LPCWSTR pwzRoleName, | ||
| 954 | ICatalogCollection** ppiUsrInRoleColl | ||
| 955 | ) | ||
| 956 | { | ||
| 957 | HRESULT hr = S_OK; | ||
| 958 | |||
| 959 | ICatalogCollection* piRoleColl = NULL; | ||
| 960 | ICatalogObject* piRoleObj = NULL; | ||
| 961 | |||
| 962 | // get roles collection | ||
| 963 | hr = CpiGetPartitionRolesCollection(pwzPartID, &piRoleColl); | ||
| 964 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
| 965 | |||
| 966 | if (S_FALSE == hr) | ||
| 967 | ExitFunction(); // partition roles collection not found, exit with hr = S_FALSE | ||
| 968 | |||
| 969 | // find object | ||
| 970 | hr = CpiFindCollectionObjectByName(piRoleColl, pwzRoleName, &piRoleObj); | ||
| 971 | ExitOnFailure(hr, "Failed to find collection object"); | ||
| 972 | |||
| 973 | if (S_FALSE == hr) | ||
| 974 | ExitFunction(); // user not found, exit with hr = S_FALSE | ||
| 975 | |||
| 976 | // get roles collection | ||
| 977 | hr = CpiGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInPartitionRole", ppiUsrInRoleColl); | ||
| 978 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
| 979 | |||
| 980 | hr = S_OK; | ||
| 981 | |||
| 982 | LExit: | ||
| 983 | // clean up | ||
| 984 | ReleaseObject(piRoleColl); | ||
| 985 | ReleaseObject(piRoleObj); | ||
| 986 | |||
| 987 | return hr; | ||
| 988 | } | ||
| 989 | |||
| 990 | HRESULT CpiGetPartitionUsersCollection( | ||
| 991 | ICatalogCollection** ppiUserColl | ||
| 992 | ) | ||
| 993 | { | ||
| 994 | HRESULT hr = S_OK; | ||
| 995 | |||
| 996 | // get roles collection | ||
| 997 | hr = CpiGetCatalogCollection(L"PartitionUsers", ppiUserColl); | ||
| 998 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
| 999 | |||
| 1000 | hr = S_OK; | ||
| 1001 | |||
| 1002 | LExit: | ||
| 1003 | return hr; | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | HRESULT CpiGetApplicationsCollection( | ||
| 1007 | LPCWSTR pwzPartID, | ||
| 1008 | ICatalogCollection** ppiAppColl | ||
| 1009 | ) | ||
| 1010 | { | ||
| 1011 | HRESULT hr = S_OK; | ||
| 1012 | |||
| 1013 | ICOMAdminCatalog* piCatalog = NULL; | ||
| 1014 | ICOMAdminCatalog2* piCatalog2 = NULL; | ||
| 1015 | BSTR bstrGlobPartID = NULL; | ||
| 1016 | |||
| 1017 | ICatalogCollection* piPartColl = NULL; | ||
| 1018 | ICatalogObject* piPartObj = NULL; | ||
| 1019 | |||
| 1020 | // get catalog | ||
| 1021 | hr = CpiGetAdminCatalog(&piCatalog); | ||
| 1022 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
| 1023 | |||
| 1024 | // get ICOMAdminCatalog2 interface | ||
| 1025 | hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2); | ||
| 1026 | |||
| 1027 | // COM+ 1.5 or later | ||
| 1028 | if (E_NOINTERFACE != hr) | ||
| 1029 | { | ||
| 1030 | ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface"); | ||
| 1031 | |||
| 1032 | // partition id | ||
| 1033 | if (!pwzPartID || !*pwzPartID) | ||
| 1034 | { | ||
| 1035 | // get global partition id | ||
| 1036 | hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID); | ||
| 1037 | ExitOnFailure(hr, "Failed to get global partition id"); | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | // get partitions collection | ||
| 1041 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
| 1042 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
| 1043 | |||
| 1044 | // find object | ||
| 1045 | hr = CpiFindCollectionObjectByStringKey(piPartColl, bstrGlobPartID ? bstrGlobPartID : pwzPartID, &piPartObj); | ||
| 1046 | ExitOnFailure(hr, "Failed to find collection object"); | ||
| 1047 | |||
| 1048 | if (S_FALSE == hr) | ||
| 1049 | ExitFunction(); // partition not found, exit with hr = S_FALSE | ||
| 1050 | |||
| 1051 | // get applications collection | ||
| 1052 | hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"Applications", ppiAppColl); | ||
| 1053 | ExitOnFailure(hr, "Failed to get catalog collection for partition"); | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | // COM+ pre 1.5 | ||
| 1057 | else | ||
| 1058 | { | ||
| 1059 | // this version of COM+ does not support partitions, make sure a partition was not specified | ||
| 1060 | if (pwzPartID && *pwzPartID) | ||
| 1061 | ExitOnFailure(hr = E_FAIL, "Partitions are not supported by this version of COM+"); | ||
| 1062 | |||
| 1063 | // get applications collection | ||
| 1064 | hr = CpiGetCatalogCollection(L"Applications", ppiAppColl); | ||
| 1065 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | hr = S_OK; | ||
| 1069 | |||
| 1070 | LExit: | ||
| 1071 | // clean up | ||
| 1072 | ReleaseObject(piCatalog); | ||
| 1073 | ReleaseObject(piCatalog2); | ||
| 1074 | ReleaseBSTR(bstrGlobPartID); | ||
| 1075 | |||
| 1076 | ReleaseObject(piPartColl); | ||
| 1077 | ReleaseObject(piPartObj); | ||
| 1078 | |||
| 1079 | return hr; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | HRESULT CpiGetRolesCollection( | ||
| 1083 | LPCWSTR pwzPartID, | ||
| 1084 | LPCWSTR pwzAppID, | ||
| 1085 | ICatalogCollection** ppiRolesColl | ||
| 1086 | ) | ||
| 1087 | { | ||
| 1088 | HRESULT hr = S_OK; | ||
| 1089 | |||
| 1090 | ICatalogCollection* piAppColl = NULL; | ||
| 1091 | ICatalogObject* piAppObj = NULL; | ||
| 1092 | |||
| 1093 | // get applications collection | ||
| 1094 | hr = CpiGetApplicationsCollection(pwzPartID, &piAppColl); | ||
| 1095 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 1096 | |||
| 1097 | if (S_FALSE == hr) | ||
| 1098 | ExitFunction(); // applications collection not found, exit with hr = S_FALSE | ||
| 1099 | |||
| 1100 | // find object | ||
| 1101 | hr = CpiFindCollectionObjectByStringKey(piAppColl, pwzAppID, &piAppObj); | ||
| 1102 | ExitOnFailure(hr, "Failed to find collection object"); | ||
| 1103 | |||
| 1104 | if (S_FALSE == hr) | ||
| 1105 | ExitFunction(); // application not found, exit with hr = S_FALSE | ||
| 1106 | |||
| 1107 | // get roles collection | ||
| 1108 | hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Roles", ppiRolesColl); | ||
| 1109 | ExitOnFailure(hr, "Failed to catalog collection"); | ||
| 1110 | |||
| 1111 | hr = S_OK; | ||
| 1112 | |||
| 1113 | LExit: | ||
| 1114 | // clean up | ||
| 1115 | ReleaseObject(piAppColl); | ||
| 1116 | ReleaseObject(piAppObj); | ||
| 1117 | |||
| 1118 | return hr; | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | HRESULT CpiGetUsersInRoleCollection( | ||
| 1122 | LPCWSTR pwzPartID, | ||
| 1123 | LPCWSTR pwzAppID, | ||
| 1124 | LPCWSTR pwzRoleName, | ||
| 1125 | ICatalogCollection** ppiUsrInRoleColl | ||
| 1126 | ) | ||
| 1127 | { | ||
| 1128 | HRESULT hr = S_OK; | ||
| 1129 | |||
| 1130 | ICatalogCollection* piRoleColl = NULL; | ||
| 1131 | ICatalogObject* piRoleObj = NULL; | ||
| 1132 | |||
| 1133 | // get roles collection | ||
| 1134 | hr = CpiGetRolesCollection(pwzPartID, pwzAppID, &piRoleColl); | ||
| 1135 | ExitOnFailure(hr, "Failed to get roles collection"); | ||
| 1136 | |||
| 1137 | if (S_FALSE == hr) | ||
| 1138 | ExitFunction(); // roles collection not found, exit with hr = S_FALSE | ||
| 1139 | |||
| 1140 | // find object | ||
| 1141 | hr = CpiFindCollectionObjectByName(piRoleColl, pwzRoleName, &piRoleObj); | ||
| 1142 | ExitOnFailure(hr, "Failed to find collection object"); | ||
| 1143 | |||
| 1144 | if (S_FALSE == hr) | ||
| 1145 | ExitFunction(); // role not found, exit with hr = S_FALSE | ||
| 1146 | |||
| 1147 | // get roles collection | ||
| 1148 | hr = CpiGetCatalogCollection(piRoleColl, piRoleObj, L"UsersInRole", ppiUsrInRoleColl); | ||
| 1149 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
| 1150 | |||
| 1151 | hr = S_OK; | ||
| 1152 | |||
| 1153 | LExit: | ||
| 1154 | // clean up | ||
| 1155 | ReleaseObject(piRoleColl); | ||
| 1156 | ReleaseObject(piRoleObj); | ||
| 1157 | |||
| 1158 | return hr; | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | HRESULT CpiGetComponentsCollection( | ||
| 1162 | LPCWSTR pwzPartID, | ||
| 1163 | LPCWSTR pwzAppID, | ||
| 1164 | ICatalogCollection** ppiCompsColl | ||
| 1165 | ) | ||
| 1166 | { | ||
| 1167 | HRESULT hr = S_OK; | ||
| 1168 | |||
| 1169 | ICatalogCollection* piAppColl = NULL; | ||
| 1170 | ICatalogObject* piAppObj = NULL; | ||
| 1171 | |||
| 1172 | // get applications collection | ||
| 1173 | hr = CpiGetApplicationsCollection(pwzPartID, &piAppColl); | ||
| 1174 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 1175 | |||
| 1176 | if (S_FALSE == hr) | ||
| 1177 | ExitFunction(); // applications collection not found, exit with hr = S_FALSE | ||
| 1178 | |||
| 1179 | // find object | ||
| 1180 | hr = CpiFindCollectionObjectByStringKey(piAppColl, pwzAppID, &piAppObj); | ||
| 1181 | ExitOnFailure(hr, "Failed to find collection object"); | ||
| 1182 | |||
| 1183 | if (S_FALSE == hr) | ||
| 1184 | ExitFunction(); // application not found, exit with hr = S_FALSE | ||
| 1185 | |||
| 1186 | // get components collection | ||
| 1187 | hr = CpiGetCatalogCollection(piAppColl, piAppObj, L"Components", ppiCompsColl); | ||
| 1188 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
| 1189 | |||
| 1190 | hr = S_OK; | ||
| 1191 | |||
| 1192 | LExit: | ||
| 1193 | // clean up | ||
| 1194 | ReleaseObject(piAppColl); | ||
| 1195 | ReleaseObject(piAppObj); | ||
| 1196 | |||
| 1197 | return hr; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | HRESULT CpiGetInterfacesCollection( | ||
| 1201 | ICatalogCollection* piCompColl, | ||
| 1202 | ICatalogObject* piCompObj, | ||
| 1203 | ICatalogCollection** ppiIntfColl | ||
| 1204 | ) | ||
| 1205 | { | ||
| 1206 | HRESULT hr = S_OK; | ||
| 1207 | |||
| 1208 | // get interfaces collection | ||
| 1209 | hr = CpiGetCatalogCollection(piCompColl, piCompObj, L"InterfacesForComponent", ppiIntfColl); | ||
| 1210 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
| 1211 | |||
| 1212 | hr = S_OK; | ||
| 1213 | |||
| 1214 | LExit: | ||
| 1215 | return hr; | ||
| 1216 | } | ||
| 1217 | |||
| 1218 | HRESULT CpiGetMethodsCollection( | ||
| 1219 | ICatalogCollection* piIntfColl, | ||
| 1220 | ICatalogObject* piIntfObj, | ||
| 1221 | ICatalogCollection** ppiMethColl | ||
| 1222 | ) | ||
| 1223 | { | ||
| 1224 | HRESULT hr = S_OK; | ||
| 1225 | |||
| 1226 | // get interfaces collection | ||
| 1227 | hr = CpiGetCatalogCollection(piIntfColl, piIntfObj, L"MethodsForInterface", ppiMethColl); | ||
| 1228 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
| 1229 | |||
| 1230 | hr = S_OK; | ||
| 1231 | |||
| 1232 | LExit: | ||
| 1233 | return hr; | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | HRESULT CpiGetSubscriptionsCollection( | ||
| 1237 | LPCWSTR pwzPartID, | ||
| 1238 | LPCWSTR pwzAppID, | ||
| 1239 | LPCWSTR pwzCompCLSID, | ||
| 1240 | ICatalogCollection** ppiSubsColl | ||
| 1241 | ) | ||
| 1242 | { | ||
| 1243 | HRESULT hr = S_OK; | ||
| 1244 | |||
| 1245 | ICatalogCollection* piCompColl = NULL; | ||
| 1246 | ICatalogObject* piCompObj = NULL; | ||
| 1247 | |||
| 1248 | // get components collection | ||
| 1249 | hr = CpiGetComponentsCollection(pwzPartID, pwzAppID, &piCompColl); | ||
| 1250 | ExitOnFailure(hr, "Failed to get components collection"); | ||
| 1251 | |||
| 1252 | if (S_FALSE == hr) | ||
| 1253 | ExitFunction(); // components collection not found, exit with hr = S_FALSE | ||
| 1254 | |||
| 1255 | // find object | ||
| 1256 | hr = CpiFindCollectionObjectByStringKey(piCompColl, pwzCompCLSID, &piCompObj); | ||
| 1257 | ExitOnFailure(hr, "Failed to find collection object"); | ||
| 1258 | |||
| 1259 | if (S_FALSE == hr) | ||
| 1260 | ExitFunction(); // component not found, exit with hr = S_FALSE | ||
| 1261 | |||
| 1262 | // get subscriptions collection | ||
| 1263 | hr = CpiGetCatalogCollection(piCompColl, piCompObj, L"SubscriptionsForComponent", ppiSubsColl); | ||
| 1264 | ExitOnFailure(hr, "Failed to get catalog collection"); | ||
| 1265 | |||
| 1266 | hr = S_OK; | ||
| 1267 | |||
| 1268 | LExit: | ||
| 1269 | // clean up | ||
| 1270 | ReleaseObject(piCompColl); | ||
| 1271 | ReleaseObject(piCompObj); | ||
| 1272 | |||
| 1273 | return hr; | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | HRESULT CpiReadPropertyList( | ||
| 1277 | LPWSTR* ppwzData, | ||
| 1278 | CPI_PROPERTY** ppPropList | ||
| 1279 | ) | ||
| 1280 | { | ||
| 1281 | HRESULT hr = S_OK; | ||
| 1282 | |||
| 1283 | CPI_PROPERTY* pItm = NULL; | ||
| 1284 | LPWSTR pwzName = NULL; | ||
| 1285 | |||
| 1286 | // clear list if it already contains items | ||
| 1287 | if (*ppPropList) | ||
| 1288 | CpiFreePropertyList(*ppPropList); | ||
| 1289 | *ppPropList = NULL; | ||
| 1290 | |||
| 1291 | // read property count | ||
| 1292 | int iPropCnt = 0; | ||
| 1293 | hr = WcaReadIntegerFromCaData(ppwzData, &iPropCnt); | ||
| 1294 | ExitOnFailure(hr, "Failed to read property count"); | ||
| 1295 | |||
| 1296 | for (int i = 0; i < iPropCnt; i++) | ||
| 1297 | { | ||
| 1298 | // allocate new element | ||
| 1299 | pItm = (CPI_PROPERTY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PROPERTY)); | ||
| 1300 | if (!pItm) | ||
| 1301 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 1302 | |||
| 1303 | // Name | ||
| 1304 | hr = WcaReadStringFromCaData(ppwzData, &pwzName); | ||
| 1305 | ExitOnFailure(hr, "Failed to read name"); | ||
| 1306 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzName); | ||
| 1307 | |||
| 1308 | // Value | ||
| 1309 | hr = WcaReadStringFromCaData(ppwzData, &pItm->pwzValue); | ||
| 1310 | ExitOnFailure(hr, "Failed to read property value"); | ||
| 1311 | |||
| 1312 | // add to list | ||
| 1313 | if (*ppPropList) | ||
| 1314 | pItm->pNext = *ppPropList; | ||
| 1315 | *ppPropList = pItm; | ||
| 1316 | pItm = NULL; | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | hr = S_OK; | ||
| 1320 | |||
| 1321 | LExit: | ||
| 1322 | // clean up | ||
| 1323 | ReleaseStr(pwzName); | ||
| 1324 | |||
| 1325 | if (pItm) | ||
| 1326 | CpiFreePropertyList(pItm); | ||
| 1327 | |||
| 1328 | return hr; | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | void CpiFreePropertyList( | ||
| 1332 | CPI_PROPERTY* pList | ||
| 1333 | ) | ||
| 1334 | { | ||
| 1335 | while (pList) | ||
| 1336 | { | ||
| 1337 | ReleaseStr(pList->pwzValue); | ||
| 1338 | |||
| 1339 | CPI_PROPERTY* pDelete = pList; | ||
| 1340 | pList = pList->pNext; | ||
| 1341 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 1342 | } | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | HRESULT CpiWriteKeyToRollbackFile( | ||
| 1346 | HANDLE hFile, | ||
| 1347 | LPCWSTR pwzKey | ||
| 1348 | ) | ||
| 1349 | { | ||
| 1350 | HRESULT hr = S_OK; | ||
| 1351 | |||
| 1352 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 1353 | ::ZeroMemory(wzKey, sizeof(wzKey)); | ||
| 1354 | hr = StringCchCopyW(wzKey, countof(wzKey), pwzKey); | ||
| 1355 | ExitOnFailure(hr, "Failed to copy key"); | ||
| 1356 | |||
| 1357 | hr = WriteFileAll(hFile, (PBYTE)wzKey, MAX_DARWIN_KEY * sizeof(WCHAR)); | ||
| 1358 | ExitOnFailure(hr, "Failed to write buffer"); | ||
| 1359 | |||
| 1360 | FlushFileBuffers(hFile); | ||
| 1361 | |||
| 1362 | hr = S_OK; | ||
| 1363 | |||
| 1364 | LExit: | ||
| 1365 | return hr; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | HRESULT CpiWriteIntegerToRollbackFile( | ||
| 1369 | HANDLE hFile, | ||
| 1370 | int i | ||
| 1371 | ) | ||
| 1372 | { | ||
| 1373 | HRESULT hr = S_OK; | ||
| 1374 | |||
| 1375 | hr = WriteFileAll(hFile, (PBYTE)&i, sizeof(int)); | ||
| 1376 | ExitOnFailure(hr, "Failed to write buffer"); | ||
| 1377 | |||
| 1378 | FlushFileBuffers(hFile); | ||
| 1379 | |||
| 1380 | hr = S_OK; | ||
| 1381 | |||
| 1382 | LExit: | ||
| 1383 | return hr; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | HRESULT CpiReadRollbackDataList( | ||
| 1387 | HANDLE hFile, | ||
| 1388 | CPI_ROLLBACK_DATA** pprdList | ||
| 1389 | ) | ||
| 1390 | { | ||
| 1391 | HRESULT hr = S_OK; | ||
| 1392 | |||
| 1393 | int iCount; | ||
| 1394 | |||
| 1395 | CPI_ROLLBACK_DATA* pItm = NULL; | ||
| 1396 | |||
| 1397 | // read count | ||
| 1398 | hr = ReadFileAll(hFile, (PBYTE)&iCount, sizeof(int)); | ||
| 1399 | if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr) | ||
| 1400 | ExitFunction1(hr = S_OK); // EOF reached, nothing left to read | ||
| 1401 | ExitOnFailure(hr, "Failed to read count"); | ||
| 1402 | |||
| 1403 | for (int i = 0; i < iCount; i++) | ||
| 1404 | { | ||
| 1405 | // allocate new element | ||
| 1406 | pItm = (CPI_ROLLBACK_DATA*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_ROLLBACK_DATA)); | ||
| 1407 | if (!pItm) | ||
| 1408 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 1409 | |||
| 1410 | // read from file | ||
| 1411 | hr = ReadFileAll(hFile, (PBYTE)pItm->wzKey, MAX_DARWIN_KEY * sizeof(WCHAR)); | ||
| 1412 | if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr) | ||
| 1413 | break; // EOF reached, nothing left to read | ||
| 1414 | ExitOnFailure(hr, "Failed to read key"); | ||
| 1415 | |||
| 1416 | hr = ReadFileAll(hFile, (PBYTE)&pItm->iStatus, sizeof(int)); | ||
| 1417 | if (HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) == hr) | ||
| 1418 | pItm->iStatus = 0; // EOF reached, the operation was interupted; set status to zero | ||
| 1419 | else | ||
| 1420 | ExitOnFailure(hr, "Failed to read status"); | ||
| 1421 | |||
| 1422 | // add to list | ||
| 1423 | if (*pprdList) | ||
| 1424 | pItm->pNext = *pprdList; | ||
| 1425 | *pprdList = pItm; | ||
| 1426 | pItm = NULL; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | hr = S_OK; | ||
| 1430 | |||
| 1431 | LExit: | ||
| 1432 | // clean up | ||
| 1433 | if (pItm) | ||
| 1434 | CpiFreeRollbackDataList(pItm); | ||
| 1435 | |||
| 1436 | return hr; | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | void CpiFreeRollbackDataList( | ||
| 1440 | CPI_ROLLBACK_DATA* pList | ||
| 1441 | ) | ||
| 1442 | { | ||
| 1443 | while (pList) | ||
| 1444 | { | ||
| 1445 | CPI_ROLLBACK_DATA* pDelete = pList; | ||
| 1446 | pList = pList->pNext; | ||
| 1447 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 1448 | } | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | HRESULT CpiFindRollbackStatus( | ||
| 1452 | CPI_ROLLBACK_DATA* pList, | ||
| 1453 | LPCWSTR pwzKey, | ||
| 1454 | int* piStatus | ||
| 1455 | ) | ||
| 1456 | { | ||
| 1457 | HRESULT hr = S_OK; | ||
| 1458 | |||
| 1459 | for (; pList; pList = pList->pNext) | ||
| 1460 | { | ||
| 1461 | if (0 == lstrcmpW(pList->wzKey, pwzKey)) | ||
| 1462 | { | ||
| 1463 | *piStatus = pList->iStatus; | ||
| 1464 | ExitFunction1(hr = S_OK); | ||
| 1465 | } | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | hr = S_FALSE; | ||
| 1469 | |||
| 1470 | LExit: | ||
| 1471 | return hr; | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | HRESULT CpiAccountNameToSid( | ||
| 1475 | LPCWSTR pwzAccountName, | ||
| 1476 | PSID* ppSid | ||
| 1477 | ) | ||
| 1478 | { | ||
| 1479 | HRESULT hr = S_OK; | ||
| 1480 | UINT er = ERROR_SUCCESS; | ||
| 1481 | NTSTATUS st = 0; | ||
| 1482 | |||
| 1483 | PSID pSid = NULL; | ||
| 1484 | LSA_OBJECT_ATTRIBUTES loaAttributes; | ||
| 1485 | LSA_HANDLE lsahPolicy = NULL; | ||
| 1486 | LSA_UNICODE_STRING lusName; | ||
| 1487 | PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL; | ||
| 1488 | PLSA_TRANSLATED_SID pltsSid = NULL; | ||
| 1489 | |||
| 1490 | ::ZeroMemory(&loaAttributes, sizeof(loaAttributes)); | ||
| 1491 | ::ZeroMemory(&lusName, sizeof(lusName)); | ||
| 1492 | |||
| 1493 | // identify well known SIDs | ||
| 1494 | for (CPI_WELLKNOWN_SID* pWS = wsWellKnownSids; pWS->pwzName; pWS++) | ||
| 1495 | { | ||
| 1496 | if (0 == lstrcmpiW(pwzAccountName, pWS->pwzName)) | ||
| 1497 | { | ||
| 1498 | // allocate SID buffer | ||
| 1499 | pSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, ::GetSidLengthRequired(pWS->nSubAuthorityCount)); | ||
| 1500 | ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID"); | ||
| 1501 | |||
| 1502 | // initialize SID | ||
| 1503 | ::InitializeSid(pSid, &pWS->iaIdentifierAuthority, pWS->nSubAuthorityCount); | ||
| 1504 | |||
| 1505 | // copy sub autorities | ||
| 1506 | for (DWORD i = 0; i < pWS->nSubAuthorityCount; i++) | ||
| 1507 | *::GetSidSubAuthority(pSid, i) = pWS->dwSubAuthority[i]; | ||
| 1508 | |||
| 1509 | break; | ||
| 1510 | } | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | // lookup name | ||
| 1514 | if (!pSid) | ||
| 1515 | { | ||
| 1516 | // open policy handle | ||
| 1517 | st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy); | ||
| 1518 | er = ::LsaNtStatusToWinError(st); | ||
| 1519 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle"); | ||
| 1520 | |||
| 1521 | // create account name lsa unicode string | ||
| 1522 | hr = InitLsaUnicodeString(&lusName, pwzAccountName, (DWORD)wcslen(pwzAccountName)); | ||
| 1523 | ExitOnFailure(hr, "Failed to initialize account name string"); | ||
| 1524 | |||
| 1525 | // lookup name | ||
| 1526 | st = ::LsaLookupNames(lsahPolicy, 1, &lusName, &plrdsDomains, &pltsSid); | ||
| 1527 | er = ::LsaNtStatusToWinError(st); | ||
| 1528 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names"); | ||
| 1529 | |||
| 1530 | if (SidTypeDomain == pltsSid->Use) | ||
| 1531 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported"); | ||
| 1532 | |||
| 1533 | // convert sid | ||
| 1534 | hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pSid); | ||
| 1535 | ExitOnFailure(hr, "Failed to convert SID"); | ||
| 1536 | } | ||
| 1537 | |||
| 1538 | *ppSid = pSid; | ||
| 1539 | pSid = NULL; | ||
| 1540 | |||
| 1541 | hr = S_OK; | ||
| 1542 | |||
| 1543 | LExit: | ||
| 1544 | // clean up | ||
| 1545 | if (pSid) | ||
| 1546 | ::HeapFree(::GetProcessHeap(), 0, pSid); | ||
| 1547 | if (lsahPolicy) | ||
| 1548 | ::LsaClose(lsahPolicy); | ||
| 1549 | if (plrdsDomains) | ||
| 1550 | ::LsaFreeMemory(plrdsDomains); | ||
| 1551 | if (pltsSid) | ||
| 1552 | ::LsaFreeMemory(pltsSid); | ||
| 1553 | FreeLsaUnicodeString(&lusName); | ||
| 1554 | |||
| 1555 | return hr; | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | HRESULT CpiSidToAccountName( | ||
| 1559 | PSID pSid, | ||
| 1560 | LPWSTR* ppwzAccountName | ||
| 1561 | ) | ||
| 1562 | { | ||
| 1563 | HRESULT hr = S_OK; | ||
| 1564 | UINT er = ERROR_SUCCESS; | ||
| 1565 | NTSTATUS st = 0; | ||
| 1566 | |||
| 1567 | LSA_OBJECT_ATTRIBUTES loaAttributes; | ||
| 1568 | LSA_HANDLE lsahPolicy = NULL; | ||
| 1569 | PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL; | ||
| 1570 | PLSA_TRANSLATED_NAME pltnName = NULL; | ||
| 1571 | |||
| 1572 | LPWSTR pwzDomain = NULL; | ||
| 1573 | LPWSTR pwzName = NULL; | ||
| 1574 | |||
| 1575 | ::ZeroMemory(&loaAttributes, sizeof(loaAttributes)); | ||
| 1576 | |||
| 1577 | // open policy handle | ||
| 1578 | st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy); | ||
| 1579 | er = ::LsaNtStatusToWinError(st); | ||
| 1580 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle"); | ||
| 1581 | |||
| 1582 | // lookup SID | ||
| 1583 | st = ::LsaLookupSids(lsahPolicy, 1, &pSid, &plrdsDomains, &pltnName); | ||
| 1584 | er = ::LsaNtStatusToWinError(st); | ||
| 1585 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed lookup SID"); | ||
| 1586 | |||
| 1587 | if (SidTypeDomain == pltnName->Use) | ||
| 1588 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported"); | ||
| 1589 | |||
| 1590 | // format account name string | ||
| 1591 | if (SidTypeWellKnownGroup != pltnName->Use) | ||
| 1592 | { | ||
| 1593 | PLSA_UNICODE_STRING plusDomain = &plrdsDomains->Domains[pltnName->DomainIndex].Name; | ||
| 1594 | hr = StrAllocString(&pwzDomain, plusDomain->Buffer, plusDomain->Length / sizeof(WCHAR)); | ||
| 1595 | ExitOnFailure(hr, "Failed to allocate name string"); | ||
| 1596 | } | ||
| 1597 | |||
| 1598 | hr = StrAllocString(&pwzName, pltnName->Name.Buffer, pltnName->Name.Length / sizeof(WCHAR)); | ||
| 1599 | ExitOnFailure(hr, "Failed to allocate domain string"); | ||
| 1600 | |||
| 1601 | hr = StrAllocFormatted(ppwzAccountName, L"%s\\%s", pwzDomain ? pwzDomain : L"", pwzName); | ||
| 1602 | ExitOnFailure(hr, "Failed to format account name string"); | ||
| 1603 | |||
| 1604 | hr = S_OK; | ||
| 1605 | |||
| 1606 | LExit: | ||
| 1607 | // clean up | ||
| 1608 | if (lsahPolicy) | ||
| 1609 | ::LsaClose(lsahPolicy); | ||
| 1610 | if (plrdsDomains) | ||
| 1611 | ::LsaFreeMemory(plrdsDomains); | ||
| 1612 | if (pltnName) | ||
| 1613 | ::LsaFreeMemory(pltnName); | ||
| 1614 | |||
| 1615 | ReleaseStr(pwzDomain); | ||
| 1616 | ReleaseStr(pwzName); | ||
| 1617 | |||
| 1618 | return hr; | ||
| 1619 | } | ||
| 1620 | |||
| 1621 | // helper function definitions | ||
| 1622 | |||
| 1623 | static HRESULT FindUserCollectionObjectIndex( | ||
| 1624 | ICatalogCollection* piColl, | ||
| 1625 | PSID pSid, | ||
| 1626 | int* pi | ||
| 1627 | ) | ||
| 1628 | { | ||
| 1629 | HRESULT hr = S_OK; | ||
| 1630 | UINT er = ERROR_SUCCESS; | ||
| 1631 | NTSTATUS st = 0; | ||
| 1632 | |||
| 1633 | long i = 0; | ||
| 1634 | long lCollCnt = 0; | ||
| 1635 | |||
| 1636 | LSA_OBJECT_ATTRIBUTES loaAttributes; | ||
| 1637 | LSA_HANDLE lsahPolicy = NULL; | ||
| 1638 | PLSA_UNICODE_STRING plusNames = NULL; | ||
| 1639 | PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL; | ||
| 1640 | PLSA_TRANSLATED_SID pltsSids = NULL; | ||
| 1641 | |||
| 1642 | IDispatch* piDisp = NULL; | ||
| 1643 | ICatalogObject* piObj = NULL; | ||
| 1644 | VARIANT vtVal; | ||
| 1645 | |||
| 1646 | PSID pTmpSid = NULL; | ||
| 1647 | |||
| 1648 | PLSA_TRANSLATED_SID pltsSid; | ||
| 1649 | |||
| 1650 | ::VariantInit(&vtVal); | ||
| 1651 | ::ZeroMemory(&loaAttributes, sizeof(loaAttributes)); | ||
| 1652 | |||
| 1653 | // open policy handle | ||
| 1654 | st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy); | ||
| 1655 | er = ::LsaNtStatusToWinError(st); | ||
| 1656 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle"); | ||
| 1657 | |||
| 1658 | // get number of elements in collection | ||
| 1659 | hr = piColl->get_Count(&lCollCnt); | ||
| 1660 | ExitOnFailure(hr, "Failed to get to number of objects in collection"); | ||
| 1661 | |||
| 1662 | if (0 == lCollCnt) | ||
| 1663 | ExitFunction1(hr = S_FALSE); // not found | ||
| 1664 | |||
| 1665 | // allocate name buffer | ||
| 1666 | plusNames = (PLSA_UNICODE_STRING)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LSA_UNICODE_STRING) * lCollCnt); | ||
| 1667 | ExitOnNull(plusNames, hr, E_OUTOFMEMORY, "Failed to allocate names buffer"); | ||
| 1668 | |||
| 1669 | // get accounts in collection | ||
| 1670 | for (i = 0; i < lCollCnt; i++) | ||
| 1671 | { | ||
| 1672 | // get ICatalogObject interface | ||
| 1673 | hr = piColl->get_Item(i, &piDisp); | ||
| 1674 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
| 1675 | |||
| 1676 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
| 1677 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
| 1678 | |||
| 1679 | // get value | ||
| 1680 | hr = piObj->get_Key(&vtVal); | ||
| 1681 | ExitOnFailure(hr, "Failed to get key"); | ||
| 1682 | |||
| 1683 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
| 1684 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 1685 | |||
| 1686 | // copy account name string | ||
| 1687 | hr = InitLsaUnicodeString(&plusNames[i], vtVal.bstrVal, ::SysStringLen(vtVal.bstrVal)); | ||
| 1688 | ExitOnFailure(hr, "Failed to initialize account name string"); | ||
| 1689 | |||
| 1690 | // clean up | ||
| 1691 | ReleaseNullObject(piDisp); | ||
| 1692 | ReleaseNullObject(piObj); | ||
| 1693 | ::VariantClear(&vtVal); | ||
| 1694 | } | ||
| 1695 | |||
| 1696 | // lookup names | ||
| 1697 | st = ::LsaLookupNames(lsahPolicy, lCollCnt, plusNames, &plrdsDomains, &pltsSids); | ||
| 1698 | er = ::LsaNtStatusToWinError(st); | ||
| 1699 | if (ERROR_NONE_MAPPED != er && ERROR_SOME_NOT_MAPPED != er) | ||
| 1700 | ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names"); | ||
| 1701 | |||
| 1702 | // compare SIDs | ||
| 1703 | for (i = 0; i < lCollCnt; i++) | ||
| 1704 | { | ||
| 1705 | // get SID | ||
| 1706 | pltsSid = &pltsSids[i]; | ||
| 1707 | if (SidTypeDomain == pltsSid->Use || SidTypeInvalid == pltsSid->Use || SidTypeUnknown == pltsSid->Use) | ||
| 1708 | continue; // ignore... | ||
| 1709 | |||
| 1710 | hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pTmpSid); | ||
| 1711 | ExitOnFailure(hr, "Failed to convert SID"); | ||
| 1712 | |||
| 1713 | // compare SIDs | ||
| 1714 | if (::EqualSid(pSid, pTmpSid)) | ||
| 1715 | { | ||
| 1716 | *pi = i; | ||
| 1717 | ExitFunction1(hr = S_OK); | ||
| 1718 | } | ||
| 1719 | } | ||
| 1720 | |||
| 1721 | if (ERROR_NONE_MAPPED == er || ERROR_SOME_NOT_MAPPED == er) | ||
| 1722 | hr = HRESULT_FROM_WIN32(er); | ||
| 1723 | else | ||
| 1724 | hr = S_FALSE; // not found | ||
| 1725 | |||
| 1726 | LExit: | ||
| 1727 | // clean up | ||
| 1728 | ReleaseObject(piDisp); | ||
| 1729 | ReleaseObject(piObj); | ||
| 1730 | ::VariantClear(&vtVal); | ||
| 1731 | |||
| 1732 | if (plusNames) | ||
| 1733 | { | ||
| 1734 | for (i = 0; i < lCollCnt; i++) | ||
| 1735 | FreeLsaUnicodeString(&plusNames[i]); | ||
| 1736 | ::HeapFree(::GetProcessHeap(), 0, plusNames); | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | if (lsahPolicy) | ||
| 1740 | ::LsaClose(lsahPolicy); | ||
| 1741 | if (plrdsDomains) | ||
| 1742 | ::LsaFreeMemory(plrdsDomains); | ||
| 1743 | if (pltsSids) | ||
| 1744 | ::LsaFreeMemory(pltsSids); | ||
| 1745 | |||
| 1746 | if (pTmpSid) | ||
| 1747 | ::HeapFree(::GetProcessHeap(), 0, pTmpSid); | ||
| 1748 | |||
| 1749 | return hr; | ||
| 1750 | } | ||
| 1751 | |||
| 1752 | static HRESULT CreateSidFromDomainRidPair( | ||
| 1753 | PSID pDomainSid, | ||
| 1754 | DWORD dwRid, | ||
| 1755 | PSID* ppSid | ||
| 1756 | ) | ||
| 1757 | { | ||
| 1758 | HRESULT hr = S_OK; | ||
| 1759 | PSID pSid = NULL; | ||
| 1760 | |||
| 1761 | // get domain SID sub authority count | ||
| 1762 | UCHAR ucSubAuthorityCount = *::GetSidSubAuthorityCount(pDomainSid); | ||
| 1763 | |||
| 1764 | // allocate SID buffer | ||
| 1765 | DWORD dwLengthRequired = ::GetSidLengthRequired(ucSubAuthorityCount + (UCHAR)1); | ||
| 1766 | if (*ppSid) | ||
| 1767 | { | ||
| 1768 | SIZE_T ccb = ::HeapSize(::GetProcessHeap(), 0, *ppSid); | ||
| 1769 | if (-1 == ccb) | ||
| 1770 | ExitOnFailure(hr = E_FAIL, "Failed to get size of SID buffer"); | ||
| 1771 | |||
| 1772 | if (ccb < dwLengthRequired) | ||
| 1773 | { | ||
| 1774 | pSid = (PSID)::HeapReAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, *ppSid, dwLengthRequired); | ||
| 1775 | ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to reallocate buffer for SID, len: %d", dwLengthRequired); | ||
| 1776 | *ppSid = pSid; | ||
| 1777 | } | ||
| 1778 | } | ||
| 1779 | else | ||
| 1780 | { | ||
| 1781 | *ppSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwLengthRequired); | ||
| 1782 | ExitOnNull(*ppSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID, len: %d", dwLengthRequired); | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | ::InitializeSid(*ppSid, ::GetSidIdentifierAuthority(pDomainSid), ucSubAuthorityCount + (UCHAR)1); | ||
| 1786 | |||
| 1787 | // copy sub autorities | ||
| 1788 | DWORD i = 0; | ||
| 1789 | for (; i < ucSubAuthorityCount; i++) | ||
| 1790 | *::GetSidSubAuthority(*ppSid, i) = *::GetSidSubAuthority(pDomainSid, i); | ||
| 1791 | *::GetSidSubAuthority(*ppSid, i) = dwRid; | ||
| 1792 | |||
| 1793 | hr = S_OK; | ||
| 1794 | |||
| 1795 | LExit: | ||
| 1796 | return hr; | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | static HRESULT InitLsaUnicodeString( | ||
| 1800 | PLSA_UNICODE_STRING plusStr, | ||
| 1801 | LPCWSTR pwzStr, | ||
| 1802 | DWORD dwLen | ||
| 1803 | ) | ||
| 1804 | { | ||
| 1805 | HRESULT hr = S_OK; | ||
| 1806 | |||
| 1807 | plusStr->Length = (USHORT)dwLen * sizeof(WCHAR); | ||
| 1808 | plusStr->MaximumLength = (USHORT)(dwLen + 1) * sizeof(WCHAR); | ||
| 1809 | |||
| 1810 | plusStr->Buffer = (WCHAR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) * (dwLen + 1)); | ||
| 1811 | ExitOnNull(plusStr->Buffer, hr, E_OUTOFMEMORY, "Failed to allocate account name string"); | ||
| 1812 | |||
| 1813 | hr = StringCchCopyW(plusStr->Buffer, dwLen + 1, pwzStr); | ||
| 1814 | ExitOnFailure(hr, "Failed to copy buffer"); | ||
| 1815 | |||
| 1816 | hr = S_OK; | ||
| 1817 | |||
| 1818 | LExit: | ||
| 1819 | return hr; | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | static void FreeLsaUnicodeString( | ||
| 1823 | PLSA_UNICODE_STRING plusStr | ||
| 1824 | ) | ||
| 1825 | { | ||
| 1826 | if (plusStr->Buffer) | ||
| 1827 | ::HeapFree(::GetProcessHeap(), 0, plusStr->Buffer); | ||
| 1828 | } | ||
| 1829 | |||
| 1830 | static HRESULT WriteFileAll( | ||
| 1831 | HANDLE hFile, | ||
| 1832 | PBYTE pbBuffer, | ||
| 1833 | DWORD dwBufferLength | ||
| 1834 | ) | ||
| 1835 | { | ||
| 1836 | HRESULT hr = S_OK; | ||
| 1837 | |||
| 1838 | DWORD dwBytesWritten; | ||
| 1839 | |||
| 1840 | while (dwBufferLength) | ||
| 1841 | { | ||
| 1842 | if (!::WriteFile(hFile, pbBuffer, dwBufferLength, &dwBytesWritten, NULL)) | ||
| 1843 | ExitFunction1(hr = HRESULT_FROM_WIN32(::GetLastError())); | ||
| 1844 | |||
| 1845 | dwBufferLength -= dwBytesWritten; | ||
| 1846 | pbBuffer += dwBytesWritten; | ||
| 1847 | } | ||
| 1848 | |||
| 1849 | hr = S_OK; | ||
| 1850 | |||
| 1851 | LExit: | ||
| 1852 | return hr; | ||
| 1853 | } | ||
| 1854 | |||
| 1855 | static HRESULT ReadFileAll( | ||
| 1856 | HANDLE hFile, | ||
| 1857 | PBYTE pbBuffer, | ||
| 1858 | DWORD dwBufferLength | ||
| 1859 | ) | ||
| 1860 | { | ||
| 1861 | HRESULT hr = S_OK; | ||
| 1862 | |||
| 1863 | DWORD dwBytesRead; | ||
| 1864 | |||
| 1865 | while (dwBufferLength) | ||
| 1866 | { | ||
| 1867 | if (!::ReadFile(hFile, pbBuffer, dwBufferLength, &dwBytesRead, NULL)) | ||
| 1868 | ExitFunction1(hr = HRESULT_FROM_WIN32(::GetLastError())); | ||
| 1869 | |||
| 1870 | if (0 == dwBytesRead) | ||
| 1871 | ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF)); | ||
| 1872 | |||
| 1873 | dwBufferLength -= dwBytesRead; | ||
| 1874 | pbBuffer += dwBytesRead; | ||
| 1875 | } | ||
| 1876 | |||
| 1877 | hr = S_OK; | ||
| 1878 | |||
| 1879 | LExit: | ||
| 1880 | return hr; | ||
| 1881 | } | ||
diff --git a/src/ca/cputilexec.h b/src/ca/cputilexec.h new file mode 100644 index 00000000..51b47583 --- /dev/null +++ b/src/ca/cputilexec.h | |||
| @@ -0,0 +1,193 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #define CPI_MAX_GUID 38 | ||
| 6 | |||
| 7 | enum eActionType { atNoOp = 0, atCreate, atRemove }; | ||
| 8 | |||
| 9 | |||
| 10 | // structs | ||
| 11 | |||
| 12 | struct CPI_PROPERTY | ||
| 13 | { | ||
| 14 | WCHAR wzName[MAX_DARWIN_KEY + 1]; | ||
| 15 | LPWSTR pwzValue; | ||
| 16 | |||
| 17 | CPI_PROPERTY* pNext; | ||
| 18 | }; | ||
| 19 | |||
| 20 | struct CPI_ROLLBACK_DATA | ||
| 21 | { | ||
| 22 | WCHAR wzKey[MAX_DARWIN_KEY + 1]; | ||
| 23 | int iStatus; | ||
| 24 | |||
| 25 | CPI_ROLLBACK_DATA* pNext; | ||
| 26 | }; | ||
| 27 | |||
| 28 | |||
| 29 | // function prototypes | ||
| 30 | |||
| 31 | void CpiInitialize(); | ||
| 32 | void CpiFinalize(); | ||
| 33 | HRESULT CpiActionStartMessage( | ||
| 34 | LPWSTR* ppwzActionData, | ||
| 35 | BOOL fSuppress | ||
| 36 | ); | ||
| 37 | HRESULT CpiActionDataMessage( | ||
| 38 | DWORD cArgs, | ||
| 39 | ... | ||
| 40 | ); | ||
| 41 | HRESULT CpiGetAdminCatalog( | ||
| 42 | ICOMAdminCatalog** ppiCatalog | ||
| 43 | ); | ||
| 44 | HRESULT CpiLogCatalogErrorInfo(); | ||
| 45 | HRESULT CpiGetCatalogCollection( | ||
| 46 | LPCWSTR pwzName, | ||
| 47 | ICatalogCollection** ppiColl | ||
| 48 | ); | ||
| 49 | HRESULT CpiGetCatalogCollection( | ||
| 50 | ICatalogCollection* piColl, | ||
| 51 | ICatalogObject* piObj, | ||
| 52 | LPCWSTR pwzName, | ||
| 53 | ICatalogCollection** ppiColl | ||
| 54 | ); | ||
| 55 | HRESULT CpiAddCollectionObject( | ||
| 56 | ICatalogCollection* piColl, | ||
| 57 | ICatalogObject** ppiObj | ||
| 58 | ); | ||
| 59 | HRESULT CpiPutCollectionObjectValue( | ||
| 60 | ICatalogObject* piObj, | ||
| 61 | LPCWSTR pwzPropName, | ||
| 62 | LPCWSTR pwzValue | ||
| 63 | ); | ||
| 64 | HRESULT CpiPutCollectionObjectValues( | ||
| 65 | ICatalogObject* piObj, | ||
| 66 | CPI_PROPERTY* pPropList | ||
| 67 | ); | ||
| 68 | HRESULT CpiGetCollectionObjectValue( | ||
| 69 | ICatalogObject* piObj, | ||
| 70 | LPCWSTR szPropName, | ||
| 71 | LPWSTR* ppwzValue | ||
| 72 | ); | ||
| 73 | HRESULT CpiResetObjectProperty( | ||
| 74 | ICatalogCollection* piColl, | ||
| 75 | ICatalogObject* piObj, | ||
| 76 | LPCWSTR pwzPropName | ||
| 77 | ); | ||
| 78 | HRESULT CpiRemoveCollectionObject( | ||
| 79 | ICatalogCollection* piColl, | ||
| 80 | LPCWSTR pwzID, | ||
| 81 | LPCWSTR pwzName, | ||
| 82 | BOOL fResetDeleteable | ||
| 83 | ); | ||
| 84 | HRESULT CpiRemoveUserCollectionObject( | ||
| 85 | ICatalogCollection* piColl, | ||
| 86 | PSID pSid | ||
| 87 | ); | ||
| 88 | HRESULT CpiFindCollectionObjectByStringKey( | ||
| 89 | ICatalogCollection* piColl, | ||
| 90 | LPCWSTR pwzKey, | ||
| 91 | ICatalogObject** ppiObj | ||
| 92 | ); | ||
| 93 | HRESULT CpiFindCollectionObjectByIntegerKey( | ||
| 94 | ICatalogCollection* piColl, | ||
| 95 | long lKey, | ||
| 96 | ICatalogObject** ppiObj | ||
| 97 | ); | ||
| 98 | HRESULT CpiFindCollectionObjectByName( | ||
| 99 | ICatalogCollection* piColl, | ||
| 100 | LPCWSTR pwzName, | ||
| 101 | ICatalogObject** ppiObj | ||
| 102 | ); | ||
| 103 | HRESULT CpiFindUserCollectionObject( | ||
| 104 | ICatalogCollection* piColl, | ||
| 105 | PSID pSid, | ||
| 106 | ICatalogObject** ppiObj | ||
| 107 | ); | ||
| 108 | HRESULT CpiGetPartitionsCollection( | ||
| 109 | ICatalogCollection** ppiPartColl | ||
| 110 | ); | ||
| 111 | HRESULT CpiGetPartitionRolesCollection( | ||
| 112 | LPCWSTR pwzPartID, | ||
| 113 | ICatalogCollection** ppiRolesColl | ||
| 114 | ); | ||
| 115 | HRESULT CpiGetUsersInPartitionRoleCollection( | ||
| 116 | LPCWSTR pwzPartID, | ||
| 117 | LPCWSTR pwzRoleName, | ||
| 118 | ICatalogCollection** ppiUsrInRoleColl | ||
| 119 | ); | ||
| 120 | HRESULT CpiGetPartitionUsersCollection( | ||
| 121 | ICatalogCollection** ppiUserColl | ||
| 122 | ); | ||
| 123 | HRESULT CpiGetApplicationsCollection( | ||
| 124 | LPCWSTR pwzPartID, | ||
| 125 | ICatalogCollection** ppiAppColl | ||
| 126 | ); | ||
| 127 | HRESULT CpiGetRolesCollection( | ||
| 128 | LPCWSTR pwzPartID, | ||
| 129 | LPCWSTR pwzAppID, | ||
| 130 | ICatalogCollection** ppiRolesColl | ||
| 131 | ); | ||
| 132 | HRESULT CpiGetUsersInRoleCollection( | ||
| 133 | LPCWSTR pwzPartID, | ||
| 134 | LPCWSTR pwzAppID, | ||
| 135 | LPCWSTR pwzRoleName, | ||
| 136 | ICatalogCollection** ppiUsrInRoleColl | ||
| 137 | ); | ||
| 138 | HRESULT CpiGetComponentsCollection( | ||
| 139 | LPCWSTR pwzPartID, | ||
| 140 | LPCWSTR pwzAppID, | ||
| 141 | ICatalogCollection** ppiCompsColl | ||
| 142 | ); | ||
| 143 | HRESULT CpiGetInterfacesCollection( | ||
| 144 | ICatalogCollection* piCompColl, | ||
| 145 | ICatalogObject* piCompObj, | ||
| 146 | ICatalogCollection** ppiIntfColl | ||
| 147 | ); | ||
| 148 | HRESULT CpiGetMethodsCollection( | ||
| 149 | ICatalogCollection* piIntfColl, | ||
| 150 | ICatalogObject* piIntfObj, | ||
| 151 | ICatalogCollection** ppiMethColl | ||
| 152 | ); | ||
| 153 | HRESULT CpiGetSubscriptionsCollection( | ||
| 154 | LPCWSTR pwzPartID, | ||
| 155 | LPCWSTR pwzAppID, | ||
| 156 | LPCWSTR pwzCompCLSID, | ||
| 157 | ICatalogCollection** ppiCompsColl | ||
| 158 | ); | ||
| 159 | HRESULT CpiReadPropertyList( | ||
| 160 | LPWSTR* ppwzData, | ||
| 161 | CPI_PROPERTY** ppPropList | ||
| 162 | ); | ||
| 163 | void CpiFreePropertyList( | ||
| 164 | CPI_PROPERTY* pList | ||
| 165 | ); | ||
| 166 | HRESULT CpiWriteKeyToRollbackFile( | ||
| 167 | HANDLE hFile, | ||
| 168 | LPCWSTR pwzKey | ||
| 169 | ); | ||
| 170 | HRESULT CpiWriteIntegerToRollbackFile( | ||
| 171 | HANDLE hFile, | ||
| 172 | int i | ||
| 173 | ); | ||
| 174 | HRESULT CpiReadRollbackDataList( | ||
| 175 | HANDLE hFile, | ||
| 176 | CPI_ROLLBACK_DATA** pprdList | ||
| 177 | ); | ||
| 178 | void CpiFreeRollbackDataList( | ||
| 179 | CPI_ROLLBACK_DATA* pList | ||
| 180 | ); | ||
| 181 | HRESULT CpiFindRollbackStatus( | ||
| 182 | CPI_ROLLBACK_DATA* pList, | ||
| 183 | LPCWSTR pwzKey, | ||
| 184 | int* piStatus | ||
| 185 | ); | ||
| 186 | HRESULT CpiAccountNameToSid( | ||
| 187 | LPCWSTR pwzAccountName, | ||
| 188 | PSID* ppSid | ||
| 189 | ); | ||
| 190 | HRESULT CpiSidToAccountName( | ||
| 191 | PSID pSid, | ||
| 192 | LPWSTR* ppwzAccountName | ||
| 193 | ); | ||
diff --git a/src/ca/cputilsched.cpp b/src/ca/cputilsched.cpp new file mode 100644 index 00000000..9dbe21ec --- /dev/null +++ b/src/ca/cputilsched.cpp | |||
| @@ -0,0 +1,885 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | |||
| 6 | // sql queries | ||
| 7 | |||
| 8 | LPCWSTR vcsActionTextQuery = | ||
| 9 | L"SELECT `Description`, `Template` FROM `ActionText` WHERE `Action` = ?"; | ||
| 10 | enum eActionTextQuery { atqDescription = 1, atqTemplate }; | ||
| 11 | |||
| 12 | LPCWSTR vcsComponentAttributesQuery = | ||
| 13 | L"SELECT `Attributes` FROM `Component` WHERE `Component` = ?"; | ||
| 14 | enum eComponentAttributesQuery { caqAttributes = 1 }; | ||
| 15 | |||
| 16 | LPCWSTR vcsUserQuery = L"SELECT `Domain`, `Name` FROM `User` WHERE `User` = ?"; | ||
| 17 | enum eUserQuery { uqDomain = 1, uqName }; | ||
| 18 | |||
| 19 | enum ePropertyQuery { pqName = 1, pqValue }; | ||
| 20 | |||
| 21 | |||
| 22 | // prototypes for private helper functions | ||
| 23 | |||
| 24 | static HRESULT FindPropertyDefinition( | ||
| 25 | CPI_PROPERTY_DEFINITION* pPropDefList, | ||
| 26 | LPCWSTR pwzName, | ||
| 27 | CPI_PROPERTY_DEFINITION** ppPropDef | ||
| 28 | ); | ||
| 29 | static HRESULT GetUserAccountName( | ||
| 30 | LPCWSTR pwzKey, | ||
| 31 | LPWSTR* ppwzAccount | ||
| 32 | ); | ||
| 33 | |||
| 34 | |||
| 35 | // variables | ||
| 36 | |||
| 37 | static ICOMAdminCatalog* gpiCatalog; | ||
| 38 | static ICatalogCollection* gpiPartColl; | ||
| 39 | static ICatalogCollection* gpiAppColl; | ||
| 40 | |||
| 41 | static int giTables; | ||
| 42 | |||
| 43 | |||
| 44 | // function definitions | ||
| 45 | |||
| 46 | void CpiInitialize() | ||
| 47 | { | ||
| 48 | // collections | ||
| 49 | gpiCatalog = NULL; | ||
| 50 | gpiPartColl = NULL; | ||
| 51 | gpiAppColl = NULL; | ||
| 52 | |||
| 53 | // tables | ||
| 54 | giTables = 0; | ||
| 55 | |||
| 56 | if (S_OK == WcaTableExists(L"ComPlusPartition")) giTables |= cptComPlusPartition; | ||
| 57 | if (S_OK == WcaTableExists(L"ComPlusPartitionProperty")) giTables |= cptComPlusPartitionProperty; | ||
| 58 | if (S_OK == WcaTableExists(L"ComPlusPartitionRole")) giTables |= cptComPlusPartitionRole; | ||
| 59 | if (S_OK == WcaTableExists(L"ComPlusUserInPartitionRole")) giTables |= cptComPlusUserInPartitionRole; | ||
| 60 | if (S_OK == WcaTableExists(L"ComPlusGroupInPartitionRole")) giTables |= cptComPlusGroupInPartitionRole; | ||
| 61 | if (S_OK == WcaTableExists(L"ComPlusPartitionUser")) giTables |= cptComPlusPartitionUser; | ||
| 62 | if (S_OK == WcaTableExists(L"ComPlusApplication")) giTables |= cptComPlusApplication; | ||
| 63 | if (S_OK == WcaTableExists(L"ComPlusApplicationProperty")) giTables |= cptComPlusApplicationProperty; | ||
| 64 | if (S_OK == WcaTableExists(L"ComPlusApplicationRole")) giTables |= cptComPlusApplicationRole; | ||
| 65 | if (S_OK == WcaTableExists(L"ComPlusApplicationRoleProperty")) giTables |= cptComPlusApplicationRoleProperty; | ||
| 66 | if (S_OK == WcaTableExists(L"ComPlusUserInApplicationRole")) giTables |= cptComPlusUserInApplicationRole; | ||
| 67 | if (S_OK == WcaTableExists(L"ComPlusGroupInApplicationRole")) giTables |= cptComPlusGroupInApplicationRole; | ||
| 68 | if (S_OK == WcaTableExists(L"ComPlusAssembly")) giTables |= cptComPlusAssembly; | ||
| 69 | if (S_OK == WcaTableExists(L"ComPlusAssemblyDependency")) giTables |= cptComPlusAssemblyDependency; | ||
| 70 | if (S_OK == WcaTableExists(L"ComPlusComponent")) giTables |= cptComPlusComponent; | ||
| 71 | if (S_OK == WcaTableExists(L"ComPlusComponentProperty")) giTables |= cptComPlusComponentProperty; | ||
| 72 | if (S_OK == WcaTableExists(L"ComPlusRoleForComponent")) giTables |= cptComPlusRoleForComponent; | ||
| 73 | if (S_OK == WcaTableExists(L"ComPlusInterface")) giTables |= cptComPlusInterface; | ||
| 74 | if (S_OK == WcaTableExists(L"ComPlusInterfaceProperty")) giTables |= cptComPlusInterfaceProperty; | ||
| 75 | if (S_OK == WcaTableExists(L"ComPlusRoleForInterface")) giTables |= cptComPlusRoleForInterface; | ||
| 76 | if (S_OK == WcaTableExists(L"ComPlusMethod")) giTables |= cptComPlusMethod; | ||
| 77 | if (S_OK == WcaTableExists(L"ComPlusMethodProperty")) giTables |= cptComPlusMethodProperty; | ||
| 78 | if (S_OK == WcaTableExists(L"ComPlusRoleForMethod")) giTables |= cptComPlusRoleForMethod; | ||
| 79 | if (S_OK == WcaTableExists(L"ComPlusSubscription")) giTables |= cptComPlusSubscription; | ||
| 80 | if (S_OK == WcaTableExists(L"ComPlusSubscriptionProperty")) giTables |= cptComPlusSubscriptionProperty; | ||
| 81 | } | ||
| 82 | |||
| 83 | void CpiFinalize() | ||
| 84 | { | ||
| 85 | // collections | ||
| 86 | ReleaseObject(gpiCatalog); | ||
| 87 | ReleaseObject(gpiPartColl); | ||
| 88 | ReleaseObject(gpiAppColl); | ||
| 89 | } | ||
| 90 | |||
| 91 | BOOL CpiTableExists( | ||
| 92 | int iTable | ||
| 93 | ) | ||
| 94 | { | ||
| 95 | return (giTables & iTable) == iTable; | ||
| 96 | } | ||
| 97 | |||
| 98 | HRESULT CpiGetAdminCatalog( | ||
| 99 | ICOMAdminCatalog** ppiCatalog | ||
| 100 | ) | ||
| 101 | { | ||
| 102 | HRESULT hr = S_OK; | ||
| 103 | |||
| 104 | if (!gpiCatalog) | ||
| 105 | { | ||
| 106 | // get collection | ||
| 107 | hr = ::CoCreateInstance(CLSID_COMAdminCatalog, NULL, CLSCTX_ALL, IID_ICOMAdminCatalog, (void**)&gpiCatalog); | ||
| 108 | ExitOnFailure(hr, "Failed to create COM+ admin catalog object"); | ||
| 109 | } | ||
| 110 | |||
| 111 | // return value | ||
| 112 | gpiCatalog->AddRef(); | ||
| 113 | *ppiCatalog = gpiCatalog; | ||
| 114 | |||
| 115 | hr = S_OK; | ||
| 116 | |||
| 117 | LExit: | ||
| 118 | return hr; | ||
| 119 | } | ||
| 120 | |||
| 121 | HRESULT CpiGetCatalogCollection( | ||
| 122 | LPCWSTR pwzName, | ||
| 123 | ICatalogCollection** ppiColl | ||
| 124 | ) | ||
| 125 | { | ||
| 126 | HRESULT hr = S_OK; | ||
| 127 | |||
| 128 | ICOMAdminCatalog* piCatalog = NULL; | ||
| 129 | IDispatch* piDisp = NULL; | ||
| 130 | BSTR bstrName = NULL; | ||
| 131 | |||
| 132 | // copy name string | ||
| 133 | bstrName = ::SysAllocString(pwzName); | ||
| 134 | ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name"); | ||
| 135 | |||
| 136 | // get catalog | ||
| 137 | hr = CpiGetAdminCatalog(&piCatalog); | ||
| 138 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
| 139 | |||
| 140 | // get collecton from catalog | ||
| 141 | hr = piCatalog->GetCollection(bstrName, &piDisp); | ||
| 142 | ExitOnFailure(hr, "Failed to get collection"); | ||
| 143 | |||
| 144 | hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl); | ||
| 145 | ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface"); | ||
| 146 | |||
| 147 | // populate collection | ||
| 148 | hr = (*ppiColl)->Populate(); | ||
| 149 | ExitOnFailure(hr, "Failed to populate collection"); | ||
| 150 | |||
| 151 | hr = S_OK; | ||
| 152 | |||
| 153 | LExit: | ||
| 154 | // clean up | ||
| 155 | ReleaseObject(piCatalog); | ||
| 156 | ReleaseObject(piDisp); | ||
| 157 | ReleaseBSTR(bstrName); | ||
| 158 | |||
| 159 | return hr; | ||
| 160 | } | ||
| 161 | |||
| 162 | HRESULT CpiGetCatalogCollection( | ||
| 163 | ICatalogCollection* piColl, | ||
| 164 | ICatalogObject* piObj, | ||
| 165 | LPCWSTR pwzName, | ||
| 166 | ICatalogCollection** ppiColl | ||
| 167 | ) | ||
| 168 | { | ||
| 169 | HRESULT hr = S_OK; | ||
| 170 | |||
| 171 | ICOMAdminCatalog* piCatalog = NULL; | ||
| 172 | IDispatch* piDisp = NULL; | ||
| 173 | BSTR bstrName = NULL; | ||
| 174 | |||
| 175 | VARIANT vtKey; | ||
| 176 | ::VariantInit(&vtKey); | ||
| 177 | |||
| 178 | // copy name string | ||
| 179 | bstrName = ::SysAllocString(pwzName); | ||
| 180 | ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "Failed to allocate BSTR for collection name"); | ||
| 181 | |||
| 182 | // get catalog | ||
| 183 | hr = CpiGetAdminCatalog(&piCatalog); | ||
| 184 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
| 185 | |||
| 186 | // get key | ||
| 187 | hr = piObj->get_Key(&vtKey); | ||
| 188 | ExitOnFailure(hr, "Failed to get object key"); | ||
| 189 | |||
| 190 | // get collecton from catalog | ||
| 191 | hr = piColl->GetCollection(bstrName, vtKey, &piDisp); | ||
| 192 | ExitOnFailure(hr, "Failed to get collection"); | ||
| 193 | |||
| 194 | hr = piDisp->QueryInterface(IID_ICatalogCollection, (void**)ppiColl); | ||
| 195 | ExitOnFailure(hr, "Failed to get IID_ICatalogCollection interface"); | ||
| 196 | |||
| 197 | // populate collection | ||
| 198 | hr = (*ppiColl)->Populate(); | ||
| 199 | ExitOnFailure(hr, "Failed to populate collection"); | ||
| 200 | |||
| 201 | hr = S_OK; | ||
| 202 | |||
| 203 | LExit: | ||
| 204 | // clean up | ||
| 205 | ReleaseObject(piCatalog); | ||
| 206 | ReleaseObject(piDisp); | ||
| 207 | ReleaseBSTR(bstrName); | ||
| 208 | ::VariantClear(&vtKey); | ||
| 209 | |||
| 210 | return hr; | ||
| 211 | } | ||
| 212 | |||
| 213 | HRESULT CpiGetKeyForObject( | ||
| 214 | ICatalogObject* piObj, | ||
| 215 | LPWSTR pwzKey, | ||
| 216 | SIZE_T cchKey | ||
| 217 | ) | ||
| 218 | { | ||
| 219 | HRESULT hr = S_OK; | ||
| 220 | |||
| 221 | VARIANT vtKey; | ||
| 222 | ::VariantInit(&vtKey); | ||
| 223 | |||
| 224 | // get key | ||
| 225 | hr = piObj->get_Key(&vtKey); | ||
| 226 | ExitOnFailure(hr, "Failed to get key"); | ||
| 227 | |||
| 228 | // change variant type | ||
| 229 | hr = ::VariantChangeType(&vtKey, &vtKey, 0, VT_BSTR); | ||
| 230 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 231 | |||
| 232 | // copy key | ||
| 233 | hr = StringCchCopyW(pwzKey, cchKey, vtKey.bstrVal); | ||
| 234 | ExitOnFailure(hr, "Failed to copy key"); | ||
| 235 | |||
| 236 | hr = S_OK; | ||
| 237 | |||
| 238 | LExit: | ||
| 239 | // clean up | ||
| 240 | ::VariantClear(&vtKey); | ||
| 241 | |||
| 242 | return hr; | ||
| 243 | } | ||
| 244 | |||
| 245 | HRESULT CpiFindCollectionObject( | ||
| 246 | ICatalogCollection* piColl, | ||
| 247 | LPCWSTR pwzID, | ||
| 248 | LPCWSTR pwzName, | ||
| 249 | ICatalogObject** ppiObj | ||
| 250 | ) | ||
| 251 | { | ||
| 252 | HRESULT hr = S_OK; | ||
| 253 | |||
| 254 | IDispatch* piDisp = NULL; | ||
| 255 | ICatalogObject* piObj = NULL; | ||
| 256 | |||
| 257 | VARIANT vtVal; | ||
| 258 | ::VariantInit(&vtVal); | ||
| 259 | |||
| 260 | long lCnt; | ||
| 261 | hr = piColl->get_Count(&lCnt); | ||
| 262 | ExitOnFailure(hr, "Failed to get to number of items in collection"); | ||
| 263 | |||
| 264 | for (long i = 0; i < lCnt; i++) | ||
| 265 | { | ||
| 266 | // get ICatalogObject interface | ||
| 267 | hr = piColl->get_Item(i, &piDisp); | ||
| 268 | ExitOnFailure(hr, "Failed to get object from collection"); | ||
| 269 | |||
| 270 | hr = piDisp->QueryInterface(IID_ICatalogObject, (void**)&piObj); | ||
| 271 | ExitOnFailure(hr, "Failed to get IID_ICatalogObject interface"); | ||
| 272 | |||
| 273 | // compare id | ||
| 274 | if (pwzID && *pwzID) | ||
| 275 | { | ||
| 276 | hr = piObj->get_Key(&vtVal); | ||
| 277 | ExitOnFailure(hr, "Failed to get key"); | ||
| 278 | |||
| 279 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
| 280 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 281 | |||
| 282 | if (0 == lstrcmpiW(vtVal.bstrVal, pwzID)) | ||
| 283 | { | ||
| 284 | if (ppiObj) | ||
| 285 | { | ||
| 286 | *ppiObj = piObj; | ||
| 287 | piObj = NULL; | ||
| 288 | } | ||
| 289 | ExitFunction1(hr = S_OK); | ||
| 290 | } | ||
| 291 | |||
| 292 | ::VariantClear(&vtVal); | ||
| 293 | } | ||
| 294 | |||
| 295 | // compare name | ||
| 296 | if (pwzName && *pwzName) | ||
| 297 | { | ||
| 298 | hr = piObj->get_Name(&vtVal); | ||
| 299 | ExitOnFailure(hr, "Failed to get name"); | ||
| 300 | |||
| 301 | hr = ::VariantChangeType(&vtVal, &vtVal, 0, VT_BSTR); | ||
| 302 | ExitOnFailure(hr, "Failed to change variant type"); | ||
| 303 | |||
| 304 | if (0 == lstrcmpW(vtVal.bstrVal, pwzName)) | ||
| 305 | { | ||
| 306 | if (ppiObj) | ||
| 307 | { | ||
| 308 | *ppiObj = piObj; | ||
| 309 | piObj = NULL; | ||
| 310 | } | ||
| 311 | ExitFunction1(hr = S_OK); | ||
| 312 | } | ||
| 313 | |||
| 314 | ::VariantClear(&vtVal); | ||
| 315 | } | ||
| 316 | |||
| 317 | // release interface pointers | ||
| 318 | ReleaseNullObject(piDisp); | ||
| 319 | ReleaseNullObject(piObj); | ||
| 320 | } | ||
| 321 | |||
| 322 | hr = S_FALSE; | ||
| 323 | |||
| 324 | LExit: | ||
| 325 | // clean up | ||
| 326 | ReleaseObject(piDisp); | ||
| 327 | ReleaseObject(piObj); | ||
| 328 | |||
| 329 | ::VariantClear(&vtVal); | ||
| 330 | |||
| 331 | return hr; | ||
| 332 | } | ||
| 333 | |||
| 334 | HRESULT CpiGetPartitionsCollection( | ||
| 335 | ICatalogCollection** ppiPartColl | ||
| 336 | ) | ||
| 337 | { | ||
| 338 | HRESULT hr = S_OK; | ||
| 339 | |||
| 340 | if (!gpiPartColl) | ||
| 341 | { | ||
| 342 | // get collection | ||
| 343 | hr = CpiGetCatalogCollection(L"Partitions", &gpiPartColl); | ||
| 344 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
| 345 | } | ||
| 346 | |||
| 347 | // return value | ||
| 348 | gpiPartColl->AddRef(); | ||
| 349 | *ppiPartColl = gpiPartColl; | ||
| 350 | |||
| 351 | hr = S_OK; | ||
| 352 | |||
| 353 | LExit: | ||
| 354 | return hr; | ||
| 355 | } | ||
| 356 | |||
| 357 | HRESULT CpiGetApplicationsCollection( | ||
| 358 | ICatalogCollection** ppiAppColl | ||
| 359 | ) | ||
| 360 | { | ||
| 361 | HRESULT hr = S_OK; | ||
| 362 | |||
| 363 | ICOMAdminCatalog* piCatalog = NULL; | ||
| 364 | ICOMAdminCatalog2* piCatalog2 = NULL; | ||
| 365 | ICatalogCollection* piPartColl = NULL; | ||
| 366 | ICatalogObject* piPartObj = NULL; | ||
| 367 | BSTR bstrGlobPartID = NULL; | ||
| 368 | |||
| 369 | if (!gpiAppColl) | ||
| 370 | { | ||
| 371 | // get catalog | ||
| 372 | hr = CpiGetAdminCatalog(&piCatalog); | ||
| 373 | ExitOnFailure(hr, "Failed to get COM+ admin catalog"); | ||
| 374 | |||
| 375 | // get ICOMAdminCatalog2 interface | ||
| 376 | hr = piCatalog->QueryInterface(IID_ICOMAdminCatalog2, (void**)&piCatalog2); | ||
| 377 | |||
| 378 | // COM+ 1.5 or later | ||
| 379 | if (E_NOINTERFACE != hr) | ||
| 380 | { | ||
| 381 | ExitOnFailure(hr, "Failed to get IID_ICOMAdminCatalog2 interface"); | ||
| 382 | |||
| 383 | // get global partition id | ||
| 384 | hr = piCatalog2->get_GlobalPartitionID(&bstrGlobPartID); | ||
| 385 | ExitOnFailure(hr, "Failed to get global partition id"); | ||
| 386 | |||
| 387 | // get partitions collection | ||
| 388 | hr = CpiGetPartitionsCollection(&piPartColl); | ||
| 389 | ExitOnFailure(hr, "Failed to get partitions collection"); | ||
| 390 | |||
| 391 | // find object | ||
| 392 | hr = CpiFindCollectionObject(piPartColl, bstrGlobPartID, NULL, &piPartObj); | ||
| 393 | ExitOnFailure(hr, "Failed to find collection object"); | ||
| 394 | |||
| 395 | if (S_FALSE == hr) | ||
| 396 | ExitFunction(); // partition not found, exit with hr = S_FALSE | ||
| 397 | |||
| 398 | // get applications collection | ||
| 399 | hr = CpiGetCatalogCollection(piPartColl, piPartObj, L"Applications", &gpiAppColl); | ||
| 400 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 401 | } | ||
| 402 | |||
| 403 | // COM+ pre 1.5 | ||
| 404 | else | ||
| 405 | { | ||
| 406 | // get applications collection | ||
| 407 | hr = CpiGetCatalogCollection(L"Applications", &gpiAppColl); | ||
| 408 | ExitOnFailure(hr, "Failed to get applications collection"); | ||
| 409 | } | ||
| 410 | } | ||
| 411 | |||
| 412 | // return value | ||
| 413 | gpiAppColl->AddRef(); | ||
| 414 | *ppiAppColl = gpiAppColl; | ||
| 415 | |||
| 416 | hr = S_OK; | ||
| 417 | |||
| 418 | LExit: | ||
| 419 | // clean up | ||
| 420 | ReleaseObject(piCatalog); | ||
| 421 | ReleaseObject(piCatalog2); | ||
| 422 | ReleaseObject(piPartColl); | ||
| 423 | ReleaseObject(piPartObj); | ||
| 424 | ReleaseBSTR(bstrGlobPartID); | ||
| 425 | |||
| 426 | return hr; | ||
| 427 | } | ||
| 428 | |||
| 429 | HRESULT CpiAddActionTextToActionData( | ||
| 430 | LPCWSTR pwzAction, | ||
| 431 | LPWSTR* ppwzActionData | ||
| 432 | ) | ||
| 433 | { | ||
| 434 | HRESULT hr = S_OK; | ||
| 435 | |||
| 436 | PMSIHANDLE hView, hRecKey, hRec; | ||
| 437 | |||
| 438 | LPWSTR pwzDescription = NULL; | ||
| 439 | LPWSTR pwzTemplate = NULL; | ||
| 440 | |||
| 441 | if (S_OK == WcaTableExists(L"ActionText")) | ||
| 442 | { | ||
| 443 | // create parameter record | ||
| 444 | hRecKey = ::MsiCreateRecord(1); | ||
| 445 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 446 | hr = WcaSetRecordString(hRecKey, 1, pwzAction); | ||
| 447 | ExitOnFailure(hr, "Failed to set record string"); | ||
| 448 | |||
| 449 | // open view | ||
| 450 | hr = WcaOpenView(vcsActionTextQuery, &hView); | ||
| 451 | ExitOnFailure(hr, "Failed to open view on ActionText table"); | ||
| 452 | hr = WcaExecuteView(hView, hRecKey); | ||
| 453 | ExitOnFailure(hr, "Failed to execute view on ActionText table"); | ||
| 454 | |||
| 455 | // fetch record | ||
| 456 | hr = WcaFetchSingleRecord(hView, &hRec); | ||
| 457 | if (S_FALSE != hr) | ||
| 458 | { | ||
| 459 | ExitOnFailure(hr, "Failed to fetch action text record"); | ||
| 460 | |||
| 461 | // get description | ||
| 462 | hr = WcaGetRecordString(hRec, atqDescription, &pwzDescription); | ||
| 463 | ExitOnFailure(hr, "Failed to get description"); | ||
| 464 | |||
| 465 | // get template | ||
| 466 | hr = WcaGetRecordString(hRec, atqTemplate, &pwzTemplate); | ||
| 467 | ExitOnFailure(hr, "Failed to get template"); | ||
| 468 | } | ||
| 469 | } | ||
| 470 | |||
| 471 | // add action name to action data | ||
| 472 | hr = WcaWriteStringToCaData(pwzAction, ppwzActionData); | ||
| 473 | ExitOnFailure(hr, "Failed to add action name to custom action data"); | ||
| 474 | |||
| 475 | // add description to action data | ||
| 476 | hr = WcaWriteStringToCaData(pwzDescription ? pwzDescription : L"", ppwzActionData); | ||
| 477 | ExitOnFailure(hr, "Failed to add description to custom action data"); | ||
| 478 | |||
| 479 | // add template to action data | ||
| 480 | hr = WcaWriteStringToCaData(pwzTemplate ? pwzTemplate : L"", ppwzActionData); | ||
| 481 | ExitOnFailure(hr, "Failed to add template to custom action data"); | ||
| 482 | |||
| 483 | hr = S_OK; | ||
| 484 | |||
| 485 | LExit: | ||
| 486 | // clean up | ||
| 487 | ReleaseStr(pwzDescription); | ||
| 488 | ReleaseStr(pwzTemplate); | ||
| 489 | |||
| 490 | return hr; | ||
| 491 | } | ||
| 492 | |||
| 493 | HRESULT CpiVerifyComponentArchitecure( | ||
| 494 | LPCWSTR pwzComponent, | ||
| 495 | BOOL* pfMatchingArchitecture | ||
| 496 | ) | ||
| 497 | { | ||
| 498 | HRESULT hr = S_OK; | ||
| 499 | |||
| 500 | PMSIHANDLE hView, hRecKey, hRec; | ||
| 501 | |||
| 502 | int iAttributes = 0; | ||
| 503 | |||
| 504 | if (S_OK == WcaTableExists(L"Component")) | ||
| 505 | { | ||
| 506 | // create parameter record | ||
| 507 | hRecKey = ::MsiCreateRecord(1); | ||
| 508 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 509 | hr = WcaSetRecordString(hRecKey, 1, pwzComponent); | ||
| 510 | ExitOnFailure(hr, "Failed to set record string"); | ||
| 511 | |||
| 512 | // open view | ||
| 513 | hr = WcaOpenView(vcsComponentAttributesQuery, &hView); | ||
| 514 | ExitOnFailure(hr, "Failed to open view on ActionText table"); | ||
| 515 | hr = WcaExecuteView(hView, hRecKey); | ||
| 516 | ExitOnFailure(hr, "Failed to execute view on ActionText table"); | ||
| 517 | |||
| 518 | // fetch record | ||
| 519 | hr = WcaFetchSingleRecord(hView, &hRec); | ||
| 520 | if (S_FALSE != hr) | ||
| 521 | { | ||
| 522 | ExitOnFailure(hr, "Failed to fetch component record"); | ||
| 523 | |||
| 524 | hr = WcaGetRecordInteger(hRec, caqAttributes, &iAttributes); | ||
| 525 | ExitOnFailure(hr, "Failed to get component attributes"); | ||
| 526 | } | ||
| 527 | } | ||
| 528 | |||
| 529 | // return values | ||
| 530 | #ifdef _WIN64 | ||
| 531 | *pfMatchingArchitecture = 256 == (iAttributes & 256); | ||
| 532 | #else | ||
| 533 | *pfMatchingArchitecture = 256 != (iAttributes & 256); | ||
| 534 | #endif | ||
| 535 | |||
| 536 | hr = S_OK; | ||
| 537 | |||
| 538 | LExit: | ||
| 539 | return hr; | ||
| 540 | } | ||
| 541 | |||
| 542 | HRESULT CpiPropertiesRead( | ||
| 543 | LPCWSTR pwzQuery, | ||
| 544 | LPCWSTR pwzKey, | ||
| 545 | CPI_PROPERTY_DEFINITION* pPropDefList, | ||
| 546 | CPI_PROPERTY** ppPropList, | ||
| 547 | int* piCount | ||
| 548 | ) | ||
| 549 | { | ||
| 550 | HRESULT hr = S_OK; | ||
| 551 | |||
| 552 | PMSIHANDLE hView, hRecKey, hRec; | ||
| 553 | |||
| 554 | CPI_PROPERTY* pItm = NULL; | ||
| 555 | LPWSTR pwzData = NULL; | ||
| 556 | |||
| 557 | int iVersionNT = 0; | ||
| 558 | |||
| 559 | CPI_PROPERTY_DEFINITION* pPropDef; | ||
| 560 | |||
| 561 | *piCount = 0; | ||
| 562 | |||
| 563 | // get NT version | ||
| 564 | hr = WcaGetIntProperty(L"VersionNT", &iVersionNT); | ||
| 565 | ExitOnFailure(hr, "Failed to set record string"); | ||
| 566 | |||
| 567 | // create parameter record | ||
| 568 | hRecKey = ::MsiCreateRecord(1); | ||
| 569 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 570 | hr = WcaSetRecordString(hRecKey, 1, pwzKey); | ||
| 571 | ExitOnFailure(hr, "Failed to set record string"); | ||
| 572 | |||
| 573 | // open view | ||
| 574 | hr = WcaOpenView(pwzQuery, &hView); | ||
| 575 | ExitOnFailure(hr, "Failed to open view on property table"); | ||
| 576 | hr = WcaExecuteView(hView, hRecKey); | ||
| 577 | ExitOnFailure(hr, "Failed to execute view on property table"); | ||
| 578 | |||
| 579 | while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) | ||
| 580 | { | ||
| 581 | // create entry | ||
| 582 | pItm = (CPI_PROPERTY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PROPERTY)); | ||
| 583 | if (!pItm) | ||
| 584 | ExitFunction1(hr = E_OUTOFMEMORY); | ||
| 585 | |||
| 586 | // get name | ||
| 587 | hr = WcaGetRecordString(hRec, pqName, &pwzData); | ||
| 588 | ExitOnFailure(hr, "Failed to get name"); | ||
| 589 | StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); | ||
| 590 | |||
| 591 | // get value | ||
| 592 | hr = WcaGetRecordFormattedString(hRec, pqValue, &pItm->pwzValue); | ||
| 593 | ExitOnFailure(hr, "Failed to get value"); | ||
| 594 | |||
| 595 | // find property definition | ||
| 596 | hr = FindPropertyDefinition(pPropDefList, pItm->wzName, &pPropDef); | ||
| 597 | ExitOnFailure(hr, "Failed to find property definition"); | ||
| 598 | |||
| 599 | if (S_FALSE == hr) | ||
| 600 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Unknown property, key: %S, property: %S", pwzKey, pItm->wzName); | ||
| 601 | |||
| 602 | // check version, ignore if catalog version is too low | ||
| 603 | if (iVersionNT < pPropDef->iMinVersionNT) | ||
| 604 | { | ||
| 605 | WcaLog(LOGMSG_VERBOSE, "Skipping property since NT version is too low, key: %S, property: %S", pwzKey, pItm->wzName); | ||
| 606 | CpiPropertiesFreeList(pItm); | ||
| 607 | pItm = NULL; | ||
| 608 | continue; | ||
| 609 | } | ||
| 610 | |||
| 611 | // if the property is a user, replace the User table key with a user account name | ||
| 612 | if (cpptUser == pPropDef->iType) | ||
| 613 | { | ||
| 614 | hr = GetUserAccountName(pItm->pwzValue, &pItm->pwzValue); | ||
| 615 | ExitOnFailure(hr, "Failed to get user account name"); | ||
| 616 | } | ||
| 617 | |||
| 618 | // add entry | ||
| 619 | ++*piCount; | ||
| 620 | if (*ppPropList) | ||
| 621 | pItm->pNext = *ppPropList; | ||
| 622 | *ppPropList = pItm; | ||
| 623 | pItm = NULL; | ||
| 624 | } | ||
| 625 | |||
| 626 | if (E_NOMOREITEMS == hr) | ||
| 627 | hr = S_OK; | ||
| 628 | |||
| 629 | LExit: | ||
| 630 | // clean up | ||
| 631 | if (pItm) | ||
| 632 | CpiPropertiesFreeList(pItm); | ||
| 633 | |||
| 634 | ReleaseStr(pwzData); | ||
| 635 | |||
| 636 | return hr; | ||
| 637 | } | ||
| 638 | |||
| 639 | void CpiPropertiesFreeList( | ||
| 640 | CPI_PROPERTY* pList | ||
| 641 | ) | ||
| 642 | { | ||
| 643 | while (pList) | ||
| 644 | { | ||
| 645 | ReleaseStr(pList->pwzValue); | ||
| 646 | |||
| 647 | CPI_PROPERTY* pDelete = pList; | ||
| 648 | pList = pList->pNext; | ||
| 649 | ::HeapFree(::GetProcessHeap(), 0, pDelete); | ||
| 650 | } | ||
| 651 | } | ||
| 652 | |||
| 653 | HRESULT CpiAddPropertiesToActionData( | ||
| 654 | int iPropCount, | ||
| 655 | CPI_PROPERTY* pPropList, | ||
| 656 | LPWSTR* ppwzActionData | ||
| 657 | ) | ||
| 658 | { | ||
| 659 | HRESULT hr = S_OK; | ||
| 660 | |||
| 661 | hr = WcaWriteIntegerToCaData(iPropCount, ppwzActionData); | ||
| 662 | ExitOnFailure(hr, "Failed to add count to custom action data"); | ||
| 663 | |||
| 664 | if (iPropCount) // count might be 0 event thought there are elements in the list | ||
| 665 | { | ||
| 666 | for (CPI_PROPERTY* pProp = pPropList; pProp; pProp = pProp->pNext) | ||
| 667 | { | ||
| 668 | hr = WcaWriteStringToCaData(pProp->wzName, ppwzActionData); | ||
| 669 | ExitOnFailure(hr, "Failed to add property name to custom action data, name: %S", pProp->wzName); | ||
| 670 | |||
| 671 | hr = WcaWriteStringToCaData(pProp->pwzValue, ppwzActionData); | ||
| 672 | ExitOnFailure(hr, "Failed to add property value to custom action data, name: %S", pProp->wzName); | ||
| 673 | } | ||
| 674 | } | ||
| 675 | |||
| 676 | hr = S_OK; | ||
| 677 | |||
| 678 | LExit: | ||
| 679 | return hr; | ||
| 680 | } | ||
| 681 | |||
| 682 | HRESULT CpiBuildAccountName( | ||
| 683 | LPCWSTR pwzDomain, | ||
| 684 | LPCWSTR pwzName, | ||
| 685 | LPWSTR* ppwzAccount | ||
| 686 | ) | ||
| 687 | { | ||
| 688 | HRESULT hr = S_OK; | ||
| 689 | |||
| 690 | WCHAR wzComputerName[MAX_COMPUTERNAME_LENGTH + 1]; | ||
| 691 | ::ZeroMemory(wzComputerName, sizeof(wzComputerName)); | ||
| 692 | |||
| 693 | // if domain is '.', get computer name | ||
| 694 | if (0 == lstrcmpW(pwzDomain, L".")) | ||
| 695 | { | ||
| 696 | DWORD dwSize = countof(wzComputerName); | ||
| 697 | if (!::GetComputerNameW(wzComputerName, &dwSize)) | ||
| 698 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to get computer name"); | ||
| 699 | } | ||
| 700 | |||
| 701 | // build account name | ||
| 702 | hr = StrAllocFormatted(ppwzAccount, L"%s\\%s", *wzComputerName ? wzComputerName : pwzDomain, pwzName); | ||
| 703 | ExitOnFailure(hr, "Failed to build domain user name"); | ||
| 704 | |||
| 705 | hr = S_OK; | ||
| 706 | |||
| 707 | LExit: | ||
| 708 | return hr; | ||
| 709 | } | ||
| 710 | |||
| 711 | HRESULT CpiGetTempFileName( | ||
| 712 | LPWSTR* ppwzTempFile | ||
| 713 | ) | ||
| 714 | { | ||
| 715 | HRESULT hr = S_OK; | ||
| 716 | |||
| 717 | // get temp path | ||
| 718 | WCHAR wzTempPath[MAX_PATH]; | ||
| 719 | DWORD dw = ::GetTempPathW(countof(wzTempPath), wzTempPath); | ||
| 720 | if (countof(wzTempPath) <= dw) | ||
| 721 | ExitOnFailure(hr = E_FAIL, "TEMP directory path too long"); | ||
| 722 | |||
| 723 | // get unique number | ||
| 724 | LARGE_INTEGER liCount; | ||
| 725 | if (!::QueryPerformanceCounter(&liCount)) | ||
| 726 | ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to query performance counter"); | ||
| 727 | |||
| 728 | // create temp file name | ||
| 729 | hr = StrAllocFormatted(ppwzTempFile, L"%sCPI%I64X.tmp", wzTempPath, liCount.QuadPart); | ||
| 730 | ExitOnFailure(hr, "Failed to create temp file name string"); | ||
| 731 | |||
| 732 | hr = S_OK; | ||
| 733 | |||
| 734 | LExit: | ||
| 735 | return hr; | ||
| 736 | } | ||
| 737 | |||
| 738 | HRESULT CpiCreateId( | ||
| 739 | LPWSTR pwzDest, | ||
| 740 | SIZE_T cchDest | ||
| 741 | ) | ||
| 742 | { | ||
| 743 | HRESULT hr = S_OK; | ||
| 744 | |||
| 745 | GUID guid; | ||
| 746 | |||
| 747 | // create new guid | ||
| 748 | hr = ::CoCreateGuid(&guid); | ||
| 749 | ExitOnFailure(hr, "Failed to create new guid"); | ||
| 750 | |||
| 751 | // convert guid to string | ||
| 752 | if (0 == ::StringFromGUID2(guid, pwzDest, (int)cchDest)) | ||
| 753 | ExitOnFailure(hr = E_FAIL, "Failed to convert guid to string"); | ||
| 754 | |||
| 755 | hr = S_OK; | ||
| 756 | |||
| 757 | LExit: | ||
| 758 | return hr; | ||
| 759 | } | ||
| 760 | |||
| 761 | BOOL CpiIsInstalled( | ||
| 762 | INSTALLSTATE isInstalled | ||
| 763 | ) | ||
| 764 | { | ||
| 765 | return INSTALLSTATE_LOCAL == isInstalled || INSTALLSTATE_SOURCE == isInstalled; | ||
| 766 | } | ||
| 767 | |||
| 768 | BOOL CpiWillBeInstalled( | ||
| 769 | INSTALLSTATE isInstalled, | ||
| 770 | INSTALLSTATE isAction | ||
| 771 | ) | ||
| 772 | { | ||
| 773 | return WcaIsInstalling(isInstalled, isAction) || | ||
| 774 | (CpiIsInstalled(isInstalled) && !WcaIsUninstalling(isInstalled, isAction)); | ||
| 775 | } | ||
| 776 | |||
| 777 | HRESULT PcaGuidToRegFormat( | ||
| 778 | LPWSTR pwzGuid, | ||
| 779 | LPWSTR pwzDest, | ||
| 780 | SIZE_T cchDest | ||
| 781 | ) | ||
| 782 | { | ||
| 783 | HRESULT hr = S_OK; | ||
| 784 | |||
| 785 | GUID guid = GUID_NULL; | ||
| 786 | int cch = 0; | ||
| 787 | |||
| 788 | WCHAR wz[39]; | ||
| 789 | ::ZeroMemory(wz, sizeof(wz)); | ||
| 790 | |||
| 791 | cch = lstrlenW(pwzGuid); | ||
| 792 | |||
| 793 | if (38 == cch && L'{' == pwzGuid[0] && L'}' == pwzGuid[37]) | ||
| 794 | StringCchCopyW(wz, countof(wz), pwzGuid); | ||
| 795 | else if (36 == cch) | ||
| 796 | StringCchPrintfW(wz, countof(wz), L"{%s}", pwzGuid); | ||
| 797 | else | ||
| 798 | ExitFunction1(hr = E_INVALIDARG); | ||
| 799 | |||
| 800 | // convert string to guid | ||
| 801 | hr = ::CLSIDFromString(wz, &guid); | ||
| 802 | ExitOnFailure(hr, "Failed to parse guid string"); | ||
| 803 | |||
| 804 | // convert guid to string | ||
| 805 | if (0 == ::StringFromGUID2(guid, pwzDest, (int)cchDest)) | ||
| 806 | ExitOnFailure(hr = E_FAIL, "Failed to convert guid to string"); | ||
| 807 | |||
| 808 | hr = S_OK; | ||
| 809 | |||
| 810 | LExit: | ||
| 811 | return hr; | ||
| 812 | } | ||
| 813 | |||
| 814 | |||
| 815 | // helper function definitions | ||
| 816 | |||
| 817 | static HRESULT FindPropertyDefinition( | ||
| 818 | CPI_PROPERTY_DEFINITION* pPropDefList, | ||
| 819 | LPCWSTR pwzName, | ||
| 820 | CPI_PROPERTY_DEFINITION** ppPropDef | ||
| 821 | ) | ||
| 822 | { | ||
| 823 | for (CPI_PROPERTY_DEFINITION* pItm = pPropDefList; pItm->pwzName; pItm++) | ||
| 824 | { | ||
| 825 | if (0 == lstrcmpW(pItm->pwzName, pwzName)) | ||
| 826 | { | ||
| 827 | *ppPropDef = pItm; | ||
| 828 | return S_OK; | ||
| 829 | } | ||
| 830 | } | ||
| 831 | |||
| 832 | return S_FALSE; | ||
| 833 | } | ||
| 834 | |||
| 835 | static HRESULT GetUserAccountName( | ||
| 836 | LPCWSTR pwzKey, | ||
| 837 | LPWSTR* ppwzAccount | ||
| 838 | ) | ||
| 839 | { | ||
| 840 | HRESULT hr = S_OK; | ||
| 841 | |||
| 842 | PMSIHANDLE hView, hRecKey, hRec; | ||
| 843 | |||
| 844 | LPWSTR pwzDomain = NULL; | ||
| 845 | LPWSTR pwzName = NULL; | ||
| 846 | |||
| 847 | // create parameter record | ||
| 848 | hRecKey = ::MsiCreateRecord(1); | ||
| 849 | ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); | ||
| 850 | hr = WcaSetRecordString(hRecKey, 1, pwzKey); | ||
| 851 | ExitOnFailure(hr, "Failed to set record string"); | ||
| 852 | |||
| 853 | // open view | ||
| 854 | hr = WcaOpenView(vcsUserQuery, &hView); | ||
| 855 | ExitOnFailure(hr, "Failed to open view on User table"); | ||
| 856 | hr = WcaExecuteView(hView, hRecKey); | ||
| 857 | ExitOnFailure(hr, "Failed to execute view on User table"); | ||
| 858 | |||
| 859 | // fetch record | ||
| 860 | hr = WcaFetchSingleRecord(hView, &hRec); | ||
| 861 | if (S_FALSE == hr) | ||
| 862 | ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "User not found, key: %S", pwzKey); | ||
| 863 | ExitOnFailure(hr, "Failed to fetch user record"); | ||
| 864 | |||
| 865 | // get user domain | ||
| 866 | hr = WcaGetRecordFormattedString(hRec, uqDomain, &pwzDomain); | ||
| 867 | ExitOnFailure(hr, "Failed to get domain"); | ||
| 868 | |||
| 869 | // get user name | ||
| 870 | hr = WcaGetRecordFormattedString(hRec, uqName, &pwzName); | ||
| 871 | ExitOnFailure(hr, "Failed to get name"); | ||
| 872 | |||
| 873 | // build account name | ||
| 874 | hr = CpiBuildAccountName(pwzDomain, pwzName, ppwzAccount); | ||
| 875 | ExitOnFailure(hr, "Failed to build account name"); | ||
| 876 | |||
| 877 | hr = S_OK; | ||
| 878 | |||
| 879 | LExit: | ||
| 880 | // clean up | ||
| 881 | ReleaseStr(pwzDomain); | ||
| 882 | ReleaseStr(pwzName); | ||
| 883 | |||
| 884 | return hr; | ||
| 885 | } | ||
diff --git a/src/ca/cputilsched.h b/src/ca/cputilsched.h new file mode 100644 index 00000000..61aaab84 --- /dev/null +++ b/src/ca/cputilsched.h | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | #pragma once | ||
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 3 | |||
| 4 | |||
| 5 | #define CPI_MAX_GUID 38 | ||
| 6 | |||
| 7 | enum eRunMode { rmDeferred = 1, rmCommit, rmRollback }; | ||
| 8 | |||
| 9 | enum eActionType { atNoOp = 0, atCreate, atRemove }; | ||
| 10 | |||
| 11 | enum eComPlusPropertyType { cpptNone = 0, cpptBoolean, cpptInteger, cpptString, cpptUser }; | ||
| 12 | |||
| 13 | enum eComPlusTables | ||
| 14 | { | ||
| 15 | cptComPlusPartition = (1 << 0), | ||
| 16 | cptComPlusPartitionProperty = (1 << 1), | ||
| 17 | cptComPlusPartitionRole = (1 << 2), | ||
| 18 | cptComPlusUserInPartitionRole = (1 << 3), | ||
| 19 | cptComPlusGroupInPartitionRole = (1 << 4), | ||
| 20 | cptComPlusPartitionUser = (1 << 5), | ||
| 21 | cptComPlusApplication = (1 << 6), | ||
| 22 | cptComPlusApplicationProperty = (1 << 7), | ||
| 23 | cptComPlusApplicationRole = (1 << 8), | ||
| 24 | cptComPlusApplicationRoleProperty = (1 << 9), | ||
| 25 | cptComPlusUserInApplicationRole = (1 << 10), | ||
| 26 | cptComPlusGroupInApplicationRole = (1 << 11), | ||
| 27 | cptComPlusAssembly = (1 << 12), | ||
| 28 | cptComPlusAssemblyDependency = (1 << 13), | ||
| 29 | cptComPlusComponent = (1 << 14), | ||
| 30 | cptComPlusComponentProperty = (1 << 15), | ||
| 31 | cptComPlusRoleForComponent = (1 << 16), | ||
| 32 | cptComPlusInterface = (1 << 17), | ||
| 33 | cptComPlusInterfaceProperty = (1 << 18), | ||
| 34 | cptComPlusRoleForInterface = (1 << 19), | ||
| 35 | cptComPlusMethod = (1 << 20), | ||
| 36 | cptComPlusMethodProperty = (1 << 21), | ||
| 37 | cptComPlusRoleForMethod = (1 << 22), | ||
| 38 | cptComPlusSubscription = (1 << 23), | ||
| 39 | cptComPlusSubscriptionProperty = (1 << 24) | ||
| 40 | }; | ||
| 41 | |||
| 42 | |||
| 43 | // structs | ||
| 44 | |||
| 45 | struct CPI_PROPERTY | ||
| 46 | { | ||
| 47 | WCHAR wzName[MAX_DARWIN_KEY + 1]; | ||
| 48 | LPWSTR pwzValue; | ||
| 49 | |||
| 50 | CPI_PROPERTY* pNext; | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct CPI_PROPERTY_DEFINITION | ||
| 54 | { | ||
| 55 | LPCWSTR pwzName; | ||
| 56 | int iType; | ||
| 57 | int iMinVersionNT; | ||
| 58 | }; | ||
| 59 | |||
| 60 | |||
| 61 | // function prototypes | ||
| 62 | |||
| 63 | void CpiInitialize(); | ||
| 64 | void CpiFinalize(); | ||
| 65 | BOOL CpiTableExists( | ||
| 66 | int iTable | ||
| 67 | ); | ||
| 68 | HRESULT CpiGetAdminCatalog( | ||
| 69 | ICOMAdminCatalog** ppiCatalog | ||
| 70 | ); | ||
| 71 | HRESULT CpiGetCatalogCollection( | ||
| 72 | LPCWSTR pwzName, | ||
| 73 | ICatalogCollection** ppiColl | ||
| 74 | ); | ||
| 75 | HRESULT CpiGetCatalogCollection( | ||
| 76 | ICatalogCollection* piColl, | ||
| 77 | ICatalogObject* piObj, | ||
| 78 | LPCWSTR pwzName, | ||
| 79 | ICatalogCollection** ppiColl | ||
| 80 | ); | ||
| 81 | HRESULT CpiGetKeyForObject( | ||
| 82 | ICatalogObject* piObj, | ||
| 83 | LPWSTR pwzKey, | ||
| 84 | SIZE_T cchKey | ||
| 85 | ); | ||
| 86 | HRESULT CpiFindCollectionObject( | ||
| 87 | ICatalogCollection* piColl, | ||
| 88 | LPCWSTR pwzID, | ||
| 89 | LPCWSTR pwzName, | ||
| 90 | ICatalogObject** ppiObj | ||
| 91 | ); | ||
| 92 | HRESULT CpiGetPartitionsCollection( | ||
| 93 | ICatalogCollection** ppiPartColl | ||
| 94 | ); | ||
| 95 | HRESULT CpiGetApplicationsCollection( | ||
| 96 | ICatalogCollection** ppiAppColl | ||
| 97 | ); | ||
| 98 | HRESULT CpiAddActionTextToActionData( | ||
| 99 | LPCWSTR pwzAction, | ||
| 100 | LPWSTR* ppwzActionData | ||
| 101 | ); | ||
| 102 | HRESULT CpiVerifyComponentArchitecure( | ||
| 103 | LPCWSTR pwzComponent, | ||
| 104 | BOOL* pfMatchingArchitecture | ||
| 105 | ); | ||
| 106 | HRESULT CpiPropertiesRead( | ||
| 107 | LPCWSTR pwzQuery, | ||
| 108 | LPCWSTR pwzKey, | ||
| 109 | CPI_PROPERTY_DEFINITION* pPropDefList, | ||
| 110 | CPI_PROPERTY** ppPropList, | ||
| 111 | int* piCount | ||
| 112 | ); | ||
| 113 | void CpiPropertiesFreeList( | ||
| 114 | CPI_PROPERTY* pList | ||
| 115 | ); | ||
| 116 | HRESULT CpiAddPropertiesToActionData( | ||
| 117 | int iPropCount, | ||
| 118 | CPI_PROPERTY* pPropList, | ||
| 119 | LPWSTR* ppwzActionData | ||
| 120 | ); | ||
| 121 | HRESULT CpiBuildAccountName( | ||
| 122 | LPCWSTR pwzDomain, | ||
| 123 | LPCWSTR pwzName, | ||
| 124 | LPWSTR* ppwzAccount | ||
| 125 | ); | ||
| 126 | HRESULT CpiGetTempFileName( | ||
| 127 | LPWSTR* ppwzTempFile | ||
| 128 | ); | ||
| 129 | HRESULT CpiCreateId( | ||
| 130 | LPWSTR pwzDest, | ||
| 131 | SIZE_T cchDest | ||
| 132 | ); | ||
| 133 | BOOL CpiIsInstalled( | ||
| 134 | INSTALLSTATE isInstalled | ||
| 135 | ); | ||
| 136 | BOOL CpiWillBeInstalled( | ||
| 137 | INSTALLSTATE isInstalled, | ||
| 138 | INSTALLSTATE isAction | ||
| 139 | ); | ||
| 140 | HRESULT PcaGuidToRegFormat( | ||
| 141 | LPWSTR pwzGuid, | ||
| 142 | LPWSTR pwzDest, | ||
| 143 | SIZE_T cchDest | ||
| 144 | ); | ||
diff --git a/src/wixext/ComPlusCompiler.cs b/src/wixext/ComPlusCompiler.cs new file mode 100644 index 00000000..7f22c56b --- /dev/null +++ b/src/wixext/ComPlusCompiler.cs | |||
| @@ -0,0 +1,2188 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Extensions | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections; | ||
| 7 | using System.Collections.Generic; | ||
| 8 | using System.Globalization; | ||
| 9 | using System.Reflection; | ||
| 10 | using System.Xml; | ||
| 11 | using System.Xml.Linq; | ||
| 12 | using System.Xml.Schema; | ||
| 13 | using WixToolset.Data; | ||
| 14 | using WixToolset.Extensibility; | ||
| 15 | |||
| 16 | /// <summary> | ||
| 17 | /// The compiler for the WiX Toolset Internet Information Services Extension. | ||
| 18 | /// </summary> | ||
| 19 | public sealed class ComPlusCompiler : CompilerExtension | ||
| 20 | { | ||
| 21 | /// <summary> | ||
| 22 | /// Instantiate a new ComPlusCompiler. | ||
| 23 | /// </summary> | ||
| 24 | public ComPlusCompiler() | ||
| 25 | { | ||
| 26 | this.Namespace = "http://wixtoolset.org/schemas/v4/wxs/complus"; | ||
| 27 | } | ||
| 28 | |||
| 29 | /// <summary> | ||
| 30 | /// </summary> | ||
| 31 | /// <remarks></remarks> | ||
| 32 | public enum CpiAssemblyAttributes | ||
| 33 | { | ||
| 34 | EventClass = (1 << 0), | ||
| 35 | DotNetAssembly = (1 << 1), | ||
| 36 | DllPathFromGAC = (1 << 2), | ||
| 37 | RegisterInCommit = (1 << 3) | ||
| 38 | } | ||
| 39 | |||
| 40 | /// <summary> | ||
| 41 | /// Processes an element for the Compiler. | ||
| 42 | /// </summary> | ||
| 43 | /// <param name="sourceLineNumbers">Source line number for the parent element.</param> | ||
| 44 | /// <param name="parentElement">Parent element of element to process.</param> | ||
| 45 | /// <param name="element">Element to process.</param> | ||
| 46 | /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param> | ||
| 47 | public override void ParseElement(XElement parentElement, XElement element, IDictionary<string, string> context) | ||
| 48 | { | ||
| 49 | switch (parentElement.Name.LocalName) | ||
| 50 | { | ||
| 51 | case "Component": | ||
| 52 | string componentId = context["ComponentId"]; | ||
| 53 | string directoryId = context["DirectoryId"]; | ||
| 54 | bool win64 = Boolean.Parse(context["Win64"]); | ||
| 55 | |||
| 56 | switch (element.Name.LocalName) | ||
| 57 | { | ||
| 58 | case "ComPlusPartition": | ||
| 59 | this.ParseComPlusPartitionElement(element, componentId, win64); | ||
| 60 | break; | ||
| 61 | case "ComPlusPartitionRole": | ||
| 62 | this.ParseComPlusPartitionRoleElement(element, componentId, null); | ||
| 63 | break; | ||
| 64 | case "ComPlusUserInPartitionRole": | ||
| 65 | this.ParseComPlusUserInPartitionRoleElement(element, componentId, null); | ||
| 66 | break; | ||
| 67 | case "ComPlusGroupInPartitionRole": | ||
| 68 | this.ParseComPlusGroupInPartitionRoleElement(element, componentId, null); | ||
| 69 | break; | ||
| 70 | case "ComPlusPartitionUser": | ||
| 71 | this.ParseComPlusPartitionUserElement(element, componentId, null); | ||
| 72 | break; | ||
| 73 | case "ComPlusApplication": | ||
| 74 | this.ParseComPlusApplicationElement(element, componentId, win64, null); | ||
| 75 | break; | ||
| 76 | case "ComPlusApplicationRole": | ||
| 77 | this.ParseComPlusApplicationRoleElement(element, componentId, null); | ||
| 78 | break; | ||
| 79 | case "ComPlusUserInApplicationRole": | ||
| 80 | this.ParseComPlusUserInApplicationRoleElement(element, componentId, null); | ||
| 81 | break; | ||
| 82 | case "ComPlusGroupInApplicationRole": | ||
| 83 | this.ParseComPlusGroupInApplicationRoleElement(element, componentId, null); | ||
| 84 | break; | ||
| 85 | case "ComPlusAssembly": | ||
| 86 | this.ParseComPlusAssemblyElement(element, componentId, win64, null); | ||
| 87 | break; | ||
| 88 | case "ComPlusRoleForComponent": | ||
| 89 | this.ParseComPlusRoleForComponentElement(element, componentId, null); | ||
| 90 | break; | ||
| 91 | case "ComPlusRoleForInterface": | ||
| 92 | this.ParseComPlusRoleForInterfaceElement(element, componentId, null); | ||
| 93 | break; | ||
| 94 | case "ComPlusRoleForMethod": | ||
| 95 | this.ParseComPlusRoleForMethodElement(element, componentId, null); | ||
| 96 | break; | ||
| 97 | case "ComPlusSubscription": | ||
| 98 | this.ParseComPlusSubscriptionElement(element, componentId, null); | ||
| 99 | break; | ||
| 100 | default: | ||
| 101 | this.Core.UnexpectedElement(parentElement, element); | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | break; | ||
| 105 | case "Fragment": | ||
| 106 | case "Module": | ||
| 107 | case "Product": | ||
| 108 | switch (element.Name.LocalName) | ||
| 109 | { | ||
| 110 | case "ComPlusPartition": | ||
| 111 | this.ParseComPlusPartitionElement(element, null, false); | ||
| 112 | break; | ||
| 113 | case "ComPlusPartitionRole": | ||
| 114 | this.ParseComPlusPartitionRoleElement(element, null, null); | ||
| 115 | break; | ||
| 116 | case "ComPlusApplication": | ||
| 117 | this.ParseComPlusApplicationElement(element, null, false, null); | ||
| 118 | break; | ||
| 119 | case "ComPlusApplicationRole": | ||
| 120 | this.ParseComPlusApplicationRoleElement(element, null, null); | ||
| 121 | break; | ||
| 122 | default: | ||
| 123 | this.Core.UnexpectedElement(parentElement, element); | ||
| 124 | break; | ||
| 125 | } | ||
| 126 | break; | ||
| 127 | default: | ||
| 128 | this.Core.UnexpectedElement(parentElement, element); | ||
| 129 | break; | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | /// <summary> | ||
| 134 | /// Parses a COM+ partition element. | ||
| 135 | /// </summary> | ||
| 136 | /// <param name="node">Element to parse.</param> | ||
| 137 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 138 | private void ParseComPlusPartitionElement(XElement node, string componentKey, bool win64) | ||
| 139 | { | ||
| 140 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 141 | |||
| 142 | string key = null; | ||
| 143 | string id = null; | ||
| 144 | string name = null; | ||
| 145 | |||
| 146 | Hashtable properties = new Hashtable(); | ||
| 147 | |||
| 148 | foreach (XAttribute attrib in node.Attributes()) | ||
| 149 | { | ||
| 150 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 151 | { | ||
| 152 | switch (attrib.Name.LocalName) | ||
| 153 | { | ||
| 154 | case "Id": | ||
| 155 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 156 | break; | ||
| 157 | case "PartitionId": | ||
| 158 | id = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
| 159 | break; | ||
| 160 | case "Name": | ||
| 161 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 162 | break; | ||
| 163 | case "Changeable": | ||
| 164 | this.Core.OnMessage(WixWarnings.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 165 | break; | ||
| 166 | case "Deleteable": | ||
| 167 | if (null == componentKey) | ||
| 168 | { | ||
| 169 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 170 | } | ||
| 171 | properties["Deleteable"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 172 | break; | ||
| 173 | case "Description": | ||
| 174 | if (null == componentKey) | ||
| 175 | { | ||
| 176 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 177 | } | ||
| 178 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 179 | break; | ||
| 180 | default: | ||
| 181 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 182 | break; | ||
| 183 | } | ||
| 184 | } | ||
| 185 | else | ||
| 186 | { | ||
| 187 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | if (null != componentKey && null == name) | ||
| 192 | { | ||
| 193 | this.Core.OnMessage(ComPlusErrors.RequiredAttributeUnderComponent(sourceLineNumbers, node.Name.LocalName, "Name")); | ||
| 194 | } | ||
| 195 | if (null == componentKey && null == id && null == name) | ||
| 196 | { | ||
| 197 | this.Core.OnMessage(ComPlusErrors.RequiredAttributeNotUnderComponent(sourceLineNumbers, node.Name.LocalName, "Id", "Name")); | ||
| 198 | } | ||
| 199 | |||
| 200 | foreach (XElement child in node.Elements()) | ||
| 201 | { | ||
| 202 | if (this.Namespace == child.Name.Namespace) | ||
| 203 | { | ||
| 204 | switch (child.Name.LocalName) | ||
| 205 | { | ||
| 206 | case "ComPlusPartitionRole": | ||
| 207 | this.ParseComPlusPartitionRoleElement(child, componentKey, key); | ||
| 208 | break; | ||
| 209 | case "ComPlusPartitionUser": | ||
| 210 | this.ParseComPlusPartitionUserElement(child, componentKey, key); | ||
| 211 | break; | ||
| 212 | case "ComPlusApplication": | ||
| 213 | this.ParseComPlusApplicationElement(child, componentKey, win64, key); | ||
| 214 | break; | ||
| 215 | default: | ||
| 216 | this.Core.UnexpectedElement(node, child); | ||
| 217 | break; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | else | ||
| 221 | { | ||
| 222 | this.Core.ParseExtensionElement(node, child); | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartition"); | ||
| 227 | row[0] = key; | ||
| 228 | row[1] = componentKey; | ||
| 229 | row[2] = id; | ||
| 230 | row[3] = name; | ||
| 231 | |||
| 232 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
| 233 | while (propertiesEnumerator.MoveNext()) | ||
| 234 | { | ||
| 235 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartitionProperty"); | ||
| 236 | propertyRow[0] = key; | ||
| 237 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
| 238 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
| 239 | } | ||
| 240 | |||
| 241 | if (componentKey != null) | ||
| 242 | { | ||
| 243 | if (win64) | ||
| 244 | { | ||
| 245 | if (this.Core.CurrentPlatform == Platform.IA64) | ||
| 246 | { | ||
| 247 | this.Core.OnMessage(WixErrors.UnsupportedPlatformForElement(sourceLineNumbers, "ia64", node.Name.LocalName)); | ||
| 248 | } | ||
| 249 | else | ||
| 250 | { | ||
| 251 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall_x64"); | ||
| 252 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall_x64"); | ||
| 253 | } | ||
| 254 | } | ||
| 255 | else | ||
| 256 | { | ||
| 257 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall"); | ||
| 258 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall"); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | /// <summary> | ||
| 264 | /// Parses a COM+ partition role element. | ||
| 265 | /// </summary> | ||
| 266 | /// <param name="node">Element to parse.</param> | ||
| 267 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 268 | /// <param name="applicationKey">Optional identifier of parent application.</param> | ||
| 269 | private void ParseComPlusPartitionRoleElement(XElement node, string componentKey, string partitionKey) | ||
| 270 | { | ||
| 271 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 272 | |||
| 273 | string key = null; | ||
| 274 | string name = null; | ||
| 275 | |||
| 276 | foreach (XAttribute attrib in node.Attributes()) | ||
| 277 | { | ||
| 278 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 279 | { | ||
| 280 | switch (attrib.Name.LocalName) | ||
| 281 | { | ||
| 282 | case "Id": | ||
| 283 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 284 | break; | ||
| 285 | case "Partition": | ||
| 286 | if (null != partitionKey) | ||
| 287 | { | ||
| 288 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 289 | } | ||
| 290 | partitionKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 291 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartition", partitionKey); | ||
| 292 | break; | ||
| 293 | case "Name": | ||
| 294 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 295 | break; | ||
| 296 | default: | ||
| 297 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 298 | break; | ||
| 299 | } | ||
| 300 | } | ||
| 301 | else | ||
| 302 | { | ||
| 303 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | if (null == partitionKey) | ||
| 308 | { | ||
| 309 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Partition")); | ||
| 310 | } | ||
| 311 | |||
| 312 | foreach (XElement child in node.Elements()) | ||
| 313 | { | ||
| 314 | if (this.Namespace == child.Name.Namespace) | ||
| 315 | { | ||
| 316 | switch (child.Name.LocalName) | ||
| 317 | { | ||
| 318 | case "ComPlusUserInPartitionRole": | ||
| 319 | this.ParseComPlusUserInPartitionRoleElement(child, componentKey, key); | ||
| 320 | break; | ||
| 321 | case "ComPlusGroupInPartitionRole": | ||
| 322 | this.ParseComPlusGroupInPartitionRoleElement(child, componentKey, key); | ||
| 323 | break; | ||
| 324 | default: | ||
| 325 | this.Core.UnexpectedElement(node, child); | ||
| 326 | break; | ||
| 327 | } | ||
| 328 | } | ||
| 329 | else | ||
| 330 | { | ||
| 331 | this.Core.ParseExtensionElement(node, child); | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | // add table row | ||
| 336 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartitionRole"); | ||
| 337 | row[0] = key; | ||
| 338 | row[1] = partitionKey; | ||
| 339 | row[3] = name; | ||
| 340 | } | ||
| 341 | |||
| 342 | /// <summary> | ||
| 343 | /// Parses a COM+ partition role user element. | ||
| 344 | /// </summary> | ||
| 345 | /// <param name="node">Element to parse.</param> | ||
| 346 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 347 | /// <param name="applicationKey">Optional identifier of parent application role.</param> | ||
| 348 | private void ParseComPlusUserInPartitionRoleElement(XElement node, string componentKey, string partitionRoleKey) | ||
| 349 | { | ||
| 350 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 351 | |||
| 352 | string key = null; | ||
| 353 | string user = null; | ||
| 354 | |||
| 355 | foreach (XAttribute attrib in node.Attributes()) | ||
| 356 | { | ||
| 357 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 358 | { | ||
| 359 | switch (attrib.Name.LocalName) | ||
| 360 | { | ||
| 361 | case "Id": | ||
| 362 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 363 | break; | ||
| 364 | case "PartitionRole": | ||
| 365 | if (null != partitionRoleKey) | ||
| 366 | { | ||
| 367 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 368 | } | ||
| 369 | partitionRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 370 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartitionRole", partitionRoleKey); | ||
| 371 | break; | ||
| 372 | case "User": | ||
| 373 | user = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 374 | this.Core.CreateSimpleReference(sourceLineNumbers, "User", user); | ||
| 375 | break; | ||
| 376 | default: | ||
| 377 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 378 | break; | ||
| 379 | } | ||
| 380 | } | ||
| 381 | else | ||
| 382 | { | ||
| 383 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | if (null == partitionRoleKey) | ||
| 388 | { | ||
| 389 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "PartitionRole")); | ||
| 390 | } | ||
| 391 | |||
| 392 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusUserInPartitionRole"); | ||
| 393 | row[0] = key; | ||
| 394 | row[1] = partitionRoleKey; | ||
| 395 | row[2] = componentKey; | ||
| 396 | row[3] = user; | ||
| 397 | } | ||
| 398 | |||
| 399 | /// <summary> | ||
| 400 | /// Parses a COM+ partition role user element. | ||
| 401 | /// </summary> | ||
| 402 | /// <param name="node">Element to parse.</param> | ||
| 403 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 404 | /// <param name="applicationKey">Optional identifier of parent application role.</param> | ||
| 405 | private void ParseComPlusGroupInPartitionRoleElement(XElement node, string componentKey, string partitionRoleKey) | ||
| 406 | { | ||
| 407 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 408 | |||
| 409 | string key = null; | ||
| 410 | string group = null; | ||
| 411 | |||
| 412 | foreach (XAttribute attrib in node.Attributes()) | ||
| 413 | { | ||
| 414 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 415 | { | ||
| 416 | switch (attrib.Name.LocalName) | ||
| 417 | { | ||
| 418 | case "Id": | ||
| 419 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 420 | break; | ||
| 421 | case "PartitionRole": | ||
| 422 | if (null != partitionRoleKey) | ||
| 423 | { | ||
| 424 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 425 | } | ||
| 426 | partitionRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 427 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartitionRole", partitionRoleKey); | ||
| 428 | break; | ||
| 429 | case "Group": | ||
| 430 | group = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 431 | this.Core.CreateSimpleReference(sourceLineNumbers, "Group", group); | ||
| 432 | break; | ||
| 433 | default: | ||
| 434 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 435 | break; | ||
| 436 | } | ||
| 437 | } | ||
| 438 | else | ||
| 439 | { | ||
| 440 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 441 | } | ||
| 442 | } | ||
| 443 | |||
| 444 | if (null == partitionRoleKey) | ||
| 445 | { | ||
| 446 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "PartitionRole")); | ||
| 447 | } | ||
| 448 | |||
| 449 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusGroupInPartitionRole"); | ||
| 450 | row[0] = key; | ||
| 451 | row[1] = partitionRoleKey; | ||
| 452 | row[2] = componentKey; | ||
| 453 | row[3] = group; | ||
| 454 | } | ||
| 455 | |||
| 456 | /// <summary> | ||
| 457 | /// Parses a COM+ partition element. | ||
| 458 | /// </summary> | ||
| 459 | /// <param name="node">Element to parse.</param> | ||
| 460 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 461 | private void ParseComPlusPartitionUserElement(XElement node, string componentKey, string partitionKey) | ||
| 462 | { | ||
| 463 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 464 | |||
| 465 | string key = null; | ||
| 466 | string user = null; | ||
| 467 | |||
| 468 | foreach (XAttribute attrib in node.Attributes()) | ||
| 469 | { | ||
| 470 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 471 | { | ||
| 472 | switch (attrib.Name.LocalName) | ||
| 473 | { | ||
| 474 | case "Id": | ||
| 475 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 476 | break; | ||
| 477 | case "Partition": | ||
| 478 | if (null != partitionKey) | ||
| 479 | { | ||
| 480 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 481 | } | ||
| 482 | partitionKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 483 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartition", partitionKey); | ||
| 484 | break; | ||
| 485 | case "User": | ||
| 486 | user = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 487 | this.Core.CreateSimpleReference(sourceLineNumbers, "User", user); | ||
| 488 | break; | ||
| 489 | default: | ||
| 490 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 491 | break; | ||
| 492 | } | ||
| 493 | } | ||
| 494 | else | ||
| 495 | { | ||
| 496 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 497 | } | ||
| 498 | } | ||
| 499 | |||
| 500 | if (null == partitionKey) | ||
| 501 | { | ||
| 502 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Partition")); | ||
| 503 | } | ||
| 504 | |||
| 505 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusPartitionUser"); | ||
| 506 | row[0] = key; | ||
| 507 | row[1] = partitionKey; | ||
| 508 | row[2] = componentKey; | ||
| 509 | row[3] = user; | ||
| 510 | } | ||
| 511 | |||
| 512 | /// <summary> | ||
| 513 | /// Parses a COM+ application element. | ||
| 514 | /// </summary> | ||
| 515 | /// <param name="node">Element to parse.</param> | ||
| 516 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 517 | /// <param name="partitionKey">Optional identifier of parent partition.</param> | ||
| 518 | private void ParseComPlusApplicationElement(XElement node, string componentKey, bool win64, string partitionKey) | ||
| 519 | { | ||
| 520 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 521 | |||
| 522 | string key = null; | ||
| 523 | string id = null; | ||
| 524 | string name = null; | ||
| 525 | |||
| 526 | Hashtable properties = new Hashtable(); | ||
| 527 | |||
| 528 | foreach (XAttribute attrib in node.Attributes()) | ||
| 529 | { | ||
| 530 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 531 | { | ||
| 532 | switch (attrib.Name.LocalName) | ||
| 533 | { | ||
| 534 | case "Id": | ||
| 535 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 536 | break; | ||
| 537 | case "Partition": | ||
| 538 | if (null != partitionKey) | ||
| 539 | { | ||
| 540 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 541 | } | ||
| 542 | partitionKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 543 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusPartition", partitionKey); | ||
| 544 | break; | ||
| 545 | case "ApplicationId": | ||
| 546 | id = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
| 547 | break; | ||
| 548 | case "Name": | ||
| 549 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 550 | break; | ||
| 551 | case "ThreeGigSupportEnabled": | ||
| 552 | if (null == componentKey) | ||
| 553 | { | ||
| 554 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 555 | } | ||
| 556 | properties["3GigSupportEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 557 | break; | ||
| 558 | case "AccessChecksLevel": | ||
| 559 | if (null == componentKey) | ||
| 560 | { | ||
| 561 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 562 | } | ||
| 563 | string accessChecksLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 564 | switch (accessChecksLevelValue) | ||
| 565 | { | ||
| 566 | case "applicationLevel": | ||
| 567 | properties["AccessChecksLevel"] = "0"; | ||
| 568 | break; | ||
| 569 | case "applicationComponentLevel": | ||
| 570 | properties["AccessChecksLevel"] = "1"; | ||
| 571 | break; | ||
| 572 | default: | ||
| 573 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "AccessChecksLevel", accessChecksLevelValue, "applicationLevel", "applicationComponentLevel")); | ||
| 574 | break; | ||
| 575 | } | ||
| 576 | break; | ||
| 577 | case "Activation": | ||
| 578 | if (null == componentKey) | ||
| 579 | { | ||
| 580 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 581 | } | ||
| 582 | string activationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 583 | switch (activationValue) | ||
| 584 | { | ||
| 585 | case "inproc": | ||
| 586 | properties["Activation"] = "Inproc"; | ||
| 587 | break; | ||
| 588 | case "local": | ||
| 589 | properties["Activation"] = "Local"; | ||
| 590 | break; | ||
| 591 | default: | ||
| 592 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "Activation", activationValue, "inproc", "local")); | ||
| 593 | break; | ||
| 594 | } | ||
| 595 | break; | ||
| 596 | case "ApplicationAccessChecksEnabled": | ||
| 597 | if (null == componentKey) | ||
| 598 | { | ||
| 599 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 600 | } | ||
| 601 | properties["ApplicationAccessChecksEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 602 | break; | ||
| 603 | case "ApplicationDirectory": | ||
| 604 | if (null == componentKey) | ||
| 605 | { | ||
| 606 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 607 | } | ||
| 608 | properties["ApplicationDirectory"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 609 | break; | ||
| 610 | case "Authentication": | ||
| 611 | if (null == componentKey) | ||
| 612 | { | ||
| 613 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 614 | } | ||
| 615 | string authenticationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 616 | switch (authenticationValue) | ||
| 617 | { | ||
| 618 | case "default": | ||
| 619 | properties["Authentication"] = "0"; | ||
| 620 | break; | ||
| 621 | case "none": | ||
| 622 | properties["Authentication"] = "1"; | ||
| 623 | break; | ||
| 624 | case "connect": | ||
| 625 | properties["Authentication"] = "2"; | ||
| 626 | break; | ||
| 627 | case "call": | ||
| 628 | properties["Authentication"] = "3"; | ||
| 629 | break; | ||
| 630 | case "packet": | ||
| 631 | properties["Authentication"] = "4"; | ||
| 632 | break; | ||
| 633 | case "integrity": | ||
| 634 | properties["Authentication"] = "5"; | ||
| 635 | break; | ||
| 636 | case "privacy": | ||
| 637 | properties["Authentication"] = "6"; | ||
| 638 | break; | ||
| 639 | default: | ||
| 640 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "Authentication", authenticationValue, "default", "none", "connect", "call", "packet", "integrity", "privacy")); | ||
| 641 | break; | ||
| 642 | } | ||
| 643 | break; | ||
| 644 | case "AuthenticationCapability": | ||
| 645 | if (null == componentKey) | ||
| 646 | { | ||
| 647 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 648 | } | ||
| 649 | string authenticationCapabilityValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 650 | switch (authenticationCapabilityValue) | ||
| 651 | { | ||
| 652 | case "none": | ||
| 653 | properties["AuthenticationCapability"] = "0"; | ||
| 654 | break; | ||
| 655 | case "secureReference": | ||
| 656 | properties["AuthenticationCapability"] = "2"; | ||
| 657 | break; | ||
| 658 | case "staticCloaking": | ||
| 659 | properties["AuthenticationCapability"] = "32"; | ||
| 660 | break; | ||
| 661 | case "dynamicCloaking": | ||
| 662 | properties["AuthenticationCapability"] = "64"; | ||
| 663 | break; | ||
| 664 | default: | ||
| 665 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "AuthenticationCapability", authenticationCapabilityValue, "none", "secureReference", "staticCloaking", "dynamicCloaking")); | ||
| 666 | break; | ||
| 667 | } | ||
| 668 | break; | ||
| 669 | case "Changeable": | ||
| 670 | this.Core.OnMessage(WixWarnings.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 671 | break; | ||
| 672 | case "CommandLine": | ||
| 673 | if (null == componentKey) | ||
| 674 | { | ||
| 675 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 676 | } | ||
| 677 | properties["CommandLine"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 678 | break; | ||
| 679 | case "ConcurrentApps": | ||
| 680 | if (null == componentKey) | ||
| 681 | { | ||
| 682 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 683 | } | ||
| 684 | properties["ConcurrentApps"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 685 | break; | ||
| 686 | case "CreatedBy": | ||
| 687 | if (null == componentKey) | ||
| 688 | { | ||
| 689 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 690 | } | ||
| 691 | properties["CreatedBy"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 692 | break; | ||
| 693 | case "CRMEnabled": | ||
| 694 | if (null == componentKey) | ||
| 695 | { | ||
| 696 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 697 | } | ||
| 698 | properties["CRMEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 699 | break; | ||
| 700 | case "CRMLogFile": | ||
| 701 | if (null == componentKey) | ||
| 702 | { | ||
| 703 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 704 | } | ||
| 705 | properties["CRMLogFile"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 706 | break; | ||
| 707 | case "Deleteable": | ||
| 708 | if (null == componentKey) | ||
| 709 | { | ||
| 710 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 711 | } | ||
| 712 | properties["Deleteable"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 713 | break; | ||
| 714 | case "Description": | ||
| 715 | if (null == componentKey) | ||
| 716 | { | ||
| 717 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 718 | } | ||
| 719 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 720 | break; | ||
| 721 | case "DumpEnabled": | ||
| 722 | if (null == componentKey) | ||
| 723 | { | ||
| 724 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 725 | } | ||
| 726 | properties["DumpEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 727 | break; | ||
| 728 | case "DumpOnException": | ||
| 729 | if (null == componentKey) | ||
| 730 | { | ||
| 731 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 732 | } | ||
| 733 | properties["DumpOnException"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 734 | break; | ||
| 735 | case "DumpOnFailfast": | ||
| 736 | if (null == componentKey) | ||
| 737 | { | ||
| 738 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 739 | } | ||
| 740 | properties["DumpOnFailfast"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 741 | break; | ||
| 742 | case "DumpPath": | ||
| 743 | if (null == componentKey) | ||
| 744 | { | ||
| 745 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 746 | } | ||
| 747 | properties["DumpPath"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 748 | break; | ||
| 749 | case "EventsEnabled": | ||
| 750 | if (null == componentKey) | ||
| 751 | { | ||
| 752 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 753 | } | ||
| 754 | properties["EventsEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 755 | break; | ||
| 756 | case "Identity": | ||
| 757 | if (null == componentKey) | ||
| 758 | { | ||
| 759 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 760 | } | ||
| 761 | properties["Identity"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 762 | break; | ||
| 763 | case "ImpersonationLevel": | ||
| 764 | if (null == componentKey) | ||
| 765 | { | ||
| 766 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 767 | } | ||
| 768 | string impersonationLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 769 | switch (impersonationLevelValue) | ||
| 770 | { | ||
| 771 | case "anonymous": | ||
| 772 | properties["ImpersonationLevel"] = "1"; | ||
| 773 | break; | ||
| 774 | case "identify": | ||
| 775 | properties["ImpersonationLevel"] = "2"; | ||
| 776 | break; | ||
| 777 | case "impersonate": | ||
| 778 | properties["ImpersonationLevel"] = "3"; | ||
| 779 | break; | ||
| 780 | case "delegate": | ||
| 781 | properties["ImpersonationLevel"] = "4"; | ||
| 782 | break; | ||
| 783 | default: | ||
| 784 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "ImpersonationLevel", impersonationLevelValue, "anonymous", "identify", "impersonate", "delegate")); | ||
| 785 | break; | ||
| 786 | } | ||
| 787 | break; | ||
| 788 | case "IsEnabled": | ||
| 789 | if (null == componentKey) | ||
| 790 | { | ||
| 791 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 792 | } | ||
| 793 | properties["IsEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 794 | break; | ||
| 795 | case "MaxDumpCount": | ||
| 796 | if (null == componentKey) | ||
| 797 | { | ||
| 798 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 799 | } | ||
| 800 | properties["MaxDumpCount"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 801 | break; | ||
| 802 | case "Password": | ||
| 803 | if (null == componentKey) | ||
| 804 | { | ||
| 805 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 806 | } | ||
| 807 | properties["Password"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 808 | break; | ||
| 809 | case "QCAuthenticateMsgs": | ||
| 810 | if (null == componentKey) | ||
| 811 | { | ||
| 812 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 813 | } | ||
| 814 | string qcAuthenticateMsgsValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 815 | switch (qcAuthenticateMsgsValue) | ||
| 816 | { | ||
| 817 | case "secureApps": | ||
| 818 | properties["QCAuthenticateMsgs"] = "0"; | ||
| 819 | break; | ||
| 820 | case "off": | ||
| 821 | properties["QCAuthenticateMsgs"] = "1"; | ||
| 822 | break; | ||
| 823 | case "on": | ||
| 824 | properties["QCAuthenticateMsgs"] = "2"; | ||
| 825 | break; | ||
| 826 | default: | ||
| 827 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "QCAuthenticateMsgs", qcAuthenticateMsgsValue, "secureApps", "off", "on")); | ||
| 828 | break; | ||
| 829 | } | ||
| 830 | break; | ||
| 831 | case "QCListenerMaxThreads": | ||
| 832 | if (null == componentKey) | ||
| 833 | { | ||
| 834 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 835 | } | ||
| 836 | properties["QCListenerMaxThreads"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 837 | break; | ||
| 838 | case "QueueListenerEnabled": | ||
| 839 | if (null == componentKey) | ||
| 840 | { | ||
| 841 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 842 | } | ||
| 843 | properties["QueueListenerEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 844 | break; | ||
| 845 | case "QueuingEnabled": | ||
| 846 | if (null == componentKey) | ||
| 847 | { | ||
| 848 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 849 | } | ||
| 850 | properties["QueuingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 851 | break; | ||
| 852 | case "RecycleActivationLimit": | ||
| 853 | if (null == componentKey) | ||
| 854 | { | ||
| 855 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 856 | } | ||
| 857 | properties["RecycleActivationLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 858 | break; | ||
| 859 | case "RecycleCallLimit": | ||
| 860 | if (null == componentKey) | ||
| 861 | { | ||
| 862 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 863 | } | ||
| 864 | properties["RecycleCallLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 865 | break; | ||
| 866 | case "RecycleExpirationTimeout": | ||
| 867 | if (null == componentKey) | ||
| 868 | { | ||
| 869 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 870 | } | ||
| 871 | properties["RecycleExpirationTimeout"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 872 | break; | ||
| 873 | case "RecycleLifetimeLimit": | ||
| 874 | if (null == componentKey) | ||
| 875 | { | ||
| 876 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 877 | } | ||
| 878 | properties["RecycleLifetimeLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 879 | break; | ||
| 880 | case "RecycleMemoryLimit": | ||
| 881 | if (null == componentKey) | ||
| 882 | { | ||
| 883 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 884 | } | ||
| 885 | properties["RecycleMemoryLimit"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 886 | break; | ||
| 887 | case "Replicable": | ||
| 888 | if (null == componentKey) | ||
| 889 | { | ||
| 890 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 891 | } | ||
| 892 | properties["Replicable"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 893 | break; | ||
| 894 | case "RunForever": | ||
| 895 | if (null == componentKey) | ||
| 896 | { | ||
| 897 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 898 | } | ||
| 899 | properties["RunForever"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 900 | break; | ||
| 901 | case "ShutdownAfter": | ||
| 902 | if (null == componentKey) | ||
| 903 | { | ||
| 904 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 905 | } | ||
| 906 | properties["ShutdownAfter"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 907 | break; | ||
| 908 | case "SoapActivated": | ||
| 909 | if (null == componentKey) | ||
| 910 | { | ||
| 911 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 912 | } | ||
| 913 | properties["SoapActivated"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 914 | break; | ||
| 915 | case "SoapBaseUrl": | ||
| 916 | if (null == componentKey) | ||
| 917 | { | ||
| 918 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 919 | } | ||
| 920 | properties["SoapBaseUrl"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 921 | break; | ||
| 922 | case "SoapMailTo": | ||
| 923 | if (null == componentKey) | ||
| 924 | { | ||
| 925 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 926 | } | ||
| 927 | properties["SoapMailTo"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 928 | break; | ||
| 929 | case "SoapVRoot": | ||
| 930 | if (null == componentKey) | ||
| 931 | { | ||
| 932 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 933 | } | ||
| 934 | properties["SoapVRoot"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 935 | break; | ||
| 936 | case "SRPEnabled": | ||
| 937 | if (null == componentKey) | ||
| 938 | { | ||
| 939 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 940 | } | ||
| 941 | properties["SRPEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 942 | break; | ||
| 943 | case "SRPTrustLevel": | ||
| 944 | if (null == componentKey) | ||
| 945 | { | ||
| 946 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 947 | } | ||
| 948 | string srpTrustLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 949 | switch (srpTrustLevelValue) | ||
| 950 | { | ||
| 951 | case "disallowed": | ||
| 952 | properties["SRPTrustLevel"] = "0"; | ||
| 953 | break; | ||
| 954 | case "fullyTrusted": | ||
| 955 | properties["SRPTrustLevel"] = "262144"; | ||
| 956 | break; | ||
| 957 | default: | ||
| 958 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusApplication", "SRPTrustLevel", srpTrustLevelValue, "disallowed", "fullyTrusted")); | ||
| 959 | break; | ||
| 960 | } | ||
| 961 | break; | ||
| 962 | default: | ||
| 963 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 964 | break; | ||
| 965 | } | ||
| 966 | } | ||
| 967 | else | ||
| 968 | { | ||
| 969 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 970 | } | ||
| 971 | } | ||
| 972 | |||
| 973 | if (null != componentKey && null == name) | ||
| 974 | { | ||
| 975 | this.Core.OnMessage(ComPlusErrors.RequiredAttributeUnderComponent(sourceLineNumbers, node.Name.LocalName, "Name")); | ||
| 976 | } | ||
| 977 | if (null == componentKey && null == id && null == name) | ||
| 978 | { | ||
| 979 | this.Core.OnMessage(ComPlusErrors.RequiredAttributeNotUnderComponent(sourceLineNumbers, node.Name.LocalName, "Id", "Name")); | ||
| 980 | } | ||
| 981 | |||
| 982 | foreach (XElement child in node.Elements()) | ||
| 983 | { | ||
| 984 | if (this.Namespace == child.Name.Namespace) | ||
| 985 | { | ||
| 986 | switch (child.Name.LocalName) | ||
| 987 | { | ||
| 988 | case "ComPlusApplicationRole": | ||
| 989 | this.ParseComPlusApplicationRoleElement(child, componentKey, key); | ||
| 990 | break; | ||
| 991 | case "ComPlusAssembly": | ||
| 992 | this.ParseComPlusAssemblyElement(child, componentKey, win64, key); | ||
| 993 | break; | ||
| 994 | default: | ||
| 995 | this.Core.UnexpectedElement(node, child); | ||
| 996 | break; | ||
| 997 | } | ||
| 998 | } | ||
| 999 | else | ||
| 1000 | { | ||
| 1001 | this.Core.ParseExtensionElement(node, child); | ||
| 1002 | } | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplication"); | ||
| 1006 | row[0] = key; | ||
| 1007 | row[1] = partitionKey; | ||
| 1008 | row[2] = componentKey; | ||
| 1009 | row[3] = id; | ||
| 1010 | row[4] = name; | ||
| 1011 | |||
| 1012 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
| 1013 | while (propertiesEnumerator.MoveNext()) | ||
| 1014 | { | ||
| 1015 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplicationProperty"); | ||
| 1016 | propertyRow[0] = key; | ||
| 1017 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
| 1018 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | if (componentKey != null) | ||
| 1022 | { | ||
| 1023 | if (win64) | ||
| 1024 | { | ||
| 1025 | if (this.Core.CurrentPlatform == Platform.IA64) | ||
| 1026 | { | ||
| 1027 | this.Core.OnMessage(WixErrors.UnsupportedPlatformForElement(sourceLineNumbers, "ia64", node.Name.LocalName)); | ||
| 1028 | } | ||
| 1029 | else | ||
| 1030 | { | ||
| 1031 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall_x64"); | ||
| 1032 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall_x64"); | ||
| 1033 | } | ||
| 1034 | } | ||
| 1035 | else | ||
| 1036 | { | ||
| 1037 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall"); | ||
| 1038 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall"); | ||
| 1039 | } | ||
| 1040 | } | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | /// <summary> | ||
| 1044 | /// Parses a COM+ application role element. | ||
| 1045 | /// </summary> | ||
| 1046 | /// <param name="node">Element to parse.</param> | ||
| 1047 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 1048 | /// <param name="applicationKey">Optional identifier of parent application.</param> | ||
| 1049 | private void ParseComPlusApplicationRoleElement(XElement node, string componentKey, string applicationKey) | ||
| 1050 | { | ||
| 1051 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 1052 | |||
| 1053 | string key = null; | ||
| 1054 | string name = null; | ||
| 1055 | |||
| 1056 | Hashtable properties = new Hashtable(); | ||
| 1057 | |||
| 1058 | foreach (XAttribute attrib in node.Attributes()) | ||
| 1059 | { | ||
| 1060 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1061 | { | ||
| 1062 | switch (attrib.Name.LocalName) | ||
| 1063 | { | ||
| 1064 | case "Id": | ||
| 1065 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1066 | break; | ||
| 1067 | case "Application": | ||
| 1068 | if (null != applicationKey) | ||
| 1069 | { | ||
| 1070 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 1071 | } | ||
| 1072 | applicationKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1073 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplication", applicationKey); | ||
| 1074 | break; | ||
| 1075 | case "Name": | ||
| 1076 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1077 | break; | ||
| 1078 | case "Description": | ||
| 1079 | if (null == componentKey) | ||
| 1080 | { | ||
| 1081 | this.Core.OnMessage(ComPlusErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
| 1082 | } | ||
| 1083 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1084 | break; | ||
| 1085 | default: | ||
| 1086 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 1087 | break; | ||
| 1088 | } | ||
| 1089 | } | ||
| 1090 | else | ||
| 1091 | { | ||
| 1092 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 1093 | } | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | if (null == applicationKey) | ||
| 1097 | { | ||
| 1098 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Application")); | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | foreach (XElement child in node.Elements()) | ||
| 1102 | { | ||
| 1103 | if (this.Namespace == child.Name.Namespace) | ||
| 1104 | { | ||
| 1105 | switch (child.Name.LocalName) | ||
| 1106 | { | ||
| 1107 | case "ComPlusUserInApplicationRole": | ||
| 1108 | this.ParseComPlusUserInApplicationRoleElement(child, componentKey, key); | ||
| 1109 | break; | ||
| 1110 | case "ComPlusGroupInApplicationRole": | ||
| 1111 | this.ParseComPlusGroupInApplicationRoleElement(child, componentKey, key); | ||
| 1112 | break; | ||
| 1113 | default: | ||
| 1114 | this.Core.UnexpectedElement(node, child); | ||
| 1115 | break; | ||
| 1116 | } | ||
| 1117 | } | ||
| 1118 | else | ||
| 1119 | { | ||
| 1120 | this.Core.ParseExtensionElement(node, child); | ||
| 1121 | } | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplicationRole"); | ||
| 1125 | row[0] = key; | ||
| 1126 | row[1] = applicationKey; | ||
| 1127 | row[2] = componentKey; | ||
| 1128 | row[3] = name; | ||
| 1129 | |||
| 1130 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
| 1131 | while (propertiesEnumerator.MoveNext()) | ||
| 1132 | { | ||
| 1133 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusApplicationRoleProperty"); | ||
| 1134 | propertyRow[0] = key; | ||
| 1135 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
| 1136 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
| 1137 | } | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | /// <summary> | ||
| 1141 | /// Parses a COM+ application role user element. | ||
| 1142 | /// </summary> | ||
| 1143 | /// <param name="node">Element to parse.</param> | ||
| 1144 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 1145 | /// <param name="applicationKey">Optional identifier of parent application role.</param> | ||
| 1146 | private void ParseComPlusUserInApplicationRoleElement(XElement node, string componentKey, string applicationRoleKey) | ||
| 1147 | { | ||
| 1148 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 1149 | |||
| 1150 | string key = null; | ||
| 1151 | string user = null; | ||
| 1152 | |||
| 1153 | foreach (XAttribute attrib in node.Attributes()) | ||
| 1154 | { | ||
| 1155 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1156 | { | ||
| 1157 | switch (attrib.Name.LocalName) | ||
| 1158 | { | ||
| 1159 | case "Id": | ||
| 1160 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1161 | break; | ||
| 1162 | case "ApplicationRole": | ||
| 1163 | if (null != applicationRoleKey) | ||
| 1164 | { | ||
| 1165 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 1166 | } | ||
| 1167 | applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1168 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplicationRole", applicationRoleKey); | ||
| 1169 | break; | ||
| 1170 | case "User": | ||
| 1171 | user = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1172 | this.Core.CreateSimpleReference(sourceLineNumbers, "User", user); | ||
| 1173 | break; | ||
| 1174 | default: | ||
| 1175 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 1176 | break; | ||
| 1177 | } | ||
| 1178 | } | ||
| 1179 | else | ||
| 1180 | { | ||
| 1181 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 1182 | } | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | if (null == applicationRoleKey) | ||
| 1186 | { | ||
| 1187 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ApplicationRole")); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusUserInApplicationRole"); | ||
| 1191 | row[0] = key; | ||
| 1192 | row[1] = applicationRoleKey; | ||
| 1193 | row[2] = componentKey; | ||
| 1194 | row[3] = user; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | /// <summary> | ||
| 1198 | /// Parses a COM+ application role group element. | ||
| 1199 | /// </summary> | ||
| 1200 | /// <param name="node">Element to parse.</param> | ||
| 1201 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 1202 | /// <param name="applicationKey">Optional identifier of parent application role.</param> | ||
| 1203 | private void ParseComPlusGroupInApplicationRoleElement(XElement node, string componentKey, string applicationRoleKey) | ||
| 1204 | { | ||
| 1205 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 1206 | |||
| 1207 | string key = null; | ||
| 1208 | string group = null; | ||
| 1209 | |||
| 1210 | foreach (XAttribute attrib in node.Attributes()) | ||
| 1211 | { | ||
| 1212 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1213 | { | ||
| 1214 | switch (attrib.Name.LocalName) | ||
| 1215 | { | ||
| 1216 | case "Id": | ||
| 1217 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1218 | break; | ||
| 1219 | case "ApplicationRole": | ||
| 1220 | if (null != applicationRoleKey) | ||
| 1221 | { | ||
| 1222 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 1223 | } | ||
| 1224 | applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1225 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplicationRole", applicationRoleKey); | ||
| 1226 | break; | ||
| 1227 | case "Group": | ||
| 1228 | group = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1229 | this.Core.CreateSimpleReference(sourceLineNumbers, "Group", group); | ||
| 1230 | break; | ||
| 1231 | default: | ||
| 1232 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 1233 | break; | ||
| 1234 | } | ||
| 1235 | } | ||
| 1236 | else | ||
| 1237 | { | ||
| 1238 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 1239 | } | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | if (null == applicationRoleKey) | ||
| 1243 | { | ||
| 1244 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ApplicationRole")); | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusGroupInApplicationRole"); | ||
| 1248 | row[0] = key; | ||
| 1249 | row[1] = applicationRoleKey; | ||
| 1250 | row[2] = componentKey; | ||
| 1251 | row[3] = group; | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | /// <summary> | ||
| 1255 | /// Parses a COM+ assembly element. | ||
| 1256 | /// </summary> | ||
| 1257 | /// <param name="node">Element to parse.</param> | ||
| 1258 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 1259 | /// <param name="applicationKey">Optional identifier of parent application.</param> | ||
| 1260 | private void ParseComPlusAssemblyElement(XElement node, string componentKey, bool win64, string applicationKey) | ||
| 1261 | { | ||
| 1262 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 1263 | |||
| 1264 | string key = null; | ||
| 1265 | string assemblyName = null; | ||
| 1266 | string dllPath = null; | ||
| 1267 | string tlbPath = null; | ||
| 1268 | string psDllPath = null; | ||
| 1269 | int attributes = 0; | ||
| 1270 | |||
| 1271 | bool hasComponents = false; | ||
| 1272 | |||
| 1273 | foreach (XAttribute attrib in node.Attributes()) | ||
| 1274 | { | ||
| 1275 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1276 | { | ||
| 1277 | switch (attrib.Name.LocalName) | ||
| 1278 | { | ||
| 1279 | case "Id": | ||
| 1280 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1281 | break; | ||
| 1282 | case "Application": | ||
| 1283 | if (null != applicationKey) | ||
| 1284 | { | ||
| 1285 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 1286 | } | ||
| 1287 | applicationKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1288 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusApplication", applicationKey); | ||
| 1289 | break; | ||
| 1290 | case "AssemblyName": | ||
| 1291 | assemblyName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1292 | break; | ||
| 1293 | case "DllPath": | ||
| 1294 | dllPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1295 | break; | ||
| 1296 | case "TlbPath": | ||
| 1297 | tlbPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1298 | break; | ||
| 1299 | case "PSDllPath": | ||
| 1300 | psDllPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1301 | break; | ||
| 1302 | case "Type": | ||
| 1303 | string typeValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1304 | switch (typeValue) | ||
| 1305 | { | ||
| 1306 | case ".net": | ||
| 1307 | attributes |= (int)CpiAssemblyAttributes.DotNetAssembly; | ||
| 1308 | break; | ||
| 1309 | case "native": | ||
| 1310 | attributes &= ~(int)CpiAssemblyAttributes.DotNetAssembly; | ||
| 1311 | break; | ||
| 1312 | default: | ||
| 1313 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusAssembly", "Type", typeValue, ".net", "native")); | ||
| 1314 | break; | ||
| 1315 | } | ||
| 1316 | break; | ||
| 1317 | case "EventClass": | ||
| 1318 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1319 | { | ||
| 1320 | attributes |= (int)CpiAssemblyAttributes.EventClass; | ||
| 1321 | } | ||
| 1322 | else | ||
| 1323 | { | ||
| 1324 | attributes &= ~(int)CpiAssemblyAttributes.EventClass; | ||
| 1325 | } | ||
| 1326 | break; | ||
| 1327 | case "DllPathFromGAC": | ||
| 1328 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1329 | { | ||
| 1330 | attributes |= (int)CpiAssemblyAttributes.DllPathFromGAC; | ||
| 1331 | } | ||
| 1332 | else | ||
| 1333 | { | ||
| 1334 | attributes &= ~(int)CpiAssemblyAttributes.DllPathFromGAC; | ||
| 1335 | } | ||
| 1336 | break; | ||
| 1337 | case "RegisterInCommit": | ||
| 1338 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
| 1339 | { | ||
| 1340 | attributes |= (int)CpiAssemblyAttributes.RegisterInCommit; | ||
| 1341 | } | ||
| 1342 | else | ||
| 1343 | { | ||
| 1344 | attributes &= ~(int)CpiAssemblyAttributes.RegisterInCommit; | ||
| 1345 | } | ||
| 1346 | break; | ||
| 1347 | default: | ||
| 1348 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 1349 | break; | ||
| 1350 | } | ||
| 1351 | } | ||
| 1352 | else | ||
| 1353 | { | ||
| 1354 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 1355 | } | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | if (null == applicationKey && 0 == (attributes & (int)CpiAssemblyAttributes.DotNetAssembly)) | ||
| 1359 | { | ||
| 1360 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Application", "Type", "native")); | ||
| 1361 | } | ||
| 1362 | if (null != assemblyName && 0 == (attributes & (int)CpiAssemblyAttributes.DllPathFromGAC)) | ||
| 1363 | { | ||
| 1364 | this.Core.OnMessage(ComPlusErrors.UnexpectedAttributeWithoutOtherValue(sourceLineNumbers, node.Name.LocalName, "AssemblyName", "DllPathFromGAC", "no")); | ||
| 1365 | } | ||
| 1366 | if (null == tlbPath && 0 != (attributes & (int)CpiAssemblyAttributes.DotNetAssembly)) | ||
| 1367 | { | ||
| 1368 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "TlbPath", "Type", ".net")); | ||
| 1369 | } | ||
| 1370 | if (null != psDllPath && 0 != (attributes & (int)CpiAssemblyAttributes.DotNetAssembly)) | ||
| 1371 | { | ||
| 1372 | this.Core.OnMessage(ComPlusErrors.UnexpectedAttributeWithOtherValue(sourceLineNumbers, node.Name.LocalName, "PSDllPath", "Type", ".net")); | ||
| 1373 | } | ||
| 1374 | if (0 != (attributes & (int)CpiAssemblyAttributes.EventClass) && 0 != (attributes & (int)CpiAssemblyAttributes.DotNetAssembly)) | ||
| 1375 | { | ||
| 1376 | this.Core.OnMessage(ComPlusErrors.UnexpectedAttributeWithOtherValue(sourceLineNumbers, node.Name.LocalName, "EventClass", "yes", "Type", ".net")); | ||
| 1377 | } | ||
| 1378 | |||
| 1379 | foreach (XElement child in node.Elements()) | ||
| 1380 | { | ||
| 1381 | if (this.Namespace == child.Name.Namespace) | ||
| 1382 | { | ||
| 1383 | switch (child.Name.LocalName) | ||
| 1384 | { | ||
| 1385 | case "ComPlusAssemblyDependency": | ||
| 1386 | this.ParseComPlusAssemblyDependencyElement(child, key); | ||
| 1387 | break; | ||
| 1388 | case "ComPlusComponent": | ||
| 1389 | this.ParseComPlusComponentElement(child, componentKey, key); | ||
| 1390 | hasComponents = true; | ||
| 1391 | break; | ||
| 1392 | default: | ||
| 1393 | this.Core.UnexpectedElement(node, child); | ||
| 1394 | break; | ||
| 1395 | } | ||
| 1396 | } | ||
| 1397 | else | ||
| 1398 | { | ||
| 1399 | this.Core.ParseExtensionElement(node, child); | ||
| 1400 | } | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | if (0 == (attributes & (int)CpiAssemblyAttributes.DotNetAssembly) && !hasComponents) | ||
| 1404 | { | ||
| 1405 | this.Core.OnMessage(ComPlusWarnings.MissingComponents(sourceLineNumbers)); | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusAssembly"); | ||
| 1409 | row[0] = key; | ||
| 1410 | row[1] = applicationKey; | ||
| 1411 | row[2] = componentKey; | ||
| 1412 | row[3] = assemblyName; | ||
| 1413 | row[4] = dllPath; | ||
| 1414 | row[5] = tlbPath; | ||
| 1415 | row[6] = psDllPath; | ||
| 1416 | row[7] = attributes; | ||
| 1417 | |||
| 1418 | if (win64) | ||
| 1419 | { | ||
| 1420 | if (this.Core.CurrentPlatform == Platform.IA64) | ||
| 1421 | { | ||
| 1422 | this.Core.OnMessage(WixErrors.UnsupportedPlatformForElement(sourceLineNumbers, "ia64", node.Name.LocalName)); | ||
| 1423 | } | ||
| 1424 | else | ||
| 1425 | { | ||
| 1426 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall_x64"); | ||
| 1427 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall_x64"); | ||
| 1428 | } | ||
| 1429 | } | ||
| 1430 | else | ||
| 1431 | { | ||
| 1432 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusInstall"); | ||
| 1433 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "ConfigureComPlusUninstall"); | ||
| 1434 | } | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | /// <summary> | ||
| 1438 | /// Parses a COM+ assembly dependency element. | ||
| 1439 | /// </summary> | ||
| 1440 | /// <param name="node">Element to parse.</param> | ||
| 1441 | /// <param name="assemblyKey">Identifier of parent assembly.</param> | ||
| 1442 | private void ParseComPlusAssemblyDependencyElement(XElement node, string assemblyKey) | ||
| 1443 | { | ||
| 1444 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 1445 | |||
| 1446 | string requiredAssemblyKey = null; | ||
| 1447 | |||
| 1448 | foreach (XAttribute attrib in node.Attributes()) | ||
| 1449 | { | ||
| 1450 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1451 | { | ||
| 1452 | switch (attrib.Name.LocalName) | ||
| 1453 | { | ||
| 1454 | case "RequiredAssembly": | ||
| 1455 | requiredAssemblyKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1456 | break; | ||
| 1457 | default: | ||
| 1458 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 1459 | break; | ||
| 1460 | } | ||
| 1461 | } | ||
| 1462 | else | ||
| 1463 | { | ||
| 1464 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 1465 | } | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusAssemblyDependency"); | ||
| 1469 | row[0] = assemblyKey; | ||
| 1470 | row[1] = requiredAssemblyKey; | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | /// <summary> | ||
| 1474 | /// Parses a COM+ component element. | ||
| 1475 | /// </summary> | ||
| 1476 | /// <param name="node">Element to parse.</param> | ||
| 1477 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 1478 | /// <param name="assemblyKey">Identifier of parent assembly.</param> | ||
| 1479 | private void ParseComPlusComponentElement(XElement node, string componentKey, string assemblyKey) | ||
| 1480 | { | ||
| 1481 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 1482 | |||
| 1483 | string key = null; | ||
| 1484 | string clsid = null; | ||
| 1485 | |||
| 1486 | Hashtable properties = new Hashtable(); | ||
| 1487 | |||
| 1488 | foreach (XAttribute attrib in node.Attributes()) | ||
| 1489 | { | ||
| 1490 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1491 | { | ||
| 1492 | switch (attrib.Name.LocalName) | ||
| 1493 | { | ||
| 1494 | case "Id": | ||
| 1495 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1496 | break; | ||
| 1497 | case "CLSID": | ||
| 1498 | clsid = "{" + this.Core.GetAttributeValue(sourceLineNumbers, attrib) + "}"; | ||
| 1499 | break; | ||
| 1500 | case "AllowInprocSubscribers": | ||
| 1501 | properties["AllowInprocSubscribers"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1502 | break; | ||
| 1503 | case "ComponentAccessChecksEnabled": | ||
| 1504 | properties["ComponentAccessChecksEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1505 | break; | ||
| 1506 | case "ComponentTransactionTimeout": | ||
| 1507 | properties["ComponentTransactionTimeout"] = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 3600).ToString(); | ||
| 1508 | break; | ||
| 1509 | case "ComponentTransactionTimeoutEnabled": | ||
| 1510 | properties["ComponentTransactionTimeoutEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1511 | break; | ||
| 1512 | case "COMTIIntrinsics": | ||
| 1513 | properties["COMTIIntrinsics"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1514 | break; | ||
| 1515 | case "ConstructionEnabled": | ||
| 1516 | properties["ConstructionEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1517 | break; | ||
| 1518 | case "ConstructorString": | ||
| 1519 | properties["ConstructorString"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1520 | break; | ||
| 1521 | case "CreationTimeout": | ||
| 1522 | properties["CreationTimeout"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1523 | break; | ||
| 1524 | case "Description": | ||
| 1525 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1526 | break; | ||
| 1527 | case "EventTrackingEnabled": | ||
| 1528 | properties["EventTrackingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1529 | break; | ||
| 1530 | case "ExceptionClass": | ||
| 1531 | properties["ExceptionClass"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1532 | break; | ||
| 1533 | case "FireInParallel": | ||
| 1534 | properties["FireInParallel"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1535 | break; | ||
| 1536 | case "IISIntrinsics": | ||
| 1537 | properties["IISIntrinsics"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1538 | break; | ||
| 1539 | case "InitializesServerApplication": | ||
| 1540 | properties["InitializesServerApplication"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1541 | break; | ||
| 1542 | case "IsEnabled": | ||
| 1543 | properties["IsEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1544 | break; | ||
| 1545 | case "IsPrivateComponent": | ||
| 1546 | properties["IsPrivateComponent"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1547 | break; | ||
| 1548 | case "JustInTimeActivation": | ||
| 1549 | properties["JustInTimeActivation"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1550 | break; | ||
| 1551 | case "LoadBalancingSupported": | ||
| 1552 | properties["LoadBalancingSupported"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1553 | break; | ||
| 1554 | case "MaxPoolSize": | ||
| 1555 | properties["MaxPoolSize"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1556 | break; | ||
| 1557 | case "MinPoolSize": | ||
| 1558 | properties["MinPoolSize"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1559 | break; | ||
| 1560 | case "MultiInterfacePublisherFilterCLSID": | ||
| 1561 | properties["MultiInterfacePublisherFilterCLSID"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1562 | break; | ||
| 1563 | case "MustRunInClientContext": | ||
| 1564 | properties["MustRunInClientContext"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1565 | break; | ||
| 1566 | case "MustRunInDefaultContext": | ||
| 1567 | properties["MustRunInDefaultContext"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1568 | break; | ||
| 1569 | case "ObjectPoolingEnabled": | ||
| 1570 | properties["ObjectPoolingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1571 | break; | ||
| 1572 | case "PublisherID": | ||
| 1573 | properties["PublisherID"] = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
| 1574 | break; | ||
| 1575 | case "SoapAssemblyName": | ||
| 1576 | properties["SoapAssemblyName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1577 | break; | ||
| 1578 | case "SoapTypeName": | ||
| 1579 | properties["SoapTypeName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1580 | break; | ||
| 1581 | case "Synchronization": | ||
| 1582 | string synchronizationValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1583 | switch (synchronizationValue) | ||
| 1584 | { | ||
| 1585 | case "ignored": | ||
| 1586 | properties["Synchronization"] = "0"; | ||
| 1587 | break; | ||
| 1588 | case "none": | ||
| 1589 | properties["Synchronization"] = "1"; | ||
| 1590 | break; | ||
| 1591 | case "supported": | ||
| 1592 | properties["Synchronization"] = "2"; | ||
| 1593 | break; | ||
| 1594 | case "required": | ||
| 1595 | properties["Synchronization"] = "3"; | ||
| 1596 | break; | ||
| 1597 | case "requiresNew": | ||
| 1598 | properties["Synchronization"] = "4"; | ||
| 1599 | break; | ||
| 1600 | default: | ||
| 1601 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusComponent", "Synchronization", synchronizationValue, "ignored", "none", "supported", "required", "requiresNew")); | ||
| 1602 | break; | ||
| 1603 | } | ||
| 1604 | break; | ||
| 1605 | case "Transaction": | ||
| 1606 | string transactionValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1607 | switch (transactionValue) | ||
| 1608 | { | ||
| 1609 | case "ignored": | ||
| 1610 | properties["Transaction"] = "0"; | ||
| 1611 | break; | ||
| 1612 | case "none": | ||
| 1613 | properties["Transaction"] = "1"; | ||
| 1614 | break; | ||
| 1615 | case "supported": | ||
| 1616 | properties["Transaction"] = "2"; | ||
| 1617 | break; | ||
| 1618 | case "required": | ||
| 1619 | properties["Transaction"] = "3"; | ||
| 1620 | break; | ||
| 1621 | case "requiresNew": | ||
| 1622 | properties["Transaction"] = "4"; | ||
| 1623 | break; | ||
| 1624 | default: | ||
| 1625 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusComponent", "Transaction", transactionValue, "ignored", "none", "supported", "required", "requiresNew")); | ||
| 1626 | break; | ||
| 1627 | } | ||
| 1628 | break; | ||
| 1629 | case "TxIsolationLevel": | ||
| 1630 | string txIsolationLevelValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1631 | switch (txIsolationLevelValue) | ||
| 1632 | { | ||
| 1633 | case "any": | ||
| 1634 | properties["TxIsolationLevel"] = "0"; | ||
| 1635 | break; | ||
| 1636 | case "readUnCommitted": | ||
| 1637 | properties["TxIsolationLevel"] = "1"; | ||
| 1638 | break; | ||
| 1639 | case "readCommitted": | ||
| 1640 | properties["TxIsolationLevel"] = "2"; | ||
| 1641 | break; | ||
| 1642 | case "repeatableRead": | ||
| 1643 | properties["TxIsolationLevel"] = "3"; | ||
| 1644 | break; | ||
| 1645 | case "serializable": | ||
| 1646 | properties["TxIsolationLevel"] = "4"; | ||
| 1647 | break; | ||
| 1648 | default: | ||
| 1649 | this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "ComPlusComponent", "TxIsolationLevel", txIsolationLevelValue, "any", "readUnCommitted", "readCommitted", "repeatableRead", "serializable")); | ||
| 1650 | break; | ||
| 1651 | } | ||
| 1652 | break; | ||
| 1653 | default: | ||
| 1654 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 1655 | break; | ||
| 1656 | } | ||
| 1657 | } | ||
| 1658 | else | ||
| 1659 | { | ||
| 1660 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 1661 | } | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | foreach (XElement child in node.Elements()) | ||
| 1665 | { | ||
| 1666 | if (this.Namespace == child.Name.Namespace) | ||
| 1667 | { | ||
| 1668 | switch (child.Name.LocalName) | ||
| 1669 | { | ||
| 1670 | case "ComPlusRoleForComponent": | ||
| 1671 | this.ParseComPlusRoleForComponentElement(child, componentKey, key); | ||
| 1672 | break; | ||
| 1673 | case "ComPlusInterface": | ||
| 1674 | this.ParseComPlusInterfaceElement(child, componentKey, key); | ||
| 1675 | break; | ||
| 1676 | case "ComPlusSubscription": | ||
| 1677 | this.ParseComPlusSubscriptionElement(child, componentKey, key); | ||
| 1678 | break; | ||
| 1679 | default: | ||
| 1680 | this.Core.UnexpectedElement(node, child); | ||
| 1681 | break; | ||
| 1682 | } | ||
| 1683 | } | ||
| 1684 | else | ||
| 1685 | { | ||
| 1686 | this.Core.ParseExtensionElement(node, child); | ||
| 1687 | } | ||
| 1688 | } | ||
| 1689 | |||
| 1690 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusComponent"); | ||
| 1691 | row[0] = key; | ||
| 1692 | row[1] = assemblyKey; | ||
| 1693 | row[2] = clsid; | ||
| 1694 | |||
| 1695 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
| 1696 | while (propertiesEnumerator.MoveNext()) | ||
| 1697 | { | ||
| 1698 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusComponentProperty"); | ||
| 1699 | propertyRow[0] = key; | ||
| 1700 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
| 1701 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
| 1702 | } | ||
| 1703 | } | ||
| 1704 | |||
| 1705 | /// <summary> | ||
| 1706 | /// Parses a COM+ application role for component element. | ||
| 1707 | /// </summary> | ||
| 1708 | /// <param name="node">Element to parse.</param> | ||
| 1709 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 1710 | /// <param name="cpcomponentKey">Identifier of parent COM+ component.</param> | ||
| 1711 | private void ParseComPlusRoleForComponentElement(XElement node, string componentKey, string cpcomponentKey) | ||
| 1712 | { | ||
| 1713 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 1714 | |||
| 1715 | string key = null; | ||
| 1716 | string applicationRoleKey = null; | ||
| 1717 | |||
| 1718 | foreach (XAttribute attrib in node.Attributes()) | ||
| 1719 | { | ||
| 1720 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1721 | { | ||
| 1722 | switch (attrib.Name.LocalName) | ||
| 1723 | { | ||
| 1724 | case "Id": | ||
| 1725 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1726 | break; | ||
| 1727 | case "Component": | ||
| 1728 | if (null != cpcomponentKey) | ||
| 1729 | { | ||
| 1730 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 1731 | } | ||
| 1732 | cpcomponentKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1733 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusComponent", cpcomponentKey); | ||
| 1734 | break; | ||
| 1735 | case "ApplicationRole": | ||
| 1736 | applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1737 | break; | ||
| 1738 | default: | ||
| 1739 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 1740 | break; | ||
| 1741 | } | ||
| 1742 | } | ||
| 1743 | else | ||
| 1744 | { | ||
| 1745 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 1746 | } | ||
| 1747 | } | ||
| 1748 | |||
| 1749 | if (null == cpcomponentKey) | ||
| 1750 | { | ||
| 1751 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Component")); | ||
| 1752 | } | ||
| 1753 | |||
| 1754 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusRoleForComponent"); | ||
| 1755 | row[0] = key; | ||
| 1756 | row[1] = cpcomponentKey; | ||
| 1757 | row[2] = applicationRoleKey; | ||
| 1758 | row[3] = componentKey; | ||
| 1759 | } | ||
| 1760 | |||
| 1761 | /// <summary> | ||
| 1762 | /// Parses a COM+ interface element. | ||
| 1763 | /// </summary> | ||
| 1764 | /// <param name="node">Element to parse.</param> | ||
| 1765 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 1766 | /// <param name="cpcomponentKey">Identifier of parent COM+ component.</param> | ||
| 1767 | private void ParseComPlusInterfaceElement(XElement node, string componentKey, string cpcomponentKey) | ||
| 1768 | { | ||
| 1769 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 1770 | |||
| 1771 | // parse attributes | ||
| 1772 | string key = null; | ||
| 1773 | string iid = null; | ||
| 1774 | |||
| 1775 | Hashtable properties = new Hashtable(); | ||
| 1776 | |||
| 1777 | foreach (XAttribute attrib in node.Attributes()) | ||
| 1778 | { | ||
| 1779 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1780 | { | ||
| 1781 | switch (attrib.Name.LocalName) | ||
| 1782 | { | ||
| 1783 | case "Id": | ||
| 1784 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1785 | break; | ||
| 1786 | case "IID": | ||
| 1787 | iid = "{" + this.Core.GetAttributeValue(sourceLineNumbers, attrib) + "}"; | ||
| 1788 | break; | ||
| 1789 | case "Description": | ||
| 1790 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1791 | break; | ||
| 1792 | case "QueuingEnabled": | ||
| 1793 | properties["QueuingEnabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1794 | break; | ||
| 1795 | default: | ||
| 1796 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 1797 | break; | ||
| 1798 | } | ||
| 1799 | } | ||
| 1800 | else | ||
| 1801 | { | ||
| 1802 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 1803 | } | ||
| 1804 | } | ||
| 1805 | |||
| 1806 | foreach (XElement child in node.Elements()) | ||
| 1807 | { | ||
| 1808 | if (this.Namespace == child.Name.Namespace) | ||
| 1809 | { | ||
| 1810 | switch (child.Name.LocalName) | ||
| 1811 | { | ||
| 1812 | case "ComPlusRoleForInterface": | ||
| 1813 | this.ParseComPlusRoleForInterfaceElement(child, componentKey, key); | ||
| 1814 | break; | ||
| 1815 | case "ComPlusMethod": | ||
| 1816 | this.ParseComPlusMethodElement(child, componentKey, key); | ||
| 1817 | break; | ||
| 1818 | default: | ||
| 1819 | this.Core.UnexpectedElement(node, child); | ||
| 1820 | break; | ||
| 1821 | } | ||
| 1822 | } | ||
| 1823 | else | ||
| 1824 | { | ||
| 1825 | this.Core.ParseExtensionElement(node, child); | ||
| 1826 | } | ||
| 1827 | } | ||
| 1828 | |||
| 1829 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusInterface"); | ||
| 1830 | row[0] = key; | ||
| 1831 | row[1] = cpcomponentKey; | ||
| 1832 | row[2] = iid; | ||
| 1833 | |||
| 1834 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
| 1835 | while (propertiesEnumerator.MoveNext()) | ||
| 1836 | { | ||
| 1837 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusInterfaceProperty"); | ||
| 1838 | propertyRow[0] = key; | ||
| 1839 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
| 1840 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
| 1841 | } | ||
| 1842 | } | ||
| 1843 | |||
| 1844 | /// <summary> | ||
| 1845 | /// Parses a COM+ application role for interface element. | ||
| 1846 | /// </summary> | ||
| 1847 | /// <param name="node">Element to parse.</param> | ||
| 1848 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 1849 | /// <param name="interfaceKey">Identifier of parent interface.</param> | ||
| 1850 | private void ParseComPlusRoleForInterfaceElement(XElement node, string componentKey, string interfaceKey) | ||
| 1851 | { | ||
| 1852 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 1853 | |||
| 1854 | string key = null; | ||
| 1855 | string applicationRoleKey = null; | ||
| 1856 | |||
| 1857 | foreach (XAttribute attrib in node.Attributes()) | ||
| 1858 | { | ||
| 1859 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1860 | { | ||
| 1861 | switch (attrib.Name.LocalName) | ||
| 1862 | { | ||
| 1863 | case "Id": | ||
| 1864 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1865 | break; | ||
| 1866 | case "Interface": | ||
| 1867 | if (null != interfaceKey) | ||
| 1868 | { | ||
| 1869 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 1870 | } | ||
| 1871 | interfaceKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1872 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusInterface", interfaceKey); | ||
| 1873 | break; | ||
| 1874 | case "ApplicationRole": | ||
| 1875 | applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1876 | break; | ||
| 1877 | default: | ||
| 1878 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 1879 | break; | ||
| 1880 | } | ||
| 1881 | } | ||
| 1882 | else | ||
| 1883 | { | ||
| 1884 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 1885 | } | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | if (null == interfaceKey) | ||
| 1889 | { | ||
| 1890 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Interface")); | ||
| 1891 | } | ||
| 1892 | |||
| 1893 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusRoleForInterface"); | ||
| 1894 | row[0] = key; | ||
| 1895 | row[1] = interfaceKey; | ||
| 1896 | row[2] = applicationRoleKey; | ||
| 1897 | row[3] = componentKey; | ||
| 1898 | } | ||
| 1899 | |||
| 1900 | /// <summary> | ||
| 1901 | /// Parses a COM+ method element. | ||
| 1902 | /// </summary> | ||
| 1903 | /// <param name="node">Element to parse.</param> | ||
| 1904 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 1905 | /// <param name="interfaceKey">Identifier of parent interface.</param> | ||
| 1906 | private void ParseComPlusMethodElement(XElement node, string componentKey, string interfaceKey) | ||
| 1907 | { | ||
| 1908 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 1909 | |||
| 1910 | string key = null; | ||
| 1911 | int index = CompilerConstants.IntegerNotSet; | ||
| 1912 | string name = null; | ||
| 1913 | |||
| 1914 | Hashtable properties = new Hashtable(); | ||
| 1915 | |||
| 1916 | foreach (XAttribute attrib in node.Attributes()) | ||
| 1917 | { | ||
| 1918 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 1919 | { | ||
| 1920 | switch (attrib.Name.LocalName) | ||
| 1921 | { | ||
| 1922 | case "Id": | ||
| 1923 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 1924 | break; | ||
| 1925 | case "Index": | ||
| 1926 | index = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue); | ||
| 1927 | break; | ||
| 1928 | case "Name": | ||
| 1929 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1930 | break; | ||
| 1931 | case "AutoComplete": | ||
| 1932 | properties["AutoComplete"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 1933 | break; | ||
| 1934 | case "Description": | ||
| 1935 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 1936 | break; | ||
| 1937 | default: | ||
| 1938 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 1939 | break; | ||
| 1940 | } | ||
| 1941 | } | ||
| 1942 | else | ||
| 1943 | { | ||
| 1944 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 1945 | } | ||
| 1946 | } | ||
| 1947 | |||
| 1948 | foreach (XElement child in node.Elements()) | ||
| 1949 | { | ||
| 1950 | if (this.Namespace == child.Name.Namespace) | ||
| 1951 | { | ||
| 1952 | switch (child.Name.LocalName) | ||
| 1953 | { | ||
| 1954 | case "ComPlusRoleForMethod": | ||
| 1955 | this.ParseComPlusRoleForMethodElement(child, componentKey, key); | ||
| 1956 | break; | ||
| 1957 | default: | ||
| 1958 | this.Core.UnexpectedElement(node, child); | ||
| 1959 | break; | ||
| 1960 | } | ||
| 1961 | } | ||
| 1962 | else | ||
| 1963 | { | ||
| 1964 | this.Core.ParseExtensionElement(node, child); | ||
| 1965 | } | ||
| 1966 | } | ||
| 1967 | |||
| 1968 | if (CompilerConstants.IntegerNotSet == index && null == name) | ||
| 1969 | { | ||
| 1970 | this.Core.OnMessage(ComPlusErrors.RequiredAttribute(sourceLineNumbers, node.Name.LocalName, "Index", "Name")); | ||
| 1971 | } | ||
| 1972 | |||
| 1973 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusMethod"); | ||
| 1974 | row[0] = key; | ||
| 1975 | row[1] = interfaceKey; | ||
| 1976 | if (CompilerConstants.IntegerNotSet != index) | ||
| 1977 | { | ||
| 1978 | row[2] = index; | ||
| 1979 | } | ||
| 1980 | row[3] = name; | ||
| 1981 | |||
| 1982 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
| 1983 | while (propertiesEnumerator.MoveNext()) | ||
| 1984 | { | ||
| 1985 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusMethodProperty"); | ||
| 1986 | propertyRow[0] = key; | ||
| 1987 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
| 1988 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
| 1989 | } | ||
| 1990 | } | ||
| 1991 | |||
| 1992 | /// <summary> | ||
| 1993 | /// Parses a COM+ application role for method element. | ||
| 1994 | /// </summary> | ||
| 1995 | /// <param name="node">Element to parse.</param> | ||
| 1996 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 1997 | /// <param name="methodKey">Identifier of parent method.</param> | ||
| 1998 | private void ParseComPlusRoleForMethodElement(XElement node, string componentKey, string methodKey) | ||
| 1999 | { | ||
| 2000 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 2001 | |||
| 2002 | string key = null; | ||
| 2003 | string applicationRoleKey = null; | ||
| 2004 | |||
| 2005 | foreach (XAttribute attrib in node.Attributes()) | ||
| 2006 | { | ||
| 2007 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 2008 | { | ||
| 2009 | switch (attrib.Name.LocalName) | ||
| 2010 | { | ||
| 2011 | case "Id": | ||
| 2012 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 2013 | break; | ||
| 2014 | case "Method": | ||
| 2015 | if (null != methodKey) | ||
| 2016 | { | ||
| 2017 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 2018 | } | ||
| 2019 | methodKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2020 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusMethod", methodKey); | ||
| 2021 | break; | ||
| 2022 | case "ApplicationRole": | ||
| 2023 | applicationRoleKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2024 | break; | ||
| 2025 | default: | ||
| 2026 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 2027 | break; | ||
| 2028 | } | ||
| 2029 | } | ||
| 2030 | else | ||
| 2031 | { | ||
| 2032 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 2033 | } | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | if (null == methodKey) | ||
| 2037 | { | ||
| 2038 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Method")); | ||
| 2039 | } | ||
| 2040 | |||
| 2041 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusRoleForMethod"); | ||
| 2042 | row[0] = key; | ||
| 2043 | row[1] = methodKey; | ||
| 2044 | row[2] = applicationRoleKey; | ||
| 2045 | row[3] = componentKey; | ||
| 2046 | } | ||
| 2047 | |||
| 2048 | /// <summary> | ||
| 2049 | /// Parses a COM+ event subscription element. | ||
| 2050 | /// </summary> | ||
| 2051 | /// <param name="node">Element to parse.</param> | ||
| 2052 | /// <param name="componentKey">Identifier of parent component.</param> | ||
| 2053 | /// <param name="cpcomponentKey">Identifier of parent COM+ component.</param> | ||
| 2054 | private void ParseComPlusSubscriptionElement(XElement node, string componentKey, string cpcomponentKey) | ||
| 2055 | { | ||
| 2056 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
| 2057 | |||
| 2058 | string key = null; | ||
| 2059 | string id = null; | ||
| 2060 | string name = null; | ||
| 2061 | string eventCLSID = null; | ||
| 2062 | string publisherID = null; | ||
| 2063 | |||
| 2064 | Hashtable properties = new Hashtable(); | ||
| 2065 | |||
| 2066 | foreach (XAttribute attrib in node.Attributes()) | ||
| 2067 | { | ||
| 2068 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
| 2069 | { | ||
| 2070 | switch (attrib.Name.LocalName) | ||
| 2071 | { | ||
| 2072 | case "Id": | ||
| 2073 | key = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
| 2074 | break; | ||
| 2075 | case "Component": | ||
| 2076 | if (null != cpcomponentKey) | ||
| 2077 | { | ||
| 2078 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
| 2079 | } | ||
| 2080 | cpcomponentKey = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2081 | this.Core.CreateSimpleReference(sourceLineNumbers, "ComPlusComponent", cpcomponentKey); | ||
| 2082 | break; | ||
| 2083 | case "SubscriptionId": | ||
| 2084 | id = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
| 2085 | break; | ||
| 2086 | case "Name": | ||
| 2087 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2088 | break; | ||
| 2089 | case "EventCLSID": | ||
| 2090 | eventCLSID = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2091 | break; | ||
| 2092 | case "PublisherID": | ||
| 2093 | publisherID = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib)); | ||
| 2094 | break; | ||
| 2095 | case "Description": | ||
| 2096 | properties["Description"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2097 | break; | ||
| 2098 | case "Enabled": | ||
| 2099 | properties["Enabled"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 2100 | break; | ||
| 2101 | case "EventClassPartitionID": | ||
| 2102 | properties["EventClassPartitionID"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2103 | break; | ||
| 2104 | case "FilterCriteria": | ||
| 2105 | properties["FilterCriteria"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2106 | break; | ||
| 2107 | case "InterfaceID": | ||
| 2108 | properties["InterfaceID"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2109 | break; | ||
| 2110 | case "MachineName": | ||
| 2111 | properties["MachineName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2112 | break; | ||
| 2113 | case "MethodName": | ||
| 2114 | properties["MethodName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2115 | break; | ||
| 2116 | case "PerUser": | ||
| 2117 | properties["PerUser"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 2118 | break; | ||
| 2119 | case "Queued": | ||
| 2120 | properties["Queued"] = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib) ? "1" : "0"; | ||
| 2121 | break; | ||
| 2122 | case "SubscriberMoniker": | ||
| 2123 | properties["SubscriberMoniker"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2124 | break; | ||
| 2125 | case "UserName": | ||
| 2126 | properties["UserName"] = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
| 2127 | break; | ||
| 2128 | default: | ||
| 2129 | this.Core.UnexpectedAttribute(node, attrib); | ||
| 2130 | break; | ||
| 2131 | } | ||
| 2132 | } | ||
| 2133 | else | ||
| 2134 | { | ||
| 2135 | this.Core.ParseExtensionAttribute(node, attrib); | ||
| 2136 | } | ||
| 2137 | } | ||
| 2138 | |||
| 2139 | if (null == cpcomponentKey) | ||
| 2140 | { | ||
| 2141 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Component")); | ||
| 2142 | } | ||
| 2143 | |||
| 2144 | this.Core.ParseForExtensionElements(node); | ||
| 2145 | |||
| 2146 | Row row = this.Core.CreateRow(sourceLineNumbers, "ComPlusSubscription"); | ||
| 2147 | row[0] = key; | ||
| 2148 | row[1] = cpcomponentKey; | ||
| 2149 | row[2] = componentKey; | ||
| 2150 | row[3] = id; | ||
| 2151 | row[4] = name; | ||
| 2152 | row[5] = eventCLSID; | ||
| 2153 | row[6] = publisherID; | ||
| 2154 | |||
| 2155 | IDictionaryEnumerator propertiesEnumerator = properties.GetEnumerator(); | ||
| 2156 | while (propertiesEnumerator.MoveNext()) | ||
| 2157 | { | ||
| 2158 | Row propertyRow = this.Core.CreateRow(sourceLineNumbers, "ComPlusSubscriptionProperty"); | ||
| 2159 | propertyRow[0] = key; | ||
| 2160 | propertyRow[1] = (string)propertiesEnumerator.Key; | ||
| 2161 | propertyRow[2] = (string)propertiesEnumerator.Value; | ||
| 2162 | } | ||
| 2163 | } | ||
| 2164 | |||
| 2165 | /// <summary> | ||
| 2166 | /// Attempts to parse the input value as a GUID, and in case the value is a valid | ||
| 2167 | /// GUID returnes it in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}". | ||
| 2168 | /// </summary> | ||
| 2169 | /// <param name="val"></param> | ||
| 2170 | /// <returns></returns> | ||
| 2171 | string TryFormatGuidValue(string val) | ||
| 2172 | { | ||
| 2173 | try | ||
| 2174 | { | ||
| 2175 | Guid guid = new Guid(val); | ||
| 2176 | return guid.ToString("B").ToUpper(); | ||
| 2177 | } | ||
| 2178 | catch (FormatException) | ||
| 2179 | { | ||
| 2180 | return val; | ||
| 2181 | } | ||
| 2182 | catch (OverflowException) | ||
| 2183 | { | ||
| 2184 | return val; | ||
| 2185 | } | ||
| 2186 | } | ||
| 2187 | } | ||
| 2188 | } | ||
diff --git a/src/wixext/ComPlusDecompiler.cs b/src/wixext/ComPlusDecompiler.cs new file mode 100644 index 00000000..27f1653e --- /dev/null +++ b/src/wixext/ComPlusDecompiler.cs | |||
| @@ -0,0 +1,1843 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Extensions | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections; | ||
| 7 | using System.Globalization; | ||
| 8 | using WixToolset.Data; | ||
| 9 | using WixToolset.Extensibility; | ||
| 10 | using ComPlus = WixToolset.Extensions.Serialize.ComPlus; | ||
| 11 | using Wix = WixToolset.Data.Serialize; | ||
| 12 | |||
| 13 | /// <summary> | ||
| 14 | /// The decompiler for the WiX Toolset COM+ Extension. | ||
| 15 | /// </summary> | ||
| 16 | public sealed class ComPlusDecompiler : DecompilerExtension | ||
| 17 | { | ||
| 18 | /// <summary> | ||
| 19 | /// Creates a decompiler for ComPlus Extension. | ||
| 20 | /// </summary> | ||
| 21 | public ComPlusDecompiler() | ||
| 22 | { | ||
| 23 | this.TableDefinitions = ComPlusExtensionData.GetExtensionTableDefinitions(); | ||
| 24 | } | ||
| 25 | |||
| 26 | /// <summary> | ||
| 27 | /// Get the extensions library to be removed. | ||
| 28 | /// </summary> | ||
| 29 | /// <param name="tableDefinitions">Table definitions for library.</param> | ||
| 30 | /// <returns>Library to remove from decompiled output.</returns> | ||
| 31 | public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions) | ||
| 32 | { | ||
| 33 | return ComPlusExtensionData.GetExtensionLibrary(tableDefinitions); | ||
| 34 | } | ||
| 35 | |||
| 36 | /// <summary> | ||
| 37 | /// Decompiles an extension table. | ||
| 38 | /// </summary> | ||
| 39 | /// <param name="table">The table to decompile.</param> | ||
| 40 | public override void DecompileTable(Table table) | ||
| 41 | { | ||
| 42 | switch (table.Name) | ||
| 43 | { | ||
| 44 | case "ComPlusPartition": | ||
| 45 | this.DecompileComPlusPartitionTable(table); | ||
| 46 | break; | ||
| 47 | case "ComPlusPartitionProperty": | ||
| 48 | this.DecompileComPlusPartitionPropertyTable(table); | ||
| 49 | break; | ||
| 50 | case "ComPlusPartitionRole": | ||
| 51 | this.DecompileComPlusPartitionRoleTable(table); | ||
| 52 | break; | ||
| 53 | case "ComPlusUserInPartitionRole": | ||
| 54 | this.DecompileComPlusUserInPartitionRoleTable(table); | ||
| 55 | break; | ||
| 56 | case "ComPlusGroupInPartitionRole": | ||
| 57 | this.DecompileComPlusGroupInPartitionRoleTable(table); | ||
| 58 | break; | ||
| 59 | case "ComPlusPartitionUser": | ||
| 60 | this.DecompileComPlusPartitionUserTable(table); | ||
| 61 | break; | ||
| 62 | case "ComPlusApplication": | ||
| 63 | this.DecompileComPlusApplicationTable(table); | ||
| 64 | break; | ||
| 65 | case "ComPlusApplicationProperty": | ||
| 66 | this.DecompileComPlusApplicationPropertyTable(table); | ||
| 67 | break; | ||
| 68 | case "ComPlusApplicationRole": | ||
| 69 | this.DecompileComPlusApplicationRoleTable(table); | ||
| 70 | break; | ||
| 71 | case "ComPlusApplicationRoleProperty": | ||
| 72 | this.DecompileComPlusApplicationRolePropertyTable(table); | ||
| 73 | break; | ||
| 74 | case "ComPlusUserInApplicationRole": | ||
| 75 | this.DecompileComPlusUserInApplicationRoleTable(table); | ||
| 76 | break; | ||
| 77 | case "ComPlusGroupInApplicationRole": | ||
| 78 | this.DecompileComPlusGroupInApplicationRoleTable(table); | ||
| 79 | break; | ||
| 80 | case "ComPlusAssembly": | ||
| 81 | this.DecompileComPlusAssemblyTable(table); | ||
| 82 | break; | ||
| 83 | case "ComPlusComponent": | ||
| 84 | this.DecompileComPlusComponentTable(table); | ||
| 85 | break; | ||
| 86 | case "ComPlusComponentProperty": | ||
| 87 | this.DecompileComPlusComponentPropertyTable(table); | ||
| 88 | break; | ||
| 89 | case "ComPlusRoleForComponent": | ||
| 90 | this.DecompileComPlusRoleForComponentTable(table); | ||
| 91 | break; | ||
| 92 | case "ComPlusInterface": | ||
| 93 | this.DecompileComPlusInterfaceTable(table); | ||
| 94 | break; | ||
| 95 | case "ComPlusInterfaceProperty": | ||
| 96 | this.DecompileComPlusInterfacePropertyTable(table); | ||
| 97 | break; | ||
| 98 | case "ComPlusRoleForInterface": | ||
| 99 | this.DecompileComPlusRoleForInterfaceTable(table); | ||
| 100 | break; | ||
| 101 | case "ComPlusMethod": | ||
| 102 | this.DecompileComPlusMethodTable(table); | ||
| 103 | break; | ||
| 104 | case "ComPlusMethodProperty": | ||
| 105 | this.DecompileComPlusMethodPropertyTable(table); | ||
| 106 | break; | ||
| 107 | case "ComPlusRoleForMethod": | ||
| 108 | this.DecompileComPlusRoleForMethodTable(table); | ||
| 109 | break; | ||
| 110 | case "ComPlusSubscription": | ||
| 111 | this.DecompileComPlusSubscriptionTable(table); | ||
| 112 | break; | ||
| 113 | case "ComPlusSubscriptionProperty": | ||
| 114 | this.DecompileComPlusSubscriptionPropertyTable(table); | ||
| 115 | break; | ||
| 116 | default: | ||
| 117 | base.DecompileTable(table); | ||
| 118 | break; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | /// <summary> | ||
| 123 | /// Decompile the ComPlusPartition table. | ||
| 124 | /// </summary> | ||
| 125 | /// <param name="table">The table to decompile.</param> | ||
| 126 | private void DecompileComPlusPartitionTable(Table table) | ||
| 127 | { | ||
| 128 | foreach (Row row in table.Rows) | ||
| 129 | { | ||
| 130 | ComPlus.ComPlusPartition partition = new ComPlus.ComPlusPartition(); | ||
| 131 | |||
| 132 | partition.Id = (string)row[0]; | ||
| 133 | |||
| 134 | if (null != row[2]) | ||
| 135 | { | ||
| 136 | partition.PartitionId = (string)row[2]; | ||
| 137 | } | ||
| 138 | |||
| 139 | if (null != row[3]) | ||
| 140 | { | ||
| 141 | partition.Name = (string)row[3]; | ||
| 142 | } | ||
| 143 | |||
| 144 | if (null != row[1]) | ||
| 145 | { | ||
| 146 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); | ||
| 147 | if (null != component) | ||
| 148 | { | ||
| 149 | component.AddChild(partition); | ||
| 150 | } | ||
| 151 | else | ||
| 152 | { | ||
| 153 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component")); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | else | ||
| 157 | { | ||
| 158 | this.Core.RootElement.AddChild(partition); | ||
| 159 | } | ||
| 160 | this.Core.IndexElement(row, partition); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | /// <summary> | ||
| 165 | /// Decompile the ComPlusPartitionProperty table. | ||
| 166 | /// </summary> | ||
| 167 | /// <param name="table">The table to decompile.</param> | ||
| 168 | private void DecompileComPlusPartitionPropertyTable(Table table) | ||
| 169 | { | ||
| 170 | foreach (Row row in table.Rows) | ||
| 171 | { | ||
| 172 | ComPlus.ComPlusPartition partition = (ComPlus.ComPlusPartition)this.Core.GetIndexedElement("ComPlusPartition", (string)row[0]); | ||
| 173 | if (null == partition) | ||
| 174 | { | ||
| 175 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Partition_", (string)row[0], "ComPlusPartition")); | ||
| 176 | } | ||
| 177 | |||
| 178 | switch ((string)row[1]) | ||
| 179 | { | ||
| 180 | case "Changeable": | ||
| 181 | switch ((string)row[2]) | ||
| 182 | { | ||
| 183 | case "1": | ||
| 184 | partition.Changeable = ComPlus.YesNoType.yes; | ||
| 185 | break; | ||
| 186 | case "0": | ||
| 187 | partition.Changeable = ComPlus.YesNoType.no; | ||
| 188 | break; | ||
| 189 | default: | ||
| 190 | // TODO: Warning | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | break; | ||
| 194 | case "Deleteable": | ||
| 195 | switch ((string)row[2]) | ||
| 196 | { | ||
| 197 | case "1": | ||
| 198 | partition.Deleteable = ComPlus.YesNoType.yes; | ||
| 199 | break; | ||
| 200 | case "0": | ||
| 201 | partition.Deleteable = ComPlus.YesNoType.no; | ||
| 202 | break; | ||
| 203 | default: | ||
| 204 | // TODO: Warning | ||
| 205 | break; | ||
| 206 | } | ||
| 207 | break; | ||
| 208 | case "Description": | ||
| 209 | partition.Description = (string)row[2]; | ||
| 210 | break; | ||
| 211 | default: | ||
| 212 | // TODO: Warning | ||
| 213 | break; | ||
| 214 | } | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | /// <summary> | ||
| 219 | /// Decompile the ComPlusPartitionRole table. | ||
| 220 | /// </summary> | ||
| 221 | /// <param name="table">The table to decompile.</param> | ||
| 222 | private void DecompileComPlusPartitionRoleTable(Table table) | ||
| 223 | { | ||
| 224 | foreach (Row row in table.Rows) | ||
| 225 | { | ||
| 226 | ComPlus.ComPlusPartitionRole partitionRole = new ComPlus.ComPlusPartitionRole(); | ||
| 227 | |||
| 228 | partitionRole.Id = (string)row[0]; | ||
| 229 | partitionRole.Partition = (string)row[1]; | ||
| 230 | partitionRole.Name = (string)row[3]; | ||
| 231 | |||
| 232 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 233 | if (null != component) | ||
| 234 | { | ||
| 235 | component.AddChild(partitionRole); | ||
| 236 | } | ||
| 237 | else | ||
| 238 | { | ||
| 239 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | /// <summary> | ||
| 245 | /// Decompile the ComPlusUserInPartitionRole table. | ||
| 246 | /// </summary> | ||
| 247 | /// <param name="table">The table to decompile.</param> | ||
| 248 | private void DecompileComPlusUserInPartitionRoleTable(Table table) | ||
| 249 | { | ||
| 250 | foreach (Row row in table.Rows) | ||
| 251 | { | ||
| 252 | ComPlus.ComPlusUserInPartitionRole userInPartitionRole = new ComPlus.ComPlusUserInPartitionRole(); | ||
| 253 | |||
| 254 | userInPartitionRole.Id = (string)row[0]; | ||
| 255 | userInPartitionRole.PartitionRole = (string)row[1]; | ||
| 256 | userInPartitionRole.User = (string)row[3]; | ||
| 257 | |||
| 258 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 259 | if (null != component) | ||
| 260 | { | ||
| 261 | component.AddChild(userInPartitionRole); | ||
| 262 | } | ||
| 263 | else | ||
| 264 | { | ||
| 265 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 266 | } | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | /// <summary> | ||
| 271 | /// Decompile the ComPlusGroupInPartitionRole table. | ||
| 272 | /// </summary> | ||
| 273 | /// <param name="table">The table to decompile.</param> | ||
| 274 | private void DecompileComPlusGroupInPartitionRoleTable(Table table) | ||
| 275 | { | ||
| 276 | foreach (Row row in table.Rows) | ||
| 277 | { | ||
| 278 | ComPlus.ComPlusGroupInPartitionRole groupInPartitionRole = new ComPlus.ComPlusGroupInPartitionRole(); | ||
| 279 | |||
| 280 | groupInPartitionRole.Id = (string)row[0]; | ||
| 281 | groupInPartitionRole.PartitionRole = (string)row[1]; | ||
| 282 | groupInPartitionRole.Group = (string)row[3]; | ||
| 283 | |||
| 284 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 285 | if (null != component) | ||
| 286 | { | ||
| 287 | component.AddChild(groupInPartitionRole); | ||
| 288 | } | ||
| 289 | else | ||
| 290 | { | ||
| 291 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | /// <summary> | ||
| 297 | /// Decompile the ComPlusPartitionUser table. | ||
| 298 | /// </summary> | ||
| 299 | /// <param name="table">The table to decompile.</param> | ||
| 300 | private void DecompileComPlusPartitionUserTable(Table table) | ||
| 301 | { | ||
| 302 | foreach (Row row in table.Rows) | ||
| 303 | { | ||
| 304 | ComPlus.ComPlusPartitionUser partitionUser = new ComPlus.ComPlusPartitionUser(); | ||
| 305 | |||
| 306 | partitionUser.Id = (string)row[0]; | ||
| 307 | partitionUser.Partition = (string)row[1]; | ||
| 308 | partitionUser.User = (string)row[3]; | ||
| 309 | |||
| 310 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 311 | if (null != component) | ||
| 312 | { | ||
| 313 | component.AddChild(partitionUser); | ||
| 314 | } | ||
| 315 | else | ||
| 316 | { | ||
| 317 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 318 | } | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | /// <summary> | ||
| 323 | /// Decompile the ComPlusApplication table. | ||
| 324 | /// </summary> | ||
| 325 | /// <param name="table">The table to decompile.</param> | ||
| 326 | private void DecompileComPlusApplicationTable(Table table) | ||
| 327 | { | ||
| 328 | foreach (Row row in table.Rows) | ||
| 329 | { | ||
| 330 | ComPlus.ComPlusApplication application = new ComPlus.ComPlusApplication(); | ||
| 331 | |||
| 332 | application.Id = (string)row[0]; | ||
| 333 | application.Partition = (string)row[1]; | ||
| 334 | |||
| 335 | if (null != row[3]) | ||
| 336 | { | ||
| 337 | application.ApplicationId = (string)row[3]; | ||
| 338 | } | ||
| 339 | |||
| 340 | if (null != row[4]) | ||
| 341 | { | ||
| 342 | application.Name = (string)row[4]; | ||
| 343 | } | ||
| 344 | |||
| 345 | if (null != row[2]) | ||
| 346 | { | ||
| 347 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]); | ||
| 348 | if (null != component) | ||
| 349 | { | ||
| 350 | component.AddChild(application); | ||
| 351 | } | ||
| 352 | else | ||
| 353 | { | ||
| 354 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 355 | } | ||
| 356 | } | ||
| 357 | else | ||
| 358 | { | ||
| 359 | this.Core.RootElement.AddChild(application); | ||
| 360 | } | ||
| 361 | this.Core.IndexElement(row, application); | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | /// <summary> | ||
| 366 | /// Decompile the ComPlusApplicationProperty table. | ||
| 367 | /// </summary> | ||
| 368 | /// <param name="table">The table to decompile.</param> | ||
| 369 | private void DecompileComPlusApplicationPropertyTable(Table table) | ||
| 370 | { | ||
| 371 | foreach (Row row in table.Rows) | ||
| 372 | { | ||
| 373 | ComPlus.ComPlusApplication application = (ComPlus.ComPlusApplication)this.Core.GetIndexedElement("ComPlusApplication", (string)row[0]); | ||
| 374 | if (null == application) | ||
| 375 | { | ||
| 376 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Application_", (string)row[0], "ComPlusApplication")); | ||
| 377 | } | ||
| 378 | |||
| 379 | switch ((string)row[1]) | ||
| 380 | { | ||
| 381 | case "3GigSupportEnabled": | ||
| 382 | switch ((string)row[2]) | ||
| 383 | { | ||
| 384 | case "1": | ||
| 385 | application.ThreeGigSupportEnabled = ComPlus.YesNoType.yes; | ||
| 386 | break; | ||
| 387 | case "0": | ||
| 388 | application.ThreeGigSupportEnabled = ComPlus.YesNoType.no; | ||
| 389 | break; | ||
| 390 | default: | ||
| 391 | // TODO: Warning | ||
| 392 | break; | ||
| 393 | } | ||
| 394 | break; | ||
| 395 | case "AccessChecksLevel": | ||
| 396 | switch ((string)row[2]) | ||
| 397 | { | ||
| 398 | case "0": | ||
| 399 | application.AccessChecksLevel = ComPlus.ComPlusApplication.AccessChecksLevelType.applicationLevel; | ||
| 400 | break; | ||
| 401 | case "1": | ||
| 402 | application.AccessChecksLevel = ComPlus.ComPlusApplication.AccessChecksLevelType.applicationComponentLevel; | ||
| 403 | break; | ||
| 404 | default: | ||
| 405 | // TODO: Warning | ||
| 406 | break; | ||
| 407 | } | ||
| 408 | break; | ||
| 409 | case "Activation": | ||
| 410 | switch ((string)row[2]) | ||
| 411 | { | ||
| 412 | case "Inproc": | ||
| 413 | application.Activation = ComPlus.ComPlusApplication.ActivationType.inproc; | ||
| 414 | break; | ||
| 415 | case "Local": | ||
| 416 | application.Activation = ComPlus.ComPlusApplication.ActivationType.local; | ||
| 417 | break; | ||
| 418 | default: | ||
| 419 | // TODO: Warning | ||
| 420 | break; | ||
| 421 | } | ||
| 422 | break; | ||
| 423 | case "ApplicationAccessChecksEnabled": | ||
| 424 | switch ((string)row[2]) | ||
| 425 | { | ||
| 426 | case "1": | ||
| 427 | application.ApplicationAccessChecksEnabled = ComPlus.YesNoType.yes; | ||
| 428 | break; | ||
| 429 | case "0": | ||
| 430 | application.ApplicationAccessChecksEnabled = ComPlus.YesNoType.no; | ||
| 431 | break; | ||
| 432 | default: | ||
| 433 | // TODO: Warning | ||
| 434 | break; | ||
| 435 | } | ||
| 436 | break; | ||
| 437 | case "ApplicationDirectory": | ||
| 438 | application.ApplicationDirectory = (string)row[2]; | ||
| 439 | break; | ||
| 440 | case "Authentication": | ||
| 441 | switch ((string)row[2]) | ||
| 442 | { | ||
| 443 | case "0": | ||
| 444 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.@default; | ||
| 445 | break; | ||
| 446 | case "1": | ||
| 447 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.none; | ||
| 448 | break; | ||
| 449 | case "2": | ||
| 450 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.connect; | ||
| 451 | break; | ||
| 452 | case "3": | ||
| 453 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.call; | ||
| 454 | break; | ||
| 455 | case "4": | ||
| 456 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.packet; | ||
| 457 | break; | ||
| 458 | case "5": | ||
| 459 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.integrity; | ||
| 460 | break; | ||
| 461 | case "6": | ||
| 462 | application.Authentication = ComPlus.ComPlusApplication.AuthenticationType.privacy; | ||
| 463 | break; | ||
| 464 | default: | ||
| 465 | // TODO: Warning | ||
| 466 | break; | ||
| 467 | } | ||
| 468 | break; | ||
| 469 | case "AuthenticationCapability": | ||
| 470 | switch ((string)row[2]) | ||
| 471 | { | ||
| 472 | case "0": | ||
| 473 | application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.none; | ||
| 474 | break; | ||
| 475 | case "2": | ||
| 476 | application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.secureReference; | ||
| 477 | break; | ||
| 478 | case "32": | ||
| 479 | application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.staticCloaking; | ||
| 480 | break; | ||
| 481 | case "64": | ||
| 482 | application.AuthenticationCapability = ComPlus.ComPlusApplication.AuthenticationCapabilityType.dynamicCloaking; | ||
| 483 | break; | ||
| 484 | default: | ||
| 485 | // TODO: Warning | ||
| 486 | break; | ||
| 487 | } | ||
| 488 | break; | ||
| 489 | case "Changeable": | ||
| 490 | switch ((string)row[2]) | ||
| 491 | { | ||
| 492 | case "1": | ||
| 493 | application.Changeable = ComPlus.YesNoType.yes; | ||
| 494 | break; | ||
| 495 | case "0": | ||
| 496 | application.Changeable = ComPlus.YesNoType.no; | ||
| 497 | break; | ||
| 498 | default: | ||
| 499 | // TODO: Warning | ||
| 500 | break; | ||
| 501 | } | ||
| 502 | break; | ||
| 503 | case "CommandLine": | ||
| 504 | application.CommandLine = (string)row[2]; | ||
| 505 | break; | ||
| 506 | case "ConcurrentApps": | ||
| 507 | int concurrentApps; | ||
| 508 | if (Int32.TryParse((string)row[2], out concurrentApps)) | ||
| 509 | { | ||
| 510 | application.ConcurrentApps = concurrentApps; | ||
| 511 | } | ||
| 512 | else | ||
| 513 | { | ||
| 514 | // TODO: Warning | ||
| 515 | } | ||
| 516 | break; | ||
| 517 | case "CreatedBy": | ||
| 518 | application.CreatedBy = (string)row[2]; | ||
| 519 | break; | ||
| 520 | case "CRMEnabled": | ||
| 521 | switch ((string)row[2]) | ||
| 522 | { | ||
| 523 | case "1": | ||
| 524 | application.CRMEnabled = ComPlus.YesNoType.yes; | ||
| 525 | break; | ||
| 526 | case "0": | ||
| 527 | application.CRMEnabled = ComPlus.YesNoType.no; | ||
| 528 | break; | ||
| 529 | default: | ||
| 530 | // TODO: Warning | ||
| 531 | break; | ||
| 532 | } | ||
| 533 | break; | ||
| 534 | case "CRMLogFile": | ||
| 535 | application.CRMLogFile = (string)row[2]; | ||
| 536 | break; | ||
| 537 | case "Deleteable": | ||
| 538 | switch ((string)row[2]) | ||
| 539 | { | ||
| 540 | case "1": | ||
| 541 | application.Deleteable = ComPlus.YesNoType.yes; | ||
| 542 | break; | ||
| 543 | case "0": | ||
| 544 | application.Deleteable = ComPlus.YesNoType.no; | ||
| 545 | break; | ||
| 546 | default: | ||
| 547 | // TODO: Warning | ||
| 548 | break; | ||
| 549 | } | ||
| 550 | break; | ||
| 551 | case "Description": | ||
| 552 | application.Description = (string)row[2]; | ||
| 553 | break; | ||
| 554 | case "DumpEnabled": | ||
| 555 | switch ((string)row[2]) | ||
| 556 | { | ||
| 557 | case "1": | ||
| 558 | application.DumpEnabled = ComPlus.YesNoType.yes; | ||
| 559 | break; | ||
| 560 | case "0": | ||
| 561 | application.DumpEnabled = ComPlus.YesNoType.no; | ||
| 562 | break; | ||
| 563 | default: | ||
| 564 | // TODO: Warning | ||
| 565 | break; | ||
| 566 | } | ||
| 567 | break; | ||
| 568 | case "DumpOnException": | ||
| 569 | switch ((string)row[2]) | ||
| 570 | { | ||
| 571 | case "1": | ||
| 572 | application.DumpOnException = ComPlus.YesNoType.yes; | ||
| 573 | break; | ||
| 574 | case "0": | ||
| 575 | application.DumpOnException = ComPlus.YesNoType.no; | ||
| 576 | break; | ||
| 577 | default: | ||
| 578 | // TODO: Warning | ||
| 579 | break; | ||
| 580 | } | ||
| 581 | break; | ||
| 582 | case "DumpOnFailfast": | ||
| 583 | switch ((string)row[2]) | ||
| 584 | { | ||
| 585 | case "1": | ||
| 586 | application.DumpOnFailfast = ComPlus.YesNoType.yes; | ||
| 587 | break; | ||
| 588 | case "0": | ||
| 589 | application.DumpOnFailfast = ComPlus.YesNoType.no; | ||
| 590 | break; | ||
| 591 | default: | ||
| 592 | // TODO: Warning | ||
| 593 | break; | ||
| 594 | } | ||
| 595 | break; | ||
| 596 | case "DumpPath": | ||
| 597 | application.DumpPath = (string)row[2]; | ||
| 598 | break; | ||
| 599 | case "EventsEnabled": | ||
| 600 | switch ((string)row[2]) | ||
| 601 | { | ||
| 602 | case "1": | ||
| 603 | application.EventsEnabled = ComPlus.YesNoType.yes; | ||
| 604 | break; | ||
| 605 | case "0": | ||
| 606 | application.EventsEnabled = ComPlus.YesNoType.no; | ||
| 607 | break; | ||
| 608 | default: | ||
| 609 | // TODO: Warning | ||
| 610 | break; | ||
| 611 | } | ||
| 612 | break; | ||
| 613 | case "Identity": | ||
| 614 | application.Identity = (string)row[2]; | ||
| 615 | break; | ||
| 616 | case "ImpersonationLevel": | ||
| 617 | switch ((string)row[2]) | ||
| 618 | { | ||
| 619 | case "1": | ||
| 620 | application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.anonymous; | ||
| 621 | break; | ||
| 622 | case "2": | ||
| 623 | application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.identify; | ||
| 624 | break; | ||
| 625 | case "3": | ||
| 626 | application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.impersonate; | ||
| 627 | break; | ||
| 628 | case "4": | ||
| 629 | application.ImpersonationLevel = ComPlus.ComPlusApplication.ImpersonationLevelType.@delegate; | ||
| 630 | break; | ||
| 631 | default: | ||
| 632 | // TODO: Warning | ||
| 633 | break; | ||
| 634 | } | ||
| 635 | break; | ||
| 636 | case "IsEnabled": | ||
| 637 | switch ((string)row[2]) | ||
| 638 | { | ||
| 639 | case "1": | ||
| 640 | application.IsEnabled = ComPlus.YesNoType.yes; | ||
| 641 | break; | ||
| 642 | case "0": | ||
| 643 | application.IsEnabled = ComPlus.YesNoType.no; | ||
| 644 | break; | ||
| 645 | default: | ||
| 646 | // TODO: Warning | ||
| 647 | break; | ||
| 648 | } | ||
| 649 | break; | ||
| 650 | case "MaxDumpCount": | ||
| 651 | int maxDumpCount; | ||
| 652 | if (Int32.TryParse((string)row[2], out maxDumpCount)) | ||
| 653 | { | ||
| 654 | application.MaxDumpCount = maxDumpCount; | ||
| 655 | } | ||
| 656 | else | ||
| 657 | { | ||
| 658 | // TODO: Warning | ||
| 659 | } | ||
| 660 | break; | ||
| 661 | case "Password": | ||
| 662 | application.Password = (string)row[2]; | ||
| 663 | break; | ||
| 664 | case "QCAuthenticateMsgs": | ||
| 665 | switch ((string)row[2]) | ||
| 666 | { | ||
| 667 | case "0": | ||
| 668 | application.QCAuthenticateMsgs = ComPlus.ComPlusApplication.QCAuthenticateMsgsType.secureApps; | ||
| 669 | break; | ||
| 670 | case "1": | ||
| 671 | application.QCAuthenticateMsgs = ComPlus.ComPlusApplication.QCAuthenticateMsgsType.off; | ||
| 672 | break; | ||
| 673 | case "2": | ||
| 674 | application.QCAuthenticateMsgs = ComPlus.ComPlusApplication.QCAuthenticateMsgsType.on; | ||
| 675 | break; | ||
| 676 | default: | ||
| 677 | // TODO: Warning | ||
| 678 | break; | ||
| 679 | } | ||
| 680 | break; | ||
| 681 | case "QCListenerMaxThreads": | ||
| 682 | int qcListenerMaxThreads; | ||
| 683 | if (Int32.TryParse((string)row[2], out qcListenerMaxThreads)) | ||
| 684 | { | ||
| 685 | application.QCListenerMaxThreads = qcListenerMaxThreads; | ||
| 686 | } | ||
| 687 | else | ||
| 688 | { | ||
| 689 | // TODO: Warning | ||
| 690 | } | ||
| 691 | break; | ||
| 692 | case "QueueListenerEnabled": | ||
| 693 | switch ((string)row[2]) | ||
| 694 | { | ||
| 695 | case "1": | ||
| 696 | application.QueueListenerEnabled = ComPlus.YesNoType.yes; | ||
| 697 | break; | ||
| 698 | case "0": | ||
| 699 | application.QueueListenerEnabled = ComPlus.YesNoType.no; | ||
| 700 | break; | ||
| 701 | default: | ||
| 702 | // TODO: Warning | ||
| 703 | break; | ||
| 704 | } | ||
| 705 | break; | ||
| 706 | case "QueuingEnabled": | ||
| 707 | switch ((string)row[2]) | ||
| 708 | { | ||
| 709 | case "1": | ||
| 710 | application.QueuingEnabled = ComPlus.YesNoType.yes; | ||
| 711 | break; | ||
| 712 | case "0": | ||
| 713 | application.QueuingEnabled = ComPlus.YesNoType.no; | ||
| 714 | break; | ||
| 715 | default: | ||
| 716 | // TODO: Warning | ||
| 717 | break; | ||
| 718 | } | ||
| 719 | break; | ||
| 720 | case "RecycleActivationLimit": | ||
| 721 | int recycleActivationLimit; | ||
| 722 | if (Int32.TryParse((string)row[2], out recycleActivationLimit)) | ||
| 723 | { | ||
| 724 | application.RecycleActivationLimit = recycleActivationLimit; | ||
| 725 | } | ||
| 726 | else | ||
| 727 | { | ||
| 728 | // TODO: Warning | ||
| 729 | } | ||
| 730 | break; | ||
| 731 | case "RecycleCallLimit": | ||
| 732 | int recycleCallLimit; | ||
| 733 | if (Int32.TryParse((string)row[2], out recycleCallLimit)) | ||
| 734 | { | ||
| 735 | application.RecycleCallLimit = recycleCallLimit; | ||
| 736 | } | ||
| 737 | else | ||
| 738 | { | ||
| 739 | // TODO: Warning | ||
| 740 | } | ||
| 741 | break; | ||
| 742 | case "RecycleExpirationTimeout": | ||
| 743 | int recycleExpirationTimeout; | ||
| 744 | if (Int32.TryParse((string)row[2], out recycleExpirationTimeout)) | ||
| 745 | { | ||
| 746 | application.RecycleExpirationTimeout = recycleExpirationTimeout; | ||
| 747 | } | ||
| 748 | else | ||
| 749 | { | ||
| 750 | // TODO: Warning | ||
| 751 | } | ||
| 752 | break; | ||
| 753 | case "RecycleLifetimeLimit": | ||
| 754 | int recycleLifetimeLimit; | ||
| 755 | if (Int32.TryParse((string)row[2], out recycleLifetimeLimit)) | ||
| 756 | { | ||
| 757 | application.RecycleLifetimeLimit = recycleLifetimeLimit; | ||
| 758 | } | ||
| 759 | else | ||
| 760 | { | ||
| 761 | // TODO: Warning | ||
| 762 | } | ||
| 763 | break; | ||
| 764 | case "RecycleMemoryLimit": | ||
| 765 | int recycleMemoryLimit; | ||
| 766 | if (Int32.TryParse((string)row[2], out recycleMemoryLimit)) | ||
| 767 | { | ||
| 768 | application.RecycleMemoryLimit = recycleMemoryLimit; | ||
| 769 | } | ||
| 770 | else | ||
| 771 | { | ||
| 772 | // TODO: Warning | ||
| 773 | } | ||
| 774 | break; | ||
| 775 | case "Replicable": | ||
| 776 | switch ((string)row[2]) | ||
| 777 | { | ||
| 778 | case "1": | ||
| 779 | application.Replicable = ComPlus.YesNoType.yes; | ||
| 780 | break; | ||
| 781 | case "0": | ||
| 782 | application.Replicable = ComPlus.YesNoType.no; | ||
| 783 | break; | ||
| 784 | default: | ||
| 785 | // TODO: Warning | ||
| 786 | break; | ||
| 787 | } | ||
| 788 | break; | ||
| 789 | case "RunForever": | ||
| 790 | switch ((string)row[2]) | ||
| 791 | { | ||
| 792 | case "1": | ||
| 793 | application.RunForever = ComPlus.YesNoType.yes; | ||
| 794 | break; | ||
| 795 | case "0": | ||
| 796 | application.RunForever = ComPlus.YesNoType.no; | ||
| 797 | break; | ||
| 798 | default: | ||
| 799 | // TODO: Warning | ||
| 800 | break; | ||
| 801 | } | ||
| 802 | break; | ||
| 803 | case "ShutdownAfter": | ||
| 804 | int shutdownAfter; | ||
| 805 | if (Int32.TryParse((string)row[2], out shutdownAfter)) | ||
| 806 | { | ||
| 807 | application.ShutdownAfter = shutdownAfter; | ||
| 808 | } | ||
| 809 | else | ||
| 810 | { | ||
| 811 | // TODO: Warning | ||
| 812 | } | ||
| 813 | break; | ||
| 814 | case "SoapActivated": | ||
| 815 | switch ((string)row[2]) | ||
| 816 | { | ||
| 817 | case "1": | ||
| 818 | application.SoapActivated = ComPlus.YesNoType.yes; | ||
| 819 | break; | ||
| 820 | case "0": | ||
| 821 | application.SoapActivated = ComPlus.YesNoType.no; | ||
| 822 | break; | ||
| 823 | default: | ||
| 824 | // TODO: Warning | ||
| 825 | break; | ||
| 826 | } | ||
| 827 | break; | ||
| 828 | case "SoapBaseUrl": | ||
| 829 | application.SoapBaseUrl = (string)row[2]; | ||
| 830 | break; | ||
| 831 | case "SoapMailTo": | ||
| 832 | application.SoapMailTo = (string)row[2]; | ||
| 833 | break; | ||
| 834 | case "SoapVRoot": | ||
| 835 | application.SoapVRoot = (string)row[2]; | ||
| 836 | break; | ||
| 837 | case "SRPEnabled": | ||
| 838 | switch ((string)row[2]) | ||
| 839 | { | ||
| 840 | case "1": | ||
| 841 | application.SRPEnabled = ComPlus.YesNoType.yes; | ||
| 842 | break; | ||
| 843 | case "0": | ||
| 844 | application.SRPEnabled = ComPlus.YesNoType.no; | ||
| 845 | break; | ||
| 846 | default: | ||
| 847 | // TODO: Warning | ||
| 848 | break; | ||
| 849 | } | ||
| 850 | break; | ||
| 851 | case "SRPTrustLevel": | ||
| 852 | switch ((string)row[2]) | ||
| 853 | { | ||
| 854 | case "0": | ||
| 855 | application.SRPTrustLevel = ComPlus.ComPlusApplication.SRPTrustLevelType.disallowed; | ||
| 856 | break; | ||
| 857 | case "262144": | ||
| 858 | application.SRPTrustLevel = ComPlus.ComPlusApplication.SRPTrustLevelType.fullyTrusted; | ||
| 859 | break; | ||
| 860 | default: | ||
| 861 | // TODO: Warning | ||
| 862 | break; | ||
| 863 | } | ||
| 864 | break; | ||
| 865 | default: | ||
| 866 | // TODO: Warning | ||
| 867 | break; | ||
| 868 | } | ||
| 869 | } | ||
| 870 | } | ||
| 871 | |||
| 872 | /// <summary> | ||
| 873 | /// Decompile the ComPlusApplicationRole table. | ||
| 874 | /// </summary> | ||
| 875 | /// <param name="table">The table to decompile.</param> | ||
| 876 | private void DecompileComPlusApplicationRoleTable(Table table) | ||
| 877 | { | ||
| 878 | foreach (Row row in table.Rows) | ||
| 879 | { | ||
| 880 | ComPlus.ComPlusApplicationRole applicationRole = new ComPlus.ComPlusApplicationRole(); | ||
| 881 | |||
| 882 | applicationRole.Id = (string)row[0]; | ||
| 883 | applicationRole.Application = (string)row[1]; | ||
| 884 | |||
| 885 | if (null != row[3]) | ||
| 886 | { | ||
| 887 | applicationRole.Name = (string)row[3]; | ||
| 888 | } | ||
| 889 | |||
| 890 | if (null != row[2]) | ||
| 891 | { | ||
| 892 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 893 | if (null != component) | ||
| 894 | { | ||
| 895 | component.AddChild(applicationRole); | ||
| 896 | } | ||
| 897 | else | ||
| 898 | { | ||
| 899 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 900 | } | ||
| 901 | } | ||
| 902 | else | ||
| 903 | { | ||
| 904 | this.Core.RootElement.AddChild(applicationRole); | ||
| 905 | } | ||
| 906 | this.Core.IndexElement(row, applicationRole); | ||
| 907 | } | ||
| 908 | } | ||
| 909 | |||
| 910 | /// <summary> | ||
| 911 | /// Decompile the ComPlusApplicationRoleProperty table. | ||
| 912 | /// </summary> | ||
| 913 | /// <param name="table">The table to decompile.</param> | ||
| 914 | private void DecompileComPlusApplicationRolePropertyTable(Table table) | ||
| 915 | { | ||
| 916 | foreach (Row row in table.Rows) | ||
| 917 | { | ||
| 918 | ComPlus.ComPlusApplicationRole applicationRole = (ComPlus.ComPlusApplicationRole)this.Core.GetIndexedElement("ComPlusApplicationRole", (string)row[0]); | ||
| 919 | if (null == applicationRole) | ||
| 920 | { | ||
| 921 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ApplicationRole_", (string)row[0], "ComPlusApplicationRole")); | ||
| 922 | } | ||
| 923 | |||
| 924 | switch ((string)row[1]) | ||
| 925 | { | ||
| 926 | case "Description": | ||
| 927 | applicationRole.Description = (string)row[2]; | ||
| 928 | break; | ||
| 929 | default: | ||
| 930 | // TODO: Warning | ||
| 931 | break; | ||
| 932 | } | ||
| 933 | } | ||
| 934 | } | ||
| 935 | |||
| 936 | /// <summary> | ||
| 937 | /// Decompile the ComPlusUserInApplicationRole table. | ||
| 938 | /// </summary> | ||
| 939 | /// <param name="table">The table to decompile.</param> | ||
| 940 | private void DecompileComPlusUserInApplicationRoleTable(Table table) | ||
| 941 | { | ||
| 942 | foreach (Row row in table.Rows) | ||
| 943 | { | ||
| 944 | ComPlus.ComPlusUserInApplicationRole userInApplicationRole = new ComPlus.ComPlusUserInApplicationRole(); | ||
| 945 | |||
| 946 | userInApplicationRole.Id = (string)row[0]; | ||
| 947 | userInApplicationRole.ApplicationRole = (string)row[1]; | ||
| 948 | userInApplicationRole.User = (string)row[3]; | ||
| 949 | |||
| 950 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 951 | if (null != component) | ||
| 952 | { | ||
| 953 | component.AddChild(userInApplicationRole); | ||
| 954 | } | ||
| 955 | else | ||
| 956 | { | ||
| 957 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 958 | } | ||
| 959 | } | ||
| 960 | } | ||
| 961 | |||
| 962 | /// <summary> | ||
| 963 | /// Decompile the ComPlusGroupInApplicationRole table. | ||
| 964 | /// </summary> | ||
| 965 | /// <param name="table">The table to decompile.</param> | ||
| 966 | private void DecompileComPlusGroupInApplicationRoleTable(Table table) | ||
| 967 | { | ||
| 968 | foreach (Row row in table.Rows) | ||
| 969 | { | ||
| 970 | ComPlus.ComPlusGroupInApplicationRole groupInApplicationRole = new ComPlus.ComPlusGroupInApplicationRole(); | ||
| 971 | |||
| 972 | groupInApplicationRole.Id = (string)row[0]; | ||
| 973 | groupInApplicationRole.ApplicationRole = (string)row[1]; | ||
| 974 | groupInApplicationRole.Group = (string)row[3]; | ||
| 975 | |||
| 976 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 977 | if (null != component) | ||
| 978 | { | ||
| 979 | component.AddChild(groupInApplicationRole); | ||
| 980 | } | ||
| 981 | else | ||
| 982 | { | ||
| 983 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 984 | } | ||
| 985 | } | ||
| 986 | } | ||
| 987 | |||
| 988 | /// <summary> | ||
| 989 | /// Decompile the ComPlusAssembly table. | ||
| 990 | /// </summary> | ||
| 991 | /// <param name="table">The table to decompile.</param> | ||
| 992 | private void DecompileComPlusAssemblyTable(Table table) | ||
| 993 | { | ||
| 994 | foreach (Row row in table.Rows) | ||
| 995 | { | ||
| 996 | ComPlus.ComPlusAssembly assembly = new ComPlus.ComPlusAssembly(); | ||
| 997 | |||
| 998 | assembly.Id = (string)row[0]; | ||
| 999 | assembly.Application = (string)row[1]; | ||
| 1000 | |||
| 1001 | if (null != row[3]) | ||
| 1002 | { | ||
| 1003 | assembly.AssemblyName = (string)row[3]; | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | if (null != row[4]) | ||
| 1007 | { | ||
| 1008 | assembly.DllPath = (string)row[4]; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | if (null != row[5]) | ||
| 1012 | { | ||
| 1013 | assembly.TlbPath = (string)row[5]; | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | if (null != row[6]) | ||
| 1017 | { | ||
| 1018 | assembly.PSDllPath = (string)row[6]; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | int attributes = (int)row[7]; | ||
| 1022 | |||
| 1023 | if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.EventClass)) | ||
| 1024 | { | ||
| 1025 | assembly.EventClass = ComPlus.YesNoType.yes; | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.DotNetAssembly)) | ||
| 1029 | { | ||
| 1030 | assembly.Type = ComPlus.ComPlusAssembly.TypeType.net; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.DllPathFromGAC)) | ||
| 1034 | { | ||
| 1035 | assembly.DllPathFromGAC = ComPlus.YesNoType.yes; | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | if (0 != (attributes & (int)ComPlusCompiler.CpiAssemblyAttributes.RegisterInCommit)) | ||
| 1039 | { | ||
| 1040 | assembly.RegisterInCommit = ComPlus.YesNoType.yes; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 1044 | if (null != component) | ||
| 1045 | { | ||
| 1046 | component.AddChild(assembly); | ||
| 1047 | } | ||
| 1048 | else | ||
| 1049 | { | ||
| 1050 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 1051 | } | ||
| 1052 | this.Core.IndexElement(row, assembly); | ||
| 1053 | } | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | /// <summary> | ||
| 1057 | /// Decompile the ComPlusAssemblyDependency table. | ||
| 1058 | /// </summary> | ||
| 1059 | /// <param name="table">The table to decompile.</param> | ||
| 1060 | private void DecompileComPlusAssemblyDependencyTable(Table table) | ||
| 1061 | { | ||
| 1062 | foreach (Row row in table.Rows) | ||
| 1063 | { | ||
| 1064 | ComPlus.ComPlusAssemblyDependency assemblyDependency = new ComPlus.ComPlusAssemblyDependency(); | ||
| 1065 | |||
| 1066 | assemblyDependency.RequiredAssembly = (string)row[1]; | ||
| 1067 | |||
| 1068 | ComPlus.ComPlusAssembly assembly = (ComPlus.ComPlusAssembly)this.Core.GetIndexedElement("ComPlusAssembly", (string)row[0]); | ||
| 1069 | if (null != assembly) | ||
| 1070 | { | ||
| 1071 | assembly.AddChild(assemblyDependency); | ||
| 1072 | } | ||
| 1073 | else | ||
| 1074 | { | ||
| 1075 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Assembly_", (string)row[0], "ComPlusAssembly")); | ||
| 1076 | } | ||
| 1077 | } | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | /// <summary> | ||
| 1081 | /// Decompile the ComPlusComponent table. | ||
| 1082 | /// </summary> | ||
| 1083 | /// <param name="table">The table to decompile.</param> | ||
| 1084 | private void DecompileComPlusComponentTable(Table table) | ||
| 1085 | { | ||
| 1086 | foreach (Row row in table.Rows) | ||
| 1087 | { | ||
| 1088 | ComPlus.ComPlusComponent comPlusComponent = new ComPlus.ComPlusComponent(); | ||
| 1089 | |||
| 1090 | comPlusComponent.Id = (string)row[0]; | ||
| 1091 | |||
| 1092 | try | ||
| 1093 | { | ||
| 1094 | Guid clsid = new Guid((string)row[2]); | ||
| 1095 | comPlusComponent.CLSID = clsid.ToString().ToUpper(); | ||
| 1096 | } | ||
| 1097 | catch | ||
| 1098 | { | ||
| 1099 | // TODO: Warning | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | ComPlus.ComPlusAssembly assembly = (ComPlus.ComPlusAssembly)this.Core.GetIndexedElement("ComPlusAssembly", (string)row[1]); | ||
| 1103 | if (null != assembly) | ||
| 1104 | { | ||
| 1105 | assembly.AddChild(comPlusComponent); | ||
| 1106 | } | ||
| 1107 | else | ||
| 1108 | { | ||
| 1109 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Assembly_", (string)row[1], "ComPlusAssembly")); | ||
| 1110 | } | ||
| 1111 | this.Core.IndexElement(row, comPlusComponent); | ||
| 1112 | } | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | /// <summary> | ||
| 1116 | /// Decompile the ComPlusComponentProperty table. | ||
| 1117 | /// </summary> | ||
| 1118 | /// <param name="table">The table to decompile.</param> | ||
| 1119 | private void DecompileComPlusComponentPropertyTable(Table table) | ||
| 1120 | { | ||
| 1121 | foreach (Row row in table.Rows) | ||
| 1122 | { | ||
| 1123 | ComPlus.ComPlusComponent comPlusComponent = (ComPlus.ComPlusComponent)this.Core.GetIndexedElement("ComPlusComponent", (string)row[0]); | ||
| 1124 | if (null == comPlusComponent) | ||
| 1125 | { | ||
| 1126 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ComPlusComponent_", (string)row[0], "ComPlusComponent")); | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | switch ((string)row[1]) | ||
| 1130 | { | ||
| 1131 | case "AllowInprocSubscribers": | ||
| 1132 | switch ((string)row[2]) | ||
| 1133 | { | ||
| 1134 | case "1": | ||
| 1135 | comPlusComponent.AllowInprocSubscribers = ComPlus.YesNoType.yes; | ||
| 1136 | break; | ||
| 1137 | case "0": | ||
| 1138 | comPlusComponent.AllowInprocSubscribers = ComPlus.YesNoType.no; | ||
| 1139 | break; | ||
| 1140 | default: | ||
| 1141 | // TODO: Warning | ||
| 1142 | break; | ||
| 1143 | } | ||
| 1144 | break; | ||
| 1145 | case "ComponentAccessChecksEnabled": | ||
| 1146 | switch ((string)row[2]) | ||
| 1147 | { | ||
| 1148 | case "1": | ||
| 1149 | comPlusComponent.ComponentAccessChecksEnabled = ComPlus.YesNoType.yes; | ||
| 1150 | break; | ||
| 1151 | case "0": | ||
| 1152 | comPlusComponent.ComponentAccessChecksEnabled = ComPlus.YesNoType.no; | ||
| 1153 | break; | ||
| 1154 | default: | ||
| 1155 | // TODO: Warning | ||
| 1156 | break; | ||
| 1157 | } | ||
| 1158 | break; | ||
| 1159 | case "ComponentTransactionTimeout": | ||
| 1160 | int componentTransactionTimeout; | ||
| 1161 | if (Int32.TryParse((string)row[2], out componentTransactionTimeout)) | ||
| 1162 | { | ||
| 1163 | comPlusComponent.ComponentTransactionTimeout = componentTransactionTimeout; | ||
| 1164 | } | ||
| 1165 | else | ||
| 1166 | { | ||
| 1167 | // TODO: Warning | ||
| 1168 | } | ||
| 1169 | break; | ||
| 1170 | case "ComponentTransactionTimeoutEnabled": | ||
| 1171 | switch ((string)row[2]) | ||
| 1172 | { | ||
| 1173 | case "1": | ||
| 1174 | comPlusComponent.ComponentTransactionTimeoutEnabled = ComPlus.YesNoType.yes; | ||
| 1175 | break; | ||
| 1176 | case "0": | ||
| 1177 | comPlusComponent.ComponentTransactionTimeoutEnabled = ComPlus.YesNoType.no; | ||
| 1178 | break; | ||
| 1179 | default: | ||
| 1180 | // TODO: Warning | ||
| 1181 | break; | ||
| 1182 | } | ||
| 1183 | break; | ||
| 1184 | case "COMTIIntrinsics": | ||
| 1185 | switch ((string)row[2]) | ||
| 1186 | { | ||
| 1187 | case "1": | ||
| 1188 | comPlusComponent.COMTIIntrinsics = ComPlus.YesNoType.yes; | ||
| 1189 | break; | ||
| 1190 | case "0": | ||
| 1191 | comPlusComponent.COMTIIntrinsics = ComPlus.YesNoType.no; | ||
| 1192 | break; | ||
| 1193 | default: | ||
| 1194 | // TODO: Warning | ||
| 1195 | break; | ||
| 1196 | } | ||
| 1197 | break; | ||
| 1198 | case "ConstructionEnabled": | ||
| 1199 | switch ((string)row[2]) | ||
| 1200 | { | ||
| 1201 | case "1": | ||
| 1202 | comPlusComponent.ConstructionEnabled = ComPlus.YesNoType.yes; | ||
| 1203 | break; | ||
| 1204 | case "0": | ||
| 1205 | comPlusComponent.ConstructionEnabled = ComPlus.YesNoType.no; | ||
| 1206 | break; | ||
| 1207 | default: | ||
| 1208 | // TODO: Warning | ||
| 1209 | break; | ||
| 1210 | } | ||
| 1211 | break; | ||
| 1212 | case "ConstructorString": | ||
| 1213 | comPlusComponent.ConstructorString = (string)row[2]; | ||
| 1214 | break; | ||
| 1215 | case "CreationTimeout": | ||
| 1216 | int creationTimeout; | ||
| 1217 | if (Int32.TryParse((string)row[2], out creationTimeout)) | ||
| 1218 | { | ||
| 1219 | comPlusComponent.CreationTimeout = creationTimeout; | ||
| 1220 | } | ||
| 1221 | else | ||
| 1222 | { | ||
| 1223 | // TODO: Warning | ||
| 1224 | } | ||
| 1225 | break; | ||
| 1226 | case "Description": | ||
| 1227 | comPlusComponent.Description = (string)row[2]; | ||
| 1228 | break; | ||
| 1229 | case "EventTrackingEnabled": | ||
| 1230 | switch ((string)row[2]) | ||
| 1231 | { | ||
| 1232 | case "1": | ||
| 1233 | comPlusComponent.EventTrackingEnabled = ComPlus.YesNoType.yes; | ||
| 1234 | break; | ||
| 1235 | case "0": | ||
| 1236 | comPlusComponent.EventTrackingEnabled = ComPlus.YesNoType.no; | ||
| 1237 | break; | ||
| 1238 | default: | ||
| 1239 | // TODO: Warning | ||
| 1240 | break; | ||
| 1241 | } | ||
| 1242 | break; | ||
| 1243 | case "ExceptionClass": | ||
| 1244 | comPlusComponent.ExceptionClass = (string)row[2]; | ||
| 1245 | break; | ||
| 1246 | case "FireInParallel": | ||
| 1247 | switch ((string)row[2]) | ||
| 1248 | { | ||
| 1249 | case "1": | ||
| 1250 | comPlusComponent.FireInParallel = ComPlus.YesNoType.yes; | ||
| 1251 | break; | ||
| 1252 | case "0": | ||
| 1253 | comPlusComponent.FireInParallel = ComPlus.YesNoType.no; | ||
| 1254 | break; | ||
| 1255 | default: | ||
| 1256 | // TODO: Warning | ||
| 1257 | break; | ||
| 1258 | } | ||
| 1259 | break; | ||
| 1260 | case "IISIntrinsics": | ||
| 1261 | switch ((string)row[2]) | ||
| 1262 | { | ||
| 1263 | case "1": | ||
| 1264 | comPlusComponent.IISIntrinsics = ComPlus.YesNoType.yes; | ||
| 1265 | break; | ||
| 1266 | case "0": | ||
| 1267 | comPlusComponent.IISIntrinsics = ComPlus.YesNoType.no; | ||
| 1268 | break; | ||
| 1269 | default: | ||
| 1270 | // TODO: Warning | ||
| 1271 | break; | ||
| 1272 | } | ||
| 1273 | break; | ||
| 1274 | case "InitializesServerApplication": | ||
| 1275 | switch ((string)row[2]) | ||
| 1276 | { | ||
| 1277 | case "1": | ||
| 1278 | comPlusComponent.InitializesServerApplication = ComPlus.YesNoType.yes; | ||
| 1279 | break; | ||
| 1280 | case "0": | ||
| 1281 | comPlusComponent.InitializesServerApplication = ComPlus.YesNoType.no; | ||
| 1282 | break; | ||
| 1283 | default: | ||
| 1284 | // TODO: Warning | ||
| 1285 | break; | ||
| 1286 | } | ||
| 1287 | break; | ||
| 1288 | case "IsEnabled": | ||
| 1289 | switch ((string)row[2]) | ||
| 1290 | { | ||
| 1291 | case "1": | ||
| 1292 | comPlusComponent.IsEnabled = ComPlus.YesNoType.yes; | ||
| 1293 | break; | ||
| 1294 | case "0": | ||
| 1295 | comPlusComponent.IsEnabled = ComPlus.YesNoType.no; | ||
| 1296 | break; | ||
| 1297 | default: | ||
| 1298 | // TODO: Warning | ||
| 1299 | break; | ||
| 1300 | } | ||
| 1301 | break; | ||
| 1302 | case "IsPrivateComponent": | ||
| 1303 | switch ((string)row[2]) | ||
| 1304 | { | ||
| 1305 | case "1": | ||
| 1306 | comPlusComponent.IsPrivateComponent = ComPlus.YesNoType.yes; | ||
| 1307 | break; | ||
| 1308 | case "0": | ||
| 1309 | comPlusComponent.IsPrivateComponent = ComPlus.YesNoType.no; | ||
| 1310 | break; | ||
| 1311 | default: | ||
| 1312 | // TODO: Warning | ||
| 1313 | break; | ||
| 1314 | } | ||
| 1315 | break; | ||
| 1316 | case "JustInTimeActivation": | ||
| 1317 | switch ((string)row[2]) | ||
| 1318 | { | ||
| 1319 | case "1": | ||
| 1320 | comPlusComponent.JustInTimeActivation = ComPlus.YesNoType.yes; | ||
| 1321 | break; | ||
| 1322 | case "0": | ||
| 1323 | comPlusComponent.JustInTimeActivation = ComPlus.YesNoType.no; | ||
| 1324 | break; | ||
| 1325 | default: | ||
| 1326 | // TODO: Warning | ||
| 1327 | break; | ||
| 1328 | } | ||
| 1329 | break; | ||
| 1330 | case "LoadBalancingSupported": | ||
| 1331 | switch ((string)row[2]) | ||
| 1332 | { | ||
| 1333 | case "1": | ||
| 1334 | comPlusComponent.LoadBalancingSupported = ComPlus.YesNoType.yes; | ||
| 1335 | break; | ||
| 1336 | case "0": | ||
| 1337 | comPlusComponent.LoadBalancingSupported = ComPlus.YesNoType.no; | ||
| 1338 | break; | ||
| 1339 | default: | ||
| 1340 | // TODO: Warning | ||
| 1341 | break; | ||
| 1342 | } | ||
| 1343 | break; | ||
| 1344 | case "MaxPoolSize": | ||
| 1345 | int maxPoolSize; | ||
| 1346 | if (Int32.TryParse((string)row[2], out maxPoolSize)) | ||
| 1347 | { | ||
| 1348 | comPlusComponent.MaxPoolSize = maxPoolSize; | ||
| 1349 | } | ||
| 1350 | else | ||
| 1351 | { | ||
| 1352 | // TODO: Warning | ||
| 1353 | } | ||
| 1354 | break; | ||
| 1355 | case "MinPoolSize": | ||
| 1356 | int minPoolSize; | ||
| 1357 | if (Int32.TryParse((string)row[2], out minPoolSize)) | ||
| 1358 | { | ||
| 1359 | comPlusComponent.MinPoolSize = minPoolSize; | ||
| 1360 | } | ||
| 1361 | else | ||
| 1362 | { | ||
| 1363 | // TODO: Warning | ||
| 1364 | } | ||
| 1365 | break; | ||
| 1366 | case "MultiInterfacePublisherFilterCLSID": | ||
| 1367 | comPlusComponent.MultiInterfacePublisherFilterCLSID = (string)row[2]; | ||
| 1368 | break; | ||
| 1369 | case "MustRunInClientContext": | ||
| 1370 | switch ((string)row[2]) | ||
| 1371 | { | ||
| 1372 | case "1": | ||
| 1373 | comPlusComponent.MustRunInClientContext = ComPlus.YesNoType.yes; | ||
| 1374 | break; | ||
| 1375 | case "0": | ||
| 1376 | comPlusComponent.MustRunInClientContext = ComPlus.YesNoType.no; | ||
| 1377 | break; | ||
| 1378 | default: | ||
| 1379 | // TODO: Warning | ||
| 1380 | break; | ||
| 1381 | } | ||
| 1382 | break; | ||
| 1383 | case "MustRunInDefaultContext": | ||
| 1384 | switch ((string)row[2]) | ||
| 1385 | { | ||
| 1386 | case "1": | ||
| 1387 | comPlusComponent.MustRunInDefaultContext = ComPlus.YesNoType.yes; | ||
| 1388 | break; | ||
| 1389 | case "0": | ||
| 1390 | comPlusComponent.MustRunInDefaultContext = ComPlus.YesNoType.no; | ||
| 1391 | break; | ||
| 1392 | default: | ||
| 1393 | // TODO: Warning | ||
| 1394 | break; | ||
| 1395 | } | ||
| 1396 | break; | ||
| 1397 | case "ObjectPoolingEnabled": | ||
| 1398 | switch ((string)row[2]) | ||
| 1399 | { | ||
| 1400 | case "1": | ||
| 1401 | comPlusComponent.ObjectPoolingEnabled = ComPlus.YesNoType.yes; | ||
| 1402 | break; | ||
| 1403 | case "0": | ||
| 1404 | comPlusComponent.ObjectPoolingEnabled = ComPlus.YesNoType.no; | ||
| 1405 | break; | ||
| 1406 | default: | ||
| 1407 | // TODO: Warning | ||
| 1408 | break; | ||
| 1409 | } | ||
| 1410 | break; | ||
| 1411 | case "PublisherID": | ||
| 1412 | comPlusComponent.PublisherID = (string)row[2]; | ||
| 1413 | break; | ||
| 1414 | case "SoapAssemblyName": | ||
| 1415 | comPlusComponent.SoapAssemblyName = (string)row[2]; | ||
| 1416 | break; | ||
| 1417 | case "SoapTypeName": | ||
| 1418 | comPlusComponent.SoapTypeName = (string)row[2]; | ||
| 1419 | break; | ||
| 1420 | case "Synchronization": | ||
| 1421 | switch ((string)row[2]) | ||
| 1422 | { | ||
| 1423 | case "0": | ||
| 1424 | comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.ignored; | ||
| 1425 | break; | ||
| 1426 | case "1": | ||
| 1427 | comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.none; | ||
| 1428 | break; | ||
| 1429 | case "2": | ||
| 1430 | comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.supported; | ||
| 1431 | break; | ||
| 1432 | case "3": | ||
| 1433 | comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.required; | ||
| 1434 | break; | ||
| 1435 | case "4": | ||
| 1436 | comPlusComponent.Synchronization = ComPlus.ComPlusComponent.SynchronizationType.requiresNew; | ||
| 1437 | break; | ||
| 1438 | default: | ||
| 1439 | // TODO: Warning | ||
| 1440 | break; | ||
| 1441 | } | ||
| 1442 | break; | ||
| 1443 | case "Transaction": | ||
| 1444 | switch ((string)row[2]) | ||
| 1445 | { | ||
| 1446 | case "0": | ||
| 1447 | comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.ignored; | ||
| 1448 | break; | ||
| 1449 | case "1": | ||
| 1450 | comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.none; | ||
| 1451 | break; | ||
| 1452 | case "2": | ||
| 1453 | comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.supported; | ||
| 1454 | break; | ||
| 1455 | case "3": | ||
| 1456 | comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.required; | ||
| 1457 | break; | ||
| 1458 | case "4": | ||
| 1459 | comPlusComponent.Transaction = ComPlus.ComPlusComponent.TransactionType.requiresNew; | ||
| 1460 | break; | ||
| 1461 | default: | ||
| 1462 | // TODO: Warning | ||
| 1463 | break; | ||
| 1464 | } | ||
| 1465 | break; | ||
| 1466 | case "TxIsolationLevel": | ||
| 1467 | switch ((string)row[2]) | ||
| 1468 | { | ||
| 1469 | case "0": | ||
| 1470 | comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.any; | ||
| 1471 | break; | ||
| 1472 | case "1": | ||
| 1473 | comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.readUnCommitted; | ||
| 1474 | break; | ||
| 1475 | case "2": | ||
| 1476 | comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.readCommitted; | ||
| 1477 | break; | ||
| 1478 | case "3": | ||
| 1479 | comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.repeatableRead; | ||
| 1480 | break; | ||
| 1481 | case "4": | ||
| 1482 | comPlusComponent.TxIsolationLevel = ComPlus.ComPlusComponent.TxIsolationLevelType.serializable; | ||
| 1483 | break; | ||
| 1484 | default: | ||
| 1485 | // TODO: Warning | ||
| 1486 | break; | ||
| 1487 | } | ||
| 1488 | break; | ||
| 1489 | default: | ||
| 1490 | // TODO: Warning | ||
| 1491 | break; | ||
| 1492 | } | ||
| 1493 | } | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | /// <summary> | ||
| 1497 | /// Decompile the ComPlusRoleForComponent table. | ||
| 1498 | /// </summary> | ||
| 1499 | /// <param name="table">The table to decompile.</param> | ||
| 1500 | private void DecompileComPlusRoleForComponentTable(Table table) | ||
| 1501 | { | ||
| 1502 | foreach (Row row in table.Rows) | ||
| 1503 | { | ||
| 1504 | ComPlus.ComPlusRoleForComponent roleForComponent = new ComPlus.ComPlusRoleForComponent(); | ||
| 1505 | |||
| 1506 | roleForComponent.Id = (string)row[0]; | ||
| 1507 | roleForComponent.Component = (string)row[1]; | ||
| 1508 | roleForComponent.ApplicationRole = (string)row[2]; | ||
| 1509 | |||
| 1510 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[3]); | ||
| 1511 | if (null != component) | ||
| 1512 | { | ||
| 1513 | component.AddChild(roleForComponent); | ||
| 1514 | } | ||
| 1515 | else | ||
| 1516 | { | ||
| 1517 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[3], "Component")); | ||
| 1518 | } | ||
| 1519 | } | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | /// <summary> | ||
| 1523 | /// Decompile the ComPlusInterface table. | ||
| 1524 | /// </summary> | ||
| 1525 | /// <param name="table">The table to decompile.</param> | ||
| 1526 | private void DecompileComPlusInterfaceTable(Table table) | ||
| 1527 | { | ||
| 1528 | foreach (Row row in table.Rows) | ||
| 1529 | { | ||
| 1530 | ComPlus.ComPlusInterface comPlusInterface = new ComPlus.ComPlusInterface(); | ||
| 1531 | |||
| 1532 | comPlusInterface.Id = (string)row[0]; | ||
| 1533 | |||
| 1534 | try | ||
| 1535 | { | ||
| 1536 | Guid iid = new Guid((string)row[2]); | ||
| 1537 | comPlusInterface.IID = iid.ToString().ToUpper(); | ||
| 1538 | } | ||
| 1539 | catch | ||
| 1540 | { | ||
| 1541 | // TODO: Warning | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | ComPlus.ComPlusComponent comPlusComponent = (ComPlus.ComPlusComponent)this.Core.GetIndexedElement("ComPlusComponent", (string)row[1]); | ||
| 1545 | if (null != comPlusComponent) | ||
| 1546 | { | ||
| 1547 | comPlusComponent.AddChild(comPlusInterface); | ||
| 1548 | } | ||
| 1549 | else | ||
| 1550 | { | ||
| 1551 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "ComPlusComponent_", (string)row[1], "ComPlusComponent")); | ||
| 1552 | } | ||
| 1553 | this.Core.IndexElement(row, comPlusInterface); | ||
| 1554 | } | ||
| 1555 | } | ||
| 1556 | |||
| 1557 | /// <summary> | ||
| 1558 | /// Decompile the ComPlusInterfaceProperty table. | ||
| 1559 | /// </summary> | ||
| 1560 | /// <param name="table">The table to decompile.</param> | ||
| 1561 | private void DecompileComPlusInterfacePropertyTable(Table table) | ||
| 1562 | { | ||
| 1563 | foreach (Row row in table.Rows) | ||
| 1564 | { | ||
| 1565 | ComPlus.ComPlusInterface comPlusInterface = (ComPlus.ComPlusInterface)this.Core.GetIndexedElement("ComPlusInterface", (string)row[0]); | ||
| 1566 | if (null == comPlusInterface) | ||
| 1567 | { | ||
| 1568 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Interface_", (string)row[0], "ComPlusInterface")); | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | switch ((string)row[1]) | ||
| 1572 | { | ||
| 1573 | case "Description": | ||
| 1574 | comPlusInterface.Description = (string)row[2]; | ||
| 1575 | break; | ||
| 1576 | case "QueuingEnabled": | ||
| 1577 | switch ((string)row[2]) | ||
| 1578 | { | ||
| 1579 | case "1": | ||
| 1580 | comPlusInterface.QueuingEnabled = ComPlus.YesNoType.yes; | ||
| 1581 | break; | ||
| 1582 | case "0": | ||
| 1583 | comPlusInterface.QueuingEnabled = ComPlus.YesNoType.no; | ||
| 1584 | break; | ||
| 1585 | default: | ||
| 1586 | // TODO: Warning | ||
| 1587 | break; | ||
| 1588 | } | ||
| 1589 | break; | ||
| 1590 | default: | ||
| 1591 | // TODO: Warning | ||
| 1592 | break; | ||
| 1593 | } | ||
| 1594 | } | ||
| 1595 | } | ||
| 1596 | |||
| 1597 | /// <summary> | ||
| 1598 | /// Decompile the ComPlusRoleForInterface table. | ||
| 1599 | /// </summary> | ||
| 1600 | /// <param name="table">The table to decompile.</param> | ||
| 1601 | private void DecompileComPlusRoleForInterfaceTable(Table table) | ||
| 1602 | { | ||
| 1603 | foreach (Row row in table.Rows) | ||
| 1604 | { | ||
| 1605 | ComPlus.ComPlusRoleForInterface roleForInterface = new ComPlus.ComPlusRoleForInterface(); | ||
| 1606 | |||
| 1607 | roleForInterface.Id = (string)row[0]; | ||
| 1608 | roleForInterface.Interface = (string)row[1]; | ||
| 1609 | roleForInterface.ApplicationRole = (string)row[2]; | ||
| 1610 | |||
| 1611 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[3]); | ||
| 1612 | if (null != component) | ||
| 1613 | { | ||
| 1614 | component.AddChild(roleForInterface); | ||
| 1615 | } | ||
| 1616 | else | ||
| 1617 | { | ||
| 1618 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[3], "Component")); | ||
| 1619 | } | ||
| 1620 | } | ||
| 1621 | } | ||
| 1622 | |||
| 1623 | /// <summary> | ||
| 1624 | /// Decompile the ComPlusMethod table. | ||
| 1625 | /// </summary> | ||
| 1626 | /// <param name="table">The table to decompile.</param> | ||
| 1627 | private void DecompileComPlusMethodTable(Table table) | ||
| 1628 | { | ||
| 1629 | foreach (Row row in table.Rows) | ||
| 1630 | { | ||
| 1631 | ComPlus.ComPlusMethod comPlusMethod = new ComPlus.ComPlusMethod(); | ||
| 1632 | |||
| 1633 | comPlusMethod.Id = (string)row[0]; | ||
| 1634 | |||
| 1635 | if (null != row[2]) | ||
| 1636 | { | ||
| 1637 | comPlusMethod.Index = (int)row[2]; | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | if (null != row[3]) | ||
| 1641 | { | ||
| 1642 | comPlusMethod.Name = (string)row[3]; | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | ComPlus.ComPlusInterface comPlusInterface = (ComPlus.ComPlusInterface)this.Core.GetIndexedElement("ComPlusInterface", (string)row[1]); | ||
| 1646 | if (null != comPlusInterface) | ||
| 1647 | { | ||
| 1648 | comPlusInterface.AddChild(comPlusMethod); | ||
| 1649 | } | ||
| 1650 | else | ||
| 1651 | { | ||
| 1652 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Interface_", (string)row[1], "ComPlusInterface")); | ||
| 1653 | } | ||
| 1654 | this.Core.IndexElement(row, comPlusMethod); | ||
| 1655 | } | ||
| 1656 | } | ||
| 1657 | |||
| 1658 | /// <summary> | ||
| 1659 | /// Decompile the ComPlusMethodProperty table. | ||
| 1660 | /// </summary> | ||
| 1661 | /// <param name="table">The table to decompile.</param> | ||
| 1662 | private void DecompileComPlusMethodPropertyTable(Table table) | ||
| 1663 | { | ||
| 1664 | foreach (Row row in table.Rows) | ||
| 1665 | { | ||
| 1666 | ComPlus.ComPlusMethod comPlusMethod = (ComPlus.ComPlusMethod)this.Core.GetIndexedElement("ComPlusMethod", (string)row[0]); | ||
| 1667 | if (null == comPlusMethod) | ||
| 1668 | { | ||
| 1669 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Method_", (string)row[0], "ComPlusMethod")); | ||
| 1670 | } | ||
| 1671 | |||
| 1672 | switch ((string)row[1]) | ||
| 1673 | { | ||
| 1674 | case "AutoComplete": | ||
| 1675 | switch ((string)row[2]) | ||
| 1676 | { | ||
| 1677 | case "1": | ||
| 1678 | comPlusMethod.AutoComplete = ComPlus.YesNoType.yes; | ||
| 1679 | break; | ||
| 1680 | case "0": | ||
| 1681 | comPlusMethod.AutoComplete = ComPlus.YesNoType.no; | ||
| 1682 | break; | ||
| 1683 | default: | ||
| 1684 | // TODO: Warning | ||
| 1685 | break; | ||
| 1686 | } | ||
| 1687 | break; | ||
| 1688 | case "Description": | ||
| 1689 | comPlusMethod.Description = (string)row[2]; | ||
| 1690 | break; | ||
| 1691 | default: | ||
| 1692 | // TODO: Warning | ||
| 1693 | break; | ||
| 1694 | } | ||
| 1695 | } | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | /// <summary> | ||
| 1699 | /// Decompile the ComPlusRoleForMethod table. | ||
| 1700 | /// </summary> | ||
| 1701 | /// <param name="table">The table to decompile.</param> | ||
| 1702 | private void DecompileComPlusRoleForMethodTable(Table table) | ||
| 1703 | { | ||
| 1704 | foreach (Row row in table.Rows) | ||
| 1705 | { | ||
| 1706 | ComPlus.ComPlusRoleForMethod roleForMethod = new ComPlus.ComPlusRoleForMethod(); | ||
| 1707 | |||
| 1708 | roleForMethod.Id = (string)row[0]; | ||
| 1709 | roleForMethod.Method = (string)row[1]; | ||
| 1710 | roleForMethod.ApplicationRole = (string)row[2]; | ||
| 1711 | |||
| 1712 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[3]); | ||
| 1713 | if (null != component) | ||
| 1714 | { | ||
| 1715 | component.AddChild(roleForMethod); | ||
| 1716 | } | ||
| 1717 | else | ||
| 1718 | { | ||
| 1719 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[3], "Component")); | ||
| 1720 | } | ||
| 1721 | } | ||
| 1722 | } | ||
| 1723 | |||
| 1724 | /// <summary> | ||
| 1725 | /// Decompile the ComPlusSubscription table. | ||
| 1726 | /// </summary> | ||
| 1727 | /// <param name="table">The table to decompile.</param> | ||
| 1728 | private void DecompileComPlusSubscriptionTable(Table table) | ||
| 1729 | { | ||
| 1730 | foreach (Row row in table.Rows) | ||
| 1731 | { | ||
| 1732 | ComPlus.ComPlusSubscription subscription = new ComPlus.ComPlusSubscription(); | ||
| 1733 | |||
| 1734 | subscription.Id = (string)row[0]; | ||
| 1735 | subscription.Component = (string)row[1]; | ||
| 1736 | subscription.SubscriptionId = (string)row[3]; | ||
| 1737 | subscription.Name = (string)row[4]; | ||
| 1738 | subscription.EventCLSID = (string)row[5]; | ||
| 1739 | subscription.PublisherID = (string)row[6]; | ||
| 1740 | |||
| 1741 | Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]); | ||
| 1742 | if (null != component) | ||
| 1743 | { | ||
| 1744 | component.AddChild(subscription); | ||
| 1745 | } | ||
| 1746 | else | ||
| 1747 | { | ||
| 1748 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component")); | ||
| 1749 | } | ||
| 1750 | this.Core.IndexElement(row, subscription); | ||
| 1751 | } | ||
| 1752 | } | ||
| 1753 | |||
| 1754 | /// <summary> | ||
| 1755 | /// Decompile the ComPlusSubscriptionProperty table. | ||
| 1756 | /// </summary> | ||
| 1757 | /// <param name="table">The table to decompile.</param> | ||
| 1758 | private void DecompileComPlusSubscriptionPropertyTable(Table table) | ||
| 1759 | { | ||
| 1760 | foreach (Row row in table.Rows) | ||
| 1761 | { | ||
| 1762 | ComPlus.ComPlusSubscription subscription = (ComPlus.ComPlusSubscription)this.Core.GetIndexedElement("ComPlusSubscription", (string)row[0]); | ||
| 1763 | if (null == subscription) | ||
| 1764 | { | ||
| 1765 | this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Subscription_", (string)row[0], "ComPlusSubscription")); | ||
| 1766 | } | ||
| 1767 | |||
| 1768 | switch ((string)row[1]) | ||
| 1769 | { | ||
| 1770 | case "Description": | ||
| 1771 | subscription.Description = (string)row[2]; | ||
| 1772 | break; | ||
| 1773 | case "Enabled": | ||
| 1774 | switch ((string)row[2]) | ||
| 1775 | { | ||
| 1776 | case "1": | ||
| 1777 | subscription.Enabled = ComPlus.YesNoType.yes; | ||
| 1778 | break; | ||
| 1779 | case "0": | ||
| 1780 | subscription.Enabled = ComPlus.YesNoType.no; | ||
| 1781 | break; | ||
| 1782 | default: | ||
| 1783 | // TODO: Warning | ||
| 1784 | break; | ||
| 1785 | } | ||
| 1786 | break; | ||
| 1787 | case "EventClassPartitionID": | ||
| 1788 | subscription.EventClassPartitionID = (string)row[2]; | ||
| 1789 | break; | ||
| 1790 | case "FilterCriteria": | ||
| 1791 | subscription.FilterCriteria = (string)row[2]; | ||
| 1792 | break; | ||
| 1793 | case "InterfaceID": | ||
| 1794 | subscription.InterfaceID = (string)row[2]; | ||
| 1795 | break; | ||
| 1796 | case "MachineName": | ||
| 1797 | subscription.MachineName = (string)row[2]; | ||
| 1798 | break; | ||
| 1799 | case "MethodName": | ||
| 1800 | subscription.MethodName = (string)row[2]; | ||
| 1801 | break; | ||
| 1802 | case "PerUser": | ||
| 1803 | switch ((string)row[2]) | ||
| 1804 | { | ||
| 1805 | case "1": | ||
| 1806 | subscription.PerUser = ComPlus.YesNoType.yes; | ||
| 1807 | break; | ||
| 1808 | case "0": | ||
| 1809 | subscription.PerUser = ComPlus.YesNoType.no; | ||
| 1810 | break; | ||
| 1811 | default: | ||
| 1812 | // TODO: Warning | ||
| 1813 | break; | ||
| 1814 | } | ||
| 1815 | break; | ||
| 1816 | case "Queued": | ||
| 1817 | switch ((string)row[2]) | ||
| 1818 | { | ||
| 1819 | case "1": | ||
| 1820 | subscription.Queued = ComPlus.YesNoType.yes; | ||
| 1821 | break; | ||
| 1822 | case "0": | ||
| 1823 | subscription.Queued = ComPlus.YesNoType.no; | ||
| 1824 | break; | ||
| 1825 | default: | ||
| 1826 | // TODO: Warning | ||
| 1827 | break; | ||
| 1828 | } | ||
| 1829 | break; | ||
| 1830 | case "SubscriberMoniker": | ||
| 1831 | subscription.SubscriberMoniker = (string)row[2]; | ||
| 1832 | break; | ||
| 1833 | case "UserName": | ||
| 1834 | subscription.UserName = (string)row[2]; | ||
| 1835 | break; | ||
| 1836 | default: | ||
| 1837 | // TODO: Warning | ||
| 1838 | break; | ||
| 1839 | } | ||
| 1840 | } | ||
| 1841 | } | ||
| 1842 | } | ||
| 1843 | } | ||
diff --git a/src/wixext/ComPlusExtensionData.cs b/src/wixext/ComPlusExtensionData.cs new file mode 100644 index 00000000..cedc2474 --- /dev/null +++ b/src/wixext/ComPlusExtensionData.cs | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Extensions | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Reflection; | ||
| 7 | using WixToolset.Data; | ||
| 8 | using WixToolset.Extensibility; | ||
| 9 | |||
| 10 | /// <summary> | ||
| 11 | /// The WiX Toolset COM+ Extension. | ||
| 12 | /// </summary> | ||
| 13 | public sealed class ComPlusExtensionData : ExtensionData | ||
| 14 | { | ||
| 15 | /// <summary> | ||
| 16 | /// Gets the default culture. | ||
| 17 | /// </summary> | ||
| 18 | /// <value>The default culture.</value> | ||
| 19 | public override string DefaultCulture | ||
| 20 | { | ||
| 21 | get { return "en-us"; } | ||
| 22 | } | ||
| 23 | |||
| 24 | /// <summary> | ||
| 25 | /// Gets the optional table definitions for this extension. | ||
| 26 | /// </summary> | ||
| 27 | /// <value>The optional table definitions for this extension.</value> | ||
| 28 | public override TableDefinitionCollection TableDefinitions | ||
| 29 | { | ||
| 30 | get | ||
| 31 | { | ||
| 32 | return ComPlusExtensionData.GetExtensionTableDefinitions(); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | /// <summary> | ||
| 37 | /// Gets the library associated with this extension. | ||
| 38 | /// </summary> | ||
| 39 | /// <param name="tableDefinitions">The table definitions to use while loading the library.</param> | ||
| 40 | /// <returns>The loaded library.</returns> | ||
| 41 | public override Library GetLibrary(TableDefinitionCollection tableDefinitions) | ||
| 42 | { | ||
| 43 | return ComPlusExtensionData.GetExtensionLibrary(tableDefinitions); | ||
| 44 | } | ||
| 45 | |||
| 46 | /// <summary> | ||
| 47 | /// Internal mechanism to access the extension's table definitions. | ||
| 48 | /// </summary> | ||
| 49 | /// <returns>Extension's table definitions.</returns> | ||
| 50 | internal static TableDefinitionCollection GetExtensionTableDefinitions() | ||
| 51 | { | ||
| 52 | return ExtensionData.LoadTableDefinitionHelper(Assembly.GetExecutingAssembly(), "WixToolset.Extensions.Data.tables.xml"); | ||
| 53 | } | ||
| 54 | |||
| 55 | /// <summary> | ||
| 56 | /// Internal mechanism to access the extension's library. | ||
| 57 | /// </summary> | ||
| 58 | /// <returns>Extension's library.</returns> | ||
| 59 | internal static Library GetExtensionLibrary(TableDefinitionCollection tableDefinitions) | ||
| 60 | { | ||
| 61 | return ExtensionData.LoadLibraryHelper(Assembly.GetExecutingAssembly(), "WixToolset.Extensions.Data.complus.wixlib", tableDefinitions); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
diff --git a/src/wixext/WixComPlusExtension.csproj b/src/wixext/WixComPlusExtension.csproj new file mode 100644 index 00000000..92cbacae --- /dev/null +++ b/src/wixext/WixComPlusExtension.csproj | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | |||
| 5 | <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | ||
| 6 | <PropertyGroup> | ||
| 7 | <ProjectGuid>{1497B777-330B-4CFE-927A-22850CD24D64}</ProjectGuid> | ||
| 8 | <AssemblyName>WixComPlusExtension</AssemblyName> | ||
| 9 | <OutputType>Library</OutputType> | ||
| 10 | <RootNamespace>WixToolset.Extensions</RootNamespace> | ||
| 11 | </PropertyGroup> | ||
| 12 | <ItemGroup> | ||
| 13 | <Compile Include="AssemblyInfo.cs" /> | ||
| 14 | <Compile Include="ComPlusCompiler.cs" /> | ||
| 15 | <Compile Include="ComPlusDecompiler.cs" /> | ||
| 16 | <Compile Include="ComPlusExtensionData.cs" /> | ||
| 17 | <MsgGenSource Include="Data\messages.xml"> | ||
| 18 | <ResourcesLogicalName>$(RootNamespace).Data.Messages.resources</ResourcesLogicalName> | ||
| 19 | </MsgGenSource> | ||
| 20 | <EmbeddedFlattenedResource Include="Data\tables.xml"> | ||
| 21 | <LogicalName>$(RootNamespace).Data.tables.xml</LogicalName> | ||
| 22 | </EmbeddedFlattenedResource> | ||
| 23 | <EmbeddedFlattenedResource Include="Xsd\complus.xsd"> | ||
| 24 | <LogicalName>$(RootNamespace).Xsd.complus.xsd</LogicalName> | ||
| 25 | </EmbeddedFlattenedResource> | ||
| 26 | <XsdGenSource Include="Xsd\complus.xsd"> | ||
| 27 | <CommonNamespace>WixToolset.Data.Serialize</CommonNamespace> | ||
| 28 | <Namespace>WixToolset.Extensions.Serialize.ComPlus</Namespace> | ||
| 29 | </XsdGenSource> | ||
| 30 | <None Include="Xsd\complus.xsd"> | ||
| 31 | <Link>complus.xsd</Link> | ||
| 32 | <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
| 33 | </None> | ||
| 34 | <EmbeddedResource Include="$(OutputPath)\complus.wixlib"> | ||
| 35 | <Link>Data\complus.wixlib</Link> | ||
| 36 | </EmbeddedResource> | ||
| 37 | </ItemGroup> | ||
| 38 | <ItemGroup> | ||
| 39 | <Reference Include="System" /> | ||
| 40 | <Reference Include="System.Xml" /> | ||
| 41 | <Reference Include="System.Xml.Linq" /> | ||
| 42 | <ProjectReference Include="..\..\..\libs\WixToolset.Data\WixToolset.Data.csproj" /> | ||
| 43 | <ProjectReference Include="..\..\..\libs\WixToolset.Extensibility\WixToolset.Extensibility.csproj" /> | ||
| 44 | <ProjectReference Include="..\..\..\tools\wix\Wix.csproj" /> | ||
| 45 | <ProjectReference Include="..\wixlib\ComPlusExtension.wixproj"> | ||
| 46 | <ReferenceOutputAssembly>false</ReferenceOutputAssembly> | ||
| 47 | </ProjectReference> | ||
| 48 | </ItemGroup> | ||
| 49 | <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.targets" /> | ||
| 50 | </Project> | ||
diff --git a/src/wixext/complus.xsd b/src/wixext/complus.xsd new file mode 100644 index 00000000..f7ddacc6 --- /dev/null +++ b/src/wixext/complus.xsd | |||
| @@ -0,0 +1,944 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | |||
| 5 | <xs:schema xmlns:html="http://www.w3.org/1999/xhtml" | ||
| 6 | xmlns:wix="http://wixtoolset.org/schemas/v4/wxs" | ||
| 7 | xmlns:xs="http://www.w3.org/2001/XMLSchema" | ||
| 8 | xmlns:xse=" http://wixtoolset.org/schemas/XmlSchemaExtension" | ||
| 9 | targetNamespace="http://wixtoolset.org/schemas/v4/wxs/complus" | ||
| 10 | xmlns="http://wixtoolset.org/schemas/v4/wxs/complus"> | ||
| 11 | <xs:annotation> | ||
| 12 | <xs:documentation> | ||
| 13 | The source code schema for the WiX Toolset COM+ Extension. | ||
| 14 | </xs:documentation> | ||
| 15 | </xs:annotation> | ||
| 16 | |||
| 17 | <xs:import namespace="http://wixtoolset.org/schemas/v4/wxs" /> | ||
| 18 | |||
| 19 | <xs:element name="ComPlusPartition"> | ||
| 20 | <xs:annotation> | ||
| 21 | <xs:appinfo> | ||
| 22 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 23 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Fragment" /> | ||
| 24 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Module" /> | ||
| 25 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Product" /> | ||
| 26 | </xs:appinfo> | ||
| 27 | <xs:documentation> | ||
| 28 | Defines a COM+ partition. If this element is a child of a | ||
| 29 | Component element, the partition will be created in association with this | ||
| 30 | component. If the element is a child of any of the Fragment, Module or Product | ||
| 31 | elements it is considered to be a locater, referencing an existing partition. | ||
| 32 | </xs:documentation> | ||
| 33 | </xs:annotation> | ||
| 34 | <xs:complexType> | ||
| 35 | <xs:sequence> | ||
| 36 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
| 37 | <xs:element ref="ComPlusPartitionRole" /> | ||
| 38 | <xs:element ref="ComPlusPartitionUser" /> | ||
| 39 | <xs:element ref="ComPlusApplication" /> | ||
| 40 | </xs:choice> | ||
| 41 | </xs:sequence> | ||
| 42 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 43 | <xs:annotation><xs:documentation> | ||
| 44 | Identifier for the element. | ||
| 45 | </xs:documentation></xs:annotation> | ||
| 46 | </xs:attribute> | ||
| 47 | <xs:attribute name="PartitionId" use="optional" type="xs:string"> | ||
| 48 | <xs:annotation><xs:documentation> | ||
| 49 | Id for the partition. This attribute can be omitted, in | ||
| 50 | which case an id will be generated on install. If the element is a locater, | ||
| 51 | this attribute can be omitted if a value is provided for the Name attribute. | ||
| 52 | </xs:documentation></xs:annotation> | ||
| 53 | </xs:attribute> | ||
| 54 | <xs:attribute name="Name" use="optional" type="xs:string"> | ||
| 55 | <xs:annotation><xs:documentation> | ||
| 56 | Name of the partition. This attribute can be omitted if | ||
| 57 | the element is a locater, and a value is provided for the PartitionId | ||
| 58 | attribute. | ||
| 59 | </xs:documentation></xs:annotation> | ||
| 60 | </xs:attribute> | ||
| 61 | <xs:attribute name="Changeable" use="optional" type="YesNoType" /> | ||
| 62 | <xs:attribute name="Deleteable" use="optional" type="YesNoType" /> | ||
| 63 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
| 64 | </xs:complexType> | ||
| 65 | </xs:element> | ||
| 66 | |||
| 67 | <xs:element name="ComPlusPartitionRole"> | ||
| 68 | <xs:annotation> | ||
| 69 | <xs:appinfo> | ||
| 70 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 71 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Fragment" /> | ||
| 72 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Module" /> | ||
| 73 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Product" /> | ||
| 74 | </xs:appinfo> | ||
| 75 | <xs:documentation> | ||
| 76 | Defines a COM+ partition role. Partition roles can not be | ||
| 77 | created; this element can only be used as a locater to reference an existing | ||
| 78 | role. | ||
| 79 | </xs:documentation> | ||
| 80 | </xs:annotation> | ||
| 81 | <xs:complexType> | ||
| 82 | <xs:sequence> | ||
| 83 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
| 84 | <xs:element ref="ComPlusUserInPartitionRole" /> | ||
| 85 | <xs:element ref="ComPlusGroupInPartitionRole" /> | ||
| 86 | </xs:choice> | ||
| 87 | </xs:sequence> | ||
| 88 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 89 | <xs:annotation><xs:documentation> | ||
| 90 | Identifier for the element. | ||
| 91 | </xs:documentation></xs:annotation> | ||
| 92 | </xs:attribute> | ||
| 93 | <xs:attribute name="Partition" use="optional" type="xs:string"> | ||
| 94 | <xs:annotation><xs:documentation> | ||
| 95 | The id of a ComPlusPartition element representing the partition | ||
| 96 | the role belongs to. | ||
| 97 | </xs:documentation></xs:annotation> | ||
| 98 | </xs:attribute> | ||
| 99 | <xs:attribute name="Name" use="required" type="xs:string"> | ||
| 100 | <xs:annotation><xs:documentation> | ||
| 101 | Name of the partition role. | ||
| 102 | </xs:documentation></xs:annotation> | ||
| 103 | </xs:attribute> | ||
| 104 | </xs:complexType> | ||
| 105 | </xs:element> | ||
| 106 | |||
| 107 | <xs:element name="ComPlusUserInPartitionRole"> | ||
| 108 | <xs:annotation> | ||
| 109 | <xs:appinfo> | ||
| 110 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 111 | </xs:appinfo> | ||
| 112 | <xs:documentation> | ||
| 113 | This element represents a user membership in a partition | ||
| 114 | role. When the parent component of this element is installed, the user will be | ||
| 115 | added to the associated partition role. | ||
| 116 | </xs:documentation> | ||
| 117 | </xs:annotation> | ||
| 118 | <xs:complexType> | ||
| 119 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 120 | <xs:annotation><xs:documentation> | ||
| 121 | Identifier for the element. | ||
| 122 | </xs:documentation></xs:annotation> | ||
| 123 | </xs:attribute> | ||
| 124 | <xs:attribute name="PartitionRole" use="optional" type="xs:string"> | ||
| 125 | <xs:annotation><xs:documentation> | ||
| 126 | The id of a ComPlusPartitionRole element representing the | ||
| 127 | partition the user should be added to. | ||
| 128 | </xs:documentation></xs:annotation> | ||
| 129 | </xs:attribute> | ||
| 130 | <xs:attribute name="User" use="required" type="xs:string"> | ||
| 131 | <xs:annotation><xs:documentation> | ||
| 132 | Foreign key into the User table. | ||
| 133 | </xs:documentation></xs:annotation> | ||
| 134 | </xs:attribute> | ||
| 135 | </xs:complexType> | ||
| 136 | </xs:element> | ||
| 137 | |||
| 138 | <xs:element name="ComPlusGroupInPartitionRole"> | ||
| 139 | <xs:annotation> | ||
| 140 | <xs:appinfo> | ||
| 141 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 142 | </xs:appinfo> | ||
| 143 | <xs:documentation> | ||
| 144 | This element represents a security group membership in a | ||
| 145 | partition role. When the parent component of this element is installed, the | ||
| 146 | security group will be added to the associated partition role. | ||
| 147 | </xs:documentation> | ||
| 148 | </xs:annotation> | ||
| 149 | <xs:complexType> | ||
| 150 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 151 | <xs:annotation><xs:documentation> | ||
| 152 | Identifier for the element. | ||
| 153 | </xs:documentation></xs:annotation> | ||
| 154 | </xs:attribute> | ||
| 155 | <xs:attribute name="PartitionRole" use="optional" type="xs:string"> | ||
| 156 | <xs:annotation><xs:documentation> | ||
| 157 | The id of a ComPlusPartitionRole element representing the | ||
| 158 | partition the user should be added to. | ||
| 159 | </xs:documentation></xs:annotation> | ||
| 160 | </xs:attribute> | ||
| 161 | <xs:attribute name="Group" use="required" type="xs:string"> | ||
| 162 | <xs:annotation><xs:documentation> | ||
| 163 | Foreign key into the Group table. | ||
| 164 | </xs:documentation></xs:annotation> | ||
| 165 | </xs:attribute> | ||
| 166 | </xs:complexType> | ||
| 167 | </xs:element> | ||
| 168 | |||
| 169 | <xs:element name="ComPlusPartitionUser"> | ||
| 170 | <xs:annotation> | ||
| 171 | <xs:appinfo> | ||
| 172 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 173 | </xs:appinfo> | ||
| 174 | <xs:documentation> | ||
| 175 | Represents a default partition definition for a user. When | ||
| 176 | the parent component of this element is installed, the default partition of the | ||
| 177 | user will be set to the referenced partition. | ||
| 178 | </xs:documentation> | ||
| 179 | </xs:annotation> | ||
| 180 | <xs:complexType> | ||
| 181 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 182 | <xs:annotation><xs:documentation> | ||
| 183 | Identifier for the element. | ||
| 184 | </xs:documentation></xs:annotation> | ||
| 185 | </xs:attribute> | ||
| 186 | <xs:attribute name="Partition" use="optional" type="xs:string"> | ||
| 187 | <xs:annotation><xs:documentation> | ||
| 188 | The id of a ComPlusPartition element representing the | ||
| 189 | partition that will be the default partition for the user. | ||
| 190 | </xs:documentation></xs:annotation> | ||
| 191 | </xs:attribute> | ||
| 192 | <xs:attribute name="User" use="required" type="xs:string"> | ||
| 193 | <xs:annotation><xs:documentation> | ||
| 194 | Foreign key into the User table. | ||
| 195 | </xs:documentation></xs:annotation> | ||
| 196 | </xs:attribute> | ||
| 197 | </xs:complexType> | ||
| 198 | </xs:element> | ||
| 199 | |||
| 200 | <xs:element name="ComPlusApplication"> | ||
| 201 | <xs:annotation> | ||
| 202 | <xs:appinfo> | ||
| 203 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 204 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Fragment" /> | ||
| 205 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Module" /> | ||
| 206 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Product" /> | ||
| 207 | </xs:appinfo> | ||
| 208 | <xs:documentation> | ||
| 209 | Defines a COM+ application. If this element is a descendent | ||
| 210 | of a Component element, the application will be created in association with | ||
| 211 | this component. If the element is a child of any of the Fragment, Module or | ||
| 212 | Product elements it is considered to be a locater, referencing an existing | ||
| 213 | application. | ||
| 214 | |||
| 215 | If the element is a child of a ComPlusPartition element, | ||
| 216 | or have its Partition attribute set, the application will be installed under | ||
| 217 | the referenced partition. | ||
| 218 | </xs:documentation> | ||
| 219 | </xs:annotation> | ||
| 220 | <xs:complexType> | ||
| 221 | <xs:sequence> | ||
| 222 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
| 223 | <xs:element ref="ComPlusApplicationRole" /> | ||
| 224 | <xs:element ref="ComPlusAssembly" /> | ||
| 225 | </xs:choice> | ||
| 226 | </xs:sequence> | ||
| 227 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 228 | <xs:annotation><xs:documentation> | ||
| 229 | Identifier for the element. | ||
| 230 | </xs:documentation></xs:annotation> | ||
| 231 | </xs:attribute> | ||
| 232 | <xs:attribute name="Partition" use="optional" type="xs:string"> | ||
| 233 | <xs:annotation><xs:documentation> | ||
| 234 | If the element is not a child of a ComPlusPartition | ||
| 235 | element, this attribute can be provided with the id of a ComPlusPartition | ||
| 236 | element representing the partition the application belongs to. | ||
| 237 | </xs:documentation></xs:annotation> | ||
| 238 | </xs:attribute> | ||
| 239 | <xs:attribute name="ApplicationId" use="optional" type="xs:string"> | ||
| 240 | <xs:annotation><xs:documentation> | ||
| 241 | Id for the application. This attribute can be omitted, in | ||
| 242 | which case an id will be generated on install. If the element is a locater, | ||
| 243 | this attribute can be omitted if a value is provided for the Name attribute. | ||
| 244 | </xs:documentation></xs:annotation> | ||
| 245 | </xs:attribute> | ||
| 246 | <xs:attribute name="Name" use="optional" type="xs:string"> | ||
| 247 | <xs:annotation><xs:documentation> | ||
| 248 | Name of the application. This attribute can be omitted if | ||
| 249 | the element is a locater, and a value is provided for the PartitionId | ||
| 250 | attribute. | ||
| 251 | </xs:documentation></xs:annotation> | ||
| 252 | </xs:attribute> | ||
| 253 | <xs:attribute name="ThreeGigSupportEnabled" use="optional" type="YesNoType" /> | ||
| 254 | <xs:attribute name="AccessChecksLevel" use="optional"> | ||
| 255 | <xs:simpleType> | ||
| 256 | <xs:restriction base="xs:NMTOKEN"> | ||
| 257 | <xs:enumeration value="applicationLevel" /> | ||
| 258 | <xs:enumeration value="applicationComponentLevel" /> | ||
| 259 | </xs:restriction> | ||
| 260 | </xs:simpleType> | ||
| 261 | </xs:attribute> | ||
| 262 | <xs:attribute name="Activation" use="optional"> | ||
| 263 | <xs:simpleType> | ||
| 264 | <xs:restriction base="xs:NMTOKEN"> | ||
| 265 | <xs:enumeration value="inproc" /> | ||
| 266 | <xs:enumeration value="local" /> | ||
| 267 | </xs:restriction> | ||
| 268 | </xs:simpleType> | ||
| 269 | </xs:attribute> | ||
| 270 | <xs:attribute name="ApplicationAccessChecksEnabled" use="optional" type="YesNoType" /> | ||
| 271 | <xs:attribute name="ApplicationDirectory" use="optional" type="xs:string" /> | ||
| 272 | <xs:attribute name="Authentication" use="optional"> | ||
| 273 | <xs:simpleType> | ||
| 274 | <xs:restriction base="xs:NMTOKEN"> | ||
| 275 | <xs:enumeration value="default" /> | ||
| 276 | <xs:enumeration value="none" /> | ||
| 277 | <xs:enumeration value="connect" /> | ||
| 278 | <xs:enumeration value="call" /> | ||
| 279 | <xs:enumeration value="packet" /> | ||
| 280 | <xs:enumeration value="integrity" /> | ||
| 281 | <xs:enumeration value="privacy" /> | ||
| 282 | </xs:restriction> | ||
| 283 | </xs:simpleType> | ||
| 284 | </xs:attribute> | ||
| 285 | <xs:attribute name="AuthenticationCapability" use="optional"> | ||
| 286 | <xs:simpleType> | ||
| 287 | <xs:restriction base="xs:NMTOKEN"> | ||
| 288 | <xs:enumeration value="none" /> | ||
| 289 | <xs:enumeration value="secureReference" /> | ||
| 290 | <xs:enumeration value="staticCloaking" /> | ||
| 291 | <xs:enumeration value="dynamicCloaking" /> | ||
| 292 | </xs:restriction> | ||
| 293 | </xs:simpleType> | ||
| 294 | </xs:attribute> | ||
| 295 | <xs:attribute name="Changeable" use="optional" type="YesNoType" /> | ||
| 296 | <xs:attribute name="CommandLine" use="optional" type="xs:string" /> | ||
| 297 | <xs:attribute name="ConcurrentApps" use="optional" type="xs:int" /> | ||
| 298 | <xs:attribute name="CreatedBy" use="optional" type="xs:string" /> | ||
| 299 | <xs:attribute name="CRMEnabled" use="optional" type="YesNoType" /> | ||
| 300 | <xs:attribute name="CRMLogFile" use="optional" type="xs:string" /> | ||
| 301 | <xs:attribute name="Deleteable" use="optional" type="YesNoType" /> | ||
| 302 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
| 303 | <xs:attribute name="DumpEnabled" use="optional" type="YesNoType" /> | ||
| 304 | <xs:attribute name="DumpOnException" use="optional" type="YesNoType" /> | ||
| 305 | <xs:attribute name="DumpOnFailfast" use="optional" type="YesNoType" /> | ||
| 306 | <xs:attribute name="DumpPath" use="optional" type="xs:string" /> | ||
| 307 | <xs:attribute name="EventsEnabled" use="optional" type="YesNoType" /> | ||
| 308 | <xs:attribute name="Identity" use="optional" type="xs:string" /> | ||
| 309 | <xs:attribute name="ImpersonationLevel" use="optional"> | ||
| 310 | <xs:simpleType> | ||
| 311 | <xs:restriction base="xs:NMTOKEN"> | ||
| 312 | <xs:enumeration value="anonymous" /> | ||
| 313 | <xs:enumeration value="identify" /> | ||
| 314 | <xs:enumeration value="impersonate" /> | ||
| 315 | <xs:enumeration value="delegate" /> | ||
| 316 | </xs:restriction> | ||
| 317 | </xs:simpleType> | ||
| 318 | </xs:attribute> | ||
| 319 | <xs:attribute name="IsEnabled" use="optional" type="YesNoType" /> | ||
| 320 | <xs:attribute name="MaxDumpCount" use="optional" type="xs:int" /> | ||
| 321 | <xs:attribute name="Password" use="optional" type="xs:string" /> | ||
| 322 | <xs:attribute name="QCAuthenticateMsgs" use="optional"> | ||
| 323 | <xs:simpleType> | ||
| 324 | <xs:restriction base="xs:NMTOKEN"> | ||
| 325 | <xs:enumeration value="secureApps" /> | ||
| 326 | <xs:enumeration value="off" /> | ||
| 327 | <xs:enumeration value="on" /> | ||
| 328 | </xs:restriction> | ||
| 329 | </xs:simpleType> | ||
| 330 | </xs:attribute> | ||
| 331 | <xs:attribute name="QCListenerMaxThreads" use="optional" type="xs:int" /> | ||
| 332 | <xs:attribute name="QueueListenerEnabled" use="optional" type="YesNoType" /> | ||
| 333 | <xs:attribute name="QueuingEnabled" use="optional" type="YesNoType" /> | ||
| 334 | <xs:attribute name="RecycleActivationLimit" use="optional" type="xs:int" /> | ||
| 335 | <xs:attribute name="RecycleCallLimit" use="optional" type="xs:int" /> | ||
| 336 | <xs:attribute name="RecycleExpirationTimeout" use="optional" type="xs:int" /> | ||
| 337 | <xs:attribute name="RecycleLifetimeLimit" use="optional" type="xs:int" /> | ||
| 338 | <xs:attribute name="RecycleMemoryLimit" use="optional" type="xs:int" /> | ||
| 339 | <xs:attribute name="Replicable" use="optional" type="YesNoType" /> | ||
| 340 | <xs:attribute name="RunForever" use="optional" type="YesNoType" /> | ||
| 341 | <xs:attribute name="ShutdownAfter" use="optional" type="xs:int" /> | ||
| 342 | <xs:attribute name="SoapActivated" use="optional" type="YesNoType" /> | ||
| 343 | <xs:attribute name="SoapBaseUrl" use="optional" type="xs:string" /> | ||
| 344 | <xs:attribute name="SoapMailTo" use="optional" type="xs:string" /> | ||
| 345 | <xs:attribute name="SoapVRoot" use="optional" type="xs:string" /> | ||
| 346 | <xs:attribute name="SRPEnabled" use="optional" type="YesNoType" /> | ||
| 347 | <xs:attribute name="SRPTrustLevel" use="optional"> | ||
| 348 | <xs:simpleType> | ||
| 349 | <xs:restriction base="xs:NMTOKEN"> | ||
| 350 | <xs:enumeration value="disallowed" /> | ||
| 351 | <xs:enumeration value="fullyTrusted" /> | ||
| 352 | </xs:restriction> | ||
| 353 | </xs:simpleType> | ||
| 354 | </xs:attribute> | ||
| 355 | </xs:complexType> | ||
| 356 | </xs:element> | ||
| 357 | |||
| 358 | <xs:element name="ComPlusApplicationRole"> | ||
| 359 | <xs:annotation> | ||
| 360 | <xs:appinfo> | ||
| 361 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 362 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Fragment" /> | ||
| 363 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Module" /> | ||
| 364 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Product" /> | ||
| 365 | </xs:appinfo> | ||
| 366 | <xs:documentation> | ||
| 367 | Defines an application role. If this element is a descendent | ||
| 368 | of a Component element, the application role will be created in association | ||
| 369 | with this component. If the element is a child of any of the Fragment, Module | ||
| 370 | or Product elements it is considered to be a locater, referencing an existing | ||
| 371 | application role. | ||
| 372 | </xs:documentation> | ||
| 373 | </xs:annotation> | ||
| 374 | <xs:complexType> | ||
| 375 | <xs:sequence> | ||
| 376 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
| 377 | <xs:element ref="ComPlusUserInApplicationRole" /> | ||
| 378 | <xs:element ref="ComPlusGroupInApplicationRole" /> | ||
| 379 | </xs:choice> | ||
| 380 | </xs:sequence> | ||
| 381 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 382 | <xs:annotation><xs:documentation> | ||
| 383 | Identifier for the element. | ||
| 384 | </xs:documentation></xs:annotation> | ||
| 385 | </xs:attribute> | ||
| 386 | <xs:attribute name="Application" use="optional" type="xs:string"> | ||
| 387 | <xs:annotation><xs:documentation> | ||
| 388 | If the element is not a child of a ComPlusApplication | ||
| 389 | element, this attribute should be provided with the id of a | ||
| 390 | ComPlusApplication element representing the application the role belongs to. | ||
| 391 | </xs:documentation></xs:annotation> | ||
| 392 | </xs:attribute> | ||
| 393 | <xs:attribute name="Name" use="required" type="xs:string"> | ||
| 394 | <xs:annotation><xs:documentation> | ||
| 395 | Name of the application role. | ||
| 396 | </xs:documentation></xs:annotation> | ||
| 397 | </xs:attribute> | ||
| 398 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
| 399 | </xs:complexType> | ||
| 400 | </xs:element> | ||
| 401 | |||
| 402 | <xs:element name="ComPlusUserInApplicationRole"> | ||
| 403 | <xs:annotation> | ||
| 404 | <xs:appinfo> | ||
| 405 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 406 | </xs:appinfo> | ||
| 407 | <xs:documentation> | ||
| 408 | This element represents a user membership in an | ||
| 409 | application role. When the parent component of this element is installed, the | ||
| 410 | user will be added to the associated application role. This element must be a descendent | ||
| 411 | of a Component element; it can not be a child of a ComPlusApplicationRole | ||
| 412 | locater element. To reference a locater element use the ApplicationRole | ||
| 413 | attribute. | ||
| 414 | </xs:documentation> | ||
| 415 | </xs:annotation> | ||
| 416 | <xs:complexType> | ||
| 417 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 418 | <xs:annotation><xs:documentation> | ||
| 419 | Identifier for the element. | ||
| 420 | </xs:documentation></xs:annotation> | ||
| 421 | </xs:attribute> | ||
| 422 | <xs:attribute name="ApplicationRole" use="optional" type="xs:string"> | ||
| 423 | <xs:annotation><xs:documentation> | ||
| 424 | If the element is not a child of a ComPlusApplicationRole | ||
| 425 | element, this attribute should be provided with the id of a | ||
| 426 | ComPlusApplicationRole element representing the application role the user is | ||
| 427 | to be added to. | ||
| 428 | </xs:documentation></xs:annotation> | ||
| 429 | </xs:attribute> | ||
| 430 | <xs:attribute name="User" use="required" type="xs:string"> | ||
| 431 | <xs:annotation><xs:documentation> | ||
| 432 | Foreign key into the User table. | ||
| 433 | </xs:documentation></xs:annotation> | ||
| 434 | </xs:attribute> | ||
| 435 | </xs:complexType> | ||
| 436 | </xs:element> | ||
| 437 | |||
| 438 | <xs:element name="ComPlusGroupInApplicationRole"> | ||
| 439 | <xs:annotation> | ||
| 440 | <xs:appinfo> | ||
| 441 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 442 | </xs:appinfo> | ||
| 443 | <xs:documentation> | ||
| 444 | This element represents a security group membership in an | ||
| 445 | application role. When the parent component of this element is installed, the | ||
| 446 | user will be added to the associated application role. This element must be a | ||
| 447 | descendent of a Component element; it can not be a child of a | ||
| 448 | ComPlusApplicationRole locater element. To reference a locater element use the | ||
| 449 | ApplicationRole attribute. | ||
| 450 | </xs:documentation> | ||
| 451 | </xs:annotation> | ||
| 452 | <xs:complexType> | ||
| 453 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 454 | <xs:annotation><xs:documentation> | ||
| 455 | Identifier for the element. | ||
| 456 | </xs:documentation></xs:annotation> | ||
| 457 | </xs:attribute> | ||
| 458 | <xs:attribute name="ApplicationRole" use="optional" type="xs:string"> | ||
| 459 | <xs:annotation><xs:documentation> | ||
| 460 | If the element is not a child of a ComPlusApplicationRole | ||
| 461 | element, this attribute should be provided with the id of a | ||
| 462 | ComPlusApplicationRole element representing the application role the user is | ||
| 463 | to be added to. | ||
| 464 | </xs:documentation></xs:annotation> | ||
| 465 | </xs:attribute> | ||
| 466 | <xs:attribute name="Group" use="required" type="xs:string"> | ||
| 467 | <xs:annotation><xs:documentation> | ||
| 468 | Foreign key into the Group table. | ||
| 469 | </xs:documentation></xs:annotation> | ||
| 470 | </xs:attribute> | ||
| 471 | </xs:complexType> | ||
| 472 | </xs:element> | ||
| 473 | |||
| 474 | <xs:element name="ComPlusAssembly"> | ||
| 475 | <xs:annotation> | ||
| 476 | <xs:documentation> | ||
| 477 | Represents a DLL or assembly to be registered with COM+. If | ||
| 478 | this element is a child of a ComPlusApplication element, the assembly will be | ||
| 479 | registered in this application. Other ways the Application attribute must be | ||
| 480 | set to an application. The element must be a descendent of a Component element, | ||
| 481 | it can not be a child of a ComPlusApplication locator element. | ||
| 482 | </xs:documentation> | ||
| 483 | <xs:appinfo> | ||
| 484 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 485 | <xse:remarks> | ||
| 486 | <html:p> | ||
| 487 | When installing a native assembly, all components | ||
| 488 | contained in the assembly must be represented as ComPlusComponent elements | ||
| 489 | under this element. Any component not listed will not be removed during | ||
| 490 | uninstall. | ||
| 491 | </html:p> | ||
| 492 | |||
| 493 | <html:p> | ||
| 494 | The fields DllPath, TlbPath and PSDllPath are formatted | ||
| 495 | fields that should contain file paths to there respective file types. A typical | ||
| 496 | value for DllPath for example, should be something like “[#MyAssembly_dll]”, | ||
| 497 | where “MyAssembly_dll” is the key of the dll file in the File table. | ||
| 498 | </html:p> | ||
| 499 | |||
| 500 | <html:p> | ||
| 501 | <html:b>Warning</html:b>: The assembly name provided in the AssemblyName | ||
| 502 | attribute must be a fully specified assembly name, if a partial name is | ||
| 503 | provided a random assembly matching the partial name will be selected. | ||
| 504 | </html:p> | ||
| 505 | </xse:remarks> | ||
| 506 | </xs:appinfo> | ||
| 507 | </xs:annotation> | ||
| 508 | <xs:complexType> | ||
| 509 | <xs:sequence> | ||
| 510 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
| 511 | <xs:element ref="ComPlusAssemblyDependency" /> | ||
| 512 | <xs:element ref="ComPlusComponent" /> | ||
| 513 | </xs:choice> | ||
| 514 | </xs:sequence> | ||
| 515 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 516 | <xs:annotation><xs:documentation> | ||
| 517 | Identifier for the element. | ||
| 518 | </xs:documentation></xs:annotation> | ||
| 519 | </xs:attribute> | ||
| 520 | <xs:attribute name="Application" use="optional" type="xs:string"> | ||
| 521 | <xs:annotation><xs:documentation> | ||
| 522 | If the element is not a child of a ComPlusApplication | ||
| 523 | element, this attribute should be provided with the id of a ComPlusApplication | ||
| 524 | element representing the application the assembly is to be registered in. | ||
| 525 | This attribute can be omitted for a .NET assembly even if the application is | ||
| 526 | not a child of a ComPlusApplication element. | ||
| 527 | </xs:documentation></xs:annotation> | ||
| 528 | </xs:attribute> | ||
| 529 | <xs:attribute name="AssemblyName" use="optional" type="xs:string"> | ||
| 530 | <xs:annotation><xs:documentation> | ||
| 531 | The name of the assembly used to identify the assembly in | ||
| 532 | the GAC. This attribute can be provided only if DllPathFromGAC is set to | ||
| 533 | “yes”. | ||
| 534 | </xs:documentation></xs:annotation> | ||
| 535 | </xs:attribute> | ||
| 536 | <xs:attribute name="DllPath" use="optional" type="xs:string"> | ||
| 537 | <xs:annotation><xs:documentation> | ||
| 538 | The path to locate the assembly DLL during registration. | ||
| 539 | This attribute should be provided if DllPathFromGAC is not set to “yes”. | ||
| 540 | </xs:documentation></xs:annotation> | ||
| 541 | </xs:attribute> | ||
| 542 | <xs:attribute name="TlbPath" use="optional" type="xs:string"> | ||
| 543 | <xs:annotation><xs:documentation> | ||
| 544 | An optional path to an external type lib for the assembly. | ||
| 545 | This attribute must be provided if the Type attribute is set to “.net”. | ||
| 546 | </xs:documentation></xs:annotation> | ||
| 547 | </xs:attribute> | ||
| 548 | <xs:attribute name="PSDllPath" use="optional" type="xs:string"> | ||
| 549 | <xs:annotation><xs:documentation> | ||
| 550 | An optional path to an external proxy/stub DLL for the assembly. | ||
| 551 | </xs:documentation></xs:annotation> | ||
| 552 | </xs:attribute> | ||
| 553 | <xs:attribute name="Type" use="required"> | ||
| 554 | <xs:annotation><xs:documentation> | ||
| 555 | </xs:documentation></xs:annotation> | ||
| 556 | <xs:simpleType> | ||
| 557 | <xs:restriction base="xs:NMTOKEN"> | ||
| 558 | <xs:enumeration value="native" /> | ||
| 559 | <xs:enumeration value=".net" /> | ||
| 560 | </xs:restriction> | ||
| 561 | </xs:simpleType> | ||
| 562 | </xs:attribute> | ||
| 563 | <xs:attribute name="EventClass" use="optional" type="YesNoType"> | ||
| 564 | <xs:annotation><xs:documentation> | ||
| 565 | Indicates that the assembly is to be installed as an event | ||
| 566 | class DLL. This attribute is only valid for native assemblies. The assembly | ||
| 567 | will be installed with the COM+ catalog’s InstallEventClass() function. | ||
| 568 | </xs:documentation></xs:annotation> | ||
| 569 | </xs:attribute> | ||
| 570 | <xs:attribute name="DllPathFromGAC" use="optional" type="YesNoType"> | ||
| 571 | <xs:annotation><xs:documentation> | ||
| 572 | Indicates that the DLL path should be extracted from the | ||
| 573 | GAC instead for being provided in the DllPath attribute. If this attribute is | ||
| 574 | set to “yes”, the name of the assembly can be provided using the AssemblyName | ||
| 575 | attribute. Or, if this AssemblyName attribute is missing, the name will be | ||
| 576 | extracted from the MsiAssemblyName table using the id of the parent Component | ||
| 577 | element. | ||
| 578 | </xs:documentation></xs:annotation> | ||
| 579 | </xs:attribute> | ||
| 580 | <xs:attribute name="RegisterInCommit" use="optional" type="YesNoType"> | ||
| 581 | <xs:annotation><xs:documentation> | ||
| 582 | Indicates that the assembly should be installed in the | ||
| 583 | commit custom action instead of the normal deferred custom action. This is | ||
| 584 | necessary when installing .NET assemblies to the GAC in the same | ||
| 585 | installation, as the assemblies are not visible in the GAC until after the | ||
| 586 | InstallFinalize action has run. | ||
| 587 | </xs:documentation></xs:annotation> | ||
| 588 | </xs:attribute> | ||
| 589 | </xs:complexType> | ||
| 590 | </xs:element> | ||
| 591 | |||
| 592 | <xs:element name="ComPlusAssemblyDependency"> | ||
| 593 | <xs:annotation> | ||
| 594 | <xs:documentation> | ||
| 595 | Defines a dependency between two assemblies. This element | ||
| 596 | affects the order in which assembles are registered. Any assemblies referenced | ||
| 597 | by this element are guarantied to be registered before, and unregistered after, | ||
| 598 | the assembly referenced by the parent ComPlusAssembly element. | ||
| 599 | </xs:documentation> | ||
| 600 | <xs:appinfo> | ||
| 601 | <xse:remarks> | ||
| 602 | It is only necessary to explicitly specify dependencies between | ||
| 603 | assemblies contained in the same package (MSI or MSM). Assemblies merged in to a | ||
| 604 | package from a merge module will always be installed before any assemblies | ||
| 605 | specified in the base package. Assemblies merged in from different merge | ||
| 606 | modules are sequenced using the ModuleDependency MSI table. It is not possible | ||
| 607 | to have cross dependencies between merge modules or have an assembly in a merge | ||
| 608 | module depend on an assembly in the base package. | ||
| 609 | </xse:remarks> | ||
| 610 | </xs:appinfo> | ||
| 611 | </xs:annotation> | ||
| 612 | <xs:complexType> | ||
| 613 | <xs:attribute name="RequiredAssembly" use="required" type="xs:string"> | ||
| 614 | <xs:annotation><xs:documentation> | ||
| 615 | Reference to the id of the assembly required by the parent | ||
| 616 | ComPlusAssembly element. | ||
| 617 | </xs:documentation></xs:annotation> | ||
| 618 | </xs:attribute> | ||
| 619 | </xs:complexType> | ||
| 620 | </xs:element> | ||
| 621 | |||
| 622 | <xs:element name="ComPlusComponent"> | ||
| 623 | <xs:annotation><xs:documentation> | ||
| 624 | Represents a COM+ component in an assembly. | ||
| 625 | </xs:documentation></xs:annotation> | ||
| 626 | <xs:complexType> | ||
| 627 | <xs:sequence> | ||
| 628 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
| 629 | <xs:element ref="ComPlusRoleForComponent" /> | ||
| 630 | <xs:element ref="ComPlusInterface" /> | ||
| 631 | <xs:element ref="ComPlusSubscription" /> | ||
| 632 | </xs:choice> | ||
| 633 | </xs:sequence> | ||
| 634 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 635 | <xs:annotation><xs:documentation> | ||
| 636 | Identifier for the element. | ||
| 637 | </xs:documentation></xs:annotation> | ||
| 638 | </xs:attribute> | ||
| 639 | <xs:attribute name="CLSID" use="required" type="uuid"> | ||
| 640 | <xs:annotation><xs:documentation> | ||
| 641 | CLSID of the component. | ||
| 642 | </xs:documentation></xs:annotation> | ||
| 643 | </xs:attribute> | ||
| 644 | <xs:attribute name="AllowInprocSubscribers" use="optional" type="YesNoType" /> | ||
| 645 | <xs:attribute name="ComponentAccessChecksEnabled" use="optional" type="YesNoType" /> | ||
| 646 | <xs:attribute name="ComponentTransactionTimeout" use="optional" type="xs:int" /> | ||
| 647 | <xs:attribute name="ComponentTransactionTimeoutEnabled" use="optional" type="YesNoType" /> | ||
| 648 | <xs:attribute name="COMTIIntrinsics" use="optional" type="YesNoType" /> | ||
| 649 | <xs:attribute name="ConstructionEnabled" use="optional" type="YesNoType" /> | ||
| 650 | <xs:attribute name="ConstructorString" use="optional" type="xs:string" /> | ||
| 651 | <xs:attribute name="CreationTimeout" use="optional" type="xs:int" /> | ||
| 652 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
| 653 | <xs:attribute name="EventTrackingEnabled" use="optional" type="YesNoType" /> | ||
| 654 | <xs:attribute name="ExceptionClass" use="optional" type="xs:string" /> | ||
| 655 | <xs:attribute name="FireInParallel" use="optional" type="YesNoType" /> | ||
| 656 | <xs:attribute name="IISIntrinsics" use="optional" type="YesNoType" /> | ||
| 657 | <xs:attribute name="InitializesServerApplication" use="optional" type="YesNoType" /> | ||
| 658 | <xs:attribute name="IsEnabled" use="optional" type="YesNoType" /> | ||
| 659 | <xs:attribute name="IsPrivateComponent" use="optional" type="YesNoType" /> | ||
| 660 | <xs:attribute name="JustInTimeActivation" use="optional" type="YesNoType" /> | ||
| 661 | <xs:attribute name="LoadBalancingSupported" use="optional" type="YesNoType" /> | ||
| 662 | <xs:attribute name="MaxPoolSize" use="optional" type="xs:int" /> | ||
| 663 | <xs:attribute name="MinPoolSize" use="optional" type="xs:int" /> | ||
| 664 | <xs:attribute name="MultiInterfacePublisherFilterCLSID" use="optional" type="xs:string" /> | ||
| 665 | <xs:attribute name="MustRunInClientContext" use="optional" type="YesNoType" /> | ||
| 666 | <xs:attribute name="MustRunInDefaultContext" use="optional" type="YesNoType" /> | ||
| 667 | <xs:attribute name="ObjectPoolingEnabled" use="optional" type="YesNoType" /> | ||
| 668 | <xs:attribute name="PublisherID" use="optional" type="xs:string" /> | ||
| 669 | <xs:attribute name="SoapAssemblyName" use="optional" type="xs:string" /> | ||
| 670 | <xs:attribute name="SoapTypeName" use="optional" type="xs:string" /> | ||
| 671 | <xs:attribute name="Synchronization" use="optional"> | ||
| 672 | <xs:simpleType> | ||
| 673 | <xs:restriction base="xs:NMTOKEN"> | ||
| 674 | <xs:enumeration value="ignored" /> | ||
| 675 | <xs:enumeration value="none" /> | ||
| 676 | <xs:enumeration value="supported" /> | ||
| 677 | <xs:enumeration value="required" /> | ||
| 678 | <xs:enumeration value="requiresNew" /> | ||
| 679 | </xs:restriction> | ||
| 680 | </xs:simpleType> | ||
| 681 | </xs:attribute> | ||
| 682 | <xs:attribute name="Transaction" use="optional"> | ||
| 683 | <xs:simpleType> | ||
| 684 | <xs:restriction base="xs:NMTOKEN"> | ||
| 685 | <xs:enumeration value="ignored" /> | ||
| 686 | <xs:enumeration value="none" /> | ||
| 687 | <xs:enumeration value="supported" /> | ||
| 688 | <xs:enumeration value="required" /> | ||
| 689 | <xs:enumeration value="requiresNew" /> | ||
| 690 | </xs:restriction> | ||
| 691 | </xs:simpleType> | ||
| 692 | </xs:attribute> | ||
| 693 | <xs:attribute name="TxIsolationLevel" use="optional"> | ||
| 694 | <xs:simpleType> | ||
| 695 | <xs:restriction base="xs:NMTOKEN"> | ||
| 696 | <xs:enumeration value="any" /> | ||
| 697 | <xs:enumeration value="readUnCommitted" /> | ||
| 698 | <xs:enumeration value="readCommitted" /> | ||
| 699 | <xs:enumeration value="repeatableRead" /> | ||
| 700 | <xs:enumeration value="serializable" /> | ||
| 701 | </xs:restriction> | ||
| 702 | </xs:simpleType> | ||
| 703 | </xs:attribute> | ||
| 704 | </xs:complexType> | ||
| 705 | </xs:element> | ||
| 706 | |||
| 707 | <xs:element name="ComPlusRoleForComponent"> | ||
| 708 | <xs:annotation> | ||
| 709 | <xs:appinfo> | ||
| 710 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 711 | </xs:appinfo> | ||
| 712 | <xs:documentation> | ||
| 713 | Represents a role assignment to a COM+ component. | ||
| 714 | </xs:documentation> | ||
| 715 | </xs:annotation> | ||
| 716 | <xs:complexType> | ||
| 717 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 718 | <xs:annotation><xs:documentation> | ||
| 719 | Identifier for the element. | ||
| 720 | </xs:documentation></xs:annotation> | ||
| 721 | </xs:attribute> | ||
| 722 | <xs:attribute name="Component" use="optional" type="xs:string"> | ||
| 723 | <xs:annotation><xs:documentation> | ||
| 724 | If the element is not a child of a ComPlusComponent | ||
| 725 | element, this attribute should be provided with the id of a ComPlusComponent | ||
| 726 | element representing the component the role is to be added to. | ||
| 727 | </xs:documentation></xs:annotation> | ||
| 728 | </xs:attribute> | ||
| 729 | <xs:attribute name="ApplicationRole" use="required" type="xs:string"> | ||
| 730 | <xs:annotation><xs:documentation> | ||
| 731 | Id of the ComPlusApplicationRole element representing the | ||
| 732 | role that shall be granted access to the component. | ||
| 733 | </xs:documentation></xs:annotation> | ||
| 734 | </xs:attribute> | ||
| 735 | </xs:complexType> | ||
| 736 | </xs:element> | ||
| 737 | |||
| 738 | <xs:element name="ComPlusInterface"> | ||
| 739 | <xs:annotation><xs:documentation> | ||
| 740 | Represents an interface for a COM+ component. | ||
| 741 | </xs:documentation></xs:annotation> | ||
| 742 | <xs:complexType> | ||
| 743 | <xs:sequence> | ||
| 744 | <xs:choice minOccurs="0" maxOccurs="unbounded"> | ||
| 745 | <xs:element ref="ComPlusRoleForInterface" /> | ||
| 746 | <xs:element ref="ComPlusMethod" /> | ||
| 747 | </xs:choice> | ||
| 748 | </xs:sequence> | ||
| 749 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 750 | <xs:annotation><xs:documentation> | ||
| 751 | Identifier for the element. | ||
| 752 | </xs:documentation></xs:annotation> | ||
| 753 | </xs:attribute> | ||
| 754 | <xs:attribute name="IID" use="required" type="uuid"> | ||
| 755 | <xs:annotation><xs:documentation> | ||
| 756 | IID of the interface. | ||
| 757 | </xs:documentation></xs:annotation> | ||
| 758 | </xs:attribute> | ||
| 759 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
| 760 | <xs:attribute name="QueuingEnabled" use="optional" type="YesNoType" /> | ||
| 761 | </xs:complexType> | ||
| 762 | </xs:element> | ||
| 763 | |||
| 764 | <xs:element name="ComPlusRoleForInterface"> | ||
| 765 | <xs:annotation> | ||
| 766 | <xs:appinfo> | ||
| 767 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 768 | </xs:appinfo> | ||
| 769 | <xs:documentation> | ||
| 770 | Represents a role assignment to an interface. | ||
| 771 | </xs:documentation> | ||
| 772 | </xs:annotation> | ||
| 773 | <xs:complexType> | ||
| 774 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 775 | <xs:annotation><xs:documentation> | ||
| 776 | Identifier for the element. | ||
| 777 | </xs:documentation></xs:annotation> | ||
| 778 | </xs:attribute> | ||
| 779 | <xs:attribute name="Interface" use="optional" type="xs:string"> | ||
| 780 | <xs:annotation><xs:documentation> | ||
| 781 | If the element is not a child of a ComPlusInterface | ||
| 782 | element, this attribute should be provided with the id of a ComPlusInterface | ||
| 783 | element representing the interface the role is to be added to. | ||
| 784 | </xs:documentation></xs:annotation> | ||
| 785 | </xs:attribute> | ||
| 786 | <xs:attribute name="ApplicationRole" use="required" type="xs:string"> | ||
| 787 | <xs:annotation><xs:documentation> | ||
| 788 | Id of the ComPlusApplicationRole element representing the | ||
| 789 | role that shall be granted access to the interface. | ||
| 790 | </xs:documentation></xs:annotation> | ||
| 791 | </xs:attribute> | ||
| 792 | </xs:complexType> | ||
| 793 | </xs:element> | ||
| 794 | |||
| 795 | <xs:element name="ComPlusMethod"> | ||
| 796 | <xs:annotation> | ||
| 797 | <xs:documentation> | ||
| 798 | Represents a method for an interface. | ||
| 799 | </xs:documentation> | ||
| 800 | </xs:annotation> | ||
| 801 | <xs:complexType> | ||
| 802 | <xs:sequence> | ||
| 803 | <xs:element ref="ComPlusRoleForMethod" minOccurs="0" maxOccurs="unbounded" /> | ||
| 804 | </xs:sequence> | ||
| 805 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 806 | <xs:annotation> | ||
| 807 | <xs:documentation> | ||
| 808 | Identifier for the element. | ||
| 809 | </xs:documentation> | ||
| 810 | </xs:annotation> | ||
| 811 | </xs:attribute> | ||
| 812 | <xs:attribute name="Index" use="optional" type="xs:int"> | ||
| 813 | <xs:annotation> | ||
| 814 | <xs:documentation> | ||
| 815 | Dispatch id of the method. If this attribute is not set a | ||
| 816 | value must be provided for the Name attribute. | ||
| 817 | </xs:documentation> | ||
| 818 | </xs:annotation> | ||
| 819 | </xs:attribute> | ||
| 820 | <xs:attribute name="Name" use="optional" type="xs:string"> | ||
| 821 | <xs:annotation> | ||
| 822 | <xs:documentation> | ||
| 823 | Name of the method. If this attribute is not set a value | ||
| 824 | must be provided for the Index attribute. | ||
| 825 | </xs:documentation> | ||
| 826 | </xs:annotation> | ||
| 827 | </xs:attribute> | ||
| 828 | <xs:attribute name="AutoComplete" use="optional" type="YesNoType" /> | ||
| 829 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
| 830 | </xs:complexType> | ||
| 831 | </xs:element> | ||
| 832 | |||
| 833 | <xs:element name="ComPlusRoleForMethod"> | ||
| 834 | <xs:annotation> | ||
| 835 | <xs:appinfo> | ||
| 836 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 837 | </xs:appinfo> | ||
| 838 | <xs:documentation> | ||
| 839 | Represents a role assignment to a COM+ method. | ||
| 840 | </xs:documentation> | ||
| 841 | </xs:annotation> | ||
| 842 | <xs:complexType> | ||
| 843 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 844 | <xs:annotation><xs:documentation> | ||
| 845 | Identifier for the element. | ||
| 846 | </xs:documentation></xs:annotation> | ||
| 847 | </xs:attribute> | ||
| 848 | <xs:attribute name="Method" use="optional" type="xs:string"> | ||
| 849 | <xs:annotation><xs:documentation> | ||
| 850 | If the element is not a child of a ComPlusMethod element, | ||
| 851 | this attribute should be provided with the id of a ComPlusMethod element | ||
| 852 | representing the method the role is to be added to. | ||
| 853 | </xs:documentation></xs:annotation> | ||
| 854 | </xs:attribute> | ||
| 855 | <xs:attribute name="ApplicationRole" use="required" type="xs:string"> | ||
| 856 | <xs:annotation><xs:documentation> | ||
| 857 | Id of the ComPlusApplicationRole element representing the | ||
| 858 | role that shall be granted access to the method. | ||
| 859 | </xs:documentation></xs:annotation> | ||
| 860 | </xs:attribute> | ||
| 861 | </xs:complexType> | ||
| 862 | </xs:element> | ||
| 863 | |||
| 864 | <xs:element name="ComPlusSubscription"> | ||
| 865 | <xs:annotation> | ||
| 866 | <xs:appinfo> | ||
| 867 | <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" /> | ||
| 868 | </xs:appinfo> | ||
| 869 | <xs:documentation> | ||
| 870 | Defines an event subscription for a COM+ component. | ||
| 871 | </xs:documentation> | ||
| 872 | </xs:annotation> | ||
| 873 | <xs:complexType> | ||
| 874 | <xs:attribute name="Id" use="required" type="xs:string"> | ||
| 875 | <xs:annotation><xs:documentation> | ||
| 876 | Identifier for the element. | ||
| 877 | </xs:documentation></xs:annotation> | ||
| 878 | </xs:attribute> | ||
| 879 | <xs:attribute name="Component" use="optional" type="xs:string"> | ||
| 880 | <xs:annotation><xs:documentation> | ||
| 881 | If the element is not a child of a ComPlusComponent | ||
| 882 | element, this attribute should be provided with the id of a ComPlusComponent | ||
| 883 | element representing the component the subscription is to be created for. | ||
| 884 | </xs:documentation></xs:annotation> | ||
| 885 | </xs:attribute> | ||
| 886 | <xs:attribute name="SubscriptionId" use="optional" type="xs:string"> | ||
| 887 | <xs:annotation><xs:documentation> | ||
| 888 | Id of the subscription. If a value is not provided for | ||
| 889 | this attribute, an id will be generated during installation. | ||
| 890 | </xs:documentation></xs:annotation> | ||
| 891 | </xs:attribute> | ||
| 892 | <xs:attribute name="Name" use="required" type="xs:string"> | ||
| 893 | <xs:annotation><xs:documentation> | ||
| 894 | Name of the subscription. | ||
| 895 | </xs:documentation></xs:annotation> | ||
| 896 | </xs:attribute> | ||
| 897 | <xs:attribute name="EventCLSID" use="optional" type="xs:string"> | ||
| 898 | <xs:annotation><xs:documentation> | ||
| 899 | CLSID of the event class for the subscription. If a value | ||
| 900 | for this attribute is not provided, a value for the PublisherID attribute | ||
| 901 | must be provided. | ||
| 902 | </xs:documentation></xs:annotation> | ||
| 903 | </xs:attribute> | ||
| 904 | <xs:attribute name="PublisherID" use="optional" type="xs:string"> | ||
| 905 | <xs:annotation><xs:documentation> | ||
| 906 | Publisher id for the subscription. If a value for this | ||
| 907 | attribute is not provided, a value for the EventCLSID attribute must be | ||
| 908 | provided. | ||
| 909 | </xs:documentation></xs:annotation> | ||
| 910 | </xs:attribute> | ||
| 911 | <xs:attribute name="Description" use="optional" type="xs:string" /> | ||
| 912 | <xs:attribute name="Enabled" use="optional" type="YesNoType" /> | ||
| 913 | <xs:attribute name="EventClassPartitionID" use="optional" type="xs:string" /> | ||
| 914 | <xs:attribute name="FilterCriteria" use="optional" type="xs:string" /> | ||
| 915 | <xs:attribute name="InterfaceID" use="optional" type="xs:string" /> | ||
| 916 | <xs:attribute name="MachineName" use="optional" type="xs:string" /> | ||
| 917 | <xs:attribute name="MethodName" use="optional" type="xs:string" /> | ||
| 918 | <xs:attribute name="PerUser" use="optional" type="YesNoType" /> | ||
| 919 | <xs:attribute name="Queued" use="optional" type="YesNoType" /> | ||
| 920 | <xs:attribute name="SubscriberMoniker" use="optional" type="xs:string" /> | ||
| 921 | <xs:attribute name="UserName" use="optional" type="xs:string" /> | ||
| 922 | </xs:complexType> | ||
| 923 | </xs:element> | ||
| 924 | |||
| 925 | <xs:simpleType name="YesNoType"> | ||
| 926 | <xs:annotation> | ||
| 927 | <xs:documentation>Values of this type will either be "yes" or "no".</xs:documentation> | ||
| 928 | </xs:annotation> | ||
| 929 | <xs:restriction base="xs:NMTOKEN"> | ||
| 930 | <xs:enumeration value="no" /> | ||
| 931 | <xs:enumeration value="yes" /> | ||
| 932 | </xs:restriction> | ||
| 933 | </xs:simpleType> | ||
| 934 | |||
| 935 | <xs:simpleType name="uuid"> | ||
| 936 | <xs:annotation> | ||
| 937 | <xs:documentation>Values of this type will look like: "01234567-89AB-CDEF-0123-456789ABCDEF".</xs:documentation> | ||
| 938 | </xs:annotation> | ||
| 939 | <xs:restriction base="xs:string"> | ||
| 940 | <xs:pattern value="[0-9A-Fa-f]{8}\-?[0-9A-Fa-f]{4}\-?[0-9A-Fa-f]{4}\-?[0-9A-Fa-f]{4}\-?[0-9A-Fa-f]{12}" /> | ||
| 941 | </xs:restriction> | ||
| 942 | </xs:simpleType> | ||
| 943 | |||
| 944 | </xs:schema> | ||
diff --git a/src/wixext/messages.xml b/src/wixext/messages.xml new file mode 100644 index 00000000..66c0a9e6 --- /dev/null +++ b/src/wixext/messages.xml | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | |||
| 5 | <Messages Namespace="WixToolset.Extensions" Resources="Data.Messages" xmlns="http://schemas.microsoft.com/genmsgs/2004/07/messages"> | ||
| 6 | <Class Name="ComPlusErrors" ContainerName="ComPlusErrorEventArgs" BaseContainerName="MessageEventArgs"> | ||
| 7 | <Message Id="IllegalAttributeWithoutComponent" Number="6000"> | ||
| 8 | <Instance> | ||
| 9 | The {0}/@{1} attribute cannot be specified unless the element has a component as an ancestor. A {0} that does not have a component ancestor is not installed. | ||
| 10 | <Parameter Type="System.String" Name="elementName" /> | ||
| 11 | <Parameter Type="System.String" Name="attributeName" /> | ||
| 12 | </Instance> | ||
| 13 | </Message> | ||
| 14 | <Message Id="IllegalElementWithoutComponent" Number="6001"> | ||
| 15 | <Instance> | ||
| 16 | The {0} element cannot be specified unless the element has a component as an ancestor. A {0} that does not have a component ancestor is not installed. | ||
| 17 | <Parameter Type="System.String" Name="elementName" /> | ||
| 18 | </Instance> | ||
| 19 | </Message> | ||
| 20 | <Message Id="UnexpectedAttributeWithOtherValue" Number="6002"> | ||
| 21 | <Instance> | ||
| 22 | The {0}/@{1} attribute cannot coexist with the {2} attribute's value of '{3}'. | ||
| 23 | <Parameter Type="System.String" Name="elementName" /> | ||
| 24 | <Parameter Type="System.String" Name="attributeName" /> | ||
| 25 | <Parameter Type="System.String" Name="otherAttributeName" /> | ||
| 26 | <Parameter Type="System.String" Name="otherValue" /> | ||
| 27 | </Instance> | ||
| 28 | <Instance> | ||
| 29 | The {0}/@{1} attribute's value, '{2}', cannot coexist with the {3} attribute's value of '{4}'. | ||
| 30 | <Parameter Type="System.String" Name="elementName" /> | ||
| 31 | <Parameter Type="System.String" Name="attributeName" /> | ||
| 32 | <Parameter Type="System.String" Name="value" /> | ||
| 33 | <Parameter Type="System.String" Name="otherAttributeName" /> | ||
| 34 | <Parameter Type="System.String" Name="otherValue" /> | ||
| 35 | </Instance> | ||
| 36 | </Message> | ||
| 37 | <Message Id="UnexpectedAttributeWithoutOtherValue" Number="6003"> | ||
| 38 | <Instance> | ||
| 39 | The {0}/@{1} cannot be provided unless the {2} attribute is provided with a value of '{3}'. | ||
| 40 | <Parameter Type="System.String" Name="elementName" /> | ||
| 41 | <Parameter Type="System.String" Name="attributeName" /> | ||
| 42 | <Parameter Type="System.String" Name="otherAttributeName" /> | ||
| 43 | <Parameter Type="System.String" Name="otherValue" /> | ||
| 44 | </Instance> | ||
| 45 | </Message> | ||
| 46 | <Message Id="RequiredAttributeUnderComponent" Number="6004"> | ||
| 47 | <Instance> | ||
| 48 | The {0}/@{1} attribute must be provided when {0} element is nested under a component. | ||
| 49 | <Parameter Type="System.String" Name="elementName" /> | ||
| 50 | <Parameter Type="System.String" Name="attributeName" /> | ||
| 51 | </Instance> | ||
| 52 | </Message> | ||
| 53 | <Message Id="RequiredAttribute" Number="6005"> | ||
| 54 | <Instance> | ||
| 55 | A {0} element must have either a {1} attribute or a {2} attribute, or both set. | ||
| 56 | <Parameter Type="System.String" Name="elementName" /> | ||
| 57 | <Parameter Type="System.String" Name="attributeName1" /> | ||
| 58 | <Parameter Type="System.String" Name="attributeName2" /> | ||
| 59 | </Instance> | ||
| 60 | </Message> | ||
| 61 | <Message Id="RequiredAttributeNotUnderComponent" Number="6006"> | ||
| 62 | <Instance> | ||
| 63 | A {0} element not nested under a component must have either a {1} attribute or a {2} attribute, or both set. | ||
| 64 | <Parameter Type="System.String" Name="elementName" /> | ||
| 65 | <Parameter Type="System.String" Name="attributeName1" /> | ||
| 66 | <Parameter Type="System.String" Name="attributeName2" /> | ||
| 67 | </Instance> | ||
| 68 | </Message> | ||
| 69 | </Class> | ||
| 70 | <Class Name="ComPlusWarnings" ContainerName="ComPlusWarningEventArgs" BaseContainerName="MessageEventArgs"> | ||
| 71 | <Message Id="MissingComponents" Number="6007"> | ||
| 72 | <Instance>The ComPlusAssembly element has a Type attribute with a value of 'native', but the element does not contain any ComPlusComponent elements. All components contained in a native assembly must be listed, or they will not be correctly removed during uninstall.</Instance> | ||
| 73 | </Message> | ||
| 74 | </Class> | ||
| 75 | <Class Name="ComPlusVerboses" ContainerName="ComPlusVerboseEventArgs" BaseContainerName="MessageEventArgs"> | ||
| 76 | </Class> | ||
| 77 | </Messages> | ||
diff --git a/src/wixext/tables.xml b/src/wixext/tables.xml new file mode 100644 index 00000000..3c3d1728 --- /dev/null +++ b/src/wixext/tables.xml | |||
| @@ -0,0 +1,250 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | |||
| 5 | <tableDefinitions xmlns="http://wixtoolset.org/schemas/v4/wi/tables"> | ||
| 6 | <tableDefinition name="ComPlusPartition" createSymbols="yes"> | ||
| 7 | <columnDefinition name="Partition" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 8 | category="identifier" description=""/> | ||
| 9 | <columnDefinition name="Component_" type="string" length="72" nullable="yes" modularize="column" | ||
| 10 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 11 | <columnDefinition name="Id" type="string" length="72" nullable="yes" modularize="property" | ||
| 12 | category="formatted" description=""/> | ||
| 13 | <columnDefinition name="Name" type="string" length="255" nullable="yes" modularize="property" | ||
| 14 | category="formatted" description=""/> | ||
| 15 | </tableDefinition> | ||
| 16 | <tableDefinition name="ComPlusPartitionProperty"> | ||
| 17 | <columnDefinition name="Partition_" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 18 | keyTable="ComPlusPartition" keyColumn="1" category="identifier" description=""/> | ||
| 19 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
| 20 | category="formatted" description=""/> | ||
| 21 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
| 22 | category="formatted" description=""/> | ||
| 23 | </tableDefinition> | ||
| 24 | <tableDefinition name="ComPlusPartitionRole" createSymbols="yes"> | ||
| 25 | <columnDefinition name="PartitionRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 26 | category="identifier" description=""/> | ||
| 27 | <columnDefinition name="Partition_" type="string" length="72" modularize="column" | ||
| 28 | keyTable="ComPlusPartition" keyColumn="1" category="identifier" description=""/> | ||
| 29 | <columnDefinition name="Component_" type="string" length="72" nullable="yes" modularize="column" | ||
| 30 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 31 | <columnDefinition name="Name" type="string" length="255" modularize="property" | ||
| 32 | category="formatted" description=""/> | ||
| 33 | </tableDefinition> | ||
| 34 | <tableDefinition name="ComPlusUserInPartitionRole" createSymbols="yes"> | ||
| 35 | <columnDefinition name="UserInPartitionRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 36 | category="identifier" description=""/> | ||
| 37 | <columnDefinition name="PartitionRole_" type="string" length="72" modularize="column" | ||
| 38 | keyTable="ComPlusPartitionRole" keyColumn="1" category="identifier" description=""/> | ||
| 39 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
| 40 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 41 | <columnDefinition name="User_" type="string" length="72" modularize="column" | ||
| 42 | category="identifier" description=""/> | ||
| 43 | </tableDefinition> | ||
| 44 | <tableDefinition name="ComPlusGroupInPartitionRole" createSymbols="yes"> | ||
| 45 | <columnDefinition name="GroupInPartitionRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 46 | category="identifier" description=""/> | ||
| 47 | <columnDefinition name="PartitionRole_" type="string" length="72" modularize="column" | ||
| 48 | keyTable="ComPlusPartitionRole" keyColumn="1" category="identifier" description=""/> | ||
| 49 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
| 50 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 51 | <columnDefinition name="Group_" type="string" length="72" modularize="column" | ||
| 52 | category="identifier" description=""/> | ||
| 53 | </tableDefinition> | ||
| 54 | <tableDefinition name="ComPlusPartitionUser" createSymbols="yes"> | ||
| 55 | <columnDefinition name="PartitionUser" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 56 | category="identifier" description=""/> | ||
| 57 | <columnDefinition name="Partition_" type="string" length="72" modularize="column" | ||
| 58 | keyTable="ComPlusPartition" keyColumn="1" category="identifier" description=""/> | ||
| 59 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
| 60 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 61 | <columnDefinition name="User_" type="string" length="72" modularize="column" | ||
| 62 | category="identifier" description=""/> | ||
| 63 | </tableDefinition> | ||
| 64 | <tableDefinition name="ComPlusApplication" createSymbols="yes"> | ||
| 65 | <columnDefinition name="Application" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 66 | category="identifier" description=""/> | ||
| 67 | <columnDefinition name="Partition_" type="string" length="72" nullable="yes" modularize="column" | ||
| 68 | keyTable="ComPlusPartition" keyColumn="1" category="identifier" description=""/> | ||
| 69 | <columnDefinition name="Component_" type="string" length="72" nullable="yes" modularize="column" | ||
| 70 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 71 | <columnDefinition name="Id" type="string" length="72" nullable="yes" modularize="property" | ||
| 72 | category="formatted" description=""/> | ||
| 73 | <columnDefinition name="Name" type="string" length="255" nullable="yes" modularize="property" | ||
| 74 | category="formatted" description=""/> | ||
| 75 | </tableDefinition> | ||
| 76 | <tableDefinition name="ComPlusApplicationProperty"> | ||
| 77 | <columnDefinition name="Application_" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 78 | keyTable="ComPlusApplication" keyColumn="1" category="identifier" description=""/> | ||
| 79 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
| 80 | category="formatted" description=""/> | ||
| 81 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
| 82 | category="formatted" description=""/> | ||
| 83 | </tableDefinition> | ||
| 84 | <tableDefinition name="ComPlusApplicationRole" createSymbols="yes"> | ||
| 85 | <columnDefinition name="ApplicationRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 86 | category="identifier" description=""/> | ||
| 87 | <columnDefinition name="Application_" type="string" length="72" modularize="column" | ||
| 88 | keyTable="ComPlusApplication" keyColumn="1" category="identifier" description=""/> | ||
| 89 | <columnDefinition name="Component_" type="string" length="72" nullable="yes" modularize="column" | ||
| 90 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 91 | <columnDefinition name="Name" type="string" length="255" modularize="property" | ||
| 92 | category="formatted" description=""/> | ||
| 93 | </tableDefinition> | ||
| 94 | <tableDefinition name="ComPlusApplicationRoleProperty"> | ||
| 95 | <columnDefinition name="ApplicationRole_" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 96 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
| 97 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
| 98 | category="formatted" description=""/> | ||
| 99 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
| 100 | category="formatted" description=""/> | ||
| 101 | </tableDefinition> | ||
| 102 | <tableDefinition name="ComPlusUserInApplicationRole" createSymbols="yes"> | ||
| 103 | <columnDefinition name="UserInApplicationRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 104 | category="identifier" description=""/> | ||
| 105 | <columnDefinition name="ApplicationRole_" type="string" length="72" modularize="column" | ||
| 106 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
| 107 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
| 108 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 109 | <columnDefinition name="User_" type="string" length="72" modularize="column" | ||
| 110 | category="identifier" description=""/> | ||
| 111 | </tableDefinition> | ||
| 112 | <tableDefinition name="ComPlusGroupInApplicationRole" createSymbols="yes"> | ||
| 113 | <columnDefinition name="GroupInApplicationRole" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 114 | category="identifier" description=""/> | ||
| 115 | <columnDefinition name="ApplicationRole_" type="string" length="72" modularize="column" | ||
| 116 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
| 117 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
| 118 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 119 | <columnDefinition name="Group_" type="string" length="72" modularize="column" | ||
| 120 | category="identifier" description=""/> | ||
| 121 | </tableDefinition> | ||
| 122 | <tableDefinition name="ComPlusAssembly" createSymbols="yes"> | ||
| 123 | <columnDefinition name="Assembly" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 124 | category="identifier" description=""/> | ||
| 125 | <columnDefinition name="Application_" type="string" length="72" nullable="yes" modularize="column" | ||
| 126 | keyTable="ComPlusApplication" keyColumn="1" category="identifier" description=""/> | ||
| 127 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
| 128 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 129 | <columnDefinition name="AssemblyName" type="string" length="255" nullable="yes" modularize="property" | ||
| 130 | category="formatted" description=""/> | ||
| 131 | <columnDefinition name="DllPath" type="string" length="255" nullable="yes" modularize="property" | ||
| 132 | category="formatted" description=""/> | ||
| 133 | <columnDefinition name="TlbPath" type="string" length="255" nullable="yes" modularize="property" | ||
| 134 | category="formatted" description=""/> | ||
| 135 | <columnDefinition name="PSDllPath" type="string" length="255" nullable="yes" modularize="property" | ||
| 136 | category="formatted" description=""/> | ||
| 137 | <columnDefinition name="Attributes" type="number" length="4" | ||
| 138 | description=""/> | ||
| 139 | </tableDefinition> | ||
| 140 | <tableDefinition name="ComPlusAssemblyDependency"> | ||
| 141 | <columnDefinition name="Assembly_" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 142 | keyTable="ComPlusAssembly" keyColumn="1" category="identifier" description=""/> | ||
| 143 | <columnDefinition name="RequiredAssembly_" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 144 | keyTable="ComPlusAssembly" keyColumn="1" category="identifier" description=""/> | ||
| 145 | </tableDefinition> | ||
| 146 | <tableDefinition name="ComPlusComponent" createSymbols="yes"> | ||
| 147 | <columnDefinition name="ComPlusComponent" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 148 | category="identifier" description=""/> | ||
| 149 | <columnDefinition name="Assembly_" type="string" length="72" modularize="column" | ||
| 150 | keyTable="ComPlusAssembly" keyColumn="1" category="identifier" description=""/> | ||
| 151 | <columnDefinition name="CLSID" type="string" length="72" modularize="property" | ||
| 152 | category="formatted" description=""/> | ||
| 153 | </tableDefinition> | ||
| 154 | <tableDefinition name="ComPlusComponentProperty"> | ||
| 155 | <columnDefinition name="ComPlusComponent_" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 156 | keyTable="ComPlusComponent" keyColumn="1" category="identifier" description=""/> | ||
| 157 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
| 158 | category="formatted" description=""/> | ||
| 159 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
| 160 | category="formatted" description=""/> | ||
| 161 | </tableDefinition> | ||
| 162 | <tableDefinition name="ComPlusRoleForComponent" createSymbols="yes"> | ||
| 163 | <columnDefinition name="RoleForComponent" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 164 | category="identifier" description=""/> | ||
| 165 | <columnDefinition name="ComPlusComponent_" type="string" length="72" modularize="column" | ||
| 166 | keyTable="ComPlusComponent" keyColumn="1" category="identifier" description=""/> | ||
| 167 | <columnDefinition name="ApplicationRole_" type="string" length="72" modularize="column" | ||
| 168 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
| 169 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
| 170 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 171 | </tableDefinition> | ||
| 172 | <tableDefinition name="ComPlusInterface" createSymbols="yes"> | ||
| 173 | <columnDefinition name="Interface" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 174 | category="identifier" description=""/> | ||
| 175 | <columnDefinition name="ComPlusComponent_" type="string" length="72" modularize="column" | ||
| 176 | keyTable="ComPlusComponent" keyColumn="1" category="identifier" description=""/> | ||
| 177 | <columnDefinition name="IID" type="string" length="72" modularize="property" | ||
| 178 | category="formatted" description=""/> | ||
| 179 | </tableDefinition> | ||
| 180 | <tableDefinition name="ComPlusInterfaceProperty"> | ||
| 181 | <columnDefinition name="Interface_" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 182 | keyTable="ComPlusInterface" keyColumn="1" category="identifier" description=""/> | ||
| 183 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
| 184 | category="formatted" description=""/> | ||
| 185 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
| 186 | category="formatted" description=""/> | ||
| 187 | </tableDefinition> | ||
| 188 | <tableDefinition name="ComPlusRoleForInterface" createSymbols="yes"> | ||
| 189 | <columnDefinition name="RoleForInterface" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 190 | category="identifier" description=""/> | ||
| 191 | <columnDefinition name="Interface_" type="string" length="72" modularize="column" | ||
| 192 | keyTable="ComPlusInterface" keyColumn="1" category="identifier" description=""/> | ||
| 193 | <columnDefinition name="ApplicationRole_" type="string" length="72" modularize="column" | ||
| 194 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
| 195 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
| 196 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 197 | </tableDefinition> | ||
| 198 | <tableDefinition name="ComPlusMethod" createSymbols="yes"> | ||
| 199 | <columnDefinition name="Method" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 200 | category="identifier" description=""/> | ||
| 201 | <columnDefinition name="Interface_" type="string" length="72" modularize="column" | ||
| 202 | keyTable="ComPlusInterface" keyColumn="1" category="identifier" description=""/> | ||
| 203 | <columnDefinition name="Index" type="number" length="4" nullable="yes" | ||
| 204 | description=""/> | ||
| 205 | <columnDefinition name="Name" type="string" length="255" nullable="yes" modularize="property" | ||
| 206 | category="formatted" description=""/> | ||
| 207 | </tableDefinition> | ||
| 208 | <tableDefinition name="ComPlusMethodProperty"> | ||
| 209 | <columnDefinition name="Method_" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 210 | keyTable="ComPlusMethod" keyColumn="1" category="identifier" description=""/> | ||
| 211 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
| 212 | category="formatted" description=""/> | ||
| 213 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
| 214 | category="formatted" description=""/> | ||
| 215 | </tableDefinition> | ||
| 216 | <tableDefinition name="ComPlusRoleForMethod" createSymbols="yes"> | ||
| 217 | <columnDefinition name="RoleForMethod" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 218 | category="identifier" description=""/> | ||
| 219 | <columnDefinition name="Method_" type="string" length="72" modularize="column" | ||
| 220 | keyTable="ComPlusMethod" keyColumn="1" category="identifier" description=""/> | ||
| 221 | <columnDefinition name="ApplicationRole_" type="string" length="72" modularize="column" | ||
| 222 | keyTable="ComPlusApplicationRole" keyColumn="1" category="identifier" description=""/> | ||
| 223 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
| 224 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 225 | </tableDefinition> | ||
| 226 | <tableDefinition name="ComPlusSubscription" createSymbols="yes"> | ||
| 227 | <columnDefinition name="Subscription" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 228 | category="identifier" description=""/> | ||
| 229 | <columnDefinition name="ComPlusComponent_" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 230 | keyTable="ComPlusComponent" keyColumn="1" category="identifier" description=""/> | ||
| 231 | <columnDefinition name="Component_" type="string" length="72" modularize="column" | ||
| 232 | keyTable="Component" keyColumn="1" category="identifier" description=""/> | ||
| 233 | <columnDefinition name="Id" type="string" length="72" nullable="yes" modularize="property" | ||
| 234 | category="formatted" description=""/> | ||
| 235 | <columnDefinition name="Name" type="string" length="255" modularize="property" | ||
| 236 | category="formatted" description=""/> | ||
| 237 | <columnDefinition name="EventCLSID" type="string" length="72" nullable="yes" modularize="property" | ||
| 238 | category="formatted" description=""/> | ||
| 239 | <columnDefinition name="PublisherID" type="string" length="72" nullable="yes" modularize="property" | ||
| 240 | category="formatted" description=""/> | ||
| 241 | </tableDefinition> | ||
| 242 | <tableDefinition name="ComPlusSubscriptionProperty"> | ||
| 243 | <columnDefinition name="Subscription_" type="string" length="72" primaryKey="yes" modularize="column" | ||
| 244 | keyTable="ComPlusSubscription" keyColumn="1" category="identifier" description=""/> | ||
| 245 | <columnDefinition name="Name" type="string" length="72" primaryKey="yes" modularize="property" | ||
| 246 | category="formatted" description=""/> | ||
| 247 | <columnDefinition name="Value" type="string" length="255" modularize="property" | ||
| 248 | category="formatted" description=""/> | ||
| 249 | </tableDefinition> | ||
| 250 | </tableDefinitions> | ||
diff --git a/src/wixlib/ComPlusExtension.wixproj b/src/wixlib/ComPlusExtension.wixproj new file mode 100644 index 00000000..49c688cd --- /dev/null +++ b/src/wixlib/ComPlusExtension.wixproj | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8" ?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | |||
| 5 | <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> | ||
| 6 | <PropertyGroup> | ||
| 7 | <ProjectGuid>{E191E61E-E098-4F71-888F-51A79F952022}</ProjectGuid> | ||
| 8 | <OutputName>complus</OutputName> | ||
| 9 | <OutputType>Library</OutputType> | ||
| 10 | <BindFiles>true</BindFiles> | ||
| 11 | <SuppressSpecificWarnings>1086</SuppressSpecificWarnings> | ||
| 12 | </PropertyGroup> | ||
| 13 | |||
| 14 | <ItemGroup> | ||
| 15 | <Compile Include="ComPlusExtension.wxs" /> | ||
| 16 | <EmbeddedResource Include="en-us.wxl" /> | ||
| 17 | <EmbeddedResource Include="es-es.wxl" /> | ||
| 18 | <EmbeddedResource Include="ja-jp.wxl" /> | ||
| 19 | </ItemGroup> | ||
| 20 | |||
| 21 | <ItemGroup> | ||
| 22 | <ProjectReference Include="..\ca\complusca.proj" /> | ||
| 23 | </ItemGroup> | ||
| 24 | |||
| 25 | <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.targets" /> | ||
| 26 | </Project> | ||
diff --git a/src/wixlib/ComPlusExtension.wxs b/src/wixlib/ComPlusExtension.wxs new file mode 100644 index 00000000..3a5c1512 --- /dev/null +++ b/src/wixlib/ComPlusExtension.wxs | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | |||
| 5 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
| 6 | <?include caerr.wxi ?> | ||
| 7 | |||
| 8 | <Fragment> | ||
| 9 | <UI Id="ComPlusUI"> | ||
| 10 | <Error Id="$(var.msierrComPlusCannotConnect)">!(loc.msierrComPlusCannotConnect)</Error> | ||
| 11 | <Error Id="$(var.msierrComPlusPartitionReadFailed)">!(loc.msierrComPlusPartitionReadFailed)</Error> | ||
| 12 | <Error Id="$(var.msierrComPlusPartitionRoleReadFailed)">!(loc.msierrComPlusPartitionRoleReadFailed)</Error> | ||
| 13 | <Error Id="$(var.msierrComPlusUserInPartitionRoleReadFailed)">!(loc.msierrComPlusUserInPartitionRoleReadFailed)</Error> | ||
| 14 | <Error Id="$(var.msierrComPlusPartitionUserReadFailed)">!(loc.msierrComPlusPartitionUserReadFailed)</Error> | ||
| 15 | <Error Id="$(var.msierrComPlusApplicationReadFailed)">!(loc.msierrComPlusApplicationReadFailed)</Error> | ||
| 16 | <Error Id="$(var.msierrComPlusApplicationRoleReadFailed)">!(loc.msierrComPlusApplicationRoleReadFailed)</Error> | ||
| 17 | <Error Id="$(var.msierrComPlusUserInApplicationRoleReadFailed)">!(loc.msierrComPlusUserInApplicationRoleReadFailed)</Error> | ||
| 18 | <Error Id="$(var.msierrComPlusAssembliesReadFailed)">!(loc.msierrComPlusAssembliesReadFailed)</Error> | ||
| 19 | <Error Id="$(var.msierrComPlusSubscriptionReadFailed)">!(loc.msierrComPlusSubscriptionReadFailed)</Error> | ||
| 20 | <Error Id="$(var.msierrComPlusPartitionDependency)">!(loc.msierrComPlusPartitionDependency)</Error> | ||
| 21 | <Error Id="$(var.msierrComPlusPartitionNotFound)">!(loc.msierrComPlusPartitionNotFound)</Error> | ||
| 22 | <Error Id="$(var.msierrComPlusPartitionIdConflict)">!(loc.msierrComPlusPartitionIdConflict)</Error> | ||
| 23 | <Error Id="$(var.msierrComPlusPartitionNameConflict)">!(loc.msierrComPlusPartitionNameConflict)</Error> | ||
| 24 | <Error Id="$(var.msierrComPlusApplicationDependency)">!(loc.msierrComPlusApplicationDependency)</Error> | ||
| 25 | <Error Id="$(var.msierrComPlusApplicationNotFound)">!(loc.msierrComPlusApplicationNotFound)</Error> | ||
| 26 | <Error Id="$(var.msierrComPlusApplicationIdConflict)">!(loc.msierrComPlusApplicationIdConflict)</Error> | ||
| 27 | <Error Id="$(var.msierrComPlusApplicationNameConflict)">!(loc.msierrComPlusApplicationNameConflict)</Error> | ||
| 28 | <Error Id="$(var.msierrComPlusApplicationRoleDependency)">!(loc.msierrComPlusApplicationRoleDependency)</Error> | ||
| 29 | <Error Id="$(var.msierrComPlusApplicationRoleNotFound)">!(loc.msierrComPlusApplicationRoleNotFound)</Error> | ||
| 30 | <Error Id="$(var.msierrComPlusApplicationRoleConflict)">!(loc.msierrComPlusApplicationRoleConflict)</Error> | ||
| 31 | <Error Id="$(var.msierrComPlusAssemblyDependency)">!(loc.msierrComPlusAssemblyDependency)</Error> | ||
| 32 | <Error Id="$(var.msierrComPlusSubscriptionIdConflict)">!(loc.msierrComPlusSubscriptionIdConflict)</Error> | ||
| 33 | <Error Id="$(var.msierrComPlusSubscriptionNameConflict)">!(loc.msierrComPlusSubscriptionNameConflict)</Error> | ||
| 34 | <Error Id="$(var.msierrComPlusFailedLookupNames)">!(loc.msierrComPlusFailedLookupNames)</Error> | ||
| 35 | |||
| 36 | <ProgressText Action="ComPlusInstallExecute">!(loc.ComPlusInstallExecute)</ProgressText> | ||
| 37 | <ProgressText Action="ComPlusUninstallExecute">!(loc.ComPlusUninstallExecute)</ProgressText> | ||
| 38 | |||
| 39 | <ProgressText Action="CreateComPlusPartitions" Template="!(loc.CreateComPlusPartitionsTemplate)">!(loc.CreateComPlusPartitions)</ProgressText> | ||
| 40 | <ProgressText Action="RemoveComPlusPartitions" Template="!(loc.RemoveComPlusPartitionsTemplate)">!(loc.RemoveComPlusPartitions)</ProgressText> | ||
| 41 | <ProgressText Action="AddUsersToComPlusPartitionRoles" Template="!(loc.AddUsersToComPlusPartitionRolesTemplate)">!(loc.AddUsersToComPlusPartitionRoles)</ProgressText> | ||
| 42 | <ProgressText Action="RemoveUsersFromComPlusPartRoles" Template="!(loc.RemoveUsersFromComPlusPartitionRolesTemplate)">!(loc.RemoveUsersFromComPlusPartitionRoles)</ProgressText> | ||
| 43 | <ProgressText Action="AddComPlusPartitionUsers" Template="!(loc.AddComPlusPartitionUsersTemplate)">!(loc.AddComPlusPartitionUsers)</ProgressText> | ||
| 44 | <ProgressText Action="RemoveComPlusPartitionUsers" Template="!(loc.RemoveComPlusPartitionUsersTemplate)">!(loc.RemoveComPlusPartitionUsers)</ProgressText> | ||
| 45 | <ProgressText Action="CreateComPlusApplications" Template="!(loc.CreateComPlusApplicationsTemplate)">!(loc.CreateComPlusApplications)</ProgressText> | ||
| 46 | <ProgressText Action="RemoveComPlusApplications" Template="!(loc.RemoveComPlusApplicationsTemplate)">!(loc.RemoveComPlusApplications)</ProgressText> | ||
| 47 | <ProgressText Action="CreateComPlusApplicationRoles" Template="!(loc.CreateComPlusApplicationRolesTemplate)">!(loc.CreateComPlusApplicationRoles)</ProgressText> | ||
| 48 | <ProgressText Action="RemoveComPlusApplicationRoles" Template="!(loc.RemoveComPlusApplicationRolesTemplate)">!(loc.RemoveComPlusApplicationRoles)</ProgressText> | ||
| 49 | <ProgressText Action="AddUsersToComPlusApplicationRoles" Template="!(loc.AddUsersToComPlusApplicationRolesTemplate)">!(loc.AddUsersToComPlusApplicationRoles)</ProgressText> | ||
| 50 | <ProgressText Action="RemoveUsersFromComPlusAppRoles" Template="!(loc.RemoveUsersFromComPlusApplicationRolesTemplate)">!(loc.RemoveUsersFromComPlusApplicationRoles)</ProgressText> | ||
| 51 | <ProgressText Action="RegisterComPlusAssemblies" Template="!(loc.RegisterComPlusAssembliesTemplate)">!(loc.RegisterComPlusAssemblies)</ProgressText> | ||
| 52 | <ProgressText Action="UnregisterComPlusAssemblies" Template="!(loc.UnregisterComPlusAssembliesTemplate)">!(loc.UnregisterComPlusAssemblies)</ProgressText> | ||
| 53 | <ProgressText Action="AddComPlusRoleAssignments" Template="!(loc.AddComPlusRoleAssignmentsTemplate)">!(loc.AddComPlusRoleAssignments)</ProgressText> | ||
| 54 | <ProgressText Action="RemoveComPlusRoleAssignments" Template="!(loc.RemoveComPlusRoleAssignmentsTemplate)">!(loc.RemoveComPlusRoleAssignments)</ProgressText> | ||
| 55 | <ProgressText Action="CreateSubscrComPlusComponents" Template="!(loc.CreateSubscriptionsComPlusComponentsTemplate)">!(loc.CreateSubscriptionsComPlusComponents)</ProgressText> | ||
| 56 | <ProgressText Action="RemoveSubscrComPlusComponents" Template="!(loc.RemoveSubscriptionsComPlusComponentsTemplate)">!(loc.RemoveSubscriptionsComPlusComponents)</ProgressText> | ||
| 57 | </UI> | ||
| 58 | </Fragment> | ||
| 59 | |||
| 60 | <Fragment> | ||
| 61 | <UIRef Id="ComPlusUI" /> | ||
| 62 | |||
| 63 | <CustomAction Id="ConfigureComPlusInstall" BinaryKey="WixCPSched_x86" DllEntry="ConfigureComPlusInstall" Execute="immediate" Return="check" SuppressModularization="yes" /> | ||
| 64 | <CustomAction Id="ConfigureComPlusUninstall" BinaryKey="WixCPSched_x86" DllEntry="ConfigureComPlusUninstall" Execute="immediate" Return="check" SuppressModularization="yes" /> | ||
| 65 | <CustomAction Id="ComPlusInstallPrepare" BinaryKey="WixCPExec_x86" DllEntry="ComPlusPrepare" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 66 | <CustomAction Id="ComPlusRollbackInstallPrepare" BinaryKey="WixCPExec_x86" DllEntry="ComPlusCleanup" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 67 | <CustomAction Id="ComPlusInstallExecute" BinaryKey="WixCPExec_x86" DllEntry="ComPlusInstallExecute" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 68 | <CustomAction Id="ComPlusInstallExecuteCommit" BinaryKey="WixCPExec_x86" DllEntry="ComPlusInstallExecuteCommit" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 69 | <CustomAction Id="ComPlusRollbackInstallExecute" BinaryKey="WixCPExec_x86" DllEntry="ComPlusRollbackInstallExecute" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 70 | <CustomAction Id="ComPlusInstallCommit" BinaryKey="WixCPExec_x86" DllEntry="ComPlusCleanup" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 71 | <CustomAction Id="ComPlusUninstallPrepare" BinaryKey="WixCPExec_x86" DllEntry="ComPlusPrepare" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 72 | <CustomAction Id="ComPlusRollbackUninstallPrepare" BinaryKey="WixCPExec_x86" DllEntry="ComPlusCleanup" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 73 | <CustomAction Id="ComPlusUninstallExecute" BinaryKey="WixCPExec_x86" DllEntry="ComPlusUninstallExecute" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 74 | <CustomAction Id="ComPlusRollbackUninstallExecute" BinaryKey="WixCPExec_x86" DllEntry="ComPlusInstallExecute" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 75 | <CustomAction Id="ComPlusUninstallCommit" BinaryKey="WixCPExec_x86" DllEntry="ComPlusCleanup" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 76 | |||
| 77 | <Property Id="ComPlusInstallPrepare" Hidden="yes" SuppressModularization="yes" /> | ||
| 78 | <Property Id="ComPlusRollbackInstallPrepare" Hidden="yes" SuppressModularization="yes" /> | ||
| 79 | <Property Id="ComPlusInstallExecute" Hidden="yes" SuppressModularization="yes" /> | ||
| 80 | <Property Id="ComPlusInstallExecuteCommit" Hidden="yes" SuppressModularization="yes" /> | ||
| 81 | <Property Id="ComPlusRollbackInstallExecute" Hidden="yes" SuppressModularization="yes" /> | ||
| 82 | <Property Id="ComPlusInstallCommit" Hidden="yes" SuppressModularization="yes" /> | ||
| 83 | <Property Id="ComPlusUninstallPrepare" Hidden="yes" SuppressModularization="yes" /> | ||
| 84 | <Property Id="ComPlusRollbackUninstallPrepare" Hidden="yes" SuppressModularization="yes" /> | ||
| 85 | <Property Id="ComPlusUninstallExecute" Hidden="yes" SuppressModularization="yes" /> | ||
| 86 | <Property Id="ComPlusRollbackUninstallExecute" Hidden="yes" SuppressModularization="yes" /> | ||
| 87 | <Property Id="ComPlusUninstallCommit" Hidden="yes" SuppressModularization="yes" /> | ||
| 88 | |||
| 89 | <InstallExecuteSequence> | ||
| 90 | <Custom Action="ConfigureComPlusUninstall" After="DeleteServices" Overridable="yes">VersionNT >= 500</Custom> | ||
| 91 | <Custom Action="ConfigureComPlusInstall" Before="InstallServices" Overridable="yes">VersionNT >= 500</Custom> | ||
| 92 | </InstallExecuteSequence> | ||
| 93 | </Fragment> | ||
| 94 | |||
| 95 | <Fragment> | ||
| 96 | <UIRef Id="ComPlusUI" /> | ||
| 97 | |||
| 98 | <CustomAction Id="ConfigureComPlusInstall_x64" BinaryKey="WixCPSched_x64" DllEntry="ConfigureComPlusInstall" Execute="immediate" Return="check" SuppressModularization="yes" /> | ||
| 99 | <CustomAction Id="ConfigureComPlusUninstall_x64" BinaryKey="WixCPSched_x64" DllEntry="ConfigureComPlusUninstall" Execute="immediate" Return="check" SuppressModularization="yes" /> | ||
| 100 | <CustomAction Id="ComPlusInstallPrepare_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusPrepare" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 101 | <CustomAction Id="ComPlusRollbackInstallPrepare_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusCleanup" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 102 | <CustomAction Id="ComPlusInstallExecute_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusInstallExecute" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 103 | <CustomAction Id="ComPlusInstallExecuteCommit_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusInstallExecuteCommit" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 104 | <CustomAction Id="ComPlusRollbackInstallExecute_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusRollbackInstallExecute" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 105 | <CustomAction Id="ComPlusInstallCommit_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusCleanup" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 106 | <CustomAction Id="ComPlusUninstallPrepare_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusPrepare" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 107 | <CustomAction Id="ComPlusRollbackUninstallPrepare_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusCleanup" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 108 | <CustomAction Id="ComPlusUninstallExecute_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusUninstallExecute" Execute="deferred" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 109 | <CustomAction Id="ComPlusRollbackUninstallExecute_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusInstallExecute" Execute="rollback" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 110 | <CustomAction Id="ComPlusUninstallCommit_64" BinaryKey="WixCPExec_x64" DllEntry="ComPlusCleanup" Execute="commit" Return="check" Impersonate="no" HideTarget="yes" SuppressModularization="yes" /> | ||
| 111 | |||
| 112 | <Property Id="ComPlusInstallPrepare_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 113 | <Property Id="ComPlusRollbackInstallPrepare_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 114 | <Property Id="ComPlusInstallExecute_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 115 | <Property Id="ComPlusInstallExecuteCommit_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 116 | <Property Id="ComPlusRollbackInstallExecute_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 117 | <Property Id="ComPlusInstallCommit_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 118 | <Property Id="ComPlusUninstallPrepare_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 119 | <Property Id="ComPlusRollbackUninstallPrepare_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 120 | <Property Id="ComPlusUninstallExecute_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 121 | <Property Id="ComPlusRollbackUninstallExecute_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 122 | <Property Id="ComPlusUninstallCommit_64" Hidden="yes" SuppressModularization="yes" /> | ||
| 123 | |||
| 124 | <InstallExecuteSequence> | ||
| 125 | <Custom Action="ConfigureComPlusUninstall_x64" After="DeleteServices" Overridable="yes">VersionNT >= 500</Custom> | ||
| 126 | <Custom Action="ConfigureComPlusInstall_x64" Before="InstallServices" Overridable="yes">VersionNT >= 500</Custom> | ||
| 127 | </InstallExecuteSequence> | ||
| 128 | </Fragment> | ||
| 129 | |||
| 130 | <Fragment> | ||
| 131 | <Binary Id="WixCPExec_x86" SourceFile="!(bindpath.x86)\cpexec.dll"/> | ||
| 132 | <Binary Id="WixCPSched_x86" SourceFile="!(bindpath.x86)\cpsched.dll"/> | ||
| 133 | </Fragment> | ||
| 134 | |||
| 135 | <Fragment> | ||
| 136 | <Binary Id="WixCPExec_x64" SourceFile="!(bindpath.x64)\cpexec.dll"/> | ||
| 137 | <Binary Id="WixCPSched_x64" SourceFile="!(bindpath.x64)\cpsched.dll"/> | ||
| 138 | </Fragment> | ||
| 139 | </Wix> | ||
diff --git a/src/wixlib/en-us.wxl b/src/wixlib/en-us.wxl new file mode 100644 index 00000000..8f6f38fc --- /dev/null +++ b/src/wixlib/en-us.wxl | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | |||
| 5 | <WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 6 | <String Id="msierrComPlusCannotConnect" Overridable="yes">Cannot connect to the COM+ admin catalog. ([2] [3] [4] [5])</String> | ||
| 7 | <String Id="msierrComPlusPartitionReadFailed" Overridable="yes">Failed to read COM+ partitions. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrComPlusPartitionRoleReadFailed" Overridable="yes">Failed to read COM+ partition roles. ([2] [3] [4] [5])</String> | ||
| 9 | <String Id="msierrComPlusUserInPartitionRoleReadFailed" Overridable="yes">Failed to read COM+ users in partition roles. ([2] [3] [4] [5])</String> | ||
| 10 | <String Id="msierrComPlusPartitionUserReadFailed" Overridable="yes">Failed to read COM+ partition users. ([2] [3] [4] [5])</String> | ||
| 11 | <String Id="msierrComPlusApplicationReadFailed" Overridable="yes">Failed to read COM+ applications. ([2] [3] [4] [5])</String> | ||
| 12 | <String Id="msierrComPlusApplicationRoleReadFailed" Overridable="yes">Failed to read COM+ application roles. ([2] [3] [4] [5])</String> | ||
| 13 | <String Id="msierrComPlusUserInApplicationRoleReadFailed" Overridable="yes">Failed to read COM+ users in application roles. ([2] [3] [4] [5])</String> | ||
| 14 | <String Id="msierrComPlusAssembliesReadFailed" Overridable="yes">Failed to read COM+ assemblies. ([2] [3] [4] [5])</String> | ||
| 15 | <String Id="msierrComPlusSubscriptionReadFailed" Overridable="yes">Failed to read COM+ event subscriptions. ([2] [3] [4] [5])</String> | ||
| 16 | <String Id="msierrComPlusPartitionDependency" Overridable="yes">Another entity is dependent on a COM+ partition that is not being installed. ([2] [3] [4] [5])</String> | ||
| 17 | <String Id="msierrComPlusPartitionNotFound" Overridable="yes">The COM+ partition was not found. ([2] [3] [4] [5])</String> | ||
| 18 | <String Id="msierrComPlusPartitionIdConflict" Overridable="yes">A COM+ partition with the same id already exists. ([2] [3] [4] [5])</String> | ||
| 19 | <String Id="msierrComPlusPartitionNameConflict" Overridable="yes">A COM+ partition with the same name already exists. ([2] [3] [4] [5])</String> | ||
| 20 | <String Id="msierrComPlusApplicationDependency" Overridable="yes">Another entity is dependent on a COM+ application that is not being installed. ([2] [3] [4] [5])</String> | ||
| 21 | <String Id="msierrComPlusApplicationNotFound" Overridable="yes">The COM+ application was not found. ([2] [3] [4] [5])</String> | ||
| 22 | <String Id="msierrComPlusApplicationIdConflict" Overridable="yes">A COM+ application with the same id already exists. ([2] [3] [4] [5])</String> | ||
| 23 | <String Id="msierrComPlusApplicationNameConflict" Overridable="yes">A COM+ application with the same name already exists. ([2] [3] [4] [5])</String> | ||
| 24 | <String Id="msierrComPlusApplicationRoleDependency" Overridable="yes">Another entity is dependent on a COM+ application role that is not being installed. ([2] [3] [4] [5])</String> | ||
| 25 | <String Id="msierrComPlusApplicationRoleNotFound" Overridable="yes">The COM+ application role was not found. ([2] [3] [4] [5])</String> | ||
| 26 | <String Id="msierrComPlusApplicationRoleConflict" Overridable="yes">A COM+ application role with the same name already exists. ([2] [3] [4] [5])</String> | ||
| 27 | <String Id="msierrComPlusAssemblyDependency" Overridable="yes">Another entity is dependent on a COM+ assembly that is not being installed. ([2] [3] [4] [5])</String> | ||
| 28 | <String Id="msierrComPlusSubscriptionIdConflict" Overridable="yes">A COM+ component event subscription with the same id already exists. ([2] [3] [4] [5])</String> | ||
| 29 | <String Id="msierrComPlusSubscriptionNameConflict" Overridable="yes">A COM+ component event subscription with the same name already exists. ([2] [3] [4] [5])</String> | ||
| 30 | <String Id="msierrComPlusFailedLookupNames" Overridable="yes">Failed to lookup user account names. ([2] [3] [4] [5])</String> | ||
| 31 | |||
| 32 | <String Id="ComPlusInstallExecute" Overridable="yes">Registering COM+ components</String> | ||
| 33 | <String Id="ComPlusUninstallExecute" Overridable="yes">Unregistering COM+ components</String> | ||
| 34 | |||
| 35 | <String Id="CreateComPlusPartitions" Overridable="yes">Creating COM+ partitions</String> | ||
| 36 | <String Id="CreateComPlusPartitionsTemplate" Overridable="yes">Partition: [1]</String> | ||
| 37 | <String Id="RemoveComPlusPartitions" Overridable="yes">Removing COM+ partitions</String> | ||
| 38 | <String Id="RemoveComPlusPartitionsTemplate" Overridable="yes">Partition: [1]</String> | ||
| 39 | <String Id="AddUsersToComPlusPartitionRoles" Overridable="yes">Adding users to COM+ partition roles</String> | ||
| 40 | <String Id="AddUsersToComPlusPartitionRolesTemplate" Overridable="yes">Role: [1]</String> | ||
| 41 | <String Id="RemoveUsersFromComPlusPartitionRoles" Overridable="yes">Removing users from COM+ partition roles</String> | ||
| 42 | <String Id="RemoveUsersFromComPlusPartitionRolesTemplate" Overridable="yes">Role: [1]</String> | ||
| 43 | <String Id="AddComPlusPartitionUsers" Overridable="yes">Setting default COM+ partitions for users</String> | ||
| 44 | <String Id="AddComPlusPartitionUsersTemplate" Overridable="yes">User: [1]</String> | ||
| 45 | <String Id="RemoveComPlusPartitionUsers" Overridable="yes">Removing default COM+ partitions for users</String> | ||
| 46 | <String Id="RemoveComPlusPartitionUsersTemplate" Overridable="yes">User: [1]</String> | ||
| 47 | <String Id="CreateComPlusApplications" Overridable="yes">Creating COM+ applications</String> | ||
| 48 | <String Id="CreateComPlusApplicationsTemplate" Overridable="yes">Application: [1]</String> | ||
| 49 | <String Id="RemoveComPlusApplications" Overridable="yes">Removing COM+ applications</String> | ||
| 50 | <String Id="RemoveComPlusApplicationsTemplate" Overridable="yes">Application: [1]</String> | ||
| 51 | <String Id="CreateComPlusApplicationRoles" Overridable="yes">Creating COM+ application roles</String> | ||
| 52 | <String Id="CreateComPlusApplicationRolesTemplate" Overridable="yes">Role: [1]</String> | ||
| 53 | <String Id="RemoveComPlusApplicationRoles" Overridable="yes">Removing COM+ application roles</String> | ||
| 54 | <String Id="RemoveComPlusApplicationRolesTemplate" Overridable="yes">Role: [1]</String> | ||
| 55 | <String Id="AddUsersToComPlusApplicationRoles" Overridable="yes">Adding users to COM+ application roles</String> | ||
| 56 | <String Id="AddUsersToComPlusApplicationRolesTemplate" Overridable="yes">User: [1]</String> | ||
| 57 | <String Id="RemoveUsersFromComPlusApplicationRoles" Overridable="yes">Removing users from COM+ application roles</String> | ||
| 58 | <String Id="RemoveUsersFromComPlusApplicationRolesTemplate" Overridable="yes">User: [1]</String> | ||
| 59 | <String Id="RegisterComPlusAssemblies" Overridable="yes">Registering COM+ components</String> | ||
| 60 | <String Id="RegisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
| 61 | <String Id="UnregisterComPlusAssemblies" Overridable="yes">Unregistering COM+ components</String> | ||
| 62 | <String Id="UnregisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
| 63 | <String Id="AddComPlusRoleAssignments" Overridable="yes">Assigning roles to COM+ components</String> | ||
| 64 | <String Id="AddComPlusRoleAssignmentsTemplate" Overridable="yes">Component: [1]</String> | ||
| 65 | <String Id="RemoveComPlusRoleAssignments" Overridable="yes">Removing role assignments from COM+ components</String> | ||
| 66 | <String Id="RemoveComPlusRoleAssignmentsTemplate" Overridable="yes">Component: [1]</String> | ||
| 67 | <String Id="CreateSubscriptionsComPlusComponents" Overridable="yes">Creating subscriptions for COM+ components</String> | ||
| 68 | <String Id="CreateSubscriptionsComPlusComponentsTemplate" Overridable="yes">Subscription: [1]</String> | ||
| 69 | <String Id="RemoveSubscriptionsComPlusComponents" Overridable="yes">Removing subscriptions for COM+ components</String> | ||
| 70 | <String Id="RemoveSubscriptionsComPlusComponentsTemplate" Overridable="yes">Subscription: [1]</String> | ||
| 71 | </WixLocalization> | ||
diff --git a/src/wixlib/es-es.wxl b/src/wixlib/es-es.wxl new file mode 100644 index 00000000..5e7eba66 --- /dev/null +++ b/src/wixlib/es-es.wxl | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | |||
| 5 | <WixLocalization Culture="es-es" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 6 | <String Id="msierrComPlusCannotConnect" Overridable="yes">No se puede conectar al catálogo de administración de COM+. ([2] [3] [4] [5])</String> | ||
| 7 | <String Id="msierrComPlusPartitionReadFailed" Overridable="yes">Falla al leer las particiones COM+. ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrComPlusPartitionRoleReadFailed" Overridable="yes">Falla al leer los roles de las particiones COM+. ([2] [3] [4] [5])</String> | ||
| 9 | <String Id="msierrComPlusUserInPartitionRoleReadFailed" Overridable="yes">Falla al leer los usuario en los roles de las particiones COM+. ([2] [3] [4] [5])</String> | ||
| 10 | <String Id="msierrComPlusPartitionUserReadFailed" Overridable="yes">Falla al leer los usuario de las particiones COM+. ([2] [3] [4] [5])</String> | ||
| 11 | <String Id="msierrComPlusApplicationReadFailed" Overridable="yes">Falla al leer las aplicaciones COM+. ([2] [3] [4] [5])</String> | ||
| 12 | <String Id="msierrComPlusApplicationRoleReadFailed" Overridable="yes">Falla al leer los roles de las aplicaciones COM+. ([2] [3] [4] [5])</String> | ||
| 13 | <String Id="msierrComPlusUserInApplicationRoleReadFailed" Overridable="yes">Falla al leer los usuario de las aplicaciones COM+. ([2] [3] [4] [5])</String> | ||
| 14 | <String Id="msierrComPlusAssembliesReadFailed" Overridable="yes">Falla al leer los ensamblados COM+. ([2] [3] [4] [5])</String> | ||
| 15 | <String Id="msierrComPlusSubscriptionReadFailed" Overridable="yes">Falla al leer las suscripciones a eventos COM+. ([2] [3] [4] [5])</String> | ||
| 16 | <String Id="msierrComPlusPartitionDependency" Overridable="yes">Otra entidad es dependiente de una partición COM+ que no está siendo instalada. ([2] [3] [4] [5])</String> | ||
| 17 | <String Id="msierrComPlusPartitionNotFound" Overridable="yes">La partición COM+ no pudo ser encontrada. ([2] [3] [4] [5])</String> | ||
| 18 | <String Id="msierrComPlusPartitionIdConflict" Overridable="yes">Ya existe otra partición COM+ con el mismo id. ([2] [3] [4] [5])</String> | ||
| 19 | <String Id="msierrComPlusPartitionNameConflict" Overridable="yes">Ya existe otra partición COM+ con el mismo nombre. ([2] [3] [4] [5])</String> | ||
| 20 | <String Id="msierrComPlusApplicationDependency" Overridable="yes">Otra entidad es dependiente de una aplicación COM+ que no está siendo instalada. ([2] [3] [4] [5])</String> | ||
| 21 | <String Id="msierrComPlusApplicationNotFound" Overridable="yes">La aplicación COM+ no pudo ser encontrada. ([2] [3] [4] [5])</String> | ||
| 22 | <String Id="msierrComPlusApplicationIdConflict" Overridable="yes">Ya existe otra aplicación COM+ con el mismo id. ([2] [3] [4] [5])</String> | ||
| 23 | <String Id="msierrComPlusApplicationNameConflict" Overridable="yes">Ya existe otra aplicación COM+ con el mismo nombre. ([2] [3] [4] [5])</String> | ||
| 24 | <String Id="msierrComPlusApplicationRoleDependency" Overridable="yes">Otra entidad es dependiente de un rol de aplicación COM+ que no está siendo instalado. ([2] [3] [4] [5])</String> | ||
| 25 | <String Id="msierrComPlusApplicationRoleNotFound" Overridable="yes">El rol de aplicación COM+ no pudo ser encontrado. ([2] [3] [4] [5])</String> | ||
| 26 | <String Id="msierrComPlusApplicationRoleConflict" Overridable="yes">Ya existe otro rol de aplicación COM+ con el mismo nombre. ([2] [3] [4] [5])</String> | ||
| 27 | <String Id="msierrComPlusAssemblyDependency" Overridable="yes">Otra entidad es dependiente de un ensamblado COM+ que no está siendo instalado. ([2] [3] [4] [5])</String> | ||
| 28 | <String Id="msierrComPlusSubscriptionIdConflict" Overridable="yes">Ya existe otra suscripción de evento al componente COM+ con el mismo id. ([2] [3] [4] [5])</String> | ||
| 29 | <String Id="msierrComPlusSubscriptionNameConflict" Overridable="yes">Ya existe otra suscripción de evento al componente COM+ con el mismo nombre. ([2] [3] [4] [5])</String> | ||
| 30 | <String Id="msierrComPlusFailedLookupNames" Overridable="yes">Falla el la búsqueda de los nombres de usuario. ([2] [3] [4] [5])</String> | ||
| 31 | |||
| 32 | <String Id="ComPlusInstallExecute" Overridable="yes">Registrando componentes COM+</String> | ||
| 33 | <String Id="ComPlusUninstallExecute" Overridable="yes">Anular el registro de componentes COM+</String> | ||
| 34 | |||
| 35 | <String Id="CreateComPlusPartitions" Overridable="yes">Creando particiones COM+</String> | ||
| 36 | <String Id="CreateComPlusPartitionsTemplate" Overridable="yes">Particiones: [1]</String> | ||
| 37 | <String Id="RemoveComPlusPartitions" Overridable="yes">Borrando particiones COM+</String> | ||
| 38 | <String Id="RemoveComPlusPartitionsTemplate" Overridable="yes">Particiones: [1]</String> | ||
| 39 | <String Id="AddUsersToComPlusPartitionRoles" Overridable="yes">Agregando usuarios a los roles de las particiones COM+</String> | ||
| 40 | <String Id="AddUsersToComPlusPartitionRolesTemplate" Overridable="yes">Rol: [1]</String> | ||
| 41 | <String Id="RemoveUsersFromComPlusPartitionRoles" Overridable="yes">Borrando usuarios a los roles de las particiones COM+</String> | ||
| 42 | <String Id="RemoveUsersFromComPlusPartitionRolesTemplate" Overridable="yes">Rol: [1]</String> | ||
| 43 | <String Id="AddComPlusPartitionUsers" Overridable="yes">Ajustando partición COM+ por omisión para los usuarios</String> | ||
| 44 | <String Id="AddComPlusPartitionUsersTemplate" Overridable="yes">Usuario: [1]</String> | ||
| 45 | <String Id="RemoveComPlusPartitionUsers" Overridable="yes">Borrando partición COM+ por omisión para los usuarios</String> | ||
| 46 | <String Id="RemoveComPlusPartitionUsersTemplate" Overridable="yes">Usuario: [1]</String> | ||
| 47 | <String Id="CreateComPlusApplications" Overridable="yes">Creando aplicación COM+</String> | ||
| 48 | <String Id="CreateComPlusApplicationsTemplate" Overridable="yes">Aplicación: [1]</String> | ||
| 49 | <String Id="RemoveComPlusApplications" Overridable="yes">Borrando aplicación COM+</String> | ||
| 50 | <String Id="RemoveComPlusApplicationsTemplate" Overridable="yes">Aplicación: [1]</String> | ||
| 51 | <String Id="CreateComPlusApplicationRoles" Overridable="yes">Creando roles de aplicación COM+</String> | ||
| 52 | <String Id="CreateComPlusApplicationRolesTemplate" Overridable="yes">Rol: [1]</String> | ||
| 53 | <String Id="RemoveComPlusApplicationRoles" Overridable="yes">Borrando roles de aplicación COM+</String> | ||
| 54 | <String Id="RemoveComPlusApplicationRolesTemplate" Overridable="yes">Rol: [1]</String> | ||
| 55 | <String Id="AddUsersToComPlusApplicationRoles" Overridable="yes">Agregando usuarios a los roles de aplicación COM+</String> | ||
| 56 | <String Id="AddUsersToComPlusApplicationRolesTemplate" Overridable="yes">Usuario: [1]</String> | ||
| 57 | <String Id="RemoveUsersFromComPlusApplicationRoles" Overridable="yes">Borrando usuarios a los roles de aplicación COM</String> | ||
| 58 | <String Id="RemoveUsersFromComPlusApplicationRolesTemplate" Overridable="yes">Usuario: [1]</String> | ||
| 59 | <String Id="RegisterComPlusAssemblies" Overridable="yes">Registrando componente COM+</String> | ||
| 60 | <String Id="RegisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
| 61 | <String Id="UnregisterComPlusAssemblies" Overridable="yes">Anulando el registro de componentes COM+</String> | ||
| 62 | <String Id="UnregisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
| 63 | <String Id="AddComPlusRoleAssignments" Overridable="yes">Asignando roles a los componentes COM+</String> | ||
| 64 | <String Id="AddComPlusRoleAssignmentsTemplate" Overridable="yes">Componente: [1]</String> | ||
| 65 | <String Id="RemoveComPlusRoleAssignments" Overridable="yes">Borrando asignación de roles a los componentes COM+</String> | ||
| 66 | <String Id="RemoveComPlusRoleAssignmentsTemplate" Overridable="yes">Componente: [1]</String> | ||
| 67 | <String Id="CreateSubscriptionsComPlusComponents" Overridable="yes">Creando suscripción a componentes COM+</String> | ||
| 68 | <String Id="CreateSubscriptionsComPlusComponentsTemplate" Overridable="yes">Suscripción: [1]</String> | ||
| 69 | <String Id="RemoveSubscriptionsComPlusComponents" Overridable="yes">Borrando suscripción a componentes COM+</String> | ||
| 70 | <String Id="RemoveSubscriptionsComPlusComponentsTemplate" Overridable="yes">Suscripción: [1]</String> | ||
| 71 | </WixLocalization> | ||
| 72 | |||
diff --git a/src/wixlib/ja-jp.wxl b/src/wixlib/ja-jp.wxl new file mode 100644 index 00000000..03b2cf1c --- /dev/null +++ b/src/wixlib/ja-jp.wxl | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> | ||
| 3 | |||
| 4 | |||
| 5 | <WixLocalization Culture="ja-jp" xmlns="http://wixtoolset.org/schemas/v4/wxl"> | ||
| 6 | <String Id="msierrComPlusCannotConnect" Overridable="yes">COM+ 管理カタログへ接続できません。 ([2] [3] [4] [5])</String> | ||
| 7 | <String Id="msierrComPlusPartitionReadFailed" Overridable="yes">COM+ パーティションの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 8 | <String Id="msierrComPlusPartitionRoleReadFailed" Overridable="yes">COM+ パーティション役割の読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 9 | <String Id="msierrComPlusUserInPartitionRoleReadFailed" Overridable="yes">COM+ パーティション役割内ユーザーの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 10 | <String Id="msierrComPlusPartitionUserReadFailed" Overridable="yes">COM+ パーティション ユーザーの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 11 | <String Id="msierrComPlusApplicationReadFailed" Overridable="yes">COM+ アプリケーションの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 12 | <String Id="msierrComPlusApplicationRoleReadFailed" Overridable="yes">COM+ アプリケーション役割の読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 13 | <String Id="msierrComPlusUserInApplicationRoleReadFailed" Overridable="yes">COM+ アプリケーション役割内ユーザーの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 14 | <String Id="msierrComPlusAssembliesReadFailed" Overridable="yes">COM+ アセンブリの読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 15 | <String Id="msierrComPlusSubscriptionReadFailed" Overridable="yes">COM+ イベント登録の読み込みに失敗しました。 ([2] [3] [4] [5])</String> | ||
| 16 | <String Id="msierrComPlusPartitionDependency" Overridable="yes">他のエンティティはインストールされない COM+ パーティションに依存します。 ([2] [3] [4] [5])</String> | ||
| 17 | <String Id="msierrComPlusPartitionNotFound" Overridable="yes">COM+ パーティションは見つかりません ([2] [3] [4] [5])</String> | ||
| 18 | <String Id="msierrComPlusPartitionIdConflict" Overridable="yes">同一 ID を持つ COM+ パーティションが既に存在します。 ([2] [3] [4] [5])</String> | ||
| 19 | <String Id="msierrComPlusPartitionNameConflict" Overridable="yes">同一名称を持つ COM+ パーティションが既に存在します。 ([2] [3] [4] [5])</String> | ||
| 20 | <String Id="msierrComPlusApplicationDependency" Overridable="yes">他のエンティティはインストールされない COM+ アプリケーションに依存します。 ([2] [3] [4] [5])</String> | ||
| 21 | <String Id="msierrComPlusApplicationNotFound" Overridable="yes">COM+ アプリケーションは見つかりません。 ([2] [3] [4] [5])</String> | ||
| 22 | <String Id="msierrComPlusApplicationIdConflict" Overridable="yes">同一 ID を持つ COM+ アプリケーションが既に存在します。 ([2] [3] [4] [5])</String> | ||
| 23 | <String Id="msierrComPlusApplicationNameConflict" Overridable="yes">同一名称を持つ COM+ アプリケーションが既に存在します。 ([2] [3] [4] [5])</String> | ||
| 24 | <String Id="msierrComPlusApplicationRoleDependency" Overridable="yes">他のエンティティはインストールされない COM+ アプリケーション役割に依存します。 ([2] [3] [4] [5])</String> | ||
| 25 | <String Id="msierrComPlusApplicationRoleNotFound" Overridable="yes">COM+ アプリケーション役割は見つかりません。 ([2] [3] [4] [5])</String> | ||
| 26 | <String Id="msierrComPlusApplicationRoleConflict" Overridable="yes">同一名称を持つ COM+ アプリケーション役割が既に存在します。 ([2] [3] [4] [5])</String> | ||
| 27 | <String Id="msierrComPlusAssemblyDependency" Overridable="yes">他のエンティティはインストールされない COM+ アセンブリに依存します。 ([2] [3] [4] [5])</String> | ||
| 28 | <String Id="msierrComPlusSubscriptionIdConflict" Overridable="yes">同一 ID を持つ COM+ コンポーネントのイベント登録が既に存在します。 ([2] [3] [4] [5])</String> | ||
| 29 | <String Id="msierrComPlusSubscriptionNameConflict" Overridable="yes">同一名称を持つ COM+ コンポーネントのイベント登録が既に存在します。 ([2] [3] [4] [5])</String> | ||
| 30 | <String Id="msierrComPlusFailedLookupNames" Overridable="yes">ユーザー アカウント名の照合に失敗しました。 ([2] [3] [4] [5])</String> | ||
| 31 | |||
| 32 | <String Id="ComPlusInstallExecute" Overridable="yes">COM+ コンポーネントを登録しています</String> | ||
| 33 | <String Id="ComPlusUninstallExecute" Overridable="yes">COM+ コンポーネント登録を解除しています</String> | ||
| 34 | |||
| 35 | <String Id="CreateComPlusPartitions" Overridable="yes">COM+ パーティションを作成しています</String> | ||
| 36 | <String Id="CreateComPlusPartitionsTemplate" Overridable="yes">パーティション: [1]</String> | ||
| 37 | <String Id="RemoveComPlusPartitions" Overridable="yes">COM+ パーティションを削除しています</String> | ||
| 38 | <String Id="RemoveComPlusPartitionsTemplate" Overridable="yes">パーティション: [1]</String> | ||
| 39 | <String Id="AddUsersToComPlusPartitionRoles" Overridable="yes">ユーザーを COM+ パーティション役割に追加しています</String> | ||
| 40 | <String Id="AddUsersToComPlusPartitionRolesTemplate" Overridable="yes">役割: [1]</String> | ||
| 41 | <String Id="RemoveUsersFromComPlusPartitionRoles" Overridable="yes">ユーザを COM+ パーティション役割より削除しています</String> | ||
| 42 | <String Id="RemoveUsersFromComPlusPartitionRolesTemplate" Overridable="yes">役割: [1]</String> | ||
| 43 | <String Id="AddComPlusPartitionUsers" Overridable="yes">ユーザーのデフォルト COM+ 役割を設定しています</String> | ||
| 44 | <String Id="AddComPlusPartitionUsersTemplate" Overridable="yes">ユーザー: [1]</String> | ||
| 45 | <String Id="RemoveComPlusPartitionUsers" Overridable="yes">ユーザーのデフォルト COM+ パーティション役割を削除しています</String> | ||
| 46 | <String Id="RemoveComPlusPartitionUsersTemplate" Overridable="yes">ユーザー: [1]</String> | ||
| 47 | <String Id="CreateComPlusApplications" Overridable="yes">COM+ アプリケーションを作成しています</String> | ||
| 48 | <String Id="CreateComPlusApplicationsTemplate" Overridable="yes">アプリケーション: [1]</String> | ||
| 49 | <String Id="RemoveComPlusApplications" Overridable="yes">COM+ アプリケーションを削除しています</String> | ||
| 50 | <String Id="RemoveComPlusApplicationsTemplate" Overridable="yes">アプリケーション: [1]</String> | ||
| 51 | <String Id="CreateComPlusApplicationRoles" Overridable="yes">COM+ アプリケーション役割を作成しています</String> | ||
| 52 | <String Id="CreateComPlusApplicationRolesTemplate" Overridable="yes">役割: [1]</String> | ||
| 53 | <String Id="RemoveComPlusApplicationRoles" Overridable="yes">COM+ アプリケーション役割を削除しています</String> | ||
| 54 | <String Id="RemoveComPlusApplicationRolesTemplate" Overridable="yes">役割: [1]</String> | ||
| 55 | <String Id="AddUsersToComPlusApplicationRoles" Overridable="yes">ユーザーを COM+ アプリケーション役割に追加しています</String> | ||
| 56 | <String Id="AddUsersToComPlusApplicationRolesTemplate" Overridable="yes">ユーザー: [1]</String> | ||
| 57 | <String Id="RemoveUsersFromComPlusApplicationRoles" Overridable="yes">ユーザーを COM+ アプリケーション役割より削除しています</String> | ||
| 58 | <String Id="RemoveUsersFromComPlusApplicationRolesTemplate" Overridable="yes">ユーザー: [1]</String> | ||
| 59 | <String Id="RegisterComPlusAssemblies" Overridable="yes">COM+ コンポーネントを登録しています</String> | ||
| 60 | <String Id="RegisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
| 61 | <String Id="UnregisterComPlusAssemblies" Overridable="yes">COM+ コンポーネント登録を解除しています</String> | ||
| 62 | <String Id="UnregisterComPlusAssembliesTemplate" Overridable="yes">DLL: [1]</String> | ||
| 63 | <String Id="AddComPlusRoleAssignments" Overridable="yes">COM+ コンポーネントへ役割を割り当てています</String> | ||
| 64 | <String Id="AddComPlusRoleAssignmentsTemplate" Overridable="yes">コンポーネント: [1]</String> | ||
| 65 | <String Id="RemoveComPlusRoleAssignments" Overridable="yes">COM+ コンポーネントより役割割当を削除しています</String> | ||
| 66 | <String Id="RemoveComPlusRoleAssignmentsTemplate" Overridable="yes">コンポーネント: [1]</String> | ||
| 67 | <String Id="CreateSubscriptionsComPlusComponents" Overridable="yes">COM+ コンポーネント用登録を作成しています</String> | ||
| 68 | <String Id="CreateSubscriptionsComPlusComponentsTemplate" Overridable="yes">登録: [1]</String> | ||
| 69 | <String Id="RemoveSubscriptionsComPlusComponents" Overridable="yes">COM+ コンポーネント用登録を削除しています</String> | ||
| 70 | <String Id="RemoveSubscriptionsComPlusComponentsTemplate" Overridable="yes">登録: [1]</String> | ||
| 71 | </WixLocalization> | ||
