main
cpp 1,226 lines 47.8 KB
Raw
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 LPCWSTR vcsFirewallExceptionQuery =
6 L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction`, `Action`, `EdgeTraversal`, `Enabled`, `Grouping`, `IcmpTypesAndCodes`, `Interfaces`, `InterfaceTypes`, `LocalAddresses`, `RemotePort`, `ServiceName`, `LocalAppPackageId`, `LocalUserAuthorizedList`, `LocalUserOwner`, `RemoteMachineAuthorizedList`, `RemoteUserAuthorizedList`, `SecureFlags` FROM `Wix5FirewallException`";
7 enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription, feqDirection, feqAction, feqEdgeTraversal, feqEnabled, feqGrouping, feqIcmpTypesAndCodes, feqInterfaces, feqInterfaceTypes, feqLocalAddresses, feqRemotePort, feqServiceName, feqLocalAppPackageId, feqLocalUserAuthorizedList, feqLocalUserOwner, feqRemoteMachineAuthorizedList, feqRemoteUserAuthorizedList, feqSecureFlags };
8 enum eFirewallExceptionAttributes { feaIgnoreFailures = 1, feaIgnoreUpdates = 2, feaEnableOnUpdate = 4, feaAddINetFwRule2 = 8, feaAddINetFwRule3 = 16 };
9
10 struct FIREWALL_EXCEPTION_ATTRIBUTES
11 {
12 LPWSTR pwzName;
13 int iAttributes;
14
15 // INetFwRule
16 int iAction;
17 LPWSTR pwzApplicationName;
18 LPWSTR pwzDescription;
19 int iDirection;
20 int iEnabled;
21 LPWSTR pwzGrouping;
22 LPWSTR pwzIcmpTypesAndCodes;
23 LPWSTR pwzInterfaces;
24 LPWSTR pwzInterfaceTypes;
25 LPWSTR pwzLocalAddresses;
26 LPWSTR pwzLocalPorts;
27 int iProfile;
28 int iProtocol;
29 LPWSTR pwzRemoteAddresses;
30 LPWSTR pwzRemotePorts;
31 LPWSTR pwzServiceName;
32
33 // INetFwRule2
34 int iEdgeTraversal;
35
36 // INetFwRule3
37 LPWSTR pwzLocalAppPackageId;
38 LPWSTR pwzLocalUserAuthorizedList;
39 LPWSTR pwzLocalUserOwner;
40 LPWSTR pwzRemoteMachineAuthorizedList;
41 LPWSTR pwzRemoteUserAuthorizedList;
42 int iSecureFlags;
43 };
44
45 /******************************************************************
46 SchedFirewallExceptions - immediate custom action worker to
47 register and remove firewall exceptions.
48
49 ********************************************************************/
50 static UINT SchedFirewallExceptions(
51 __in MSIHANDLE hInstall,
52 __in WCA_TODO todoSched
53 )
54 {
55 HRESULT hr = S_OK;
56 UINT er = ERROR_SUCCESS;
57 int cFirewallExceptions = 0;
58
59 PMSIHANDLE hView = NULL;
60 PMSIHANDLE hRec = NULL;
61
62 LPWSTR pwzCustomActionData = NULL;
63 LPWSTR pwzComponent = NULL;
64
65 FIREWALL_EXCEPTION_ATTRIBUTES attrs = { 0 };
66
67 // initialize
68 hr = WcaInitialize(hInstall, "SchedFirewallExceptions");
69 ExitOnFailure(hr, "Failed to initialize");
70
71 // anything to do?
72 if (S_OK != WcaTableExists(L"Wix5FirewallException"))
73 {
74 WcaLog(LOGMSG_STANDARD, "Wix5FirewallException table doesn't exist, so there are no firewall exceptions to configure.");
75 ExitFunction();
76 }
77
78 // query and loop through all the firewall exceptions
79 hr = WcaOpenExecuteView(vcsFirewallExceptionQuery, &hView);
80 ExitOnFailure(hr, "Failed to open view on Wix5FirewallException table");
81
82 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
83 {
84 hr = WcaGetRecordFormattedString(hRec, feqName, &attrs.pwzName);
85 ExitOnFailure(hr, "Failed to get firewall exception name.");
86
87 hr = WcaGetRecordFormattedString(hRec, feqRemoteAddresses, &attrs.pwzRemoteAddresses);
88 ExitOnFailure(hr, "Failed to get firewall exception remote addresses.");
89
90 hr = WcaGetRecordFormattedString(hRec, feqPort, &attrs.pwzLocalPorts);
91 ExitOnFailure(hr, "Failed to get firewall exception port.");
92
93 hr = WcaGetRecordFormattedInteger(hRec, feqProtocol, &attrs.iProtocol);
94 ExitOnFailure(hr, "Failed to get firewall exception protocol.");
95
96 hr = WcaGetRecordFormattedString(hRec, feqProgram, &attrs.pwzApplicationName);
97 ExitOnFailure(hr, "Failed to get firewall exception program.");
98
99 hr = WcaGetRecordInteger(hRec, feqAttributes, &attrs.iAttributes);
100 ExitOnFailure(hr, "Failed to get firewall exception attributes.");
101
102 hr = WcaGetRecordFormattedInteger(hRec, feqProfile, &attrs.iProfile);
103 ExitOnFailure(hr, "Failed to get firewall exception profile.");
104
105 hr = WcaGetRecordString(hRec, feqComponent, &pwzComponent);
106 ExitOnFailure(hr, "Failed to get firewall exception component.");
107
108 hr = WcaGetRecordFormattedString(hRec, feqDescription, &attrs.pwzDescription);
109 ExitOnFailure(hr, "Failed to get firewall exception description.");
110
111 hr = WcaGetRecordInteger(hRec, feqDirection, &attrs.iDirection);
112 ExitOnFailure(hr, "Failed to get firewall exception direction.");
113
114 hr = WcaGetRecordFormattedInteger(hRec, feqAction, &attrs.iAction);
115 ExitOnFailure(hr, "Failed to get firewall exception action.");
116
117 hr = WcaGetRecordFormattedInteger(hRec, feqEdgeTraversal, &attrs.iEdgeTraversal);
118 ExitOnFailure(hr, "Failed to get firewall exception edge traversal.");
119
120 hr = WcaGetRecordFormattedInteger(hRec, feqEnabled, &attrs.iEnabled);
121 ExitOnFailure(hr, "Failed to get firewall exception enabled flag.");
122
123 hr = WcaGetRecordFormattedString(hRec, feqGrouping, &attrs.pwzGrouping);
124 ExitOnFailure(hr, "Failed to get firewall exception grouping.");
125
126 hr = WcaGetRecordFormattedString(hRec, feqIcmpTypesAndCodes, &attrs.pwzIcmpTypesAndCodes);
127 ExitOnFailure(hr, "Failed to get firewall exception ICMP types and codes.");
128
129 hr = WcaGetRecordFormattedString(hRec, feqInterfaces, &attrs.pwzInterfaces);
130 ExitOnFailure(hr, "Failed to get firewall exception interfaces.");
131
132 hr = WcaGetRecordFormattedString(hRec, feqInterfaceTypes, &attrs.pwzInterfaceTypes);
133 ExitOnFailure(hr, "Failed to get firewall exception interface types.");
134
135 hr = WcaGetRecordFormattedString(hRec, feqLocalAddresses, &attrs.pwzLocalAddresses);
136 ExitOnFailure(hr, "Failed to get firewall exception local addresses.");
137
138 hr = WcaGetRecordFormattedString(hRec, feqRemotePort, &attrs.pwzRemotePorts);
139 ExitOnFailure(hr, "Failed to get firewall exception remote port.");
140
141 hr = WcaGetRecordFormattedString(hRec, feqServiceName, &attrs.pwzServiceName);
142 ExitOnFailure(hr, "Failed to get firewall exception service name.");
143
144 hr = WcaGetRecordFormattedString(hRec, feqLocalAppPackageId, &attrs.pwzLocalAppPackageId);
145 ExitOnFailure(hr, "Failed to get firewall exception local app package id.");
146
147 hr = WcaGetRecordFormattedString(hRec, feqLocalUserAuthorizedList, &attrs.pwzLocalUserAuthorizedList);
148 ExitOnFailure(hr, "Failed to get firewall exception local user authorized list.");
149
150 hr = WcaGetRecordFormattedString(hRec, feqLocalUserOwner, &attrs.pwzLocalUserOwner);
151 ExitOnFailure(hr, "Failed to get firewall exception local user owner.");
152
153 hr = WcaGetRecordFormattedString(hRec, feqRemoteMachineAuthorizedList, &attrs.pwzRemoteMachineAuthorizedList);
154 ExitOnFailure(hr, "Failed to get firewall exception remote machine authorized list.");
155
156 hr = WcaGetRecordFormattedString(hRec, feqRemoteUserAuthorizedList, &attrs.pwzRemoteUserAuthorizedList);
157 ExitOnFailure(hr, "Failed to get firewall exception remote user authorized list.");
158
159 hr = WcaGetRecordFormattedInteger(hRec, feqSecureFlags, &attrs.iSecureFlags);
160 ExitOnFailure(hr, "Failed to get firewall exception secure flag.");
161
162 // figure out what we're doing for this exception, treating reinstall the same as install
163 WCA_TODO todoComponent = WcaGetComponentToDo(pwzComponent);
164 if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched)
165 {
166 WcaLog(LOGMSG_STANDARD, "Component '%ls' action state (%d) doesn't match request (%d)", pwzComponent, todoComponent, todoSched);
167 continue;
168 }
169
170 ++cFirewallExceptions;
171 hr = WcaWriteIntegerToCaData(todoComponent, &pwzCustomActionData);
172 ExitOnFailure(hr, "failed to write exception action to custom action data");
173
174 hr = WcaWriteStringToCaData(attrs.pwzName, &pwzCustomActionData);
175 ExitOnFailure(hr, "failed to write exception name to custom action data");
176
177 hr = WcaWriteIntegerToCaData(attrs.iProfile, &pwzCustomActionData);
178 ExitOnFailure(hr, "failed to write exception profile to custom action data");
179
180 hr = WcaWriteStringToCaData(attrs.pwzRemoteAddresses, &pwzCustomActionData);
181 ExitOnFailure(hr, "failed to write exception remote addresses to custom action data");
182
183 hr = WcaWriteIntegerToCaData(attrs.iAttributes, &pwzCustomActionData);
184 ExitOnFailure(hr, "failed to write exception attributes to custom action data");
185
186 hr = WcaWriteStringToCaData(attrs.pwzApplicationName, &pwzCustomActionData);
187 ExitOnFailure(hr, "failed to write application path to custom action data");
188
189 hr = WcaWriteStringToCaData(attrs.pwzLocalPorts, &pwzCustomActionData);
190 ExitOnFailure(hr, "failed to write local ports to custom action data");
191
192 hr = WcaWriteIntegerToCaData(attrs.iProtocol, &pwzCustomActionData);
193 ExitOnFailure(hr, "failed to write exception protocol to custom action data");
194
195 hr = WcaWriteStringToCaData(attrs.pwzDescription, &pwzCustomActionData);
196 ExitOnFailure(hr, "failed to write firewall exception description to custom action data");
197
198 hr = WcaWriteIntegerToCaData(attrs.iDirection, &pwzCustomActionData);
199 ExitOnFailure(hr, "failed to write firewall exception direction to custom action data");
200
201 hr = WcaWriteIntegerToCaData(attrs.iAction, &pwzCustomActionData);
202 ExitOnFailure(hr, "failed to write exception action to custom action data");
203
204 hr = WcaWriteIntegerToCaData(attrs.iEdgeTraversal, &pwzCustomActionData);
205 ExitOnFailure(hr, "failed to write exception edge traversal to custom action data");
206
207 hr = WcaWriteIntegerToCaData(attrs.iEnabled, &pwzCustomActionData);
208 ExitOnFailure(hr, "failed to write exception enabled flag to custom action data");
209
210 hr = WcaWriteStringToCaData(attrs.pwzGrouping, &pwzCustomActionData);
211 ExitOnFailure(hr, "failed to write grouping to custom action data");
212
213 hr = WcaWriteStringToCaData(attrs.pwzIcmpTypesAndCodes, &pwzCustomActionData);
214 ExitOnFailure(hr, "failed to write icmp types and codes to custom action data");
215
216 hr = WcaWriteStringToCaData(attrs.pwzInterfaces, &pwzCustomActionData);
217 ExitOnFailure(hr, "failed to write interfaces to custom action data");
218
219 hr = WcaWriteStringToCaData(attrs.pwzInterfaceTypes, &pwzCustomActionData);
220 ExitOnFailure(hr, "failed to write interface types to custom action data");
221
222 hr = WcaWriteStringToCaData(attrs.pwzLocalAddresses, &pwzCustomActionData);
223 ExitOnFailure(hr, "failed to write local addresses to custom action data");
224
225 hr = WcaWriteStringToCaData(attrs.pwzRemotePorts, &pwzCustomActionData);
226 ExitOnFailure(hr, "failed to write remote ports to custom action data");
227
228 hr = WcaWriteStringToCaData(attrs.pwzServiceName, &pwzCustomActionData);
229 ExitOnFailure(hr, "failed to write service name to custom action data");
230
231 hr = WcaWriteStringToCaData(attrs.pwzLocalAppPackageId, &pwzCustomActionData);
232 ExitOnFailure(hr, "failed to write local app package id to custom action data");
233
234 hr = WcaWriteStringToCaData(attrs.pwzLocalUserAuthorizedList, &pwzCustomActionData);
235 ExitOnFailure(hr, "failed to write local user authorized list to custom action data");
236
237 hr = WcaWriteStringToCaData(attrs.pwzLocalUserOwner, &pwzCustomActionData);
238 ExitOnFailure(hr, "failed to write local user owner to custom action data");
239
240 hr = WcaWriteStringToCaData(attrs.pwzRemoteMachineAuthorizedList, &pwzCustomActionData);
241 ExitOnFailure(hr, "failed to write remote machine authorized list to custom action data");
242
243 hr = WcaWriteStringToCaData(attrs.pwzRemoteUserAuthorizedList, &pwzCustomActionData);
244 ExitOnFailure(hr, "failed to write remote user authorized list to custom action data");
245
246 hr = WcaWriteIntegerToCaData(attrs.iSecureFlags, &pwzCustomActionData);
247 ExitOnFailure(hr, "failed to write exception secure flags to custom action data");
248 }
249
250 // reaching the end of the list is actually a good thing, not an error
251 if (E_NOMOREITEMS == hr)
252 {
253 hr = S_OK;
254 }
255 ExitOnFailure(hr, "failure occured while processing Wix5FirewallException table");
256
257 // schedule ExecFirewallExceptions if there's anything to do
258 if (pwzCustomActionData && *pwzCustomActionData)
259 {
260 WcaLog(LOGMSG_STANDARD, "Scheduling firewall exception (%ls)", pwzCustomActionData);
261
262 if (WCA_TODO_INSTALL == todoSched)
263 {
264 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
265 ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback");
266 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
267 ExitOnFailure(hr, "failed to schedule firewall install exceptions execution");
268 }
269 else
270 {
271 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
272 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback");
273 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
274 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution");
275 }
276 }
277 else
278 {
279 WcaLog(LOGMSG_STANDARD, "No firewall exceptions scheduled");
280 }
281
282 LExit:
283 ReleaseStr(attrs.pwzName);
284 ReleaseStr(attrs.pwzRemoteAddresses);
285 ReleaseStr(attrs.pwzLocalPorts);
286 ReleaseStr(attrs.pwzApplicationName);
287 ReleaseStr(attrs.pwzDescription);
288 ReleaseStr(attrs.pwzGrouping);
289 ReleaseStr(attrs.pwzIcmpTypesAndCodes);
290 ReleaseStr(attrs.pwzInterfaces);
291 ReleaseStr(attrs.pwzInterfaceTypes);
292 ReleaseStr(attrs.pwzLocalAddresses);
293 ReleaseStr(attrs.pwzRemotePorts);
294 ReleaseStr(attrs.pwzServiceName);
295 ReleaseStr(attrs.pwzLocalAppPackageId);
296 ReleaseStr(attrs.pwzLocalUserAuthorizedList);
297 ReleaseStr(attrs.pwzLocalUserOwner);
298 ReleaseStr(attrs.pwzRemoteMachineAuthorizedList);
299 ReleaseStr(attrs.pwzRemoteUserAuthorizedList);
300 ReleaseStr(pwzComponent);
301 ReleaseStr(pwzCustomActionData);
302
303 return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er);
304 }
305
306
307 /*******************************************************************
308 SchedFirewallExceptionsInstall - immediate custom action entry
309 point to register firewall exceptions.
310
311 ********************************************************************/
312 extern "C" UINT __stdcall SchedFirewallExceptionsInstall(
313 __in MSIHANDLE hInstall
314 )
315 {
316 return SchedFirewallExceptions(hInstall, WCA_TODO_INSTALL);
317 }
318
319
320 /*******************************************************************
321 SchedFirewallExceptionsUninstall - immediate custom action entry
322 point to remove firewall exceptions.
323
324 ********************************************************************/
325 extern "C" UINT __stdcall SchedFirewallExceptionsUninstall(
326 __in MSIHANDLE hInstall
327 )
328 {
329 return SchedFirewallExceptions(hInstall, WCA_TODO_UNINSTALL);
330 }
331
332
333 /*******************************************************************
334 GetFirewallRules - Get the collection of firewall rules.
335
336 ********************************************************************/
337 static HRESULT GetFirewallRules(
338 __in BOOL fIgnoreFailures,
339 __out INetFwRules** ppNetFwRules
340 )
341 {
342 HRESULT hr = S_OK;
343 INetFwPolicy2* pNetFwPolicy2 = NULL;
344 INetFwRules* pNetFwRules = NULL;
345 *ppNetFwRules = NULL;
346
347 do
348 {
349 ReleaseNullObject(pNetFwPolicy2);
350 ReleaseNullObject(pNetFwRules);
351
352 if (SUCCEEDED(hr = ::CoCreateInstance(__uuidof(NetFwPolicy2), NULL, CLSCTX_ALL, __uuidof(INetFwPolicy2), (void**)&pNetFwPolicy2)) &&
353 SUCCEEDED(hr = pNetFwPolicy2->get_Rules(&pNetFwRules)))
354 {
355 break;
356 }
357 else if (fIgnoreFailures)
358 {
359 ExitFunction1(hr = S_FALSE);
360 }
361 else
362 {
363 WcaLog(LOGMSG_STANDARD, "Failed to connect to Windows Firewall");
364 UINT er = WcaErrorMessage(msierrFirewallCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
365 switch (er)
366 {
367 case IDABORT: // exit with the current HRESULT
368 ExitFunction();
369 case IDRETRY: // clean up and retry the loop
370 hr = S_FALSE;
371 break;
372 case IDIGNORE: // pass S_FALSE back to the caller, who knows how to ignore the failure
373 ExitFunction1(hr = S_FALSE);
374 default: // No UI, so default is to fail.
375 ExitFunction();
376 }
377 }
378 } while (S_FALSE == hr);
379
380 *ppNetFwRules = pNetFwRules;
381 pNetFwRules = NULL;
382
383 LExit:
384 ReleaseObject(pNetFwPolicy2);
385 ReleaseObject(pNetFwRules);
386
387 return hr;
388 }
389
390
391 /*******************************************************************
392 CreateFwRuleObject - CoCreate a firewall rule, and set the name
393
394 ********************************************************************/
395 static HRESULT CreateFwRuleObject(
396 __in BSTR bstrName,
397 __out INetFwRule** ppNetFwRule
398 )
399 {
400 HRESULT hr = S_OK;
401 INetFwRule* pNetFwRule = NULL;
402 *ppNetFwRule = NULL;
403
404 hr = ::CoCreateInstance(__uuidof(NetFwRule), NULL, CLSCTX_ALL, __uuidof(INetFwRule), (LPVOID*)&pNetFwRule);
405 ExitOnFailure(hr, "failed to create NetFwRule object");
406
407 hr = pNetFwRule->put_Name(bstrName);
408 ExitOnFailure(hr, "failed to set firewall exception name");
409
410 *ppNetFwRule = pNetFwRule;
411
412 LExit:
413 return hr;
414 }
415
416
417 /*********************************************************************
418 GetFwRuleInterfaces - pack firewall rule interfaces into a VARIANT.
419 The populated VARIANT needs to be cleaned up by the calling function.
420
421 **********************************************************************/
422 static HRESULT GetFwRuleInterfaces(
423 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs,
424 __out VARIANT& vInterfaces
425 )
426 {
427 HRESULT hr = S_OK;
428 BSTR bstrInterfaces = NULL;
429 const WCHAR FORBIDDEN_FIREWALL_CHAR = L'|';
430 LONG iInterfacesCount = 0;
431 UINT iLength = 0;
432 LONG iIndex = 0;
433
434 ::VariantInit(&vInterfaces);
435 ExitOnNull(attrs.pwzInterfaces, hr, S_OK, "No interfaces to pack");
436
437 bstrInterfaces = ::SysAllocString(attrs.pwzInterfaces);
438 ExitOnNull(bstrInterfaces, hr, E_OUTOFMEMORY, "failed SysAllocString for interfaces");
439
440 iLength = ::SysStringLen(bstrInterfaces);
441
442 LPWSTR pwzT = bstrInterfaces;
443 while (*pwzT)
444 {
445 if (FORBIDDEN_FIREWALL_CHAR == *pwzT)
446 {
447 *pwzT = L'\0';
448 pwzT++;
449
450 // skip empty values inside the interfaces eg. |||
451 if (*pwzT && FORBIDDEN_FIREWALL_CHAR != *pwzT)
452 {
453 iInterfacesCount++;
454 }
455 }
456 else
457 {
458 if (pwzT == bstrInterfaces)
459 {
460 iInterfacesCount++;
461 }
462
463 pwzT++;
464 }
465 }
466
467 ExitOnNull(iInterfacesCount, hr, S_OK, "All interfaces are empty values");
468
469 vInterfaces.vt = VT_ARRAY | VT_VARIANT;
470 // this will be cleaned up by ReleaseVariant call of the calling function
471 vInterfaces.parray = SafeArrayCreateVector(VT_VARIANT, 0, iInterfacesCount);
472
473 for (LPCWSTR pwzElement = bstrInterfaces; pwzElement < (bstrInterfaces + iLength); ++pwzElement)
474 {
475 if (*pwzElement)
476 {
477 VARIANT vElement;
478 ::VariantInit(&vElement);
479
480 vElement.vt = VT_BSTR;
481 // this will be cleaned up by ReleaseVariant call of the calling function
482 vElement.bstrVal = ::SysAllocString(pwzElement);
483 ExitOnNull(vElement.bstrVal, hr, E_OUTOFMEMORY, "failed SysAllocString for interface element");
484
485 hr = SafeArrayPutElement(vInterfaces.parray, &iIndex, &vElement);
486 ExitOnFailure(hr, "failed to put interface '%ls' into safe array", pwzElement);
487
488 pwzElement += ::SysStringLen(vElement.bstrVal);
489 iIndex++;
490 }
491 }
492
493 LExit:
494 ReleaseBSTR(bstrInterfaces);
495
496 return hr;
497 }
498
499 /******************************************************************************
500 UpdateFwRule2Object - update properties for a firewall INetFwRule2 interface.
501 Requires Windows 7 / 2008 R2
502
503 ******************************************************************************/
504 static HRESULT UpdateFwRule2Object(
505 __in INetFwRule* pNetFwRule,
506 __in BOOL fUpdateRule,
507 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs
508 )
509 {
510 HRESULT hr = S_OK;
511 INetFwRule2* pNetFwRule2 = NULL;
512
513 hr = pNetFwRule->QueryInterface(__uuidof(INetFwRule2), (LPVOID*)&pNetFwRule2);
514 ExitOnFailure(hr, "failed to query INetFwRule2 interface");
515
516 if (MSI_NULL_INTEGER != attrs.iEdgeTraversal)
517 {
518 hr = pNetFwRule2->put_EdgeTraversalOptions(attrs.iEdgeTraversal);
519 ExitOnFailure(hr, "failed to set exception edge traversal option");
520 }
521 else if (fUpdateRule)
522 {
523 hr = pNetFwRule2->put_EdgeTraversalOptions(NET_FW_EDGE_TRAVERSAL_TYPE_DENY);
524 ExitOnFailure(hr, "failed to remove exception edge traversal option");
525 }
526
527 LExit:
528 ReleaseObject(pNetFwRule2);
529
530 return hr;
531 }
532
533
534 /******************************************************************************
535 UpdateFwRule3Object - update properties for a firewall INetFwRule3 interface.
536 Requires Windows 8 / 2012
537
538 ******************************************************************************/
539 static HRESULT UpdateFwRule3Object(
540 __in INetFwRule* pNetFwRule,
541 __in BOOL fUpdateRule,
542 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs
543 )
544 {
545 HRESULT hr = S_OK;
546
547 BSTR bstrLocalAppPackageId = NULL;
548 BSTR bstrLocalUserAuthorizedList = NULL;
549 BSTR bstrLocalUserOwner = NULL;
550 BSTR bstrRemoteMachineAuthorizedList = NULL;
551 BSTR bstrRemoteUserAuthorizedList = NULL;
552 INetFwRule3* pNetFwRule3 = NULL;
553
554 bstrLocalAppPackageId = ::SysAllocString(attrs.pwzLocalAppPackageId);
555 ExitOnNull(bstrLocalAppPackageId, hr, E_OUTOFMEMORY, "failed SysAllocString for local app package id");
556 bstrLocalUserAuthorizedList = ::SysAllocString(attrs.pwzLocalUserAuthorizedList);
557 ExitOnNull(bstrLocalUserAuthorizedList, hr, E_OUTOFMEMORY, "failed SysAllocString for local user authorized list");
558 bstrLocalUserOwner = ::SysAllocString(attrs.pwzLocalUserOwner);
559 ExitOnNull(bstrLocalUserOwner, hr, E_OUTOFMEMORY, "failed SysAllocString for local user owner");
560 bstrRemoteMachineAuthorizedList = ::SysAllocString(attrs.pwzRemoteMachineAuthorizedList);
561 ExitOnNull(bstrRemoteMachineAuthorizedList, hr, E_OUTOFMEMORY, "failed SysAllocString for remote machine authorized list");
562 bstrRemoteUserAuthorizedList = ::SysAllocString(attrs.pwzRemoteUserAuthorizedList);
563 ExitOnNull(bstrRemoteUserAuthorizedList, hr, E_OUTOFMEMORY, "failed SysAllocString for remote user authorized list");
564
565 hr = pNetFwRule->QueryInterface(__uuidof(INetFwRule3), (LPVOID*)&pNetFwRule3);
566 ExitOnFailure(hr, "failed to query INetFwRule3 interface");
567
568 if (bstrLocalAppPackageId && *bstrLocalAppPackageId)
569 {
570 hr = pNetFwRule3->put_LocalAppPackageId(bstrLocalAppPackageId);
571 ExitOnFailure(hr, "failed to set exception local app package id");
572 }
573 else if (fUpdateRule)
574 {
575 hr = pNetFwRule3->put_LocalAppPackageId(NULL);
576 ExitOnFailure(hr, "failed to remove exception local app package id");
577 }
578
579 if (bstrLocalUserAuthorizedList && *bstrLocalUserAuthorizedList)
580 {
581 hr = pNetFwRule3->put_LocalUserAuthorizedList(bstrLocalUserAuthorizedList);
582 ExitOnFailure(hr, "failed to set exception local user authorized list");
583 }
584 else if (fUpdateRule)
585 {
586 hr = pNetFwRule3->put_LocalUserAuthorizedList(NULL);
587 ExitOnFailure(hr, "failed to remove exception local user authorized list");
588 }
589
590 if (bstrLocalUserOwner && *bstrLocalUserOwner)
591 {
592 hr = pNetFwRule3->put_LocalUserOwner(bstrLocalUserOwner);
593 ExitOnFailure(hr, "failed to set exception local user owner");
594 }
595 else if (fUpdateRule)
596 {
597 hr = pNetFwRule3->put_LocalUserOwner(NULL);
598 ExitOnFailure(hr, "failed to remove exception local user owner");
599 }
600
601 if (bstrRemoteMachineAuthorizedList && *bstrRemoteMachineAuthorizedList)
602 {
603 hr = pNetFwRule3->put_RemoteMachineAuthorizedList(bstrRemoteMachineAuthorizedList);
604 ExitOnFailure(hr, "failed to set exception remote machine authorized list");
605 }
606 else if (fUpdateRule)
607 {
608 hr = pNetFwRule3->put_RemoteMachineAuthorizedList(NULL);
609 ExitOnFailure(hr, "failed to remove exception remote machine authorized list");
610 }
611
612 if (bstrRemoteUserAuthorizedList && *bstrRemoteUserAuthorizedList)
613 {
614 hr = pNetFwRule3->put_RemoteUserAuthorizedList(bstrRemoteUserAuthorizedList);
615 ExitOnFailure(hr, "failed to set exception remote user authorized list");
616 }
617 else if (fUpdateRule)
618 {
619 hr = pNetFwRule3->put_RemoteUserAuthorizedList(NULL);
620 ExitOnFailure(hr, "failed to remove exception remote user authorized list");
621 }
622
623 if (MSI_NULL_INTEGER != attrs.iSecureFlags)
624 {
625 hr = pNetFwRule3->put_SecureFlags(attrs.iSecureFlags);
626 ExitOnFailure(hr, "failed to set exception IPsec secure flags");
627 }
628 else if (fUpdateRule)
629 {
630 hr = pNetFwRule3->put_SecureFlags(NET_FW_AUTHENTICATE_NONE);
631 ExitOnFailure(hr, "failed to reset exception IPsec secure flags");
632 }
633
634 LExit:
635 ReleaseBSTR(bstrLocalAppPackageId);
636 ReleaseBSTR(bstrLocalUserAuthorizedList);
637 ReleaseBSTR(bstrLocalUserOwner);
638 ReleaseBSTR(bstrRemoteMachineAuthorizedList);
639 ReleaseBSTR(bstrRemoteUserAuthorizedList);
640 ReleaseObject(pNetFwRule3);
641
642 return hr;
643 }
644
645
646 /**********************************************************************
647 UpdateFwRuleObject - update all properties for a basic firewall rule.
648 Requires Windows Vista / 2008
649
650 **********************************************************************/
651 static HRESULT UpdateFwRuleObject(
652 __in INetFwRule* pNetFwRule,
653 __in BOOL fUpdateRule,
654 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs
655 )
656 {
657 HRESULT hr = S_OK;
658 BSTR bstrEmpty = NULL;
659 BSTR bstrRemoteAddresses = NULL;
660 BSTR bstrFile = NULL;
661 BSTR bstrPort = NULL;
662 BSTR bstrDescription = NULL;
663 BSTR bstrGrouping = NULL;
664 BSTR bstrIcmpTypesAndCodes = NULL;
665 BSTR bstrInterfaceTypes = NULL;
666 BSTR bstrLocalAddresses = NULL;
667 BSTR bstrRemotePort = NULL;
668 BSTR bstrServiceName = NULL;
669 VARIANT vInterfaces;
670 ::VariantInit(&vInterfaces);
671 LONG iProtocol = 0;
672
673 INetFwRule2* pNetFwRule2 = NULL;
674
675 // convert to BSTRs to make COM happy
676 bstrEmpty = ::SysAllocString(L"");
677 ExitOnNull(bstrEmpty, hr, E_OUTOFMEMORY, "failed SysAllocString for empty placeholder");
678
679 bstrRemoteAddresses = ::SysAllocString(attrs.pwzRemoteAddresses);
680 ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses");
681 bstrFile = ::SysAllocString(attrs.pwzApplicationName);
682 ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for application name");
683 bstrPort = ::SysAllocString(attrs.pwzLocalPorts);
684 ExitOnNull(bstrPort, hr, E_OUTOFMEMORY, "failed SysAllocString for port");
685 bstrDescription = ::SysAllocString(attrs.pwzDescription);
686 ExitOnNull(bstrDescription, hr, E_OUTOFMEMORY, "failed SysAllocString for description");
687 bstrGrouping = ::SysAllocString(attrs.pwzGrouping);
688 ExitOnNull(bstrGrouping, hr, E_OUTOFMEMORY, "failed SysAllocString for grouping");
689 bstrIcmpTypesAndCodes = ::SysAllocString(attrs.pwzIcmpTypesAndCodes);
690 ExitOnNull(bstrIcmpTypesAndCodes, hr, E_OUTOFMEMORY, "failed SysAllocString for icmp types and codes");
691 bstrInterfaceTypes = ::SysAllocString(attrs.pwzInterfaceTypes);
692 ExitOnNull(bstrInterfaceTypes, hr, E_OUTOFMEMORY, "failed SysAllocString for interface types");
693 bstrLocalAddresses = ::SysAllocString(attrs.pwzLocalAddresses);
694 ExitOnNull(bstrLocalAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for local addresses");
695 bstrRemotePort = ::SysAllocString(attrs.pwzRemotePorts);
696 ExitOnNull(bstrRemotePort, hr, E_OUTOFMEMORY, "failed SysAllocString for remote port");
697 bstrServiceName = ::SysAllocString(attrs.pwzServiceName);
698 ExitOnNull(bstrServiceName, hr, E_OUTOFMEMORY, "failed SysAllocString for service name");
699
700 if (fUpdateRule)
701 {
702 hr = pNetFwRule->get_Protocol(&iProtocol);
703 ExitOnFailure(hr, "failed to get exception protocol");
704
705 // If you are editing a TCP port rule and converting it into an ICMP rule,
706 // first delete the ports, change protocol from TCP to ICMP, and then add the ports.
707
708 switch (iProtocol)
709 {
710 case NET_FW_IP_PROTOCOL_ANY:
711 break;
712
713 case 1: // ICMP
714 hr = pNetFwRule->put_IcmpTypesAndCodes(NULL);
715 ExitOnFailure(hr, "failed to remove exception icmp types and codes");
716 // fall through and reset ports too
717
718 default:
719 hr = pNetFwRule->put_LocalPorts(NULL);
720 ExitOnFailure(hr, "failed to update exception local ports to NULL");
721
722 hr = pNetFwRule->put_RemotePorts(NULL);
723 ExitOnFailure(hr, "failed to update exception remote ports to NULL");
724 break;
725 }
726 }
727
728 if (MSI_NULL_INTEGER != attrs.iProfile)
729 {
730 hr = pNetFwRule->put_Profiles(static_cast<NET_FW_PROFILE_TYPE2> (attrs.iProfile));
731 ExitOnFailure(hr, "failed to set exception profile");
732 }
733 else if (fUpdateRule)
734 {
735 hr = pNetFwRule->put_Profiles(NET_FW_PROFILE2_ALL);
736 ExitOnFailure(hr, "failed to reset exception profile to all");
737 }
738
739 // The Protocol property must be set before the LocalPorts/RemotePorts properties or an error will be returned.
740 if (MSI_NULL_INTEGER != attrs.iProtocol)
741 {
742 hr = pNetFwRule->put_Protocol(static_cast<NET_FW_IP_PROTOCOL> (attrs.iProtocol));
743 ExitOnFailure(hr, "failed to set exception protocol");
744 }
745 else if (fUpdateRule)
746 {
747 if ((bstrPort && *bstrPort) || (bstrRemotePort && *bstrRemotePort))
748 {
749 // default protocol is "TCP" in the WiX firewall compiler if a port is specified
750 hr = pNetFwRule->put_Protocol(NET_FW_IP_PROTOCOL_TCP);
751 ExitOnFailure(hr, "failed to reset exception protocol to TCP");
752 }
753 else
754 {
755 hr = pNetFwRule->put_Protocol(NET_FW_IP_PROTOCOL_ANY);
756 ExitOnFailure(hr, "failed to reset exception protocol to ANY");
757 }
758 }
759
760 if (bstrPort && *bstrPort)
761 {
762 hr = pNetFwRule->put_LocalPorts(bstrPort);
763 ExitOnFailure(hr, "failed to set exception local ports '%ls'", bstrPort);
764 }
765
766 if (bstrRemoteAddresses && *bstrRemoteAddresses)
767 {
768 hr = pNetFwRule->put_RemoteAddresses(bstrRemoteAddresses);
769 ExitOnFailure(hr, "failed to set exception remote addresses '%ls'", bstrRemoteAddresses);
770 }
771 else if (fUpdateRule)
772 {
773 hr = pNetFwRule->put_RemoteAddresses(bstrEmpty);
774 ExitOnFailure(hr, "failed to remove exception remote addresses");
775 }
776
777 if (bstrDescription && *bstrDescription)
778 {
779 hr = pNetFwRule->put_Description(bstrDescription);
780 ExitOnFailure(hr, "failed to set exception description '%ls'", bstrDescription);
781 }
782 else if (fUpdateRule)
783 {
784 hr = pNetFwRule->put_Description(bstrEmpty);
785 ExitOnFailure(hr, "failed to remove exception description");
786 }
787
788 if (MSI_NULL_INTEGER != attrs.iDirection)
789 {
790 hr = pNetFwRule->put_Direction(static_cast<NET_FW_RULE_DIRECTION> (attrs.iDirection));
791 ExitOnFailure(hr, "failed to set exception direction");
792 }
793 else if (fUpdateRule)
794 {
795 hr = pNetFwRule->put_Direction(NET_FW_RULE_DIR_IN);
796 ExitOnFailure(hr, "failed to reset exception direction to in");
797 }
798
799 if (MSI_NULL_INTEGER != attrs.iAction)
800 {
801 hr = pNetFwRule->put_Action(static_cast<NET_FW_ACTION> (attrs.iAction));
802 ExitOnFailure(hr, "failed to set exception action");
803 }
804 else if (fUpdateRule)
805 {
806 hr = pNetFwRule->put_Action(NET_FW_ACTION_ALLOW);
807 ExitOnFailure(hr, "failed to reset exception action to allow");
808 }
809
810 if (bstrFile && *bstrFile)
811 {
812 hr = pNetFwRule->put_ApplicationName(bstrFile);
813 ExitOnFailure(hr, "failed to set exception application name");
814 }
815 else if (fUpdateRule)
816 {
817 hr = pNetFwRule->put_ApplicationName(NULL);
818 ExitOnFailure(hr, "failed to remove exception application name");
819 }
820
821 if (MSI_NULL_INTEGER != attrs.iEdgeTraversal)
822 {
823 switch (attrs.iEdgeTraversal)
824 {
825 default:
826 hr = pNetFwRule->put_EdgeTraversal(NET_FW_EDGE_TRAVERSAL_TYPE_DENY != attrs.iEdgeTraversal ? VARIANT_TRUE : VARIANT_FALSE);
827 ExitOnFailure(hr, "failed to set exception edge traversal");
828 break;
829
830 // handled by put_EdgeTraversalOptions
831 case NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_APP:
832 case NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER:
833 break;
834 }
835 }
836 else if (fUpdateRule)
837 {
838 hr = pNetFwRule->put_EdgeTraversal(VARIANT_FALSE);
839 ExitOnFailure(hr, "failed to remove exception edge traversal");
840 }
841
842 // enable even when iEnabled == MSI_NULL_INTEGER
843 hr = pNetFwRule->put_Enabled(attrs.iEnabled ? VARIANT_TRUE : VARIANT_FALSE);
844 ExitOnFailure(hr, "failed to set exception enabled flag");
845
846 if (bstrGrouping && *bstrGrouping)
847 {
848 hr = pNetFwRule->put_Grouping(bstrGrouping);
849 ExitOnFailure(hr, "failed to set exception grouping '%ls'", bstrGrouping);
850 }
851 else if (fUpdateRule)
852 {
853 hr = pNetFwRule->put_Grouping(bstrEmpty);
854 ExitOnFailure(hr, "failed to remove exception grouping");
855 }
856
857 if (bstrIcmpTypesAndCodes && *bstrIcmpTypesAndCodes)
858 {
859 hr = pNetFwRule->put_IcmpTypesAndCodes(bstrIcmpTypesAndCodes);
860 ExitOnFailure(hr, "failed to set exception icmp types and codes '%ls'", bstrIcmpTypesAndCodes);
861 }
862
863 hr = GetFwRuleInterfaces(attrs, vInterfaces);
864 ExitOnFailure(hr, "failed to prepare exception interfaces '%ls'", attrs.pwzInterfaces);
865
866 if (attrs.pwzInterfaces && *attrs.pwzInterfaces)
867 {
868 hr = pNetFwRule->put_Interfaces(vInterfaces);
869 ExitOnFailure(hr, "failed to set exception interfaces '%ls'", attrs.pwzInterfaces);
870 }
871 else if (fUpdateRule)
872 {
873 hr = pNetFwRule->put_Interfaces(vInterfaces);
874 ExitOnFailure(hr, "failed to remove exception interfaces");
875 }
876
877 if (bstrInterfaceTypes && *bstrInterfaceTypes)
878 {
879 hr = pNetFwRule->put_InterfaceTypes(bstrInterfaceTypes);
880 ExitOnFailure(hr, "failed to set exception interface types '%ls'", bstrInterfaceTypes);
881 }
882 else if (fUpdateRule)
883 {
884 hr = pNetFwRule->put_InterfaceTypes(bstrEmpty);
885 ExitOnFailure(hr, "failed to remove exception interface types");
886 }
887
888 if (bstrLocalAddresses && *bstrLocalAddresses)
889 {
890 hr = pNetFwRule->put_LocalAddresses(bstrLocalAddresses);
891 ExitOnFailure(hr, "failed to set exception local addresses '%ls'", bstrLocalAddresses);
892 }
893 else if (fUpdateRule)
894 {
895 hr = pNetFwRule->put_LocalAddresses(bstrEmpty);
896 ExitOnFailure(hr, "failed to remove exception local addresses");
897 }
898
899 if (bstrRemotePort && *bstrRemotePort)
900 {
901 hr = pNetFwRule->put_RemotePorts(bstrRemotePort);
902 ExitOnFailure(hr, "failed to set exception remote ports '%ls'", bstrRemotePort);
903 }
904
905 if (bstrServiceName && *bstrServiceName)
906 {
907 hr = pNetFwRule->put_ServiceName(bstrServiceName);
908 ExitOnFailure(hr, "failed to set exception service name '%ls'", bstrServiceName);
909 }
910 else if (fUpdateRule)
911 {
912 hr = pNetFwRule->put_ServiceName(NULL);
913 ExitOnFailure(hr, "failed to remove exception service name");
914 }
915
916 LExit:
917 ReleaseBSTR(bstrRemoteAddresses);
918 ReleaseBSTR(bstrFile);
919 ReleaseBSTR(bstrPort);
920 ReleaseBSTR(bstrDescription);
921 ReleaseBSTR(bstrGrouping);
922 ReleaseBSTR(bstrIcmpTypesAndCodes);
923 ReleaseBSTR(bstrInterfaceTypes);
924 ReleaseBSTR(bstrLocalAddresses);
925 ReleaseBSTR(bstrRemotePort);
926 ReleaseBSTR(bstrServiceName);
927 ReleaseVariant(vInterfaces);
928 ReleaseObject(pNetFwRule2);
929
930 return hr;
931 }
932
933
934 /*******************************************************************
935 AddFirewallException
936
937 ********************************************************************/
938 static HRESULT AddFirewallException(
939 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs,
940 __in BOOL fIgnoreFailures
941 )
942 {
943 HRESULT hr = S_OK;
944 BSTR bstrName = NULL;
945 INetFwRules* pNetFwRules = NULL;
946 INetFwRule* pNetFwRule = NULL;
947
948 BOOL fIgnoreUpdates = feaIgnoreUpdates == (attrs.iAttributes & feaIgnoreUpdates);
949 BOOL fEnableOnUpdate = feaEnableOnUpdate == (attrs.iAttributes & feaEnableOnUpdate);
950 BOOL fAddINetFwRule2 = feaAddINetFwRule2 == (attrs.iAttributes & feaAddINetFwRule2);
951 BOOL fAddINetFwRule3 = feaAddINetFwRule3 == (attrs.iAttributes & feaAddINetFwRule3);
952
953 // convert to BSTRs to make COM happy
954 bstrName = ::SysAllocString(attrs.pwzName);
955 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name");
956
957 // get the collection of firewall rules
958 hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules);
959 ExitOnFailure(hr, "failed to get firewall exception object");
960 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
961 {
962 ExitFunction();
963 }
964
965 // try to find it (i.e., support reinstall)
966 hr = pNetFwRules->Item(bstrName, &pNetFwRule);
967 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
968 {
969 hr = CreateFwRuleObject(bstrName, &pNetFwRule);
970 ExitOnFailure(hr, "failed to create FwRule object '%ls'", attrs.pwzName);
971
972 // set attributes of the new firewall rule
973 hr = UpdateFwRuleObject(pNetFwRule, FALSE, attrs);
974 ExitOnFailure(hr, "failed to create INetFwRule firewall exception '%ls'", attrs.pwzName);
975
976 if (fAddINetFwRule2)
977 {
978 hr = UpdateFwRule2Object(pNetFwRule, FALSE, attrs);
979 ExitOnFailure(hr, "failed to create INetFwRule2 firewall exception '%ls'", attrs.pwzName);
980 }
981
982 if (fAddINetFwRule3)
983 {
984 hr = UpdateFwRule3Object(pNetFwRule, FALSE, attrs);
985 ExitOnFailure(hr, "failed to create INetFwRule3 firewall exception '%ls'", attrs.pwzName);
986 }
987
988 hr = pNetFwRules->Add(pNetFwRule);
989 ExitOnFailure(hr, "failed to add firewall exception '%ls' to the list", attrs.pwzName);
990 }
991 else
992 {
993 // we found an existing firewall rule (if we succeeded, that is)
994 ExitOnFailure(hr, "failed trying to find existing firewall exception '%ls'", attrs.pwzName);
995
996 if (fEnableOnUpdate)
997 {
998 hr = pNetFwRule->put_Enabled(VARIANT_TRUE);
999 ExitOnFailure(hr, "failed to enable existing firewall exception '%ls'", attrs.pwzName);
1000 }
1001 else if (!fIgnoreUpdates)
1002 {
1003 // overwrite attributes of the existing firewall rule
1004 hr = UpdateFwRuleObject(pNetFwRule, TRUE, attrs);
1005 ExitOnFailure(hr, "failed to update INetFwRule firewall exception '%ls'", attrs.pwzName);
1006
1007 if (fAddINetFwRule2)
1008 {
1009 hr = UpdateFwRule2Object(pNetFwRule, TRUE, attrs);
1010 ExitOnFailure(hr, "failed to update INetFwRule2 firewall exception '%ls'", attrs.pwzName);
1011 }
1012
1013 if (fAddINetFwRule3)
1014 {
1015 hr = UpdateFwRule3Object(pNetFwRule, TRUE, attrs);
1016 ExitOnFailure(hr, "failed to update INetFwRule3 firewall exception '%ls'", attrs.pwzName);
1017 }
1018 }
1019 }
1020
1021 LExit:
1022 ReleaseBSTR(bstrName);
1023 ReleaseObject(pNetFwRules);
1024 ReleaseObject(pNetFwRule);
1025
1026 return fIgnoreFailures ? S_OK : hr;
1027 }
1028
1029
1030 /*******************************************************************
1031 RemoveException - Removes all exception rules with the given name.
1032
1033 ********************************************************************/
1034 static HRESULT RemoveException(
1035 __in LPCWSTR wzName,
1036 __in BOOL fIgnoreFailures
1037 )
1038 {
1039 HRESULT hr = S_OK;;
1040 INetFwRules* pNetFwRules = NULL;
1041
1042 // convert to BSTRs to make COM happy
1043 BSTR bstrName = ::SysAllocString(wzName);
1044 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for path");
1045
1046 // get the collection of firewall rules
1047 hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules);
1048 ExitOnFailure(hr, "failed to get firewall rules object");
1049 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
1050 {
1051 ExitFunction();
1052 }
1053
1054 hr = pNetFwRules->Remove(bstrName);
1055 ExitOnFailure(hr, "failed to remove firewall exception for name %ls", wzName);
1056
1057 LExit:
1058 ReleaseBSTR(bstrName);
1059 ReleaseObject(pNetFwRules);
1060
1061 return fIgnoreFailures ? S_OK : hr;
1062 }
1063
1064
1065 /*******************************************************************
1066 ExecFirewallExceptions - deferred custom action entry point to
1067 register and remove firewall exceptions.
1068
1069 ********************************************************************/
1070 extern "C" UINT __stdcall ExecFirewallExceptions(
1071 __in MSIHANDLE hInstall
1072 )
1073 {
1074 HRESULT hr = S_OK;
1075 LPWSTR pwz = NULL;
1076 LPWSTR pwzCustomActionData = NULL;
1077 int iTodo = WCA_TODO_UNKNOWN;
1078
1079 FIREWALL_EXCEPTION_ATTRIBUTES attrs = { 0 };
1080
1081 // initialize
1082 hr = WcaInitialize(hInstall, "ExecFirewallExceptions");
1083 ExitOnFailure(hr, "failed to initialize");
1084
1085 hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
1086 ExitOnFailure(hr, "failed to get CustomActionData");
1087 WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);
1088
1089 hr = ::CoInitialize(NULL);
1090 ExitOnFailure(hr, "failed to initialize COM");
1091
1092 // loop through all the passed in data
1093 pwz = pwzCustomActionData;
1094 while (pwz && *pwz)
1095 {
1096 // extract the custom action data and if rolling back, swap INSTALL and UNINSTALL
1097 hr = WcaReadIntegerFromCaData(&pwz, &iTodo);
1098 ExitOnFailure(hr, "failed to read todo from custom action data");
1099 if (::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK))
1100 {
1101 if (WCA_TODO_INSTALL == iTodo)
1102 {
1103 iTodo = WCA_TODO_UNINSTALL;
1104 }
1105 else if (WCA_TODO_UNINSTALL == iTodo)
1106 {
1107 iTodo = WCA_TODO_INSTALL;
1108 }
1109 }
1110
1111 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzName);
1112 ExitOnFailure(hr, "failed to read name from custom action data");
1113
1114 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iProfile);
1115 ExitOnFailure(hr, "failed to read profile from custom action data");
1116
1117 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzRemoteAddresses);
1118 ExitOnFailure(hr, "failed to read remote addresses from custom action data");
1119
1120 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iAttributes);
1121 ExitOnFailure(hr, "failed to read attributes from custom action data");
1122 BOOL fIgnoreFailures = feaIgnoreFailures == (attrs.iAttributes & feaIgnoreFailures);
1123
1124 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzApplicationName);
1125 ExitOnFailure(hr, "failed to read file path from custom action data");
1126
1127 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalPorts);
1128 ExitOnFailure(hr, "failed to read port from custom action data");
1129
1130 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iProtocol);
1131 ExitOnFailure(hr, "failed to read protocol from custom action data");
1132
1133 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzDescription);
1134 ExitOnFailure(hr, "failed to read protocol from custom action data");
1135
1136 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iDirection);
1137 ExitOnFailure(hr, "failed to read direction from custom action data");
1138
1139 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iAction);
1140 ExitOnFailure(hr, "failed to read action from custom action data");
1141
1142 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iEdgeTraversal);
1143 ExitOnFailure(hr, "failed to read edge traversal from custom action data");
1144
1145 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iEnabled);
1146 ExitOnFailure(hr, "failed to read enabled flag from custom action data");
1147
1148 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzGrouping);
1149 ExitOnFailure(hr, "failed to read grouping from custom action data");
1150
1151 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzIcmpTypesAndCodes);
1152 ExitOnFailure(hr, "failed to read icmp types and codes from custom action data");
1153
1154 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzInterfaces);
1155 ExitOnFailure(hr, "failed to read interfaces from custom action data");
1156
1157 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzInterfaceTypes);
1158 ExitOnFailure(hr, "failed to read interface types from custom action data");
1159
1160 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalAddresses);
1161 ExitOnFailure(hr, "failed to read local addresses from custom action data");
1162
1163 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzRemotePorts);
1164 ExitOnFailure(hr, "failed to read remote port from custom action data");
1165
1166 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzServiceName);
1167 ExitOnFailure(hr, "failed to read service name from custom action data");
1168
1169 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalAppPackageId);
1170 ExitOnFailure(hr, "failed to read local app package id from custom action data");
1171
1172 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalUserAuthorizedList);
1173 ExitOnFailure(hr, "failed to read local user authorized list from custom action data");
1174
1175 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalUserOwner);
1176 ExitOnFailure(hr, "failed to read local user owner from custom action data");
1177
1178 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzRemoteMachineAuthorizedList);
1179 ExitOnFailure(hr, "failed to read remote machine authorized list from custom action data");
1180
1181 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzRemoteUserAuthorizedList);
1182 ExitOnFailure(hr, "failed to read remote user authorized list from custom action data");
1183
1184 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iSecureFlags);
1185 ExitOnFailure(hr, "failed to read exception secure flags from custom action data");
1186
1187 switch (iTodo)
1188 {
1189 case WCA_TODO_INSTALL:
1190 case WCA_TODO_REINSTALL:
1191 WcaLog(LOGMSG_STANDARD, "Installing firewall exception %ls", attrs.pwzName);
1192 hr = AddFirewallException(attrs, fIgnoreFailures);
1193 ExitOnFailure(hr, "failed to add/update firewall exception for name '%ls'", attrs.pwzName);
1194 break;
1195
1196 case WCA_TODO_UNINSTALL:
1197 WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception %ls", attrs.pwzName);
1198 hr = RemoveException(attrs.pwzName, fIgnoreFailures);
1199 ExitOnFailure(hr, "failed to remove firewall exception");
1200 break;
1201 }
1202 }
1203
1204 LExit:
1205 ReleaseStr(pwzCustomActionData);
1206 ReleaseStr(attrs.pwzName);
1207 ReleaseStr(attrs.pwzRemoteAddresses);
1208 ReleaseStr(attrs.pwzApplicationName);
1209 ReleaseStr(attrs.pwzLocalPorts);
1210 ReleaseStr(attrs.pwzDescription);
1211 ReleaseStr(attrs.pwzGrouping);
1212 ReleaseStr(attrs.pwzIcmpTypesAndCodes);
1213 ReleaseStr(attrs.pwzInterfaces);
1214 ReleaseStr(attrs.pwzInterfaceTypes);
1215 ReleaseStr(attrs.pwzLocalAddresses);
1216 ReleaseStr(attrs.pwzRemotePorts);
1217 ReleaseStr(attrs.pwzServiceName);
1218 ReleaseStr(attrs.pwzLocalAppPackageId);
1219 ReleaseStr(attrs.pwzLocalUserAuthorizedList);
1220 ReleaseStr(attrs.pwzLocalUserOwner);
1221 ReleaseStr(attrs.pwzRemoteMachineAuthorizedList);
1222 ReleaseStr(attrs.pwzRemoteUserAuthorizedList);
1223 ::CoUninitialize();
1224
1225 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
1226 }