/********************************************************************++ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. Copyright (c) Microsoft Corporation. All Rights Reserved. Abstract: This C++ file includes sample code for enumerating Windows Firewall rules using the Microsoft Windows Firewall APIs. ********************************************************************/ #include #include #include // for getprotocolbyname #include #include #include // for SHLoadIndirectString #define IP_PROTOCOL_ICMP4 1 #define IP_PROTOCOL_ICMP6 58 // Forward declarations void DumpFWRulesInCollection(INetFwRule* FwRule); void EnumerateFWRules() { HRESULT hr; // Retrieve INetFwPolicy2 CComPtr pNetFwPolicy2; hr = pNetFwPolicy2.CoCreateInstance(__uuidof(NetFwPolicy2)); if (FAILED(hr)) { wprintf(L"CoCreateInstance failed: 0x%08lx\n", hr); return; } // Retrieve INetFwRules CComPtr pFwRules; hr = pNetFwPolicy2->get_Rules(&pFwRules); if (FAILED(hr)) { wprintf(L"get_Rules failed: 0x%08lx\n", hr); return; } // Obtain the number of Firewall rules long fwRuleCount; hr = pFwRules->get_Count(&fwRuleCount); if (FAILED(hr)) { wprintf(L"get_Count failed: 0x%08lx\n", hr); return; } wprintf(L"The number of rules in the Windows Firewall are %d\n", fwRuleCount); // Iterate through all of the rules in pFwRules CComPtr pEnumerator; hr = pFwRules->get__NewEnum(&pEnumerator); if (FAILED(hr)) { wprintf(L"get__NewEnum failed: 0x%08lx\n", hr); return; } CComPtr pVariant; hr = pEnumerator.QueryInterface(&pVariant); if (FAILED(hr)) { wprintf(L"get__NewEnum failed to produce IEnumVariant: 0x%08lx\n", hr); return; } ULONG cFetched = 0; for (CComVariant var; pVariant->Next(1, &var, &cFetched) == S_OK; var.Clear()) { CComPtr pFwRule; if (SUCCEEDED(var.ChangeType(VT_DISPATCH)) && SUCCEEDED(V_DISPATCH(&var)->QueryInterface(IID_PPV_ARGS(&pFwRule)))) { // Output the properties of this rule DumpFWRulesInCollection(pFwRule); } } } void PrintLocalizableString(PCWSTR label, PCWSTR value) { wchar_t buffer[256]; if (value[0] == L'@' && SUCCEEDED(SHLoadIndirectString(value, buffer, ARRAYSIZE(buffer), nullptr))) { value = buffer; } wprintf(L"%s%s\n", label, value); } // Output properties of a Firewall rule void DumpFWRulesInCollection(INetFwRule* FwRule) { wprintf(L"---------------------------------------------\n"); CComBSTR name; if (SUCCEEDED(FwRule->get_Name(&name)) && name) { PrintLocalizableString(L"Name: ", name); } CComBSTR description; if (SUCCEEDED(FwRule->get_Description(&description)) && description) { PrintLocalizableString(L"Description: ", description); } CComBSTR applicationName; if (SUCCEEDED(FwRule->get_ApplicationName(&applicationName)) && applicationName) { wprintf(L"Application Name: %ls\n", static_cast(applicationName)); } CComBSTR serviceName; if (SUCCEEDED(FwRule->get_ServiceName(&serviceName)) && serviceName) { wprintf(L"Service Name: %ls\n", static_cast(serviceName)); } long protocolNumber = 0; if (SUCCEEDED(FwRule->get_Protocol(&protocolNumber))) { // Try to convert the protocol number to a name, for readability. PCSTR protocolName = nullptr; // This special value means "any protocol". if (protocolNumber == NET_FW_IP_PROTOCOL_ANY) { protocolName = "Any"; } else { protoent* ent = getprotobynumber(protocolNumber); if (ent) { protocolName = ent->p_name; } } if (protocolName) { wprintf(L"IP Protocol: %d (%hs)\n", protocolNumber, protocolName); } else { wprintf(L"IP Protocol: %d\n", protocolNumber); } if (protocolNumber != IP_PROTOCOL_ICMP4 && protocolNumber != IP_PROTOCOL_ICMP6) { CComBSTR localPorts; if (SUCCEEDED(FwRule->get_LocalPorts(&localPorts)) && localPorts) { wprintf(L"Local Ports: %ls\n", static_cast(localPorts)); } CComBSTR remotePorts; if (SUCCEEDED(FwRule->get_RemotePorts(&remotePorts)) && remotePorts) { wprintf(L"Remote Ports: %ls\n", static_cast(remotePorts)); } } else { CComBSTR icmpTypesAndCodes; if (SUCCEEDED(FwRule->get_IcmpTypesAndCodes(&icmpTypesAndCodes)) && icmpTypesAndCodes) { wprintf(L"ICMP TypeCode: %ls\n", static_cast(icmpTypesAndCodes)); } } } CComBSTR localAddresses; if (SUCCEEDED(FwRule->get_LocalAddresses(&localAddresses)) && localAddresses) { wprintf(L"LocalAddresses: %ls\n", static_cast(localAddresses)); } CComBSTR remoteAddresses; if (SUCCEEDED(FwRule->get_RemoteAddresses(&remoteAddresses)) && remoteAddresses) { wprintf(L"RemoteAddresses: %ls\n", static_cast(remoteAddresses)); } long lProfileBitmask = 0; if (SUCCEEDED(FwRule->get_Profiles(&lProfileBitmask))) { // The returned bitmask can have more than 1 bit set if multiple profiles // are active or current at the same time static const struct ProfileMapElement { NET_FW_PROFILE_TYPE2 Id; LPCWSTR Name; } ProfileMap[3] = { { NET_FW_PROFILE2_DOMAIN, L"Domain" }, { NET_FW_PROFILE2_PRIVATE, L"Private" }, { NET_FW_PROFILE2_PUBLIC, L"Public" }, }; for (ProfileMapElement const& entry : ProfileMap) { if (lProfileBitmask & entry.Id) { wprintf(L"Profile: %ls\n", entry.Name); } } } NET_FW_RULE_DIRECTION fwDirection; if (SUCCEEDED(FwRule->get_Direction(&fwDirection))) { switch (fwDirection) { case NET_FW_RULE_DIR_IN: wprintf(L"Direction: In\n"); break; case NET_FW_RULE_DIR_OUT: wprintf(L"Direction: Out\n"); break; } } NET_FW_ACTION fwAction; if (SUCCEEDED(FwRule->get_Action(&fwAction))) { switch (fwAction) { case NET_FW_ACTION_BLOCK: wprintf(L"Action: Block\n"); break; case NET_FW_ACTION_ALLOW: wprintf(L"Action: Allow\n"); break; } } CComVariant InterfaceArray; if (SUCCEEDED(FwRule->get_Interfaces(&InterfaceArray))) { if (InterfaceArray.vt == (VT_VARIANT | VT_ARRAY)) { SAFEARRAY* pSa = NULL; pSa = InterfaceArray.parray; for (long index = pSa->rgsabound->lLbound; index < (long)pSa->rgsabound->cElements; index++) { CComVariant InterfaceString; if (SUCCEEDED(SafeArrayGetElement(pSa, &index, &InterfaceString)) && (InterfaceString.vt == VT_BSTR)) { wprintf(L"Interfaces: %ls\n", InterfaceString.bstrVal); } } } } CComBSTR interfaceTypes; if (SUCCEEDED(FwRule->get_InterfaceTypes(&interfaceTypes)) && interfaceTypes) { wprintf(L"Interface Types: %ls\n", static_cast(interfaceTypes)); } VARIANT_BOOL enabled; if (SUCCEEDED(FwRule->get_Enabled(&enabled))) { wprintf(L"Enabled: %ls\n", enabled ? L"TRUE" : L"FALSE"); } CComBSTR grouping; if (SUCCEEDED(FwRule->get_Grouping(&grouping)) && grouping) { PrintLocalizableString(L"Grouping: ", grouping); } if (SUCCEEDED(FwRule->get_EdgeTraversal(&enabled))) { wprintf(L"Edge Traversal: %ls\n", enabled ? L"TRUE" : L"FALSE"); } } int __cdecl main() { // Initialize COM. if (SUCCEEDED(CoInitialize(0))) { // We use WinSock only to convert protocol numbers to names. // If we cannot initialize WinSock, then just proceed without it. WSADATA wsaData; int err = WSAStartup(MAKEWORD(2, 2), &wsaData); EnumerateFWRules(); // Clean up WinSock if we had started it. if (err == 0) { WSACleanup(); } // Uninitialize COM. CoUninitialize(); } return 0; }