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.2 2004/09/15 09:39:53 shersche
27 Retry the method INetFwPolicy::get_CurrentProfile on error
29 Revision 1.1 2004/09/13 07:32:31 shersche
30 Wrapper for Windows Firewall API code
45 static const int kMaxTries
= 30;
46 static const int kRetrySleepPeriod
= 1 * 1000; // 1 second
50 mDNSFirewallInitialize(OUT INetFwProfile
** fwProfile
)
52 INetFwMgr
* fwMgr
= NULL
;
53 INetFwPolicy
* fwPolicy
= NULL
;
57 _ASSERT(fwProfile
!= NULL
);
61 // Use COM to get a reference to the firewall settings manager. This
62 // call will fail on anything other than XP SP2
64 err
= CoCreateInstance( __uuidof(NetFwMgr
), NULL
, CLSCTX_INPROC_SERVER
, __uuidof(INetFwMgr
), (void**)&fwMgr
);
65 require(SUCCEEDED(err
), exit
);
67 // Use the reference to get the local firewall policy
69 err
= fwMgr
->get_LocalPolicy(&fwPolicy
);
70 require(SUCCEEDED(err
), exit
);
72 // Use the reference to get the extant profile. Empirical evidence
73 // suggests that there is the potential for a race condition when a system
74 // service whose startup type is automatic calls this method.
75 // This is true even when the service declares itself to be dependent
76 // on the firewall service. Re-trying the method will succeed within
81 err
= fwPolicy
->get_CurrentProfile(fwProfile
);
85 Sleep(kRetrySleepPeriod
);
88 while (err
&& (numRetries
++ < kMaxTries
));
90 require(SUCCEEDED(err
), exit
);
96 // Release temporary COM objects
115 IN INetFwProfile
* fwProfile
118 // Call Release on the COM reference.
120 if (fwProfile
!= NULL
)
122 fwProfile
->Release();
128 mDNSFirewallAppIsEnabled
130 IN INetFwProfile
* fwProfile
,
131 IN
const wchar_t * fwProcessImageFileName
,
132 OUT BOOL
* fwAppEnabled
135 BSTR fwBstrProcessImageFileName
= NULL
;
136 VARIANT_BOOL fwEnabled
;
137 INetFwAuthorizedApplication
* fwApp
= NULL
;
138 INetFwAuthorizedApplications
* fwApps
= NULL
;
139 OSStatus err
= kNoErr
;
141 _ASSERT(fwProfile
!= NULL
);
142 _ASSERT(fwProcessImageFileName
!= NULL
);
143 _ASSERT(fwAppEnabled
!= NULL
);
145 *fwAppEnabled
= FALSE
;
147 // Get the list of authorized applications
149 err
= fwProfile
->get_AuthorizedApplications(&fwApps
);
150 require(SUCCEEDED(err
), exit
);
152 fwBstrProcessImageFileName
= SysAllocString(fwProcessImageFileName
);
153 require_action(SysStringLen(fwBstrProcessImageFileName
) > 0, exit
, err
= kNoMemoryErr
);
157 err
= fwApps
->Item(fwBstrProcessImageFileName
, &fwApp
);
161 // It's listed, but is it enabled?
163 err
= fwApp
->get_Enabled(&fwEnabled
);
164 require(SUCCEEDED(err
), exit
);
166 if (fwEnabled
!= VARIANT_FALSE
)
170 *fwAppEnabled
= TRUE
;
178 // Deallocate the BSTR
180 SysFreeString(fwBstrProcessImageFileName
);
182 // Release the COM objects
201 IN INetFwProfile
* fwProfile
,
202 IN
const wchar_t * fwProcessImageFileName
,
203 IN
const wchar_t * fwName
207 BSTR fwBstrName
= NULL
;
208 BSTR fwBstrProcessImageFileName
= NULL
;
209 INetFwAuthorizedApplication
* fwApp
= NULL
;
210 INetFwAuthorizedApplications
* fwApps
= NULL
;
213 _ASSERT(fwProfile
!= NULL
);
214 _ASSERT(fwProcessImageFileName
!= NULL
);
215 _ASSERT(fwName
!= NULL
);
217 // First check to see if the application is already authorized.
218 err
= mDNSFirewallAppIsEnabled( fwProfile
, fwProcessImageFileName
, &fwAppEnabled
);
219 require_noerr(err
, exit
);
221 // Only add the application if it isn't enabled
225 // Get the list of authorized applications
227 err
= fwProfile
->get_AuthorizedApplications(&fwApps
);
228 require(SUCCEEDED(err
), exit
);
230 // Create an instance of an authorized application.
232 err
= CoCreateInstance( __uuidof(NetFwAuthorizedApplication
), NULL
, CLSCTX_INPROC_SERVER
, __uuidof(INetFwAuthorizedApplication
), (void**)&fwApp
);
233 require(SUCCEEDED(err
), exit
);
235 fwBstrProcessImageFileName
= SysAllocString(fwProcessImageFileName
);
236 require_action(SysStringLen(fwBstrProcessImageFileName
) > 0, exit
, err
= kNoMemoryErr
);
238 // Set the executable file name
240 err
= fwApp
->put_ProcessImageFileName(fwBstrProcessImageFileName
);
241 require(SUCCEEDED(err
), exit
);
243 fwBstrName
= SysAllocString(fwName
);
244 require_action(SysStringLen(fwBstrName
) > 0, exit
, err
= kNoMemoryErr
);
246 // Set the friendly name
248 err
= fwApp
->put_Name(fwBstrName
);
249 require(SUCCEEDED(err
), exit
);
251 // Now add the application
253 err
= fwApps
->Add(fwApp
);
254 require(SUCCEEDED(err
), exit
);
261 // Deallocate the BSTR objects
263 SysFreeString(fwBstrName
);
264 SysFreeString(fwBstrProcessImageFileName
);
266 // Release the COM objects
289 INetFwProfile
* fwProfile
= NULL
;
290 HRESULT comInit
= E_FAIL
;
291 OSStatus err
= kNoErr
;
295 comInit
= CoInitializeEx( 0, COINIT_APARTMENTTHREADED
| COINIT_DISABLE_OLE1DDE
);
297 // Ignore this case. RPC_E_CHANGED_MODE means that COM has already been
298 // initialized with a different mode.
300 if (comInit
!= RPC_E_CHANGED_MODE
)
303 require(SUCCEEDED(err
), exit
);
306 // Connect to the firewall
308 err
= mDNSFirewallInitialize(&fwProfile
);
309 require_noerr(err
, exit
);
311 // Add us to the list of exempt programs
313 err
= mDNSFirewallAddApp( fwProfile
, executable
, name
);
314 require_noerr(err
, exit
);
318 // Disconnect from the firewall
320 mDNSFirewallCleanup(fwProfile
);
324 if (SUCCEEDED(comInit
))