#if !defined(_WIN32_DCOM)
# define _WIN32_DCOM
#endif
#include "Firewall.h"
#include <windows.h>
#include <crtdbg.h>
#include <netfw.h>
#include <objbase.h>
#include <oleauto.h>
static const int kMaxTries = 30;
static const int kRetrySleepPeriod = 1 * 1000;
static OSStatus
mDNSFirewallInitialize(OUT INetFwProfile ** fwProfile)
{
INetFwMgr * fwMgr = NULL;
INetFwPolicy * fwPolicy = NULL;
int numRetries = 0;
HRESULT err = kNoErr;
_ASSERT(fwProfile != NULL);
*fwProfile = NULL;
err = CoCreateInstance( __uuidof(NetFwMgr), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwMgr), (void**)&fwMgr );
require(SUCCEEDED(err) && ( fwMgr != NULL ), exit);
err = fwMgr->get_LocalPolicy(&fwPolicy);
require(SUCCEEDED(err) && ( fwPolicy != NULL ), exit);
do
{
err = fwPolicy->get_CurrentProfile(fwProfile);
if (err)
{
Sleep(kRetrySleepPeriod);
}
}
while (err && (numRetries++ < kMaxTries));
require(SUCCEEDED(err), exit);
err = kNoErr;
exit:
if (fwPolicy != NULL)
{
fwPolicy->Release();
}
if (fwMgr != NULL)
{
fwMgr->Release();
}
return err;
}
static void
mDNSFirewallCleanup
(
IN INetFwProfile * fwProfile
)
{
if (fwProfile != NULL)
{
fwProfile->Release();
}
}
static OSStatus
mDNSFirewallAppIsEnabled
(
IN INetFwProfile * fwProfile,
IN const wchar_t * fwProcessImageFileName,
OUT BOOL * fwAppEnabled
)
{
BSTR fwBstrProcessImageFileName = NULL;
VARIANT_BOOL fwEnabled;
INetFwAuthorizedApplication * fwApp = NULL;
INetFwAuthorizedApplications* fwApps = NULL;
OSStatus err = kNoErr;
_ASSERT(fwProfile != NULL);
_ASSERT(fwProcessImageFileName != NULL);
_ASSERT(fwAppEnabled != NULL);
*fwAppEnabled = FALSE;
err = fwProfile->get_AuthorizedApplications(&fwApps);
require(SUCCEEDED(err) && ( fwApps != NULL ), exit);
fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
require_action( ( fwProcessImageFileName != NULL ) && ( SysStringLen(fwBstrProcessImageFileName) > 0 ), exit, err = kNoMemoryErr);
err = fwApps->Item(fwBstrProcessImageFileName, &fwApp);
if (SUCCEEDED(err) && ( fwApp != NULL ) )
{
err = fwApp->get_Enabled(&fwEnabled);
require(SUCCEEDED(err), exit);
if (fwEnabled != VARIANT_FALSE)
{
*fwAppEnabled = TRUE;
}
}
err = kNoErr;
exit:
if ( fwBstrProcessImageFileName != NULL )
{
SysFreeString(fwBstrProcessImageFileName);
}
if (fwApp != NULL)
{
fwApp->Release();
}
if (fwApps != NULL)
{
fwApps->Release();
}
return err;
}
static OSStatus
mDNSFirewallAddApp
(
IN INetFwProfile * fwProfile,
IN const wchar_t * fwProcessImageFileName,
IN const wchar_t * fwName
)
{
BOOL fwAppEnabled;
BSTR fwBstrName = NULL;
BSTR fwBstrProcessImageFileName = NULL;
INetFwAuthorizedApplication * fwApp = NULL;
INetFwAuthorizedApplications* fwApps = NULL;
OSStatus err = S_OK;
_ASSERT(fwProfile != NULL);
_ASSERT(fwProcessImageFileName != NULL);
_ASSERT(fwName != NULL);
err = mDNSFirewallAppIsEnabled( fwProfile, fwProcessImageFileName, &fwAppEnabled );
require_noerr(err, exit);
if (!fwAppEnabled)
{
err = fwProfile->get_AuthorizedApplications(&fwApps);
require(SUCCEEDED(err) && ( fwApps != NULL ), exit);
err = CoCreateInstance( __uuidof(NetFwAuthorizedApplication), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwAuthorizedApplication), (void**)&fwApp );
require(SUCCEEDED(err) && ( fwApp != NULL ), exit);
fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
require_action(( fwProcessImageFileName != NULL ) && ( SysStringLen(fwBstrProcessImageFileName) > 0 ), exit, err = kNoMemoryErr);
err = fwApp->put_ProcessImageFileName(fwBstrProcessImageFileName);
require(SUCCEEDED(err), exit);
fwBstrName = SysAllocString(fwName);
require_action( ( fwBstrName != NULL ) && ( SysStringLen(fwBstrName) > 0 ), exit, err = kNoMemoryErr);
err = fwApp->put_Name(fwBstrName);
require(SUCCEEDED(err), exit);
err = fwApps->Add(fwApp);
require(SUCCEEDED(err), exit);
}
err = kNoErr;
exit:
if ( fwBstrName != NULL )
{
SysFreeString(fwBstrName);
}
if ( fwBstrProcessImageFileName != NULL )
{
SysFreeString(fwBstrProcessImageFileName);
}
if (fwApp != NULL)
{
fwApp->Release();
}
if (fwApps != NULL)
{
fwApps->Release();
}
return err;
}
static OSStatus
mDNSFirewallIsFileAndPrintSharingEnabled
(
IN INetFwProfile * fwProfile,
OUT BOOL * fwServiceEnabled
)
{
VARIANT_BOOL fwEnabled;
INetFwService* fwService = NULL;
INetFwServices* fwServices = NULL;
OSStatus err = S_OK;
_ASSERT(fwProfile != NULL);
_ASSERT(fwServiceEnabled != NULL);
*fwServiceEnabled = FALSE;
err = fwProfile->get_Services(&fwServices);
require( SUCCEEDED( err ), exit );
err = fwServices->Item(NET_FW_SERVICE_FILE_AND_PRINT, &fwService);
require( SUCCEEDED( err ), exit );
err = fwService->get_Enabled(&fwEnabled);
require( SUCCEEDED( err ), exit );
if (fwEnabled != VARIANT_FALSE)
{
*fwServiceEnabled = TRUE;
}
exit:
if (fwService != NULL)
{
fwService->Release();
}
if (fwServices != NULL)
{
fwServices->Release();
}
return err;
}
OSStatus
mDNSAddToFirewall
(
LPWSTR executable,
LPWSTR name
)
{
INetFwProfile * fwProfile = NULL;
HRESULT comInit = E_FAIL;
OSStatus err = kNoErr;
comInit = CoInitializeEx( 0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
if (comInit != RPC_E_CHANGED_MODE)
{
err = comInit;
require(SUCCEEDED(err), exit);
}
err = mDNSFirewallInitialize(&fwProfile);
require( SUCCEEDED( err ) && ( fwProfile != NULL ), exit);
err = mDNSFirewallAddApp( fwProfile, executable, name );
require_noerr(err, exit);
exit:
if ( fwProfile != NULL )
{
mDNSFirewallCleanup(fwProfile);
}
if (SUCCEEDED(comInit))
{
CoUninitialize();
}
return err;
}
BOOL
mDNSIsFileAndPrintSharingEnabled( BOOL * retry )
{
INetFwProfile * fwProfile = NULL;
HRESULT comInit = E_FAIL;
BOOL enabled = FALSE;
OSStatus err = kNoErr;
*retry = FALSE;
comInit = CoInitializeEx( 0, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
if (comInit != RPC_E_CHANGED_MODE)
{
*retry = TRUE;
err = comInit;
require(SUCCEEDED(err), exit);
}
err = mDNSFirewallInitialize(&fwProfile);
require( SUCCEEDED( err ) && ( fwProfile != NULL ), exit);
err = mDNSFirewallIsFileAndPrintSharingEnabled( fwProfile, &enabled );
require_noerr( err, exit );
exit:
if ( fwProfile != NULL )
{
mDNSFirewallCleanup(fwProfile);
}
if (SUCCEEDED(comInit))
{
CoUninitialize();
}
return enabled;
}