1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15+ #include " internal/platform/implementation/windows/wifi_direct.h"
16+
17+ #include < comutil.h>
18+ #include < winrt/base.h>
19+
20+ #include < netfw.h>
1521#include < cstdint>
1622#include < exception>
1723#include < memory>
3137#include " internal/platform/flags/nearby_platform_feature_flags.h"
3238#include " internal/platform/implementation/wifi_direct.h"
3339#include " internal/platform/implementation/windows/socket_address.h"
40+ #include " internal/platform/implementation/windows/string_utils.h"
3441#include " internal/platform/implementation/windows/utils.h"
35- #include " internal/platform/implementation/windows/wifi_direct.h"
3642#include " internal/platform/logging.h"
3743#include " internal/platform/prng.h"
3844#include " internal/platform/wifi_credential.h"
@@ -53,11 +59,9 @@ WifiDirectMedium::WifiDirectMedium() {
5359 LOG (WARNING) << " Failed to get DispatcherQueue for current thread. "
5460 " ConnectAsync might fail if not called from UI thread." ;
5561 }
56- is_interface_valid_ = IsWifiDirectServiceSupported ();
5762}
5863
5964WifiDirectMedium::~WifiDirectMedium () {
60- is_interface_valid_ = false ;
6165 listener_executor_.Shutdown ();
6266 StopWifiDirect ();
6367 DisconnectWifiDirect ();
@@ -73,6 +77,133 @@ WifiDirectMedium::~WifiDirectMedium() {
7377 }
7478}
7579
80+ // If Windows Firewall rule "WFD ASP Coordination Protocol (UDP-In)" is not
81+ // enabled, WifiDirectService GO will fail to create WiFiDirectServiceSession.
82+ bool WifiDirectMedium::IsFirewallWfdAspProtoEnabled () {
83+ LOG (INFO)
84+ << " Check Windows Firewall rule WFD ASP Coordination Protocol (UDP-In)" ;
85+ bool com_initialized = false ;
86+ winrt::com_ptr<INetFwPolicy2> p_net_fw_policy2;
87+ winrt::com_ptr<INetFwRules> p_fw_rules;
88+ winrt::com_ptr<INetFwRule> p_fw_rule;
89+ // Default to true if the firewall rule is not found or enabled.
90+ bool is_firewall_wfd_asp_proto_enabled = true ;
91+
92+ // Initialize COM.
93+ HRESULT hr = CoInitializeEx (nullptr , COINIT_MULTITHREADED);
94+ if (FAILED (hr)) {
95+ if (hr == RPC_E_CHANGED_MODE) {
96+ LOG (INFO) << " COM already initialized with a different mode. Proceeding." ;
97+ } else {
98+ LOG (ERROR) << absl::StrFormat (" CoInitializeEx failed: 0x%08lx" , hr);
99+ return is_firewall_wfd_asp_proto_enabled;
100+ }
101+ } else {
102+ com_initialized = true ;
103+ }
104+
105+ // Create an instance of the firewall policy object.
106+ hr = CoCreateInstance (__uuidof (NetFwPolicy2), nullptr , CLSCTX_INPROC_SERVER,
107+ __uuidof (INetFwPolicy2), p_net_fw_policy2.put_void ());
108+ if (FAILED (hr)) {
109+ LOG (ERROR) << " CoCreateInstance for INetFwPolicy2 failed" ;
110+ if (com_initialized) CoUninitialize ();
111+ return is_firewall_wfd_asp_proto_enabled;
112+ }
113+
114+ if (p_net_fw_policy2 == nullptr ) {
115+ LOG (ERROR) << " p_net_fw_policy2 is null" ;
116+ if (com_initialized) CoUninitialize ();
117+ return is_firewall_wfd_asp_proto_enabled;
118+ }
119+
120+ // Retrieve the Rules collection.
121+ hr = p_net_fw_policy2->get_Rules (p_fw_rules.put ());
122+ if (FAILED (hr)) {
123+ LOG (ERROR) << " Failed to retrieve firewall rules collection" ;
124+ if (com_initialized) CoUninitialize ();
125+ return is_firewall_wfd_asp_proto_enabled;
126+ }
127+
128+ if (p_fw_rules == nullptr ) {
129+ LOG (ERROR) << " p_fw_rules is null" ;
130+ if (com_initialized) CoUninitialize ();
131+ return is_firewall_wfd_asp_proto_enabled;
132+ }
133+
134+ winrt::com_ptr<IUnknown> p_unk;
135+ winrt::com_ptr<IEnumVARIANT> p_enum;
136+ hr = p_fw_rules->get__NewEnum (p_unk.put ());
137+ if (FAILED (hr) || !p_unk) {
138+ LOG (ERROR) << " Failed to get rule enumerator." ;
139+ if (com_initialized) CoUninitialize ();
140+ return is_firewall_wfd_asp_proto_enabled;
141+ }
142+
143+ hr = p_unk->QueryInterface (__uuidof (IEnumVARIANT), p_enum.put_void ());
144+ if (FAILED (hr) || !p_enum) {
145+ LOG (ERROR) << " Failed to query IEnumVARIANT." ;
146+ if (com_initialized) CoUninitialize ();
147+ return is_firewall_wfd_asp_proto_enabled;
148+ }
149+
150+ VARIANT var{};
151+ while (p_enum->Next (1 , &var, nullptr ) == S_OK) {
152+ if (var.vt == VT_DISPATCH && var.pdispVal != nullptr ) {
153+ winrt::com_ptr<INetFwRule> rule;
154+ hr = var.pdispVal ->QueryInterface (__uuidof (INetFwRule), rule.put_void ());
155+ if (SUCCEEDED (hr) && rule) {
156+ LONG protocol = 0 ;
157+ rule->get_Protocol (&protocol);
158+ NET_FW_RULE_DIRECTION direction;
159+ rule->get_Direction (&direction);
160+ BSTR bstr_svc = nullptr ;
161+ rule->get_ServiceName (&bstr_svc);
162+ _bstr_t service_name (bstr_svc, false );
163+ BSTR bstr_name = nullptr ;
164+ rule->get_Name (&bstr_name);
165+ _bstr_t rule_name (bstr_name, false );
166+
167+ if (direction == NET_FW_RULE_DIR_IN &&
168+ protocol == NET_FW_IP_PROTOCOL_UDP &&
169+ service_name == _bstr_t (L" WlanSvc" )) {
170+ LOG (INFO) << " Firewall rule name="
171+ << (bstr_name ? string_utils::WideStringToString (bstr_name)
172+ : " null" );
173+ p_fw_rule = rule;
174+ VariantClear (&var);
175+ break ;
176+ }
177+ }
178+ }
179+ VariantClear (&var);
180+ }
181+
182+ if (p_fw_rule == nullptr ) {
183+ LOG (ERROR)
184+ << " Failed to find the rule 'WFD ASP Coordination Protocol (UDP-In)'." ;
185+ if (com_initialized) CoUninitialize ();
186+ return is_firewall_wfd_asp_proto_enabled;
187+ }
188+
189+ // Check if it is currently enabled.
190+ VARIANT_BOOL b_enabled;
191+ hr = p_fw_rule->get_Enabled (&b_enabled);
192+ if (SUCCEEDED (hr)) {
193+ if (b_enabled == VARIANT_TRUE) {
194+ LOG (INFO) << " Rule is enabled." ;
195+ } else {
196+ is_firewall_wfd_asp_proto_enabled = false ;
197+ LOG (INFO) << " Rule is disabled." ;
198+ }
199+ }
200+
201+ if (com_initialized) {
202+ CoUninitialize ();
203+ }
204+ return is_firewall_wfd_asp_proto_enabled;
205+ }
206+
76207bool WifiDirectMedium::IsWifiDirectServiceSupported () {
77208 if (!IsIntelWifiAdapter ()) {
78209 LOG (INFO) << " Intel Wifi adapter is not found, WifiDirectService is not "
@@ -96,7 +227,14 @@ bool WifiDirectMedium::IsWifiDirectServiceSupported() {
96227}
97228
98229bool WifiDirectMedium::IsInterfaceValid () const {
99- return is_interface_valid_;
230+ static const bool kIsInterfaceValid = IsWifiDirectServiceSupported ();
231+ return kIsInterfaceValid ;
232+ }
233+
234+ bool WifiDirectMedium::IsGOInterfaceValid () const {
235+ static const bool kIsFirewallWfdAspProtoEnabled =
236+ IsFirewallWfdAspProtoEnabled ();
237+ return kIsFirewallWfdAspProtoEnabled && IsInterfaceValid ();
100238}
101239
102240// Discoverer connects to server socket
0 commit comments