diff options
author | chris_bednarski <Chris.Bednarski@minfos.com.au> | 2023-08-21 11:34:51 +1000 |
---|---|---|
committer | Bob Arnson <github@bobs.org> | 2023-08-26 19:09:59 -0400 |
commit | e29b4aacf89ce060509b20a5f81df200f7d2fbc1 (patch) | |
tree | 974188334fce21c60396400075579060ce2df62d | |
parent | b3deb46def7d303a79f4a5eba6a921e45d5f16ef (diff) | |
download | wix-e29b4aacf89ce060509b20a5f81df200f7d2fbc1.tar.gz wix-e29b4aacf89ce060509b20a5f81df200f7d2fbc1.tar.bz2 wix-e29b4aacf89ce060509b20a5f81df200f7d2fbc1.zip |
remove windows xp specific code from firewall extension
5 files changed, 102 insertions, 438 deletions
diff --git a/src/ext/Firewall/ca/firewall.cpp b/src/ext/Firewall/ca/firewall.cpp index 35c8be6e..491b10fa 100644 --- a/src/ext/Firewall/ca/firewall.cpp +++ b/src/ext/Firewall/ca/firewall.cpp | |||
@@ -348,90 +348,6 @@ LExit: | |||
348 | } | 348 | } |
349 | 349 | ||
350 | /****************************************************************** | 350 | /****************************************************************** |
351 | FSupportProfiles - Returns true if we support profiles on this machine. | ||
352 | (Only on Vista or later) | ||
353 | |||
354 | ********************************************************************/ | ||
355 | static BOOL FSupportProfiles() | ||
356 | { | ||
357 | BOOL fSupportProfiles = FALSE; | ||
358 | INetFwRules* pNetFwRules = NULL; | ||
359 | |||
360 | // We only support profiles if we can co-create an instance of NetFwPolicy2. | ||
361 | // This will not work on pre-vista machines. | ||
362 | if (SUCCEEDED(GetFirewallRules(TRUE, &pNetFwRules)) && pNetFwRules != NULL) | ||
363 | { | ||
364 | fSupportProfiles = TRUE; | ||
365 | ReleaseObject(pNetFwRules); | ||
366 | } | ||
367 | |||
368 | return fSupportProfiles; | ||
369 | } | ||
370 | |||
371 | /****************************************************************** | ||
372 | GetCurrentFirewallProfile - get the active firewall profile as an | ||
373 | INetFwProfile, which owns the lists of exceptions we're | ||
374 | updating. | ||
375 | |||
376 | ********************************************************************/ | ||
377 | static HRESULT GetCurrentFirewallProfile( | ||
378 | __in BOOL fIgnoreFailures, | ||
379 | __out INetFwProfile** ppfwProfile | ||
380 | ) | ||
381 | { | ||
382 | HRESULT hr = S_OK; | ||
383 | INetFwMgr* pfwMgr = NULL; | ||
384 | INetFwPolicy* pfwPolicy = NULL; | ||
385 | INetFwProfile* pfwProfile = NULL; | ||
386 | *ppfwProfile = NULL; | ||
387 | |||
388 | do | ||
389 | { | ||
390 | ReleaseNullObject(pfwPolicy); | ||
391 | ReleaseNullObject(pfwMgr); | ||
392 | ReleaseNullObject(pfwProfile); | ||
393 | |||
394 | if (SUCCEEDED(hr = ::CoCreateInstance(__uuidof(NetFwMgr), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwMgr), (void**)&pfwMgr)) && | ||
395 | SUCCEEDED(hr = pfwMgr->get_LocalPolicy(&pfwPolicy)) && | ||
396 | SUCCEEDED(hr = pfwPolicy->get_CurrentProfile(&pfwProfile))) | ||
397 | { | ||
398 | break; | ||
399 | } | ||
400 | else if (fIgnoreFailures) | ||
401 | { | ||
402 | ExitFunction1(hr = S_FALSE); | ||
403 | } | ||
404 | else | ||
405 | { | ||
406 | WcaLog(LOGMSG_STANDARD, "Failed to connect to Windows Firewall"); | ||
407 | UINT er = WcaErrorMessage(msierrFirewallCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); | ||
408 | switch (er) | ||
409 | { | ||
410 | case IDABORT: // exit with the current HRESULT | ||
411 | ExitFunction(); | ||
412 | case IDRETRY: // clean up and retry the loop | ||
413 | hr = S_FALSE; | ||
414 | break; | ||
415 | case IDIGNORE: // pass S_FALSE back to the caller, who knows how to ignore the failure | ||
416 | ExitFunction1(hr = S_FALSE); | ||
417 | default: // No UI, so default is to fail. | ||
418 | ExitFunction(); | ||
419 | } | ||
420 | } | ||
421 | } while (S_FALSE == hr); | ||
422 | |||
423 | *ppfwProfile = pfwProfile; | ||
424 | pfwProfile = NULL; | ||
425 | |||
426 | LExit: | ||
427 | ReleaseObject(pfwPolicy); | ||
428 | ReleaseObject(pfwMgr); | ||
429 | ReleaseObject(pfwProfile); | ||
430 | |||
431 | return hr; | ||
432 | } | ||
433 | |||
434 | /****************************************************************** | ||
435 | AddApplicationException | 351 | AddApplicationException |
436 | 352 | ||
437 | ********************************************************************/ | 353 | ********************************************************************/ |
@@ -509,92 +425,6 @@ LExit: | |||
509 | } | 425 | } |
510 | 426 | ||
511 | /****************************************************************** | 427 | /****************************************************************** |
512 | AddApplicationExceptionOnCurrentProfile | ||
513 | |||
514 | ********************************************************************/ | ||
515 | static HRESULT AddApplicationExceptionOnCurrentProfile( | ||
516 | __in LPCWSTR wzFile, | ||
517 | __in LPCWSTR wzName, | ||
518 | __in_opt LPCWSTR wzRemoteAddresses, | ||
519 | __in BOOL fIgnoreFailures | ||
520 | ) | ||
521 | { | ||
522 | HRESULT hr = S_OK; | ||
523 | BSTR bstrFile = NULL; | ||
524 | BSTR bstrName = NULL; | ||
525 | BSTR bstrRemoteAddresses = NULL; | ||
526 | INetFwProfile* pfwProfile = NULL; | ||
527 | INetFwAuthorizedApplications* pfwApps = NULL; | ||
528 | INetFwAuthorizedApplication* pfwApp = NULL; | ||
529 | |||
530 | // convert to BSTRs to make COM happy | ||
531 | bstrFile = ::SysAllocString(wzFile); | ||
532 | ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for path"); | ||
533 | bstrName = ::SysAllocString(wzName); | ||
534 | ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name"); | ||
535 | bstrRemoteAddresses = ::SysAllocString(wzRemoteAddresses); | ||
536 | ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses"); | ||
537 | |||
538 | // get the firewall profile, which is our entry point for adding exceptions | ||
539 | hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile); | ||
540 | ExitOnFailure(hr, "failed to get firewall profile"); | ||
541 | if (S_FALSE == hr) // user or package author chose to ignore missing firewall | ||
542 | { | ||
543 | ExitFunction(); | ||
544 | } | ||
545 | |||
546 | // first, let's see if the app is already on the exception list | ||
547 | hr = pfwProfile->get_AuthorizedApplications(&pfwApps); | ||
548 | ExitOnFailure(hr, "failed to get list of authorized apps"); | ||
549 | |||
550 | // try to find it (i.e., support reinstall) | ||
551 | hr = pfwApps->Item(bstrFile, &pfwApp); | ||
552 | if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
553 | { | ||
554 | // not found, so we get to add it | ||
555 | hr = ::CoCreateInstance(__uuidof(NetFwAuthorizedApplication), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwAuthorizedApplication), reinterpret_cast<void**>(&pfwApp)); | ||
556 | ExitOnFailure(hr, "failed to create authorized app"); | ||
557 | |||
558 | // set the display name | ||
559 | hr = pfwApp->put_Name(bstrName); | ||
560 | ExitOnFailure(hr, "failed to set authorized app name"); | ||
561 | |||
562 | // set path | ||
563 | hr = pfwApp->put_ProcessImageFileName(bstrFile); | ||
564 | ExitOnFailure(hr, "failed to set authorized app path"); | ||
565 | |||
566 | // set the allowed remote addresses | ||
567 | if (bstrRemoteAddresses && *bstrRemoteAddresses) | ||
568 | { | ||
569 | hr = pfwApp->put_RemoteAddresses(bstrRemoteAddresses); | ||
570 | ExitOnFailure(hr, "failed to set authorized app remote addresses"); | ||
571 | } | ||
572 | |||
573 | // add it to the list of authorized apps | ||
574 | hr = pfwApps->Add(pfwApp); | ||
575 | ExitOnFailure(hr, "failed to add app to the authorized apps list"); | ||
576 | } | ||
577 | else | ||
578 | { | ||
579 | // we found an existing app exception (if we succeeded, that is) | ||
580 | ExitOnFailure(hr, "failed trying to find existing app"); | ||
581 | |||
582 | // enable it (just in case it was disabled) | ||
583 | pfwApp->put_Enabled(VARIANT_TRUE); | ||
584 | } | ||
585 | |||
586 | LExit: | ||
587 | ReleaseBSTR(bstrRemoteAddresses); | ||
588 | ReleaseBSTR(bstrName); | ||
589 | ReleaseBSTR(bstrFile); | ||
590 | ReleaseObject(pfwApp); | ||
591 | ReleaseObject(pfwApps); | ||
592 | ReleaseObject(pfwProfile); | ||
593 | |||
594 | return fIgnoreFailures ? S_OK : hr; | ||
595 | } | ||
596 | |||
597 | /****************************************************************** | ||
598 | AddPortException | 428 | AddPortException |
599 | 429 | ||
600 | ********************************************************************/ | 430 | ********************************************************************/ |
@@ -659,79 +489,11 @@ LExit: | |||
659 | } | 489 | } |
660 | 490 | ||
661 | /****************************************************************** | 491 | /****************************************************************** |
662 | AddPortExceptionOnCurrentProfile | 492 | RemoveException - Removes all exception rules with the given name. |
663 | |||
664 | ********************************************************************/ | ||
665 | static HRESULT AddPortExceptionOnCurrentProfile( | ||
666 | __in LPCWSTR wzName, | ||
667 | __in_opt LPCWSTR wzRemoteAddresses, | ||
668 | __in BOOL fIgnoreFailures, | ||
669 | __in int iPort, | ||
670 | __in int iProtocol | ||
671 | ) | ||
672 | { | ||
673 | HRESULT hr = S_OK; | ||
674 | BSTR bstrName = NULL; | ||
675 | BSTR bstrRemoteAddresses = NULL; | ||
676 | INetFwProfile* pfwProfile = NULL; | ||
677 | INetFwOpenPorts* pfwPorts = NULL; | ||
678 | INetFwOpenPort* pfwPort = NULL; | ||
679 | |||
680 | // convert to BSTRs to make COM happy | ||
681 | bstrName = ::SysAllocString(wzName); | ||
682 | ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name"); | ||
683 | bstrRemoteAddresses = ::SysAllocString(wzRemoteAddresses); | ||
684 | ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses"); | ||
685 | |||
686 | // create and initialize a new open port object | ||
687 | hr = ::CoCreateInstance(__uuidof(NetFwOpenPort), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwOpenPort), reinterpret_cast<void**>(&pfwPort)); | ||
688 | ExitOnFailure(hr, "failed to create new open port"); | ||
689 | |||
690 | hr = pfwPort->put_Port(iPort); | ||
691 | ExitOnFailure(hr, "failed to set exception port"); | ||
692 | |||
693 | hr = pfwPort->put_Protocol(static_cast<NET_FW_IP_PROTOCOL>(iProtocol)); | ||
694 | ExitOnFailure(hr, "failed to set exception protocol"); | ||
695 | |||
696 | if (bstrRemoteAddresses && *bstrRemoteAddresses) | ||
697 | { | ||
698 | hr = pfwPort->put_RemoteAddresses(bstrRemoteAddresses); | ||
699 | ExitOnFailure(hr, "failed to set exception remote addresses '%ls'", bstrRemoteAddresses); | ||
700 | } | ||
701 | |||
702 | hr = pfwPort->put_Name(bstrName); | ||
703 | ExitOnFailure(hr, "failed to set exception name"); | ||
704 | |||
705 | // get the firewall profile, its current list of open ports, and add ours | ||
706 | hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile); | ||
707 | ExitOnFailure(hr, "failed to get firewall profile"); | ||
708 | if (S_FALSE == hr) // user or package author chose to ignore missing firewall | ||
709 | { | ||
710 | ExitFunction(); | ||
711 | } | ||
712 | |||
713 | hr = pfwProfile->get_GloballyOpenPorts(&pfwPorts); | ||
714 | ExitOnFailure(hr, "failed to get open ports"); | ||
715 | |||
716 | hr = pfwPorts->Add(pfwPort); | ||
717 | ExitOnFailure(hr, "failed to add exception to global list"); | ||
718 | |||
719 | LExit: | ||
720 | ReleaseBSTR(bstrRemoteAddresses); | ||
721 | ReleaseBSTR(bstrName); | ||
722 | ReleaseObject(pfwProfile); | ||
723 | ReleaseObject(pfwPorts); | ||
724 | ReleaseObject(pfwPort); | ||
725 | |||
726 | return fIgnoreFailures ? S_OK : hr; | ||
727 | } | ||
728 | |||
729 | /****************************************************************** | ||
730 | RemoveException - Removes the exception rule with the given name. | ||
731 | 493 | ||
732 | ********************************************************************/ | 494 | ********************************************************************/ |
733 | static HRESULT RemoveException( | 495 | static HRESULT RemoveException( |
734 | __in LPCWSTR wzName, | 496 | __in LPCWSTR wzName, |
735 | __in BOOL fIgnoreFailures | 497 | __in BOOL fIgnoreFailures |
736 | ) | 498 | ) |
737 | { | 499 | { |
@@ -751,7 +513,7 @@ static HRESULT RemoveException( | |||
751 | } | 513 | } |
752 | 514 | ||
753 | hr = pNetFwRules->Remove(bstrName); | 515 | hr = pNetFwRules->Remove(bstrName); |
754 | ExitOnFailure(hr, "failed to remove authorized app"); | 516 | ExitOnFailure(hr, "failed to remove firewall rule"); |
755 | 517 | ||
756 | LExit: | 518 | LExit: |
757 | ReleaseBSTR(bstrName); | 519 | ReleaseBSTR(bstrName); |
@@ -761,192 +523,6 @@ LExit: | |||
761 | } | 523 | } |
762 | 524 | ||
763 | /****************************************************************** | 525 | /****************************************************************** |
764 | RemoveApplicationExceptionFromCurrentProfile | ||
765 | |||
766 | ********************************************************************/ | ||
767 | static HRESULT RemoveApplicationExceptionFromCurrentProfile( | ||
768 | __in LPCWSTR wzFile, | ||
769 | __in BOOL fIgnoreFailures | ||
770 | ) | ||
771 | { | ||
772 | HRESULT hr = S_OK; | ||
773 | INetFwProfile* pfwProfile = NULL; | ||
774 | INetFwAuthorizedApplications* pfwApps = NULL; | ||
775 | |||
776 | // convert to BSTRs to make COM happy | ||
777 | BSTR bstrFile = ::SysAllocString(wzFile); | ||
778 | ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for path"); | ||
779 | |||
780 | // get the firewall profile, which is our entry point for removing exceptions | ||
781 | hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile); | ||
782 | ExitOnFailure(hr, "failed to get firewall profile"); | ||
783 | if (S_FALSE == hr) // user or package author chose to ignore missing firewall | ||
784 | { | ||
785 | ExitFunction(); | ||
786 | } | ||
787 | |||
788 | // now get the list of app exceptions and remove the one | ||
789 | hr = pfwProfile->get_AuthorizedApplications(&pfwApps); | ||
790 | ExitOnFailure(hr, "failed to get list of authorized apps"); | ||
791 | |||
792 | hr = pfwApps->Remove(bstrFile); | ||
793 | ExitOnFailure(hr, "failed to remove authorized app"); | ||
794 | |||
795 | LExit: | ||
796 | ReleaseBSTR(bstrFile); | ||
797 | ReleaseObject(pfwApps); | ||
798 | ReleaseObject(pfwProfile); | ||
799 | |||
800 | return fIgnoreFailures ? S_OK : hr; | ||
801 | } | ||
802 | |||
803 | /****************************************************************** | ||
804 | RemovePortExceptionFromCurrentProfile | ||
805 | |||
806 | ********************************************************************/ | ||
807 | static HRESULT RemovePortExceptionFromCurrentProfile( | ||
808 | __in int iPort, | ||
809 | __in int iProtocol, | ||
810 | __in BOOL fIgnoreFailures | ||
811 | ) | ||
812 | { | ||
813 | HRESULT hr = S_OK; | ||
814 | INetFwProfile* pfwProfile = NULL; | ||
815 | INetFwOpenPorts* pfwPorts = NULL; | ||
816 | |||
817 | // get the firewall profile, which is our entry point for adding exceptions | ||
818 | hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile); | ||
819 | ExitOnFailure(hr, "failed to get firewall profile"); | ||
820 | if (S_FALSE == hr) // user or package author chose to ignore missing firewall | ||
821 | { | ||
822 | ExitFunction(); | ||
823 | } | ||
824 | |||
825 | hr = pfwProfile->get_GloballyOpenPorts(&pfwPorts); | ||
826 | ExitOnFailure(hr, "failed to get open ports"); | ||
827 | |||
828 | hr = pfwPorts->Remove(iPort, static_cast<NET_FW_IP_PROTOCOL>(iProtocol)); | ||
829 | ExitOnFailure(hr, "failed to remove open port %d, protocol %d", iPort, iProtocol); | ||
830 | |||
831 | LExit: | ||
832 | return fIgnoreFailures ? S_OK : hr; | ||
833 | } | ||
834 | |||
835 | static HRESULT AddApplicationException( | ||
836 | __in BOOL fSupportProfiles, | ||
837 | __in LPCWSTR wzFile, | ||
838 | __in LPCWSTR wzName, | ||
839 | __in int iProfile, | ||
840 | __in_opt LPCWSTR wzRemoteAddresses, | ||
841 | __in BOOL fIgnoreFailures, | ||
842 | __in LPCWSTR wzPort, | ||
843 | __in int iProtocol, | ||
844 | __in LPCWSTR wzDescription, | ||
845 | __in int iDirection | ||
846 | ) | ||
847 | { | ||
848 | HRESULT hr = S_OK; | ||
849 | |||
850 | if (fSupportProfiles) | ||
851 | { | ||
852 | hr = AddApplicationException(wzFile, wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription, iDirection); | ||
853 | } | ||
854 | else | ||
855 | { | ||
856 | if (0 != *wzPort || MSI_NULL_INTEGER != iProtocol) | ||
857 | { | ||
858 | // NOTE: This is treated as an error rather than either creating a rule based on just the application (no port), or | ||
859 | // just the port because it is unclear what is the proper fall back. For example, suppose that you have code that | ||
860 | // runs in dllhost.exe. Clearly falling back to opening all of dllhost is wrong. Because the firewall is a security | ||
861 | // feature, it seems better to require the MSI author to indicate the behavior that they want. | ||
862 | WcaLog(LOGMSG_STANDARD, "FirewallExtension: Cannot add firewall rule '%ls', which defines both an application and a port or protocol. Such a rule requires Microsoft Windows Vista or later.", wzName); | ||
863 | return fIgnoreFailures ? S_OK : E_NOTIMPL; | ||
864 | } | ||
865 | |||
866 | hr = AddApplicationExceptionOnCurrentProfile(wzFile, wzName, wzRemoteAddresses, fIgnoreFailures); | ||
867 | } | ||
868 | |||
869 | return hr; | ||
870 | } | ||
871 | |||
872 | static HRESULT AddPortException( | ||
873 | __in BOOL fSupportProfiles, | ||
874 | __in LPCWSTR wzName, | ||
875 | __in int iProfile, | ||
876 | __in_opt LPCWSTR wzRemoteAddresses, | ||
877 | __in BOOL fIgnoreFailures, | ||
878 | __in LPCWSTR wzPort, | ||
879 | __in int iProtocol, | ||
880 | __in LPCWSTR wzDescription, | ||
881 | __in int iDirection | ||
882 | ) | ||
883 | { | ||
884 | HRESULT hr = S_OK; | ||
885 | |||
886 | if (fSupportProfiles) | ||
887 | { | ||
888 | hr = AddPortException(wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription, iDirection); | ||
889 | } | ||
890 | else | ||
891 | { | ||
892 | hr = AddPortExceptionOnCurrentProfile(wzName, wzRemoteAddresses, fIgnoreFailures, wcstol(wzPort, NULL, 10), iProtocol); | ||
893 | } | ||
894 | |||
895 | return hr; | ||
896 | } | ||
897 | |||
898 | static HRESULT RemoveApplicationException( | ||
899 | __in BOOL fSupportProfiles, | ||
900 | __in LPCWSTR wzName, | ||
901 | __in LPCWSTR wzFile, | ||
902 | __in BOOL fIgnoreFailures, | ||
903 | __in LPCWSTR wzPort, | ||
904 | __in int iProtocol | ||
905 | ) | ||
906 | { | ||
907 | HRESULT hr = S_OK; | ||
908 | |||
909 | if (fSupportProfiles) | ||
910 | { | ||
911 | hr = RemoveException(wzName, fIgnoreFailures); | ||
912 | } | ||
913 | else | ||
914 | { | ||
915 | if (0 != *wzPort || MSI_NULL_INTEGER != iProtocol) | ||
916 | { | ||
917 | WcaLog(LOGMSG_STANDARD, "FirewallExtension: Cannot remove firewall rule '%ls', which defines both an application and a port or protocol. Such a rule requires Microsoft Windows Vista or later.", wzName); | ||
918 | return S_OK; | ||
919 | } | ||
920 | |||
921 | hr = RemoveApplicationExceptionFromCurrentProfile(wzFile, fIgnoreFailures); | ||
922 | } | ||
923 | |||
924 | return hr; | ||
925 | } | ||
926 | |||
927 | static HRESULT RemovePortException( | ||
928 | __in BOOL fSupportProfiles, | ||
929 | __in LPCWSTR wzName, | ||
930 | __in LPCWSTR wzPort, | ||
931 | __in int iProtocol, | ||
932 | __in BOOL fIgnoreFailures | ||
933 | ) | ||
934 | { | ||
935 | HRESULT hr = S_OK; | ||
936 | |||
937 | if (fSupportProfiles) | ||
938 | { | ||
939 | hr = RemoveException(wzName, fIgnoreFailures); | ||
940 | } | ||
941 | else | ||
942 | { | ||
943 | hr = RemovePortExceptionFromCurrentProfile(wcstol(wzPort, NULL, 10), iProtocol, fIgnoreFailures); | ||
944 | } | ||
945 | |||
946 | return hr; | ||
947 | } | ||
948 | |||
949 | /****************************************************************** | ||
950 | ExecFirewallExceptions - deferred custom action entry point to | 526 | ExecFirewallExceptions - deferred custom action entry point to |
951 | register and remove firewall exceptions. | 527 | register and remove firewall exceptions. |
952 | 528 | ||
@@ -956,7 +532,6 @@ extern "C" UINT __stdcall ExecFirewallExceptions( | |||
956 | ) | 532 | ) |
957 | { | 533 | { |
958 | HRESULT hr = S_OK; | 534 | HRESULT hr = S_OK; |
959 | BOOL fSupportProfiles = FALSE; | ||
960 | LPWSTR pwz = NULL; | 535 | LPWSTR pwz = NULL; |
961 | LPWSTR pwzCustomActionData = NULL; | 536 | LPWSTR pwzCustomActionData = NULL; |
962 | int iTodo = WCA_TODO_UNKNOWN; | 537 | int iTodo = WCA_TODO_UNKNOWN; |
@@ -982,9 +557,6 @@ extern "C" UINT __stdcall ExecFirewallExceptions( | |||
982 | hr = ::CoInitialize(NULL); | 557 | hr = ::CoInitialize(NULL); |
983 | ExitOnFailure(hr, "failed to initialize COM"); | 558 | ExitOnFailure(hr, "failed to initialize COM"); |
984 | 559 | ||
985 | // Find out if we support profiles (only on Vista or later) | ||
986 | fSupportProfiles = FSupportProfiles(); | ||
987 | |||
988 | // loop through all the passed in data | 560 | // loop through all the passed in data |
989 | pwz = pwzCustomActionData; | 561 | pwz = pwzCustomActionData; |
990 | while (pwz && *pwz) | 562 | while (pwz && *pwz) |
@@ -1043,13 +615,13 @@ extern "C" UINT __stdcall ExecFirewallExceptions( | |||
1043 | case WCA_TODO_INSTALL: | 615 | case WCA_TODO_INSTALL: |
1044 | case WCA_TODO_REINSTALL: | 616 | case WCA_TODO_REINSTALL: |
1045 | WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol); | 617 | WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol); |
1046 | hr = AddPortException(fSupportProfiles, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection); | 618 | hr = AddPortException(pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection); |
1047 | ExitOnFailure(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol); | 619 | ExitOnFailure(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol); |
1048 | break; | 620 | break; |
1049 | 621 | ||
1050 | case WCA_TODO_UNINSTALL: | 622 | case WCA_TODO_UNINSTALL: |
1051 | WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol); | 623 | WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol); |
1052 | hr = RemovePortException(fSupportProfiles, pwzName, pwzPort, iProtocol, fIgnoreFailures); | 624 | hr = RemoveException(pwzName, fIgnoreFailures); |
1053 | ExitOnFailure(hr, "failed to remove port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol); | 625 | ExitOnFailure(hr, "failed to remove port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol); |
1054 | break; | 626 | break; |
1055 | } | 627 | } |
@@ -1061,13 +633,13 @@ extern "C" UINT __stdcall ExecFirewallExceptions( | |||
1061 | case WCA_TODO_INSTALL: | 633 | case WCA_TODO_INSTALL: |
1062 | case WCA_TODO_REINSTALL: | 634 | case WCA_TODO_REINSTALL: |
1063 | WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls (%ls)", pwzName, pwzFile); | 635 | WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls (%ls)", pwzName, pwzFile); |
1064 | hr = AddApplicationException(fSupportProfiles, pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection); | 636 | hr = AddApplicationException(pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection); |
1065 | ExitOnFailure(hr, "failed to add/update application exception for name '%ls', file '%ls'", pwzName, pwzFile); | 637 | ExitOnFailure(hr, "failed to add/update application exception for name '%ls', file '%ls'", pwzName, pwzFile); |
1066 | break; | 638 | break; |
1067 | 639 | ||
1068 | case WCA_TODO_UNINSTALL: | 640 | case WCA_TODO_UNINSTALL: |
1069 | WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls (%ls)", pwzName, pwzFile); | 641 | WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls (%ls)", pwzName, pwzFile); |
1070 | hr = RemoveApplicationException(fSupportProfiles, pwzName, pwzFile, fIgnoreFailures, pwzPort, iProtocol); | 642 | hr = RemoveException(pwzName, fIgnoreFailures); |
1071 | ExitOnFailure(hr, "failed to remove application exception for name '%ls', file '%ls'", pwzName, pwzFile); | 643 | ExitOnFailure(hr, "failed to remove application exception for name '%ls', file '%ls'", pwzName, pwzFile); |
1072 | break; | 644 | break; |
1073 | } | 645 | } |
diff --git a/src/test/burn/WixTestTools/Firewall/Verifier.cs b/src/test/burn/WixTestTools/Firewall/Verifier.cs index c1bf3219..2c273e7a 100644 --- a/src/test/burn/WixTestTools/Firewall/Verifier.cs +++ b/src/test/burn/WixTestTools/Firewall/Verifier.cs | |||
@@ -254,7 +254,13 @@ namespace WixTestTools.Firewall | |||
254 | rule.Enabled = false; | 254 | rule.Enabled = false; |
255 | } | 255 | } |
256 | 256 | ||
257 | public static void RemoveFirewallRulesByName(string name) | 257 | /// <summary> |
258 | /// Removes a firewall rule by name. If multiple rules with the same name exist, only one of them is removed.<br/> | ||
259 | /// This behavior is different from <b>netsh advfirewall firewall delete rule</b> where all matching rules are deleted if multiple matches are found.<br/> | ||
260 | /// The firewall rule name cannot be null or an empty string. | ||
261 | /// </summary> | ||
262 | /// <param name="name">Name of the firewall rule to be removed.</param> | ||
263 | public static void RemoveFirewallRuleByName(string name) | ||
258 | { | 264 | { |
259 | var rules = GetINetFwRules(); | 265 | var rules = GetINetFwRules(); |
260 | rules.Remove(name); | 266 | rules.Remove(name); |
diff --git a/src/test/msi/TestData/FirewallExtensionTests/IgnoreFailedFirewallRules/IgnoreFailedFirewallRules.wixproj b/src/test/msi/TestData/FirewallExtensionTests/IgnoreFailedFirewallRules/IgnoreFailedFirewallRules.wixproj new file mode 100644 index 00000000..b1770b0f --- /dev/null +++ b/src/test/msi/TestData/FirewallExtensionTests/IgnoreFailedFirewallRules/IgnoreFailedFirewallRules.wixproj | |||
@@ -0,0 +1,13 @@ | |||
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 | <Project Sdk="WixToolset.Sdk"> | ||
3 | <PropertyGroup> | ||
4 | <UpgradeCode>{4D188568-1CCF-4EEE-BC27-17C3DCC83E58}</UpgradeCode> | ||
5 | <ProductComponentsRef>true</ProductComponentsRef> | ||
6 | </PropertyGroup> | ||
7 | <ItemGroup> | ||
8 | <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" /> | ||
9 | </ItemGroup> | ||
10 | <ItemGroup> | ||
11 | <PackageReference Include="WixToolset.Firewall.wixext" /> | ||
12 | </ItemGroup> | ||
13 | </Project> \ No newline at end of file | ||
diff --git a/src/test/msi/TestData/FirewallExtensionTests/IgnoreFailedFirewallRules/product.wxs b/src/test/msi/TestData/FirewallExtensionTests/IgnoreFailedFirewallRules/product.wxs new file mode 100644 index 00000000..d615f0c6 --- /dev/null +++ b/src/test/msi/TestData/FirewallExtensionTests/IgnoreFailedFirewallRules/product.wxs | |||
@@ -0,0 +1,35 @@ | |||
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 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall"> | ||
4 | <Fragment> | ||
5 | <ComponentGroup Id="ProductComponents"> | ||
6 | <ComponentRef Id="FirewallComponent3"/> | ||
7 | </ComponentGroup> | ||
8 | |||
9 | <Property Id="RULENAME" Secure="yes" /> | ||
10 | <CustomAction Id="SetRuleNameDefaultValue" Property="RULENAME" Value="WiXToolset401 Test - 0008 removal" Execute="firstSequence" /> | ||
11 | |||
12 | <InstallExecuteSequence> | ||
13 | <Custom Action="SetRuleNameDefaultValue" After="AppSearch" Condition="NOT NORULENAME" /> | ||
14 | </InstallExecuteSequence> | ||
15 | |||
16 | </Fragment> | ||
17 | |||
18 | <Fragment> | ||
19 | <Component Id="FirewallComponent3" Guid="AA693149-B39C-4012-9DDE-92AB0CEA2386" Directory="INSTALLFOLDER" Transitive="yes"> | ||
20 | <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" > | ||
21 | <fw:FirewallException Id="FirewallException6" | ||
22 | Description="WiX Toolset firewall exception rule integration test | ignore failed app properties" | ||
23 | Name="WiXToolset401 Test - 0006 pipe" Scope="any" IgnoreFailure="yes" /> | ||
24 | </File> | ||
25 | <fw:FirewallException Id="FirewallException7" | ||
26 | Description="WiX Toolset firewall exception rule integration test | ignore failed port properties" | ||
27 | Name="WiXToolset401 Test - 0007 pipe" Scope="any" Port="65123" IgnoreFailure="yes" /> | ||
28 | |||
29 | <fw:FirewallException Id="FirewallException8" | ||
30 | Description="WiX Toolset firewall exception rule integration test - removal test" | ||
31 | Name="[RULENAME]" Scope="any" Port="52390" Program="test.exe" | ||
32 | IgnoreFailure="yes" /> | ||
33 | </Component> | ||
34 | </Fragment> | ||
35 | </Wix> | ||
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs b/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs index 3e605d7a..4106cd72 100644 --- a/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs +++ b/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs | |||
@@ -144,7 +144,7 @@ namespace WixToolsetTest.MsiE2E | |||
144 | var product = this.CreatePackageInstaller("FirewallRules"); | 144 | var product = this.CreatePackageInstaller("FirewallRules"); |
145 | product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); | 145 | product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); |
146 | 146 | ||
147 | Verifier.RemoveFirewallRulesByName("WiXToolset401 Test - 0002"); | 147 | Verifier.RemoveFirewallRuleByName("WiXToolset401 Test - 0002"); |
148 | Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0002")); | 148 | Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0002")); |
149 | 149 | ||
150 | product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS); | 150 | product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS); |
@@ -176,7 +176,7 @@ namespace WixToolsetTest.MsiE2E | |||
176 | var product = this.CreatePackageInstaller("FirewallRules"); | 176 | var product = this.CreatePackageInstaller("FirewallRules"); |
177 | product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); | 177 | product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); |
178 | 178 | ||
179 | Verifier.RemoveFirewallRulesByName("WiXToolset401 Test - 0001"); | 179 | Verifier.RemoveFirewallRuleByName("WiXToolset401 Test - 0001"); |
180 | Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0001")); | 180 | Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0001")); |
181 | 181 | ||
182 | product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS); | 182 | product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS); |
@@ -277,5 +277,43 @@ namespace WixToolsetTest.MsiE2E | |||
277 | Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0004")); | 277 | Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0004")); |
278 | Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0005 - 9999")); | 278 | Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0005 - 9999")); |
279 | } | 279 | } |
280 | |||
281 | [RuntimeFact] | ||
282 | public void SucceedWhenIgnoreOnFailureIsSet() | ||
283 | { | ||
284 | var product = this.CreatePackageInstaller("IgnoreFailedFirewallRules"); | ||
285 | var log1 = product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); | ||
286 | |||
287 | Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0006 pipe")); | ||
288 | Assert.True(LogVerifier.MessageInLogFile(log1, "failed to add app to the authorized apps list")); | ||
289 | |||
290 | Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0007 pipe")); | ||
291 | Assert.True(LogVerifier.MessageInLogFile(log1, "failed to add app to the authorized ports list")); | ||
292 | |||
293 | var expected = new RuleDetails("WiXToolset401 Test - 0008 removal") | ||
294 | { | ||
295 | Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW, | ||
296 | ApplicationName = "test.exe", | ||
297 | Description = "WiX Toolset firewall exception rule integration test - removal test", | ||
298 | Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN, | ||
299 | EdgeTraversal = true, | ||
300 | EdgeTraversalOptions = 1, | ||
301 | Enabled = true, | ||
302 | InterfaceTypes = "All", | ||
303 | LocalPorts = "52390", | ||
304 | LocalAddresses = "*", | ||
305 | Profiles = Int32.MaxValue, | ||
306 | Protocol = 6, | ||
307 | RemoteAddresses = "*", | ||
308 | RemotePorts = "*", | ||
309 | SecureFlags = 0, | ||
310 | }; | ||
311 | |||
312 | Verifier.VerifyFirewallRule("WiXToolset401 Test - 0008 removal", expected); | ||
313 | Verifier.RemoveFirewallRuleByName("WiXToolset401 Test - 0008 removal"); | ||
314 | |||
315 | var log2 = product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, "NORULENAME=1"); | ||
316 | Assert.True(LogVerifier.MessageInLogFile(log2, "failed to remove firewall rule")); | ||
317 | } | ||
280 | } | 318 | } |
281 | } | 319 | } |