2 * Copyright (c) 2003-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
25 $Log: Firewall.cpp,v $
26 Revision 1.3 2005/09/29 06:33:54 herscher
27 <rdar://problem/4278931> Fix compilation error when using latest Microsoft Platform SDK.
29 Revision 1.2 2004/09/15 09:39:53 shersche
30 Retry the method INetFwPolicy::get_CurrentProfile on error
32 Revision 1.1 2004/09/13 07:32:31 shersche
33 Wrapper for Windows Firewall API code
38 // <rdar://problem/4278931> Doesn't compile correctly with latest Platform SDK
40 #if !defined(_WIN32_DCOM)
45 #if !defined(_WSPIAPI_COUNTOF)
46 # define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))
57 static const int kMaxTries
= 30;
58 static const int kRetrySleepPeriod
= 1 * 1000; // 1 second
62 mDNSFirewallInitialize(OUT INetFwProfile
** fwProfile
)
64 INetFwMgr
* fwMgr
= NULL
;
65 INetFwPolicy
* fwPolicy
= NULL
;
69 _ASSERT(fwProfile
!= NULL
);
73 // Use COM to get a reference to the firewall settings manager. This
74 // call will fail on anything other than XP SP2
76 err
= CoCreateInstance( __uuidof(NetFwMgr
), NULL
, CLSCTX_INPROC_SERVER
, __uuidof(INetFwMgr
), (void**)&fwMgr
);
77 require(SUCCEEDED(err
), exit
);
79 // Use the reference to get the local firewall policy
81 err
= fwMgr
->get_LocalPolicy(&fwPolicy
);
82 require(SUCCEEDED(err
), exit
);
84 // Use the reference to get the extant profile. Empirical evidence
85 // suggests that there is the potential for a race condition when a system
86 // service whose startup type is automatic calls this method.
87 // This is true even when the service declares itself to be dependent
88 // on the firewall service. Re-trying the method will succeed within
93 err
= fwPolicy
->get_CurrentProfile(fwProfile
);
97 Sleep(kRetrySleepPeriod
);
100 while (err
&& (numRetries
++ < kMaxTries
));
102 require(SUCCEEDED(err
), exit
);
108 // Release temporary COM objects
110 if (fwPolicy
!= NULL
)
127 IN INetFwProfile
* fwProfile
130 // Call Release on the COM reference.
132 if (fwProfile
!= NULL
)
134 fwProfile
->Release();
140 mDNSFirewallAppIsEnabled
142 IN INetFwProfile
* fwProfile
,
143 IN
const wchar_t * fwProcessImageFileName
,
144 OUT BOOL
* fwAppEnabled
147 BSTR fwBstrProcessImageFileName
= NULL
;
148 VARIANT_BOOL fwEnabled
;
149 INetFwAuthorizedApplication
* fwApp
= NULL
;
150 INetFwAuthorizedApplications
* fwApps
= NULL
;
151 OSStatus err
= kNoErr
;
153 _ASSERT(fwProfile
!= NULL
);
154 _ASSERT(fwProcessImageFileName
!= NULL
);
155 _ASSERT(fwAppEnabled
!= NULL
);
157 *fwAppEnabled
= FALSE
;
159 // Get the list of authorized applications
161 err
= fwProfile
->get_AuthorizedApplications(&fwApps
);
162 require(SUCCEEDED(err
), exit
);
164 fwBstrProcessImageFileName
= SysAllocString(fwProcessImageFileName
);
165 require_action(SysStringLen(fwBstrProcessImageFileName
) > 0, exit
, err
= kNoMemoryErr
);
169 err
= fwApps
->Item(fwBstrProcessImageFileName
, &fwApp
);
173 // It's listed, but is it enabled?
175 err
= fwApp
->get_Enabled(&fwEnabled
);
176 require(SUCCEEDED(err
), exit
);
178 if (fwEnabled
!= VARIANT_FALSE
)
182 *fwAppEnabled
= TRUE
;
190 // Deallocate the BSTR
192 SysFreeString(fwBstrProcessImageFileName
);
194 // Release the COM objects
213 IN INetFwProfile
* fwProfile
,
214 IN
const wchar_t * fwProcessImageFileName
,
215 IN
const wchar_t * fwName
219 BSTR fwBstrName
= NULL
;
220 BSTR fwBstrProcessImageFileName
= NULL
;
221 INetFwAuthorizedApplication
* fwApp
= NULL
;
222 INetFwAuthorizedApplications
* fwApps
= NULL
;
225 _ASSERT(fwProfile
!= NULL
);
226 _ASSERT(fwProcessImageFileName
!= NULL
);
227 _ASSERT(fwName
!= NULL
);
229 // First check to see if the application is already authorized.
230 err
= mDNSFirewallAppIsEnabled( fwProfile
, fwProcessImageFileName
, &fwAppEnabled
);
231 require_noerr(err
, exit
);
233 // Only add the application if it isn't enabled
237 // Get the list of authorized applications
239 err
= fwProfile
->get_AuthorizedApplications(&fwApps
);
240 require(SUCCEEDED(err
), exit
);
242 // Create an instance of an authorized application.
244 err
= CoCreateInstance( __uuidof(NetFwAuthorizedApplication
), NULL
, CLSCTX_INPROC_SERVER
, __uuidof(INetFwAuthorizedApplication
), (void**)&fwApp
);
245 require(SUCCEEDED(err
), exit
);
247 fwBstrProcessImageFileName
= SysAllocString(fwProcessImageFileName
);
248 require_action(SysStringLen(fwBstrProcessImageFileName
) > 0, exit
, err
= kNoMemoryErr
);
250 // Set the executable file name
252 err
= fwApp
->put_ProcessImageFileName(fwBstrProcessImageFileName
);
253 require(SUCCEEDED(err
), exit
);
255 fwBstrName
= SysAllocString(fwName
);
256 require_action(SysStringLen(fwBstrName
) > 0, exit
, err
= kNoMemoryErr
);
258 // Set the friendly name
260 err
= fwApp
->put_Name(fwBstrName
);
261 require(SUCCEEDED(err
), exit
);
263 // Now add the application
265 err
= fwApps
->Add(fwApp
);
266 require(SUCCEEDED(err
), exit
);
273 // Deallocate the BSTR objects
275 SysFreeString(fwBstrName
);
276 SysFreeString(fwBstrProcessImageFileName
);
278 // Release the COM objects
301 INetFwProfile
* fwProfile
= NULL
;
302 HRESULT comInit
= E_FAIL
;
303 OSStatus err
= kNoErr
;
307 comInit
= CoInitializeEx( 0, COINIT_APARTMENTTHREADED
| COINIT_DISABLE_OLE1DDE
);
309 // Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
310 // initialized with a different mode.
312 if (comInit
!= RPC_E_CHANGED_MODE
)
315 require(SUCCEEDED(err
), exit
);
318 // Connect to the firewall
320 err
= mDNSFirewallInitialize(&fwProfile
);
321 require_noerr(err
, exit
);
323 // Add us to the list of exempt programs
325 err
= mDNSFirewallAddApp( fwProfile
, executable
, name
);
326 require_noerr(err
, exit
);
330 // Disconnect from the firewall
332 mDNSFirewallCleanup(fwProfile
);
336 if (SUCCEEDED(comInit
))