
// PublicDNSPluginConfigDlg.cpp : файл реализации
//

#include "stdafx.h"
#include "PublicDNSPluginConfig.h"
#include "PublicDNSPluginConfigDlg.h"
#include "AboutBox.h"
#include "commrcfg.h"
#include "RTSDDMessageBox.h"
#include "WaitThread.h"
#include "Trace.h"
#include "PublicDNSPluginConfigDlg.tmh"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// диалоговое окно CPublicDNSPluginConfigDlg

BEGIN_DHTML_EVENT_MAP(CPublicDNSPluginConfigDlg)
    DHTML_EVENT_ONCLICK(_T("setup_button"), OnSetupClick)
    DHTML_EVENT_ONCLICK(_T("exit_button"), OnExitClick)
    DHTML_EVENT_ONCLICK(_T("about_icon"), DoAboutBox)
    DHTML_EVENT_ONCLICK(_T("test_dns_zone_name"), TestDnsZoneName)
    DHTML_EVENT_ONCLICK(_T("test_public_ip_button"), TestPublicIP)
    DHTML_EVENT_ONCLICK(_T("test_private_ip_button"), TestPrivateIP)
    DHTML_EVENT_ONCLICK(_T("test_public_range_button"), TestPublicRange)
    DHTML_EVENT_ONCLICK(_T("test_private_range_button"), TestPrivateRange)
    DHTML_EVENT_ONCLICK(_T("test_public_subnet_button"), TestPublicSubnet)
    DHTML_EVENT_ONCLICK(_T("test_private_subnet_button"), TestPrivateSubnet)
    DHTML_EVENT_ONCLICK(_T("test_public_ip6_button"), TestPublicIPv6)
    DHTML_EVENT_ONCLICK(_T("test_private_ip6_button"), TestPrivateIPv6)
    DHTML_EVENT_ONCLICK(_T("save_button"), SaveParameters)
    DHTML_EVENT_ONCLICK(_T("load_button"), ReloadParameters)
    DHTML_EVENT_ONCLICK(_T("uninstall_button"), OnUninstallClick)
    DHTML_EVENT_ONCLICK(_T("restart_button"), OnRestartClick)
END_DHTML_EVENT_MAP()



CPublicDNSPluginConfigDlg::CPublicDNSPluginConfigDlg(CWnd* pParent /*=NULL*/)
: CDHtmlDialog(_T("PUBLICDNSPLUGINCONFIG_DIALOG"), _T("PUBLICDNSPLUGINCONFIG.HTM"), pParent)
, m_bNoBreakStage(false)
, m_sFileVersion(theApp.m_sVersionHTMLString)
, m_sStatusStr(_T("Готово"))
, m_sDomainZoneName(_T(""))
, m_sSetupImageSRC(_T("SETUP_HIDEN.GIF"))
, m_bHTMLInit(false)
, m_bServiceInstalled(false)
, m_sUninstallImageSRC(_T("UNINSTALL32_GRAY.PNG"))
, m_sRestartImageSRC(_T("RESTARTHS_GRAY.PNG"))
, m_sCopyRightDates(theApp.m_sCopyRightDates)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_bUseHtmlTitle = TRUE;
	m_sDomainZoneName = GetConfigString(
        _T("service_settings"),
        _T("dns_zone_name"),
        _T("")
        );
}

void CPublicDNSPluginConfigDlg::DoDataExchange(CDataExchange* pDX)
{
    DDX_DHtml_ElementInnerHtml(
        pDX,
        _T("version_descript"),
        m_sFileVersion
        );
    DDX_DHtml_ElementInnerHtml(
        pDX,
        _T("version_str"),
        m_sFileVersion
        );
    DDX_DHtml_ElementInnerText(
        pDX,
        _T("cr_dates"),
        m_sCopyRightDates
        );
    DDX_DHtml_ElementInnerText(
        pDX,
        _T("status_text"),
        m_sStatusStr
        );
    DDX_DHtml_ElementValue(
        pDX,
        _T("dns_zone_name"),
        m_sDomainZoneName
        );
    DDX_DHtml_Img_Src(
        pDX,
        _T("setup_image"),
        m_sSetupImageSRC
        );
    DDX_DHtml_Img_Src(
        pDX,
        _T("uninstall_image"),
        m_sUninstallImageSRC
        );
    DDX_DHtml_Img_Src(
        pDX,
        _T("restart_image"),
        m_sRestartImageSRC
        );
	CDHtmlDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CPublicDNSPluginConfigDlg, CDHtmlDialog)
	ON_WM_SYSCOMMAND()
    ON_WM_SIZE()
    ON_WM_CLOSE()
    ON_WM_DESTROY()
END_MESSAGE_MAP()


// обработчики сообщений CPublicDNSPluginConfigDlg

BOOL CPublicDNSPluginConfigDlg::OnInitDialog()
{
    SetHostFlags(
        DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_DIALOG
        );
	CDHtmlDialog::OnInitDialog();
	// Добавление пункта "О программе..." в системное меню.
	// IDM_ABOUTBOX должен быть в пределах системной команды.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);
	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}
	// Задает значок для этого диалогового окна. Среда делает это автоматически,
	//  если главное окно приложения не является диалоговым
	SetIcon(m_hIcon, TRUE);			// Крупный значок
	SetIcon(m_hIcon, FALSE);		// Мелкий значок
	return TRUE;  // возврат значения TRUE, если фокус не передан элементу управления
}

void CPublicDNSPluginConfigDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutBox dlgAbout(this);
		dlgAbout.DoModal();
	}
	else
	{
		CDHtmlDialog::OnSysCommand(nID, lParam);
	}
}

// При добавлении кнопки свертывания в диалоговое окно нужно воспользоваться приведенным ниже кодом,
//  чтобы нарисовать значок. Для приложений MFC, использующих модель документов или представлений,
//  это автоматически выполняется рабочей областью.

void CPublicDNSPluginConfigDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // контекст устройства для рисования

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Выравнивание значка по центру клиентского прямоугольника
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Нарисуйте значок
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDHtmlDialog::OnPaint();
	}
}

// Система вызывает эту функцию для получения отображения курсора при перемещении
//  свернутого окна.
HCURSOR CPublicDNSPluginConfigDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CPublicDNSPluginConfigDlg::OnSize(UINT nType, int cx, int cy)
{
    CDHtmlDialog::OnSize(nType, cx, cy);
    if(nType == SIZE_RESTORED) {
        UpdateWindow();
    }
}


void CPublicDNSPluginConfigDlg::OnClose()
{
    if(!m_bNoBreakStage) {
        DestroyModeless( );
    }
}


#pragma warning(push)
#pragma warning(disable: 4701 4703)
HRESULT CPublicDNSPluginConfigDlg::OnSetupClick(IHTMLElement* pElement)
{
    // инсталяция сервиса
    HRESULT                         hr;
    SC_HANDLE                       schSCManager;
    SC_HANDLE                       schService;
    DWORD                           nErrorCode;
    BOOL                            bRet = UpdateData(TRUE);
    MSHTML::IHTMLElementPtr         spIHTMLElement;
    MSHTML::IHTMLButtonElementPtr   spHTMLButtonElement;
    INT_PTR                         nDialogRet;
    CRTSDDMessageBox                oRTSDDMessageBox(this);
    CRegKey                         oDnsDbgKey;
    LONG                            nRet;
    bool                            bValidRegistry;
    DWORD                           dwDisposition;
    SERVICE_STATUS                  stServiceStatus;
    SERVICE_STATUS_PROCESS          stServiceProcessStatus;
    DWORD                           cbBytesNeeded, dwStopCount = 0;
    CWaitThread*                    pWaitThread = NULL;
    DWORD                           dwWaitCode;
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_PLUGIN_CONFIG_DLG,
        "%!FUNC! line:%!LINE! %!LEVEL! Enter"
        );
    spHTMLButtonElement = pElement;
    if (spHTMLButtonElement->disabled)
    {
        return S_OK;
    }
    schSCManager = OpenSCManager(
        NULL,                 // local machine
        NULL,                 // ServicesActive database
        SC_MANAGER_ALL_ACCESS // full access rights
        );
    if(NULL == schSCManager)
    {
        nErrorCode = ::GetLastError();
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_PLUGIN_CONFIG_DLG,
            "%!FUNC! line:%!LINE! %!LEVEL! Call \"OpenSCManager\" failed with error:  %!WINERROR!",
            nErrorCode
            );
        oRTSDDMessageBox.m_sMessageText.Format(
            _T("\"OpenSCManager\" failed!! Error code = %d"),
            nErrorCode
            );
        nDialogRet = oRTSDDMessageBox.DoModal();
        return S_OK;
    }
    schService = OpenService(
        schSCManager,
        _T("DNS"),
        SERVICE_ALL_ACCESS
        );
    if (NULL == schService)
    {
        nErrorCode = ::GetLastError();
        bRet = CloseServiceHandle(schSCManager);
        if (ERROR_SERVICE_DOES_NOT_EXIST != nErrorCode)
        {
            TraceEvents(
                TRACE_LEVEL_ERROR,
                TRACE_PLUGIN_CONFIG_DLG,
                "%!FUNC! line:%!LINE! %!LEVEL! Call \"OpenService\" failed with error:  %!WINERROR!",
                nErrorCode
                );
            oRTSDDMessageBox.m_sMessageText.Format(
                _T("OpenService failed. Error code = %d"),
                nErrorCode
                );
        }
        else
        {
            oRTSDDMessageBox.m_sMessageText = _T("The DNS server role is not installed.");
            spHTMLButtonElement->disabled = VARIANT_TRUE;
            m_sSetupImageSRC = _T("SETUP_HIDEN.GIF");
            hr = GetElement(
                _T("uninstall_button"),
                (IHTMLElement**) &spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
            spHTMLButtonElement->disabled = VARIANT_TRUE;
            m_sUninstallImageSRC = _T("UNINSTALL32_GRAY.PNG");
            hr = GetElement(
                _T("restart_button"),
                (IHTMLElement**) &spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
            spHTMLButtonElement->disabled = VARIANT_TRUE;
            m_sRestartImageSRC = _T("RESTARTHS_GRAY.PNG");
            TraceEvents(
                TRACE_LEVEL_ERROR,
                TRACE_PLUGIN_CONFIG_DLG,
                "%!FUNC! line:%!LINE! %!LEVEL! Exit \"The DNS server role is not installed.\""
                );
        }
        nDialogRet = oRTSDDMessageBox.DoModal();
        return S_OK;
    }
    bRet = CloseServiceHandle(schSCManager);
    nRet = oDnsDbgKey.Create(
        HKEY_LOCAL_MACHINE,
        _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\dns.exe"),
        REG_NONE,
        REG_OPTION_NON_VOLATILE,
        KEY_ALL_ACCESS,
        NULL,
        &dwDisposition
        );
    bValidRegistry = (ERROR_SUCCESS == nRet);
    ASSERT(bValidRegistry);
    nRet = oDnsDbgKey.SetStringValue(
        _T("Debugger"),
        theApp.m_sDnsLauncherFileName
        );
    bValidRegistry = (ERROR_SUCCESS == nRet);
    ASSERT(bValidRegistry);
    for (dwStopCount = 0; dwStopCount < 120; dwStopCount++)
    {
        RtlZeroMemory(
            &stServiceProcessStatus,
            sizeof(stServiceProcessStatus)
            );
        RtlZeroMemory(
            &stServiceStatus,
            sizeof(stServiceStatus)
            );
        bRet = QueryServiceStatusEx(
            schService,
            SC_STATUS_PROCESS_INFO,
            (LPBYTE) &stServiceProcessStatus,
            sizeof(stServiceProcessStatus),
            &cbBytesNeeded
            );
        if (SERVICE_RUNNING == stServiceProcessStatus.dwCurrentState)
        {
            TraceEvents(
                TRACE_LEVEL_INFORMATION,
                TRACE_PLUGIN_CONFIG_DLG,
                "%!FUNC! line:%!LINE! %!LEVEL! Service \"DNS\" will be stoped."
                );
            if (0 == dwStopCount)
            {
                pWaitThread = new CWaitThread(
                    _T("Завершение служвы фильтрации адресов DNS-сервера может занять несколько минут!"),
                    this
                    );
                bRet = pWaitThread->CreateThread();
                ASSERT(bRet);
                bRet = ControlService(
                    schService,
                    SERVICE_CONTROL_STOP,
                    &stServiceStatus
                    );
                if (!bRet)
                {
                    nErrorCode = ::GetLastError();
                    TraceEvents(
                        TRACE_LEVEL_ERROR,
                        TRACE_PLUGIN_CONFIG_DLG,
                        "%!FUNC! line:%!LINE! %!LEVEL! Call \"ControlService\" failed with error:  %!WINERROR!",
                        nErrorCode
                        );
                    ASSERT(bRet);
                    bRet = pWaitThread->PostThreadMessage(
                        WM_QUIT,
                        0,
                        0
                        );
                    pWaitThread = NULL;
                    break;
                }
            }
            dwWaitCode = SleepEx(1000, TRUE);
        }
        else
        {
            if (NULL != pWaitThread)
            {
                bRet = pWaitThread->PostThreadMessage(
                    WM_QUIT,
                    0,
                    0
                    );
                pWaitThread = NULL;
            }
            break;
        }
    }
    if (dwStopCount >= 120)
    {
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_PLUGIN_CONFIG_DLG,
            "%!FUNC! line:%!LINE! %!LEVEL! Stop service command limit exceeded."
            );
        bRet = pWaitThread->PostThreadMessage(
            WM_QUIT,
            0,
            0
            );
        pWaitThread = NULL;
        ASSERT(false);
    }
    bRet = StartService(
        schService,
        0,
        NULL
        );
    if (!bRet)
    {
        nErrorCode = GetLastError();
        ASSERT(bRet);
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_PLUGIN_CONFIG_DLG,
            "%!FUNC! line:%!LINE! %!LEVEL! Call \"StartService\" failed with error code = %!WINERROR!",
            nErrorCode
            );
    }
    bRet = CloseServiceHandle(schService);
    oRTSDDMessageBox.m_sMessageText = _T("Служба фильтрации адресов DNS-сервера успешно инсталирована.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    hr = GetElement(
        _T("setup_button"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
    spHTMLButtonElement->disabled = VARIANT_TRUE;
    m_sSetupImageSRC = _T("SETUP_HIDEN.GIF");
    hr = GetElement(
        _T("uninstall_button"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
    spHTMLButtonElement->disabled = VARIANT_FALSE;
    m_sUninstallImageSRC = _T("UNINSTALL32.PNG");
    hr = GetElement(
        _T("restart_button"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
    spHTMLButtonElement->disabled = VARIANT_FALSE;
    m_sRestartImageSRC = _T("RESTARTHS.PNG");
    bRet = UpdateData(FALSE);
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_PLUGIN_CONFIG_DLG,
        "%!FUNC! line:%!LINE! %!LEVEL! Exit"
        );
    return S_OK;
}
#pragma warning(pop)


HRESULT CPublicDNSPluginConfigDlg::OnExitClick(IHTMLElement* pElement)
{
    UNREFERENCED_PARAMETER(pElement);
    if(!m_bNoBreakStage) {
        DestroyModeless( );
    }
    return S_OK;
}


HRESULT CPublicDNSPluginConfigDlg::DoAboutBox(IHTMLElement* pElement)
{
    CAboutBox oAboutBox(this);
    INT_PTR nRet;
    UNREFERENCED_PARAMETER(pElement);
    nRet = oAboutBox.DoModal();
    return S_OK;
}


void CPublicDNSPluginConfigDlg::OnDestroy()
{
    WINDOWPLACEMENT strcWndPl;
    if(!GetWindowPlacement( &strcWndPl )) {
        CDHtmlDialog::OnDestroy( );
        return;
    }
    if(strcWndPl.showCmd == SW_SHOWMAXIMIZED) {
        theApp.WriteProfileInt(
            _T("WindowPlacement"),
            _T("showMaximized"),
            1
            );
    } else {
        theApp.WriteProfileInt(
            _T("WindowPlacement"),
            _T("showMaximized"),
            0
            );
    }
    theApp.WriteProfileInt(
        _T("WindowPlacement"),
        _T("leftNormal"),
        strcWndPl.rcNormalPosition.left
        );
    theApp.WriteProfileInt(
        _T("WindowPlacement"),
        _T("topNormal"),
        strcWndPl.rcNormalPosition.top
        );
    theApp.WriteProfileInt(
        _T("WindowPlacement"),
        _T("rightNormal"),
        strcWndPl.rcNormalPosition.right
        );
    theApp.WriteProfileInt(
        _T("WindowPlacement"),
        _T("bottomNormal"),
        strcWndPl.rcNormalPosition.bottom
        );
    CDHtmlDialog::OnDestroy();
}

STDMETHODIMP CPublicDNSPluginConfigDlg::ShowContextMenu(
    DWORD dwID,
    POINT* ppt,
    IUnknown* pcmdtReserved,
    IDispatch* pdispReserved
    )
{
    UNREFERENCED_PARAMETER(ppt);
    UNREFERENCED_PARAMETER(pcmdtReserved);
    UNREFERENCED_PARAMETER(pdispReserved);
    if(dwID == CONTEXT_MENU_CONTROL) {
        return S_FALSE;
    }
    return S_OK;
}

STDMETHODIMP CPublicDNSPluginConfigDlg::GetHostInfo(
    DOCHOSTUIINFO *pInfo
    )
{
	pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_DIALOG;
    pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
    return S_OK;
}


HRESULT CPublicDNSPluginConfigDlg::TestDnsZoneName(IHTMLElement* pElement)
{
    HRESULT                         hr;
    BOOL                            bRet = FALSE;
    MSHTML::IHTMLElementPtr         spDomainZoneName;
    MSHTML::IHTMLElement2Ptr        spDomainZoneNameElement2;
    MSHTML::IHTMLInputElementPtr    spDomainZoneNameInput;
    bool                            bIPExist = false;
    int                             nZoneNameLength;
    DNS_STATUS                      nDnsStatus;
    PDNS_RECORD                     pQueryResultsSet = NULL;
    PDNS_RECORD                     pCurrentRR, pNextRR;
    CString                         sNamePrimaryServer;
    CString                         sNameAdministrator;
    PDNS_SOA_DATA                   pSoaData;
    INT_PTR                         nDialogRet;
    CRTSDDMessageBox                oRTSDDMessageBox(this);
    UNREFERENCED_PARAMETER(pElement);
    bRet = UpdateData(TRUE);
    hr = GetElement(
        _T("dns_zone_name"),
        (IHTMLElement**)&spDomainZoneName
        );
    hr = spDomainZoneName->QueryInterface(&spDomainZoneNameElement2);
    hr = spDomainZoneName->QueryInterface(&spDomainZoneNameInput);
    nZoneNameLength = m_sDomainZoneName.GetLength();
    if(0 == nZoneNameLength)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Нечего проверять!\nЗаполните поле имени DNS-зоны.");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spDomainZoneNameElement2->focus();
        hr = spDomainZoneNameInput->select();
        return S_OK;
    }
    if(_T('.') != m_sDomainZoneName[nZoneNameLength - 1])
    {
        m_sDomainZoneName += _T('.');
        bRet = UpdateData(FALSE);
    }
    nDnsStatus = DnsQuery_W(
        (LPCWSTR)m_sDomainZoneName,
        DNS_TYPE_SOA,
        DNS_QUERY_STANDARD,
        NULL,
        &pQueryResultsSet,
        NULL
        );
    if(NO_ERROR != nDnsStatus)
    {
        CString sMsg;
        if(NULL != pQueryResultsSet)
        {
            DnsRecordListFree(
                pQueryResultsSet,
                DnsFreeRecordList
                );
        }
        sMsg.Format(
            _T("Ошибка вызова функции \"DnsQuery_W\"!\n\tКод ошибки = %u (0x%08X)\n"),
            nDnsStatus,
            nDnsStatus
            );
        oRTSDDMessageBox.m_sMessageText = sMsg;
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spDomainZoneNameElement2->focus();
        hr = spDomainZoneNameInput->select();
        return S_OK;
    }
    ASSERT(NULL != pQueryResultsSet);
    pCurrentRR = pQueryResultsSet;
    while(NULL != pCurrentRR)
    {
        pNextRR = pCurrentRR->pNext;
        if(DNS_TYPE_SOA == pCurrentRR->wType)
        {
            pSoaData = &pCurrentRR->Data.SOA;
            sNamePrimaryServer = pSoaData->pNamePrimaryServer;
            sNameAdministrator = pSoaData->pNameAdministrator;
        }
        else
        if(DNS_TYPE_A == pCurrentRR->wType)
        {
            IP4_ADDRESS nIpAddress;
            bool        bPublic;
            nIpAddress = pCurrentRR->Data.A.IpAddress;
            bPublic = IsPublic(nIpAddress);
            if(bPublic)
            {
                bIPExist = true;
            }
        }
        pCurrentRR = pNextRR;
    }
    {
        CString sMsg;
        if(sNamePrimaryServer.IsEmpty())
        {
            sMsg  = _T("Первичный контролер домена \"");
            sMsg += m_sDomainZoneName;
            sMsg += _T("\" не найден!");
            oRTSDDMessageBox.m_sMessageText = sMsg;
            nDialogRet = oRTSDDMessageBox.DoModal();
            hr = spDomainZoneNameElement2->focus();
            hr = spDomainZoneNameInput->select();
            return S_OK;
        }
        sMsg  = _T("Первичный контролер домена \"");
        sMsg += m_sDomainZoneName;
        sMsg += _T("\" -- \"");
        sMsg += sNamePrimaryServer;
        sMsg += _T("\"\nАдминистратор домена -- \"");
        sMsg += sNameAdministrator;
        sMsg += _T("\"\n");
        if(bIPExist)
        {
            oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
            sMsg += _T("Первичный контролер домена имеет публичный IP-адрес.");
            oRTSDDMessageBox.m_sMessageText = sMsg;
            nDialogRet = oRTSDDMessageBox.DoModal();
            hr = spDomainZoneNameElement2->focus();
            return S_OK;
        }
        oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("WARNING_ICON.PNG");
        sMsg += _T("IP-адрес первичного контролера домена не найден в списке публичных адресов или список адресов пуст.");
        oRTSDDMessageBox.m_sMessageText = sMsg;
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spDomainZoneNameElement2->focus();
        hr = spDomainZoneNameInput->select();
    }
    return S_OK;
}


HRESULT CPublicDNSPluginConfigDlg::TestPublicIP(IHTMLElement* pElement)
{
    HRESULT hr;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    CString                             sIPAddress;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    LONG                                nRet;
    LPCTSTR                             pTerminator;
    IN_ADDR                             stIP4Address;
    MSHTML::IHTMLElement2Ptr            spPublicIPElement2;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    spIHTMLElement = pElement;
    spIHTMLElement = spIHTMLElement->parentElement;
    spDispatch = spIHTMLElement->children;
    hr = spDispatch->QueryInterface(&spHTMLElementCollection);
    spDispatch = spHTMLElementCollection->item(_variant_t(L"public_ip"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spPublicIPElement2);
    sIPAddress = (LPCTSTR)spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = _T("Поле публичного IPv4-адреса не должно быть пустым!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv4StringToAddress(
        sIPAddress,
        TRUE,
        &pTerminator,
        &stIP4Address
        );
    if(NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата IPv4-адреса!!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    oRTSDDMessageBox.m_sMessageText = _T("Формат публичного IPv-адреса верен.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    return S_OK;
}

HRESULT CPublicDNSPluginConfigDlg::TestPrivateIP(IHTMLElement* pElement)
{
    HRESULT                             hr;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    CString                             sIPAddress;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    LONG                                nRet;
    LPCTSTR                             pTerminator;
    IN_ADDR                             stIP4Address;
    MSHTML::IHTMLElement2Ptr            spPrivateIPElement2;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    spIHTMLElement = pElement;
    spIHTMLElement = spIHTMLElement->parentElement;
    spDispatch = spIHTMLElement->children;
    hr = spDispatch->QueryInterface(&spHTMLElementCollection);
    spDispatch = spHTMLElementCollection->item(_variant_t(L"private_ip"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spPrivateIPElement2);
    sIPAddress = (LPCTSTR)spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = _T("Поле приватного IPv4-адреса не должно быть пустым!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv4StringToAddress(
        sIPAddress,
        TRUE,
        &pTerminator,
        &stIP4Address
        );
    if(NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата IPv4-адреса!!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    oRTSDDMessageBox.m_sMessageText = _T("Формат приватного IPv4-адреса верен.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    return S_OK;
}


HRESULT CPublicDNSPluginConfigDlg::TestPublicRange(IHTMLElement* pElement)
{
    HRESULT                             hr;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    CString                             sIPAddress;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    LONG                                nRet;
    LPCTSTR                             pTerminator;
    IN_ADDR                             stIP4Address;
    MSHTML::IHTMLElement2Ptr            spPublicIPElement2;
    u_long                              nhBeginAddress, nhEndAddress;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    spIHTMLElement = pElement;
    spIHTMLElement = spIHTMLElement->parentElement;
    spDispatch = spIHTMLElement->children;
    hr = spDispatch->QueryInterface(&spHTMLElementCollection);
    spDispatch = spHTMLElementCollection->item(_variant_t(L"range_begin"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spPublicIPElement2);
    sIPAddress = (LPCTSTR)spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = _T("Поле начального значения диапазона публичных IPv4-адресов не должно быть пустым!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv4StringToAddress(
        sIPAddress,
        TRUE,
        &pTerminator,
        &stIP4Address
        );
    if(NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата начального значения диапазона публичных IPv4-адресов!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nhBeginAddress = ntohl(stIP4Address.S_un.S_addr);
    spDispatch = spHTMLElementCollection->item(_variant_t(L"range_end"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spPublicIPElement2);
    sIPAddress = (LPCTSTR)spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = _T("Поле конечного значения диапазона публичных IPv4-адресов не должно быть пустым!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv4StringToAddress(
        sIPAddress,
        TRUE,
        &pTerminator,
        &stIP4Address
        );
    if(NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата конечного значения диапазона публичных IPv4-адресов!!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nhEndAddress = ntohl(stIP4Address.S_un.S_addr);
    if(nhBeginAddress > nhEndAddress)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Значение начального адреса диапазона больше конечного!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    if(nhBeginAddress == nhEndAddress)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Значение начального адреса диапазона равно конечному, т.е задан единственный IPv4-адрес!");
        oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("WARNING_ICON.PNG");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    oRTSDDMessageBox.m_sMessageText = _T("Формат диапазона публичных IPv4-адресов верен.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    return S_OK;
}

HRESULT CPublicDNSPluginConfigDlg::TestPrivateRange(IHTMLElement* pElement)
{
    HRESULT                             hr;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    CString                             sIPAddress;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    LONG                                nRet;
    LPCTSTR                             pTerminator;
    IN_ADDR                             stIP4Address;
    MSHTML::IHTMLElement2Ptr            spPrivateIPElement2;
    u_long                              nhBeginAddress, nhEndAddress;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    spIHTMLElement = pElement;
    spIHTMLElement = spIHTMLElement->parentElement;
    spDispatch = spIHTMLElement->children;
    hr = spDispatch->QueryInterface(&spHTMLElementCollection);
    spDispatch = spHTMLElementCollection->item(_variant_t(L"private_range_begin"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spPrivateIPElement2);
    sIPAddress = (LPCTSTR)spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = _T("Поле начального значения диапазона приватных IPv4-адресов не должно быть пустым!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv4StringToAddress(
        sIPAddress,
        TRUE,
        &pTerminator,
        &stIP4Address
        );
    if(NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата начального значения диапазона приватных IPv4-адресов!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nhBeginAddress = ntohl(stIP4Address.S_un.S_addr);
    spDispatch = spHTMLElementCollection->item(_variant_t(L"private_range_end"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spPrivateIPElement2);
    sIPAddress = (LPCTSTR)spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = _T("Поле конечного значения диапазона приватных IPv4-адресов не должно быть пустым!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv4StringToAddress(
        sIPAddress,
        TRUE,
        &pTerminator,
        &stIP4Address
        );
    if(NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата конечного значения диапазона приватных IPv4-адресов!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nhEndAddress = ntohl(stIP4Address.S_un.S_addr);
    if(nhBeginAddress > nhEndAddress)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Значение начального адреса диапазона больше конечного!!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    if(nhBeginAddress == nhEndAddress)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Значение начального адреса диапазона равно конечному, т.е задан единственный IPv4-адрес!");
        oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("WARNING_ICON.PNG");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    oRTSDDMessageBox.m_sMessageText = _T("Формат диапазона приватных IPv4-адресов верен.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    return S_OK;
}


HRESULT CPublicDNSPluginConfigDlg::TestPublicSubnet(IHTMLElement* pElement)
{
    HRESULT                             hr;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    CString                             sIPAddress;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    LONG                                nRet;
    LPCTSTR                             pTerminator;
    IN_ADDR                             stIP4Address;
    MSHTML::IHTMLElement2Ptr            spPublicIPElement2;
    NETIO_STATUS                        nioStatus;
    UINT8                               nMaskLength;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    spIHTMLElement = pElement;
    spIHTMLElement = spIHTMLElement->parentElement;
    spDispatch = spIHTMLElement->children;
    hr = spDispatch->QueryInterface(&spHTMLElementCollection);
    spDispatch = spHTMLElementCollection->item(_variant_t(L"subnet_address"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spPublicIPElement2);
    sIPAddress = (LPCTSTR)spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = L"Поле IP-адреса публичной IPv4-подсети не должно быть пустым!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv4StringToAddress(
        sIPAddress,
        TRUE,
        &pTerminator,
        &stIP4Address
        );
    if(NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата адреса публичной IPv4-подсети!!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    spDispatch = spHTMLElementCollection->item(_variant_t(L"subnet_mask"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spPublicIPElement2);
    sIPAddress = (LPCTSTR)spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = L"Поле маски публичной IPv4-подсети не должно быть пустым!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv4StringToAddress(
        sIPAddress,
        TRUE,
        &pTerminator,
        &stIP4Address
        );
    if(NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата маски публичной IPv4-подсети!!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nioStatus = ConvertIpv4MaskToLength(
        (ULONG) stIP4Address.S_un.S_addr,
        &nMaskLength
        );
    if (NO_ERROR != nioStatus)
    {
        oRTSDDMessageBox.m_sMessageText = L"Неверный формат маски публичной IPv4-подсети (нельзя преобразовать маску в длину префикса маски)!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    oRTSDDMessageBox.m_sMessageText = _T("Формат публичной IPv4-подсети верен.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    return S_OK;
}

HRESULT CPublicDNSPluginConfigDlg::TestPrivateSubnet(IHTMLElement* pElement)
{
    HRESULT                             hr;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    CString                             sIPAddress;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    LONG                                nRet;
    LPCTSTR                             pTerminator;
    IN_ADDR                             stIP4Address;
    MSHTML::IHTMLElement2Ptr            spPrivateIPElement2;
    NETIO_STATUS                        nioStatus;
    UINT8                               nMaskLength;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    spIHTMLElement = pElement;
    spIHTMLElement = spIHTMLElement->parentElement;
    spDispatch = spIHTMLElement->children;
    hr = spDispatch->QueryInterface(&spHTMLElementCollection);
    spDispatch = spHTMLElementCollection->item(_variant_t(L"private_subnet_address"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spPrivateIPElement2);
    sIPAddress = (LPCTSTR)spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = L"Поле IP-адреса приватной IPv4-подсети не должно быть пустым!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv4StringToAddress(
        sIPAddress,
        TRUE,
        &pTerminator,
        &stIP4Address
        );
    if(NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата адреса приватной IPv4-подсети!!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    spDispatch = spHTMLElementCollection->item(_variant_t(L"private_subnet_mask"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spPrivateIPElement2);
    sIPAddress = (LPCTSTR)spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = L"Поле маски приватной IPv4-подсети не должно быть пустым!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv4StringToAddress(
        sIPAddress,
        TRUE,
        &pTerminator,
        &stIP4Address
        );
    if(NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата маски приватной IPv4-подсети!!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
    }
    nioStatus = ConvertIpv4MaskToLength(
        (ULONG) stIP4Address.S_un.S_addr,
        &nMaskLength
        );
    if (NO_ERROR != nioStatus)
    {
        oRTSDDMessageBox.m_sMessageText = L"Неверный формат маски приватной IPv4-подсети (нельзя преобразовать маску в длину префикса маски)!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPrivateIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    oRTSDDMessageBox.m_sMessageText = _T("Формат приватной IPv4-подсети верен.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    return S_OK;
}


#pragma warning(push)
#pragma warning(disable: 4701)
HRESULT CPublicDNSPluginConfigDlg::SaveParameters(IHTMLElement* pElement)
{
    HRESULT                             hr;
    CFileStatus                         stFileStatus;
    BOOL                                bRet;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTableRowPtr            spIHTMLTableRow;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    CString                             sIPAddress;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLElementCollectionPtr   spCellChildrens;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    LONG                                nRet;
    LPCTSTR                             pTerminator;
    IN_ADDR                             stIP4Address;
    MSHTML::IHTMLElement2Ptr            spPublicIPElement2;
    int i, nSingleIP = 0, nRangeIP = 0, nSubnetIP = 0, nPublicIPv6 = 0;
    int nSinglePrivateIP = 0, nRangePrivateIP = 0, nSubnetPrivateIP = 0, nPrivateIPv6 = 0;
    bool                                bIPExist = false;
    BOOL                                bCollection = FALSE;
    u_long                              nhBeginAddress, nhEndAddress;
    CString                             sSectionName;
    int                                 nZoneNameLength;
    DNS_STATUS                          nDnsStatus;
    PDNS_RECORD                         pQueryResultsSet = NULL;
    PDNS_RECORD                         pCurrentRR, pNextRR;
    CString                             sNamePrimaryServer;
    CString                             sNameAdministrator;
    PDNS_SOA_DATA                       pSoaData;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    NETIO_STATUS                        nioStatus;
    UINT8                               nMaskLength;
    IN6_ADDR                            stIP6Address;
    LONG                                nPrefixLength;
    DWORD                               dwSerialNo, dwRefresh, dwRetry, dwExpire, dwDefaultTtl, dwFlags, dwTtl;
    UNREFERENCED_PARAMETER(pElement);
    bRet = UpdateData(TRUE);
    hr = GetElement(
        _T("dns_zone_name"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spPublicIPElement2);
    hr = spIHTMLElement->QueryInterface(&spInputText);
    nZoneNameLength = m_sDomainZoneName.GetLength();
    if(0 == nZoneNameLength)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Поле имени DNS-зоны не должно быть пустым!\nЗаполните поле имени DNS-зоны.");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    if(_T('.') != m_sDomainZoneName[nZoneNameLength - 1])
    {
        m_sDomainZoneName += _T('.');
        bRet = UpdateData(FALSE);
    }
    nDnsStatus = DnsQuery_W(
        (LPCWSTR)m_sDomainZoneName,
        DNS_TYPE_SOA,
        DNS_QUERY_STANDARD,
        NULL,
        &pQueryResultsSet,
        NULL
        );
    if(FAILED(nDnsStatus))
    {
        CString sMsg;
        if(NULL != pQueryResultsSet)
        {
            DnsRecordListFree(
                pQueryResultsSet,
                DnsFreeRecordList
                );
        }
        sMsg.Format(
            _T("Ошибка вызова функции \"DnsQuery_W\"!\n\tКод ошибки = 0x%08X\n"),
            nDnsStatus
            );
        oRTSDDMessageBox.m_sMessageText = sMsg;
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spPublicIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    ASSERT(NULL != pQueryResultsSet);
    pCurrentRR = pQueryResultsSet;
    while(NULL != pCurrentRR)
    {
        pNextRR = pCurrentRR->pNext;
        if(DNS_TYPE_SOA == pCurrentRR->wType)
        {
            pSoaData = &pCurrentRR->Data.SOA;
            sNamePrimaryServer = pSoaData->pNamePrimaryServer;
            sNameAdministrator = pSoaData->pNameAdministrator;
            dwSerialNo = pSoaData->dwSerialNo;
            dwRefresh = pSoaData->dwRefresh;
            dwRetry = pSoaData->dwRetry;
            dwExpire = pSoaData->dwExpire;
            dwDefaultTtl = pSoaData->dwDefaultTtl;
            dwFlags = pCurrentRR->Flags.DW;
            dwTtl = pCurrentRR->dwTtl;
        }
        else
        if(DNS_TYPE_A == pCurrentRR->wType)
        {
            IP4_ADDRESS nIpAddress;
            bool        bPublic;
            nIpAddress = pCurrentRR->Data.A.IpAddress;
            bPublic = IsPublic(nIpAddress);
            if(bPublic)
            {
                bIPExist = true;
            }
        }
        pCurrentRR = pNextRR;
    }
    {
        CString sMsg;
        if(sNamePrimaryServer.IsEmpty())
        {
            sMsg  = _T("Первичный контролер домена \"");
            sMsg += m_sDomainZoneName;
            sMsg += _T("\" не найден!");
            oRTSDDMessageBox.m_sMessageText = sMsg;
            nDialogRet = oRTSDDMessageBox.DoModal();
            hr = spPublicIPElement2->focus();
            hr = spInputText->select();
            return S_OK;
        }
        sMsg  = _T("Первичный контролер домена \"");
        sMsg += m_sDomainZoneName;
        sMsg += _T("\" -- \"");
        sMsg += sNamePrimaryServer;
        sMsg += _T("\"\nАдминистратор домена -- \"");
        sMsg += sNameAdministrator;
        sMsg += _T("\"\n");
        if(!bIPExist)
        {
            sMsg += _T("IP-адрес первичного контролера домена не найден в списке публичных адресов или список адресов пуст!");
            oRTSDDMessageBox.m_sMessageText = sMsg;
            nDialogRet = oRTSDDMessageBox.DoModal();
            hr = spPublicIPElement2->focus();
            hr = spInputText->select();
            return S_OK;
        }
    }
    DnsRecordListFree(
        pQueryResultsSet,
        DnsFreeRecordList
        );
    hr = GetElement(
        _T("public_ip"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_ip_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR)spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = _T("Поле публичного IPv4-адреса не должно быть пустым!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата IPv4-адреса!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nSingleIP++;
        }
    }
    hr = GetElement(
        _T("range_begin"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_range_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR)spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = _T("Поле начального значения диапазона публичных IPv4-адресов не должно быть пустым!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата начального значения диапазона публичных IPv4-адресов!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nhBeginAddress = ntohl(stIP4Address.S_un.S_addr);
            spDispatch = spCellChildrens->item(_variant_t(L"range_end"));
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR)spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = _T("Поле конечного значения диапазона публичных IPv4-адресов не должно быть пустым!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата конечного значения диапазона публичных IPv4-адресов!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nhEndAddress = ntohl(stIP4Address.S_un.S_addr);
            if(nhBeginAddress > nhEndAddress)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Значение начального адреса диапазона больше конечного!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            if(nhBeginAddress == nhEndAddress)
            {
                INT_PTR nDialogRet;
                CRTSDDMessageBox    oRTSDDMessageBox(this);
                oRTSDDMessageBox.m_sMessageText = _T("Значение начального адреса диапазона равно конечному, т.е задан единственный IPv4-адрес!");
                oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("WARNING_ICON.PNG");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
            }
            nRangeIP++;
        }
    }
    hr = GetElement(
        _T("subnet_address"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_subnet_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR)spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = _T("Поле адреса публичной IPv4-подсети не должно быть пустым!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата адреса публичной IPv4-подсети!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            spDispatch = spCellChildrens->item(_variant_t(L"subnet_mask"));
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR)spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = _T("Поле маски публичной IPv4-подсети не должно быть пустым!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата маски публичной IPv4-подсети!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nioStatus = ConvertIpv4MaskToLength(
                (ULONG) stIP4Address.S_un.S_addr,
                &nMaskLength
                );
            if (NO_ERROR != nioStatus)
            {
                oRTSDDMessageBox.m_sMessageText = L"Неверный формат маски публичной IPv4-подсети (нельзя преобразовать маску в длину префикса маски)!";
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nSubnetIP++;
        }
    }
    hr = GetElement(
        _T("ip6_prefix"),
        &spDispatch,
        &bCollection
        );
    if (bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for (i = 0; i < spHTMLElementCollection->length; i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if (spIHTMLElement->id == _bstr_t(L"public_ip6_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR) spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = L"Поле префикса публичной IPv6-подсети не должно быть пустым!";
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv6StringToAddress(
                sIPAddress,
                &pTerminator,
                &stIP6Address
                );
            if (NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата префикса публичной IPv6-подсети!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            spDispatch = spCellChildrens->item(_variant_t(L"prefix_length"));
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR) spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = L"Поле длины префикса публичной IPv6-подсети не должно быть пустым!";
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nPrefixLength = _tstol(sIPAddress);
            if ((nPrefixLength < 1) || (nPrefixLength > 128))
            {
                oRTSDDMessageBox.m_sMessageText = L"Длина префикса публичной IPv6-подсети должна быть в диапазоне от 1 до 128!";
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nPublicIPv6++;
        }
    }
    hr = GetElement(
        _T("private_ip"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"private_ip_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR)spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = _T("Поле публичного IPv4-адреса не должно быть пустым!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата публичного IPv4-адреса!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nSinglePrivateIP++;
        }
    }
    hr = GetElement(
        _T("private_range_begin"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"private_range_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR)spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = _T("Поле начального значения диапазона приватных IPv4-адресов не должно быть пустым!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата начального значения диапазона приватных IPv4-адресов!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nhBeginAddress = ntohl(stIP4Address.S_un.S_addr);
            spDispatch = spCellChildrens->item(_variant_t(L"private_range_end"));
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR)spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = _T("Поле конечного значения диапазона приватных IPv4-адресов не должно быть пустым!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата конечного значения диапазона приватных IPv4-адресов!!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nhEndAddress = ntohl(stIP4Address.S_un.S_addr);
            if(nhBeginAddress > nhEndAddress)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Значение начального адреса диапазона больше конечного!!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            if(nhBeginAddress == nhEndAddress)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Значение начального адреса диапазона равно конечному, т.е задан единственный IP-адрес!");
                oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("WARNING_ICON.PNG");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
            }
            nRangePrivateIP++;
        }
    }
    hr = GetElement(
        _T("private_subnet_address"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"private_subnet_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR)spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = _T("Поле адреса приватной IPv4-подсети не должно быть пустым!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата адреса приватной IPv4-подсети!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            spDispatch = spCellChildrens->item(_variant_t(L"private_subnet_mask"));
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR)spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = _T("Поле маски приватной IPv4-подсети не должно быть пустым!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата маски приватной IPv4-подсети!!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nioStatus = ConvertIpv4MaskToLength(
                (ULONG) stIP4Address.S_un.S_addr,
                &nMaskLength
                );
            if (NO_ERROR != nioStatus)
            {
                oRTSDDMessageBox.m_sMessageText = L"Неверный формат маски приватной IPv4-подсети (нельзя преобразовать маску в длину префикса маски)!";
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nSubnetPrivateIP++;
        }
    }
    hr = GetElement(
        _T("ip6_private_prefix"),
        &spDispatch,
        &bCollection
        );
    if (bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for (i = 0; i < spHTMLElementCollection->length; i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if (spIHTMLElement->id == _bstr_t(L"privaite_ip6_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR) spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = L"Поле префикса приватной IPv6-подсети не должно быть пустым!";
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nRet = RtlIpv6StringToAddress(
                sIPAddress,
                &pTerminator,
                &stIP6Address
                );
            if (NO_ERROR != nRet)
            {
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата префикса приватной IPv6-подсети!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            spDispatch = spCellChildrens->item(_variant_t(L"prefix_private_length"));
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR) spInputText->value;
            if (sIPAddress.IsEmpty())
            {
                oRTSDDMessageBox.m_sMessageText = L"Поле длины префикса приватной IPv6-подсети не должно быть пустым!";
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nPrefixLength = _tstol(sIPAddress);
            if ((nPrefixLength < 1) || (nPrefixLength > 128))
            {
                oRTSDDMessageBox.m_sMessageText = L"Длина префикса приватной IPv6-подсети должна быть в диапазоне от 1 до 128!";
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return S_OK;
            }
            nPrivateIPv6++;
        }
    }
    bRet = WriteConfigString(
        _T("service_settings"),
        _T("dns_zone_name"),
        m_sDomainZoneName
        );
    bRet = WriteConfigString(
        _T("service_settings"),
        _T("pNamePrimaryServer"),
        sNamePrimaryServer
        );
    bRet = WriteConfigString(
        _T("service_settings"),
        _T("pNameAdministrator"),
        sNameAdministrator
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("dwSerialNo"),
        dwSerialNo
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("dwRefresh"),
        dwRefresh
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("dwRetry"),
        dwRetry
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("dwExpire"),
        dwExpire
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("dwDefaultTtl"),
        dwDefaultTtl
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("dwFlags"),
        dwFlags
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("dwTtl"),
        dwTtl
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("public_ip_count"),
        nSingleIP
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("public_range_count"),
        nRangeIP
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("public_subnet_count"),
        nSubnetIP
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("public_ip6_count"),
        nPublicIPv6
        );
    if (nSingleIP > 0)
    {
        nSingleIP = 0;
        hr = GetElement(
            _T("public_ip"),
            &spDispatch,
            &bCollection
            );
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_ip_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            sIPAddress = (LPCTSTR)spInputText->value;
            sSectionName.Format(
                _T("single_ip%d"),
                nSingleIP
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            nSingleIP++;
        }
    }
    if(nRangeIP > 0)
    {
        nRangeIP = 0;
        hr = GetElement(
            _T("range_begin"),
            &spDispatch,
            &bCollection
            );
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_range_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR)spInputText->value;
            sSectionName.Format(
                _T("range_begin_ip%d"),
                nRangeIP
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            spDispatch = spCellChildrens->item(_variant_t(L"range_end"));
            hr = spDispatch->QueryInterface(&spInputText);
            sIPAddress = (LPCTSTR)spInputText->value;
            sSectionName.Format(
                _T("range_end_ip%d"),
                nRangeIP
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            nRangeIP++;
        }
    }
    if(nSubnetIP > 0)
    {
        nSubnetIP = 0;
        hr = GetElement(
            _T("subnet_address"),
            &spDispatch,
            &bCollection
            );
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_subnet_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR)spInputText->value;
            sSectionName.Format(
                _T("subnet_address_ip%d"),
                nSubnetIP
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            spDispatch = spCellChildrens->item(_variant_t(L"subnet_mask"));
            hr = spDispatch->QueryInterface(&spInputText);
            sIPAddress = (LPCTSTR)spInputText->value;
            sSectionName.Format(
                _T("subnet_mask_ip%d"),
                nSubnetIP
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            nSubnetIP++;
        }
    }
    if (nPublicIPv6 > 0)
    {
        nPublicIPv6 = 0;
        hr = GetElement(
            _T("ip6_prefix"),
            &spDispatch,
            &bCollection
            );
        ASSERT(bCollection);
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for (i = 0; i<spHTMLElementCollection->length; i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if (spIHTMLElement->id == _bstr_t(L"public_ip6_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR) spInputText->value;
            sSectionName.Format(
                _T("public_ip6_prefix%d"),
                nPublicIPv6
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            spDispatch = spCellChildrens->item(_variant_t(L"prefix_length"));
            hr = spDispatch->QueryInterface(&spInputText);
            sIPAddress = (LPCTSTR) spInputText->value;
            nPrefixLength = _tstol(sIPAddress);
            sSectionName.Format(
                _T("public_ip6_prefix_length%d"),
                nPublicIPv6
                );
            bRet = WriteConfigInt(
                _T("service_settings"),
                sSectionName,
                nPrefixLength
                );
            nPublicIPv6++;
        }
    }
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("private_ip_count"),
        nSinglePrivateIP
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("private_range_count"),
        nRangePrivateIP
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("private_subnet_count"),
        nSubnetPrivateIP
        );
    bRet = WriteConfigInt(
        _T("service_settings"),
        _T("private_ip6_count"),
        nPrivateIPv6
        );
    if (nSinglePrivateIP > 0)
    {
        nSinglePrivateIP = 0;
        hr = GetElement(
            _T("private_ip"),
            &spDispatch,
            &bCollection
            );
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"private_ip_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            sIPAddress = (LPCTSTR)spInputText->value;
            sSectionName.Format(
                _T("private_ip%d"),
                nSinglePrivateIP
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            nSinglePrivateIP++;
        }
    }
    if(nRangePrivateIP > 0)
    {
        nRangePrivateIP = 0;
        hr = GetElement(
            _T("private_range_begin"),
            &spDispatch,
            &bCollection
            );
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"private_range_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR)spInputText->value;
            sSectionName.Format(
                _T("private_range_begin%d"),
                nRangePrivateIP
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            spDispatch = spCellChildrens->item(_variant_t(L"private_range_end"));
            hr = spDispatch->QueryInterface(&spInputText);
            sIPAddress = (LPCTSTR)spInputText->value;
            sSectionName.Format(
                _T("private_range_end%d"),
                nRangePrivateIP
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            nRangePrivateIP++;
        }
    }
    if(nSubnetPrivateIP > 0)
    {
        nSubnetPrivateIP = 0;
        hr = GetElement(
            _T("private_subnet_address"),
            &spDispatch,
            &bCollection
            );
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"private_subnet_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR)spInputText->value;
            sSectionName.Format(
                _T("private_subnet_address%d"),
                nSubnetPrivateIP
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            spDispatch = spCellChildrens->item(_variant_t(L"private_subnet_mask"));
            hr = spDispatch->QueryInterface(&spInputText);
            sIPAddress = (LPCTSTR)spInputText->value;
            sSectionName.Format(
                _T("private_subnet_mask%d"),
                nSubnetPrivateIP
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            nSubnetPrivateIP++;
        }
    }
    if (nPrivateIPv6 > 0)
    {
        nPrivateIPv6 = 0;
        hr = GetElement(
            _T("ip6_private_prefix"),
            &spDispatch,
            &bCollection
            );
        ASSERT(bCollection);
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for (i = 0; i<spHTMLElementCollection->length; i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if (spIHTMLElement->id == _bstr_t(L"privaite_ip6_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR) spInputText->value;
            sSectionName.Format(
                _T("private_ip6_prefix%d"),
                nPrivateIPv6
                );
            bRet = WriteConfigString(
                _T("service_settings"),
                sSectionName,
                sIPAddress
                );
            spDispatch = spCellChildrens->item(_variant_t(L"prefix_private_length"));
            hr = spDispatch->QueryInterface(&spInputText);
            sIPAddress = (LPCTSTR) spInputText->value;
            nPrefixLength = _tstol(sIPAddress);
            sSectionName.Format(
                _T("private_ip6_prefix_length%d"),
                nPrivateIPv6
                );
            bRet = WriteConfigInt(
                _T("service_settings"),
                sSectionName,
                nPrefixLength
                );
            nPrivateIPv6++;
        }
    }
    return S_OK;
}
#pragma warning(pop)


void CPublicDNSPluginConfigDlg::OnDocumentComplete(LPDISPATCH pDisp, LPCTSTR szUrl)
{
    HRESULT hr;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTableRowPtr            spPublicIPTemplateRow;
    long                                nRowIndex;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    _bstr_t                             sCellHTML;
    MSHTML::IHTMLTableRowPtr            spNewRow;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLStylePtr               spStyle;
    MSHTML::IHTMLTableCellPtr           spNewCell;
    int i, nSingleIP = 0, nRangeIP = 0, nSubnetIP = 0, nPublicIPv6 = 0;
    int nSinglePrivateIP = 0, nRangePrivateIP = 0, nSubnetPrivateIP = 0, nPrivateIPv6 = 0;
    CString                             sSectionName;
    CString                             sIPAddress;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    SC_HANDLE                           schSCManager;
    SC_HANDLE                           schService;
    DWORD                               nErrorCode;
    BOOL                                bRet;
    MSHTML::IHTMLButtonElementPtr       spHTMLButtonElement;
    UINT32                              nPrefixLength;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    CRegKey                             oDnsDbgKey;
    LONG                                nRet;
    bool                                bValidRegistry;
    TCHAR                               szValueString [MAX_PATH];
    ULONG                               ulChars;
    CDHtmlDialog::OnDocumentComplete(pDisp, szUrl);
    if(m_bHTMLInit)
    {
        return;
    }
    hr = GetElement(
        _T("setup_button"),
        (IHTMLElement**) &spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
    schSCManager = OpenSCManager(
        NULL,                 // local machine
        NULL,                 // ServicesActive database
        SC_MANAGER_ALL_ACCESS // full access rights
        );
    if(NULL == schSCManager)
    {
        INT_PTR nDialogRet;
        nErrorCode = ::GetLastError();
        CRTSDDMessageBox    oRTSDDMessageBox(this);
        oRTSDDMessageBox.m_sMessageText.Format(
            _T("\"OpenSCManager\" failed. Error code = %d"),
            nErrorCode
            );
        nDialogRet = oRTSDDMessageBox.DoModal();
        return;
    }
    schService = OpenService(
        schSCManager,
        _T("DNS"),
        SERVICE_ALL_ACCESS
        );
    if (NULL == schService)
    {
        nErrorCode = ::GetLastError();
        bRet = CloseServiceHandle(schSCManager);
        if (ERROR_SERVICE_DOES_NOT_EXIST != nErrorCode)
        {
            oRTSDDMessageBox.m_sMessageText.Format(
                _T("OpenService failed. Error code = %d"),
                nErrorCode
                );
        }
        else
        {
            oRTSDDMessageBox.m_sMessageText = _T("The DNS server role is not installed.");
            spHTMLButtonElement->disabled = VARIANT_TRUE;
            m_sSetupImageSRC = _T("SETUP_HIDEN.GIF");
            hr = GetElement(
                _T("uninstall_button"),
                (IHTMLElement**) &spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
            spHTMLButtonElement->disabled = VARIANT_TRUE;
            m_sUninstallImageSRC = _T("UNINSTALL32_GRAY.PNG");
            hr = GetElement(
                _T("restart_button"),
                (IHTMLElement**) &spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
            spHTMLButtonElement->disabled = VARIANT_TRUE;
            m_sRestartImageSRC = _T("RESTARTHS_GRAY.PNG");
        }
        nDialogRet = oRTSDDMessageBox.DoModal();
        return;
    }
    bRet = CloseServiceHandle(schService);
    bRet = CloseServiceHandle(schSCManager);
    nRet = oDnsDbgKey.Open(
        HKEY_LOCAL_MACHINE,
        _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\dns.exe")
        );
    bValidRegistry = (ERROR_SUCCESS == nRet);
    if (bValidRegistry)
    {
        ulChars = MAX_PATH;
        nRet = oDnsDbgKey.QueryStringValue(
            _T("Debugger"),
            szValueString,
            &ulChars
            );
        bValidRegistry = (ERROR_SUCCESS == nRet);
    }
    if (bValidRegistry)
    {
        bValidRegistry = (theApp.m_sDnsLauncherFileName.MakeLower() == CString(szValueString).MakeLower());
    }
    if (!bValidRegistry)
    {
        spHTMLButtonElement->disabled = VARIANT_FALSE;
        m_sSetupImageSRC = _T("SETUP.GIF");
        hr = GetElement(
            _T("uninstall_button"),
            (IHTMLElement**)&spIHTMLElement
            );
        hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
        spHTMLButtonElement->disabled = VARIANT_TRUE;
        m_sUninstallImageSRC = _T("UNINSTALL32_GRAY.PNG");
        hr = GetElement(
            _T("restart_button"),
            (IHTMLElement**)&spIHTMLElement
            );
        hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
        spHTMLButtonElement->disabled = VARIANT_TRUE;
        m_sRestartImageSRC = _T("RESTARTHS_GRAY.PNG");
    }
    else
    {
        spHTMLButtonElement->disabled = VARIANT_TRUE;
        m_sSetupImageSRC = _T("SETUP_HIDEN.GIF");
        hr = GetElement(
            _T("uninstall_button"),
            (IHTMLElement**)&spIHTMLElement
            );
        hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
        spHTMLButtonElement->disabled = VARIANT_FALSE;
        m_sUninstallImageSRC = _T("UNINSTALL32.PNG");
        hr = GetElement(
            _T("restart_button"),
            (IHTMLElement**)&spIHTMLElement
            );
        hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
        spHTMLButtonElement->disabled = VARIANT_FALSE;
        m_sRestartImageSRC = _T("RESTARTHS.PNG");
    }
    bRet = UpdateData(FALSE);
	nSingleIP = GetConfigInt(
        _T("service_settings"),
        _T("public_ip_count"),
        0
        );
	nRangeIP = GetConfigInt(
        _T("service_settings"),
        _T("public_range_count"),
        0
        );
	nSubnetIP = GetConfigInt(
        _T("service_settings"),
        _T("public_subnet_count"),
        0
        );
    nPublicIPv6 = GetConfigInt(
        _T("service_settings"),
        _T("public_ip6_count"),
        0
        );
    hr = GetElement(
        _T("public_settings_table"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spSettingsTable);
    if(nSingleIP > 0)
    {
        for(i=0;i<nSingleIP;i++)
        {
            hr = GetElement(
                _T("public_ip_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("public_ip_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("public_ip_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_public_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_public_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"public_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("single_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_public_ip_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if(nRangeIP > 0)
    {
        for(i=0;i<nRangeIP;i++)
        {
            hr = GetElement(
                _T("public_range_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("public_range_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("public_range_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_public_range"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_public_range"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"range_begin"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("range_begin_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"range_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"range_end"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("range_end_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_public_range_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if(nSubnetIP > 0)
    {
        for(i=0;i<nSubnetIP;i++)
        {
            hr = GetElement(
                _T("public_subnet_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("public_subnet_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("public_subnet_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_public_subnet"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_public_subnet"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"subnet_address"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("subnet_address_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"subnet_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"subnet_mask"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("subnet_mask_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_public_subnet_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if (nPublicIPv6 > 0)
    {
        for (i = 0; i<nPublicIPv6; i++)
        {
            hr = GetElement(
                _T("public_ip6_row_template"),
                (IHTMLElement**) &spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("public_ip6_description"),
                (IHTMLElement**) &spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("public_ip6_cell"),
                (IHTMLElement**) &spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_public_ip6"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_public_ip6"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"ip6_prefix"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("public_ip6_prefix%d"),
                i
                );
            sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR) sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"ip6_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"prefix_length"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("public_ip6_prefix_length%d"),
                i
                );
            nPrefixLength = GetConfigInt(
                _T("service_settings"),
                sSectionName,
                0
                );
            spInputText->value = _bstr_t(_variant_t(nPrefixLength));
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_public_ip6_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    nSinglePrivateIP = GetConfigInt(
        _T("service_settings"),
        _T("private_ip_count"),
        0
        );
	nRangePrivateIP = GetConfigInt(
        _T("service_settings"),
        _T("private_range_count"),
        0
        );
	nSubnetPrivateIP = GetConfigInt(
        _T("service_settings"),
        _T("private_subnet_count"),
        0
        );
    nPrivateIPv6 = GetConfigInt(
        _T("service_settings"),
        _T("private_ip6_count"),
        0
        );
    hr = GetElement(
        _T("private_settings_table"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spSettingsTable);
    if(nSinglePrivateIP > 0)
    {
        for(i=0;i<nSinglePrivateIP;i++)
        {
            hr = GetElement(
                _T("private_ip_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("private_ip_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("private_ip_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_private_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_private_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_private_ip_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if(nRangePrivateIP > 0)
    {
        for(i=0;i<nRangePrivateIP;i++)
        {
            hr = GetElement(
                _T("private_range_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("private_range_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("private_range_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_private_range"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_private_range"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_range_begin"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_range_begin%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_range_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_range_end"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_range_end%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_private_range_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if(nSubnetPrivateIP > 0)
    {
        for(i=0;i<nSubnetPrivateIP;i++)
        {
            hr = GetElement(
                _T("private_subnet_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("private_subnet_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("private_subnet_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_private_subnet"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_private_subnet"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_subnet_address"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_subnet_address%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_subnet_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_subnet_mask"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_subnet_mask%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_private_subnet_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if (nPrivateIPv6 > 0)
    {
        for (i = 0; i<nPrivateIPv6; i++)
        {
            hr = GetElement(
                _T("privaite_ip6_row_template"),
                (IHTMLElement**) &spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("privaite_ip6_description"),
                (IHTMLElement**) &spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("privaite_ip6_cell"),
                (IHTMLElement**) &spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_privaite_ip6"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_private_ip6"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"ip6_private_prefix"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_ip6_prefix%d"),
                i
                );
            sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR) sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"ip6_private_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"prefix_private_length"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_ip6_prefix_length%d"),
                i
                );
            nPrefixLength = GetConfigInt(
                _T("service_settings"),
                sSectionName,
                0
                );
            spInputText->value = _bstr_t(_variant_t(nPrefixLength));
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_private_ip6_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    m_bHTMLInit = true;
}


HRESULT CPublicDNSPluginConfigDlg::ReloadParameters(IHTMLElement* pElement)
{
    HRESULT hr;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTableRowPtr            spPublicIPTemplateRow;
    long                                nRowIndex;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    _bstr_t                             sCellHTML;
    MSHTML::IHTMLTableRowPtr            spNewRow;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLStylePtr               spStyle;
    MSHTML::IHTMLTableCellPtr           spNewCell;
    int i, nSingleIP = 0, nRangeIP = 0, nSubnetIP = 0, nPublicIPv6 = 0;
    int nSinglePrivateIP = 0, nRangePrivateIP = 0, nSubnetPrivateIP = 0, nPrivateIPv6 = 0;
    CString                             sSectionName;
    CString                             sIPAddress;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    BOOL                                bCollection;
    BOOL                                bRet;
    SC_HANDLE                           schSCManager;
    SC_HANDLE                           schService;
    DWORD                               nErrorCode;
    MSHTML::IHTMLButtonElementPtr       spHTMLButtonElement;
    UINT32                              nPrefixLength;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    LONG                                nRet;
    CRegKey                             oDnsDbgKey;
    bool                                bValidRegistry;
    TCHAR                               szValueString[MAX_PATH];
    ULONG                               ulChars;
    UNREFERENCED_PARAMETER(pElement);
    hr = GetElement(
        _T("public_settings_table"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spSettingsTable);
    hr = GetElement(
        _T("public_ip"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=spHTMLElementCollection->length-1;i>=0;i--)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_ip_cell"))
            {
                continue;
            }
            spIHTMLElement = spIHTMLElement->parentElement;
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            hr = spSettingsTable->deleteRow(nRowIndex);
        }
    }
    hr = GetElement(
        _T("range_begin"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=spHTMLElementCollection->length-1;i>=0;i--)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_range_cell"))
            {
                continue;
            }
            spIHTMLElement = spIHTMLElement->parentElement;
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            hr = spSettingsTable->deleteRow(nRowIndex);
        }
    }
    hr = GetElement(
        _T("subnet_address"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=spHTMLElementCollection->length-1;i>=0;i--)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_subnet_cell"))
            {
                continue;
            }
            spIHTMLElement = spIHTMLElement->parentElement;
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            hr = spSettingsTable->deleteRow(nRowIndex);
        }
    }
    hr = GetElement(
        _T("ip6_prefix"),
        &spDispatch,
        &bCollection
        );
    if (bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for (i = spHTMLElementCollection->length - 1; i >= 0; i--)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if (spIHTMLElement->id == _bstr_t(L"public_ip6_cell"))
            {
                continue;
            }
            spIHTMLElement = spIHTMLElement->parentElement;
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            hr = spSettingsTable->deleteRow(nRowIndex);
        }
    }
    hr = GetElement(
        _T("private_settings_table"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spSettingsTable);
    hr = GetElement(
        _T("private_ip"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=spHTMLElementCollection->length-1;i>=0;i--)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"private_ip_cell"))
            {
                continue;
            }
            spIHTMLElement = spIHTMLElement->parentElement;
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            hr = spSettingsTable->deleteRow(nRowIndex);
        }
    }
    hr = GetElement(
        _T("private_range_begin"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=spHTMLElementCollection->length-1;i>=0;i--)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"private_range_cell"))
            {
                continue;
            }
            spIHTMLElement = spIHTMLElement->parentElement;
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            hr = spSettingsTable->deleteRow(nRowIndex);
        }
    }
    hr = GetElement(
        _T("private_subnet_address"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=spHTMLElementCollection->length-1;i>=0;i--)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"private_subnet_cell"))
            {
                continue;
            }
            spIHTMLElement = spIHTMLElement->parentElement;
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            hr = spSettingsTable->deleteRow(nRowIndex);
        }
    }
    hr = GetElement(
        _T("ip6_private_prefix"),
        &spDispatch,
        &bCollection
        );
    if (bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for (i = spHTMLElementCollection->length - 1; i >= 0; i--)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if (spIHTMLElement->id == _bstr_t(L"privaite_ip6_cell"))
            {
                continue;
            }
            spIHTMLElement = spIHTMLElement->parentElement;
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            hr = spSettingsTable->deleteRow(nRowIndex);
        }
    }
    m_sDomainZoneName = GetConfigString(
        _T("service_settings"),
        _T("dns_zone_name"),
        _T("")
        );
    schSCManager = OpenSCManager(
        NULL,                 // local machine
        NULL,                 // ServicesActive database
        SC_MANAGER_ALL_ACCESS // full access rights
        );
    if(NULL == schSCManager)
    {
        nErrorCode = ::GetLastError();
        oRTSDDMessageBox.m_sMessageText.Format(
            _T("\"OpenSCManager\" failed. Error code = %d"),
            nErrorCode
            );
        nDialogRet = oRTSDDMessageBox.DoModal();
        return S_OK;
    }
    hr = GetElement(
        _T("setup_button"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
    schService = OpenService(
        schSCManager,
        _T("DNS"),
        SERVICE_ALL_ACCESS
        );
    if (NULL == schService)
    {
        nErrorCode = ::GetLastError();
        bRet = CloseServiceHandle(schSCManager);
        if (ERROR_SERVICE_DOES_NOT_EXIST != nErrorCode)
        {
            oRTSDDMessageBox.m_sMessageText.Format(
                _T("OpenService failed. Error code = %d"),
                nErrorCode
                );
        }
        else
        {
            oRTSDDMessageBox.m_sMessageText = _T("The DNS server role is not installed.");
            spHTMLButtonElement->disabled = VARIANT_TRUE;
            m_sSetupImageSRC = _T("SETUP_HIDEN.GIF");
            hr = GetElement(
                _T("uninstall_button"),
                (IHTMLElement**) &spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
            spHTMLButtonElement->disabled = VARIANT_TRUE;
            m_sUninstallImageSRC = _T("UNINSTALL32_GRAY.PNG");
            hr = GetElement(
                _T("restart_button"),
                (IHTMLElement**) &spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
            spHTMLButtonElement->disabled = VARIANT_TRUE;
            m_sRestartImageSRC = _T("RESTARTHS_GRAY.PNG");
        }
        nDialogRet = oRTSDDMessageBox.DoModal();
        return S_OK;
    }
    bRet = CloseServiceHandle(schService);
    bRet = CloseServiceHandle(schSCManager);
    nRet = oDnsDbgKey.Open(
        HKEY_LOCAL_MACHINE,
        _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\dns.exe")
        );
    bValidRegistry = (ERROR_SUCCESS == nRet);
    if (bValidRegistry)
    {
        nRet = oDnsDbgKey.QueryStringValue(
            _T("Debugger"),
            szValueString,
            &ulChars
            );
        bValidRegistry = (ERROR_SUCCESS == nRet);
    }
    if (bValidRegistry)
    {
        bValidRegistry = (theApp.m_sDnsLauncherFileName == szValueString);
    }
    if (!bValidRegistry)
    {
        spHTMLButtonElement->disabled = VARIANT_FALSE;
        m_sSetupImageSRC = _T("SETUP.GIF");
        hr = GetElement(
            _T("uninstall_button"),
            (IHTMLElement**) &spIHTMLElement
            );
        hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
        spHTMLButtonElement->disabled = VARIANT_TRUE;
        m_sUninstallImageSRC = _T("UNINSTALL32_GRAY.PNG");
        hr = GetElement(
            _T("restart_button"),
            (IHTMLElement**) &spIHTMLElement
            );
        hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
        spHTMLButtonElement->disabled = VARIANT_TRUE;
        m_sRestartImageSRC = _T("RESTARTHS_GRAY.PNG");
    }
    else
    {
        spHTMLButtonElement->disabled = VARIANT_TRUE;
        m_sSetupImageSRC = _T("SETUP_HIDEN.GIF");
        hr = GetElement(
            _T("uninstall_button"),
            (IHTMLElement**) &spIHTMLElement
            );
        hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
        spHTMLButtonElement->disabled = VARIANT_FALSE;
        m_sUninstallImageSRC = _T("UNINSTALL32.PNG");
        hr = GetElement(
            _T("restart_button"),
            (IHTMLElement**) &spIHTMLElement
            );
        hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
        spHTMLButtonElement->disabled = VARIANT_FALSE;
        m_sRestartImageSRC = _T("RESTARTHS.PNG");
    }
    bRet = UpdateData(FALSE);
	nSingleIP = GetConfigInt(
        _T("service_settings"),
        _T("public_ip_count"),
        0
        );
	nRangeIP = GetConfigInt(
        _T("service_settings"),
        _T("public_range_count"),
        0
        );
	nSubnetIP = GetConfigInt(
        _T("service_settings"),
        _T("public_subnet_count"),
        0
        );
    nPublicIPv6 = GetConfigInt(
        _T("service_settings"),
        _T("public_ip6_count"),
        0
        );
    hr = GetElement(
        _T("public_settings_table"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spSettingsTable);
    if(nSingleIP > 0)
    {
        for(i=0;i<nSingleIP;i++)
        {
            hr = GetElement(
                _T("public_ip_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("public_ip_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("public_ip_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_public_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_public_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"public_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("single_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_public_ip_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if(nRangeIP > 0)
    {
        for(i=0;i<nRangeIP;i++)
        {
            hr = GetElement(
                _T("public_range_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("public_range_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("public_range_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_public_range"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_public_range"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"range_begin"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("range_begin_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"range_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"range_end"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("range_end_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_public_range_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if(nSubnetIP > 0)
    {
        for(i=0;i<nSubnetIP;i++)
        {
            hr = GetElement(
                _T("public_subnet_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("public_subnet_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("public_subnet_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_public_subnet"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_public_subnet"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"subnet_address"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("subnet_address_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"subnet_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"subnet_mask"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("subnet_mask_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_public_subnet_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if (nPublicIPv6 > 0)
    {
        for (i = 0; i<nPublicIPv6; i++)
        {
            hr = GetElement(
                _T("public_ip6_row_template"),
                (IHTMLElement**) &spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("public_ip6_description"),
                (IHTMLElement**) &spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("public_ip6_cell"),
                (IHTMLElement**) &spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_public_ip6"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_public_ip6"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"ip6_prefix"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("public_ip6_prefix%d"),
                i
                );
            sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR) sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"ip6_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"prefix_length"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("public_ip6_prefix_length%d"),
                i
                );
            nPrefixLength = GetConfigInt(
                _T("service_settings"),
                sSectionName,
                0
                );
            spInputText->value = _bstr_t(_variant_t(nPrefixLength));
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_public_ip6_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    nSinglePrivateIP = GetConfigInt(
        _T("service_settings"),
        _T("private_ip_count"),
        0
        );
	nRangePrivateIP = GetConfigInt(
        _T("service_settings"),
        _T("private_range_count"),
        0
        );
	nSubnetPrivateIP = GetConfigInt(
        _T("service_settings"),
        _T("private_subnet_count"),
        0
        );
    nPrivateIPv6 = GetConfigInt(
        _T("service_settings"),
        _T("private_ip6_count"),
        0
        );
    hr = GetElement(
        _T("private_settings_table"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spSettingsTable);
    if(nSinglePrivateIP > 0)
    {
        for(i=0;i<nSinglePrivateIP;i++)
        {
            hr = GetElement(
                _T("private_ip_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("private_ip_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("private_ip_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_private_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_private_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_ip"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_ip%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_private_ip_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if(nRangePrivateIP > 0)
    {
        for(i=0;i<nRangePrivateIP;i++)
        {
            hr = GetElement(
                _T("private_range_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("private_range_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("private_range_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_private_range"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_private_range"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_range_begin"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_range_begin%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_range_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_range_end"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_range_end%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_private_range_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if(nSubnetPrivateIP > 0)
    {
        for(i=0;i<nSubnetPrivateIP;i++)
        {
            hr = GetElement(
                _T("private_subnet_row_template"),
                (IHTMLElement**)&spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("private_subnet_description"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("private_subnet_cell"),
                (IHTMLElement**)&spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_private_subnet"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_private_subnet"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_subnet_address"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_subnet_address%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_subnet_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"private_subnet_mask"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_subnet_mask%d"),
                i
                );
	        sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR)sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_private_subnet_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    if (nPrivateIPv6 > 0)
    {
        for (i = 0; i<nPrivateIPv6; i++)
        {
            hr = GetElement(
                _T("privaite_ip6_row_template"),
                (IHTMLElement**) &spIHTMLElement
                );
            hr = spIHTMLElement->QueryInterface(&spPublicIPTemplateRow);
            nRowIndex = spPublicIPTemplateRow->rowIndex;
            spDispatch = spSettingsTable->insertRow(nRowIndex);
            hr = spDispatch->QueryInterface(&spNewRow);
            hr = GetElement(
                _T("privaite_ip6_description"),
                (IHTMLElement**) &spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spNewCell);
            spNewCell->align = _bstr_t(L"right");
            spNewCell->width = _variant_t(L"45%");
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            hr = GetElement(
                _T("privaite_ip6_cell"),
                (IHTMLElement**) &spIHTMLElement
                );
            sCellHTML = spIHTMLElement->innerHTML;
            spDispatch = spNewRow->insertCell(-1);
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement->innerHTML = sCellHTML;
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spHTMLElementCollection);
            spDispatch = spHTMLElementCollection->item(_variant_t(L"insert_privaite_ip6"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"none");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"delete_private_ip6"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"ip6_private_prefix"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_ip6_prefix%d"),
                i
                );
            sIPAddress = GetConfigString(
                _T("service_settings"),
                sSectionName,
                _T("")
                );
            spInputText->value = _bstr_t((LPCTSTR) sIPAddress);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"ip6_private_symbol"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"prefix_private_length"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            hr = spDispatch->QueryInterface(&spInputText);
            sSectionName.Format(
                _T("private_ip6_prefix_length%d"),
                i
                );
            nPrefixLength = GetConfigInt(
                _T("service_settings"),
                sSectionName,
                0
                );
            spInputText->value = _bstr_t(_variant_t(nPrefixLength));
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
            spDispatch = spHTMLElementCollection->item(_variant_t(L"test_private_ip6_button"));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spStyle = spIHTMLElement->style;
            spStyle->display = _bstr_t(L"inline");
        }
    }
    return S_OK;
}


HRESULT CPublicDNSPluginConfigDlg::OnUninstallClick(IHTMLElement* pElement)
{
    HRESULT hr;
    SC_HANDLE                       schSCManager;
    SC_HANDLE                       schService;
    DWORD                           nErrorCode;
    BOOL                            bRet;
    MSHTML::IHTMLElementPtr         spIHTMLElement;
    MSHTML::IHTMLButtonElementPtr   spHTMLButtonElement;
    SERVICE_STATUS                  stServiceStatus;
    INT_PTR                         nDialogRet;
    CRTSDDMessageBox                oRTSDDMessageBox(this);
    CRegKey                         oDnsDbgKey;
    LONG                            nRet;
    bool                            bValidRegistry;
    SERVICE_STATUS_PROCESS          stServiceProcessStatus;
    DWORD                           cbBytesNeeded, dwStopCount = 0;
    CWaitThread*                    pWaitThread = NULL;
    DWORD                           dwWaitCode;
    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_PLUGIN_CONFIG_DLG, "%!FUNC! line:%!LINE! %!LEVEL! Enter");
    spHTMLButtonElement = pElement;
    if (spHTMLButtonElement->disabled)
    {
        return S_OK;
    }
    // удаление службы фильтрации адресов DNS-сервера
    nRet = oDnsDbgKey.Open(
        HKEY_LOCAL_MACHINE,
        _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\dns.exe")
        );
    bValidRegistry = (ERROR_SUCCESS == nRet);
    ASSERT(bValidRegistry);
    nRet = oDnsDbgKey.DeleteValue(
        _T("Debugger")
        );
    bValidRegistry = (ERROR_SUCCESS == nRet);
    ASSERT(bValidRegistry);
    schSCManager = OpenSCManager(
        NULL,                 // local machine
        NULL,                 // ServicesActive database
        SC_MANAGER_ALL_ACCESS // full access rights
        );
    ASSERT(NULL != schSCManager);
    schService = OpenService(
        schSCManager,
        _T("DNS"),
        SERVICE_ALL_ACCESS
        );
    ASSERT(NULL != schService);
    bRet = CloseServiceHandle(schSCManager);
    for (dwStopCount = 0; dwStopCount < 120; dwStopCount++)
    {
        RtlZeroMemory(
            &stServiceProcessStatus,
            sizeof(stServiceProcessStatus)
            );
        RtlZeroMemory(
            &stServiceStatus,
            sizeof(stServiceStatus)
            );
        bRet = QueryServiceStatusEx(
            schService,
            SC_STATUS_PROCESS_INFO,
            (LPBYTE) &stServiceProcessStatus,
            sizeof(stServiceProcessStatus),
            &cbBytesNeeded
            );
        if (SERVICE_RUNNING == stServiceProcessStatus.dwCurrentState)
        {
            TraceEvents(
                TRACE_LEVEL_INFORMATION,
                TRACE_PLUGIN_CONFIG_DLG,
                "%!FUNC! line:%!LINE! %!LEVEL! Service \"DNS\" will be stoped."
                );
            if (0 == dwStopCount)
            {
                pWaitThread = new CWaitThread(
                    _T("Завершение служвы фильтрации адресов DNS-сервера может занять несколько минут!"),
                    this
                    );
                bRet = pWaitThread->CreateThread();
                ASSERT(bRet);
                bRet = ControlService(
                    schService,
                    SERVICE_CONTROL_STOP,
                    &stServiceStatus
                    );
                if (!bRet)
                {
                    nErrorCode = ::GetLastError();
                    TraceEvents(
                        TRACE_LEVEL_ERROR,
                        TRACE_PLUGIN_CONFIG_DLG,
                        "%!FUNC! line:%!LINE! %!LEVEL! Call \"ControlService\" failed with error:  %!WINERROR!",
                        nErrorCode
                        );
                    ASSERT(bRet);
                    bRet = pWaitThread->PostThreadMessage(
                        WM_QUIT,
                        0,
                        0
                        );
                    pWaitThread = NULL;
                    break;
                }
            }
            dwWaitCode = SleepEx(1000, TRUE);
        }
        else
        {
            if (NULL != pWaitThread)
            {
                bRet = pWaitThread->PostThreadMessage(
                    WM_QUIT,
                    0,
                    0
                    );
                pWaitThread = NULL;
            }
            break;
        }
    }
    if (dwStopCount >= 120)
    {
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_PLUGIN_CONFIG_DLG,
            "%!FUNC! line:%!LINE! %!LEVEL! Stop service command limit exceeded."
            );
        bRet = pWaitThread->PostThreadMessage(
            WM_QUIT,
            0,
            0
            );
        pWaitThread = NULL;
        ASSERT(false);
    }
    bRet = StartService(
        schService,
        0,
        NULL
        );
    if (!bRet)
    {
        nErrorCode = GetLastError();
        ASSERT(bRet);
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_PLUGIN_CONFIG_DLG,
            "%!FUNC! line:%!LINE! %!LEVEL! Call \"StartService\" failed with error code = %!WINERROR!",
            nErrorCode
            );
    }
    bRet = CloseServiceHandle(schService);
    oRTSDDMessageBox.m_sMessageText = _T("Служба фильтрации адресов DNS-сервера успешно удалёна.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    hr = GetElement(
        _T("setup_button"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
    spHTMLButtonElement->disabled = VARIANT_FALSE;
    m_sSetupImageSRC = _T("SETUP.GIF");
    hr = GetElement(
        _T("uninstall_button"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
    spHTMLButtonElement->disabled = VARIANT_TRUE;
    m_sUninstallImageSRC = _T("UNINSTALL32_GRAY.PNG");
    hr = GetElement(
        _T("restart_button"),
        (IHTMLElement**)&spIHTMLElement
        );
    hr = spIHTMLElement->QueryInterface(&spHTMLButtonElement);
    spHTMLButtonElement->disabled = VARIANT_TRUE;
    m_sRestartImageSRC = _T("RESTARTHS_GRAY.PNG");
    bRet = UpdateData(FALSE);
    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_PLUGIN_CONFIG_DLG, "%!FUNC! line:%!LINE! %!LEVEL! Exit");
    return S_OK;
}


HRESULT CPublicDNSPluginConfigDlg::OnRestartClick(IHTMLElement* pElement)
{
    SC_HANDLE                       schSCManager;
    SC_HANDLE                       schService;
    DWORD                           nErrorCode;
    BOOL                            bRet;
    MSHTML::IHTMLButtonElementPtr   spHTMLButtonElement;
    SERVICE_STATUS                  stServiceStatus;
    INT_PTR                         nDialogRet;
    CRTSDDMessageBox                oRTSDDMessageBox(this);
    SERVICE_STATUS_PROCESS          stServiceProcessStatus;
    DWORD                           cbBytesNeeded, dwStopCount = 0;
    CWaitThread*                    pWaitThread = NULL;
    DWORD                           dwWaitCode;
    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_PLUGIN_CONFIG_DLG, "%!FUNC! line:%!LINE! %!LEVEL! Enter");
    spHTMLButtonElement = pElement;
    if (spHTMLButtonElement->disabled)
    {
        return S_OK;
    }
    // перезапуск службы фильтрации адресов DNS-сервера (вообщето просто перезапуск DNS-сервера)
    schSCManager = OpenSCManager(
        NULL,                 // local machine
        NULL,                 // ServicesActive database
        SC_MANAGER_ALL_ACCESS // full access rights
        );
    ASSERT(NULL != schSCManager);
    schService = OpenService(
        schSCManager,
        _T("DNS"),
        SERVICE_ALL_ACCESS
        );
    ASSERT(NULL != schService);
    bRet = CloseServiceHandle(schSCManager);
    for (dwStopCount = 0; dwStopCount < 120; dwStopCount++)
    {
        RtlZeroMemory(
            &stServiceProcessStatus,
            sizeof(stServiceProcessStatus)
            );
        RtlZeroMemory(
            &stServiceStatus,
            sizeof(stServiceStatus)
            );
        bRet = QueryServiceStatusEx(
            schService,
            SC_STATUS_PROCESS_INFO,
            (LPBYTE) &stServiceProcessStatus,
            sizeof(stServiceProcessStatus),
            &cbBytesNeeded
            );
        if (SERVICE_RUNNING == stServiceProcessStatus.dwCurrentState)
        {
            TraceEvents(
                TRACE_LEVEL_INFORMATION,
                TRACE_PLUGIN_CONFIG_DLG,
                "%!FUNC! line:%!LINE! %!LEVEL! Service \"DNS\" will be stoped."
                );
            if (0 == dwStopCount)
            {
                pWaitThread = new CWaitThread(
                    _T("Завершение служвы фильтрации адресов DNS-сервера может занять несколько минут!"),
                    this
                    );
                bRet = pWaitThread->CreateThread();
                ASSERT(bRet);
                bRet = ControlService(
                    schService,
                    SERVICE_CONTROL_STOP,
                    &stServiceStatus
                    );
                if (!bRet)
                {
                    nErrorCode = ::GetLastError();
                    TraceEvents(
                        TRACE_LEVEL_ERROR,
                        TRACE_PLUGIN_CONFIG_DLG,
                        "%!FUNC! line:%!LINE! %!LEVEL! Call \"ControlService\" failed with error:  %!WINERROR!",
                        nErrorCode
                        );
                    //ASSERT(bRet);
                    bRet = pWaitThread->PostThreadMessage(
                        WM_QUIT,
                        0,
                        0
                        );
                    pWaitThread = NULL;
                    break;
                }
            }
            dwWaitCode = SleepEx(1000, TRUE);
        }
        else
        {
            if (NULL != pWaitThread)
            {
                bRet = pWaitThread->PostThreadMessage(
                    WM_QUIT,
                    0,
                    0
                    );
                pWaitThread = NULL;
            }
            break;
        }
    }
    if (dwStopCount >= 120)
    {
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_PLUGIN_CONFIG_DLG,
            "%!FUNC! line:%!LINE! %!LEVEL! Stop service command limit exceeded."
            );
        bRet = pWaitThread->PostThreadMessage(
            WM_QUIT,
            0,
            0
            );
        pWaitThread = NULL;
        ASSERT(false);
    }
    bRet = StartService(
        schService,
        0,
        NULL
        );
    if (!bRet)
    {
        nErrorCode = GetLastError();
        //ASSERT(bRet);
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_PLUGIN_CONFIG_DLG,
            "%!FUNC! line:%!LINE! %!LEVEL! Call \"StartService\" failed with error code = %!WINERROR!",
            nErrorCode
            );
    }
    bRet = CloseServiceHandle(schService);
    oRTSDDMessageBox.m_sMessageText = _T("Служба фильтрации адресов DNS-сервера перезапущена с текущими сохранёнными параметрами.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_PLUGIN_CONFIG_DLG, "%!FUNC! line:%!LINE! %!LEVEL! Exit");
    return S_OK;
}


bool CPublicDNSPluginConfigDlg::IsPublic(IP4_ADDRESS nIpAddress)
{
    HRESULT hr;
    IDispatchPtr                        spDispatch;
    BOOL                                bCollection = FALSE;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    int i, nSingleIP = 0, nRangeIP = 0, nSubnetIP = 0;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    MSHTML::IHTMLElement2Ptr            spPublicIPElement2;
    CString                             sIPAddress;
    LONG                                nRet;
    LPCTSTR                             pTerminator;
    IN_ADDR                             stIP4Address;
    MSHTML::IHTMLElementCollectionPtr   spCellChildrens;
    u_long                              nhBeginAddress, nhEndAddress, nhIpAddres;
    nhIpAddres = ntohl(nIpAddress);
    hr = GetElement(
        _T("public_ip"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_ip_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR)spInputText->value;
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                INT_PTR nDialogRet;
                CRTSDDMessageBox    oRTSDDMessageBox(this);
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата IP-адреса!!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return false;
            }
            if(nIpAddress == stIP4Address.S_un.S_addr)
            {
                return true;
            }
            nSingleIP++;
        }
    }
    hr = GetElement(
        _T("range_begin"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_range_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR)spInputText->value;
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                INT_PTR nDialogRet;
                CRTSDDMessageBox    oRTSDDMessageBox(this);
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата начального значения диапазона публичных IP-адресов!!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return false;
            }
            nhBeginAddress = ntohl(stIP4Address.S_un.S_addr);
            spDispatch = spCellChildrens->item(_variant_t(L"range_end"));
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR)spInputText->value;
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                INT_PTR nDialogRet;
                CRTSDDMessageBox    oRTSDDMessageBox(this);
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата конечного значения диапазона публичных IP-адресов!!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return false;
            }
            nhEndAddress = ntohl(stIP4Address.S_un.S_addr);
            if(nhBeginAddress > nhEndAddress)
            {
                INT_PTR nDialogRet;
                CRTSDDMessageBox    oRTSDDMessageBox(this);
                oRTSDDMessageBox.m_sMessageText = _T("Значение начального адреса диапазона больше конечного!!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return false;
            }
            if((nhIpAddres >= nhBeginAddress) && (nhIpAddres <= nhEndAddress))
            {
                return true;
            }
            nRangeIP++;
        }
    }
    hr = GetElement(
        _T("subnet_address"),
        &spDispatch,
        &bCollection
        );
    if(bCollection)
    {
        IP4_ADDRESS nSubnetAddress, nSubnetMask;
        hr = spDispatch->QueryInterface(&spHTMLElementCollection);
        for(i=0;i<spHTMLElementCollection->length;i++)
        {
            spDispatch = spHTMLElementCollection->item(_variant_t(i));
            hr = spDispatch->QueryInterface(&spIHTMLElement);
            spIHTMLElement = spIHTMLElement->parentElement;
            if(spIHTMLElement->id == _bstr_t(L"public_subnet_cell"))
            {
                continue;
            }
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            spDispatch = spIHTMLElement->children;
            hr = spDispatch->QueryInterface(&spCellChildrens);
            sIPAddress = (LPCTSTR)spInputText->value;
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                INT_PTR nDialogRet;
                CRTSDDMessageBox    oRTSDDMessageBox(this);
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата адреса публичной IP-подсети!!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return false;
            }
            nSubnetAddress = stIP4Address.S_un.S_addr;
            spDispatch = spCellChildrens->item(_variant_t(L"subnet_mask"));
            hr = spDispatch->QueryInterface(&spInputText);
            hr = spDispatch->QueryInterface(&spPublicIPElement2);
            sIPAddress = (LPCTSTR)spInputText->value;
            nRet = RtlIpv4StringToAddress(
                sIPAddress,
                TRUE,
                &pTerminator,
                &stIP4Address
                );
            if(NO_ERROR != nRet)
            {
                INT_PTR nDialogRet;
                CRTSDDMessageBox    oRTSDDMessageBox(this);
                oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата маски публичной IP-подсети!!");
                nDialogRet = oRTSDDMessageBox.DoModal();
                hr = spPublicIPElement2->focus();
                hr = spInputText->select();
                return false;
            }
            nSubnetMask = stIP4Address.S_un.S_addr;
            if((nIpAddress & nSubnetMask) == nSubnetAddress)
            {
                return true;
            }
            nSubnetIP++;
        }
    }
    return false;
}


void CPublicDNSPluginConfigDlg::OnCancel()
{
}


void CPublicDNSPluginConfigDlg::OnOK()
{
}


HRESULT CPublicDNSPluginConfigDlg::TestPublicIPv6(IHTMLElement* pElement)
{
    HRESULT hr;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    CString                             sIPAddress;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    LONG                                nRet;
    LPCTSTR                             pTerminator;
    IN6_ADDR                            stIP6Address;
    MSHTML::IHTMLElement2Ptr            spIPElement2;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    LONG                                nPrefixLength;
    spIHTMLElement = pElement;
    spIHTMLElement = spIHTMLElement->parentElement;
    spDispatch = spIHTMLElement->children;
    hr = spDispatch->QueryInterface(&spHTMLElementCollection);
    spDispatch = spHTMLElementCollection->item(_variant_t(L"ip6_prefix"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spIPElement2);
    sIPAddress = (LPCTSTR) spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = L"Поле префикса публичной IPv6-подсети не должно быть пустым!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv6StringToAddress(
        sIPAddress,
        &pTerminator,
        &stIP6Address
        );
    if (NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата префикса публичной IPv6-подсети!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    spDispatch = spHTMLElementCollection->item(_variant_t(L"prefix_length"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spIPElement2);
    sIPAddress = (LPCTSTR) spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = L"Поле длины префикса публичной IPv6-подсети не должно быть пустым!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nPrefixLength = _tstol(sIPAddress);
    if ((nPrefixLength < 1) || (nPrefixLength > 128))
    {
        oRTSDDMessageBox.m_sMessageText = L"Длина префикса публичной IPv6-подсети должна быть в диапазоне от 1 до 128!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    oRTSDDMessageBox.m_sMessageText = _T("Формат публичной IPv6-подсети верен.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    return S_OK;
}


HRESULT CPublicDNSPluginConfigDlg::TestPrivateIPv6(IHTMLElement* pElement)
{
    HRESULT hr;
    MSHTML::IHTMLElementPtr             spIHTMLElement;
    MSHTML::IHTMLTablePtr               spSettingsTable;
    CString                             sIPAddress;
    IDispatchPtr                        spDispatch;
    MSHTML::IHTMLElementCollectionPtr   spHTMLElementCollection;
    MSHTML::IHTMLInputTextElementPtr    spInputText;
    LONG                                nRet;
    LPCTSTR                             pTerminator;
    IN6_ADDR                            stIP6Address;
    MSHTML::IHTMLElement2Ptr            spIPElement2;
    INT_PTR                             nDialogRet;
    CRTSDDMessageBox                    oRTSDDMessageBox(this);
    LONG                                nPrefixLength;
    spIHTMLElement = pElement;
    spIHTMLElement = spIHTMLElement->parentElement;
    spDispatch = spIHTMLElement->children;
    hr = spDispatch->QueryInterface(&spHTMLElementCollection);
    spDispatch = spHTMLElementCollection->item(_variant_t(L"ip6_private_prefix"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spIPElement2);
    sIPAddress = (LPCTSTR) spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = L"Поле префикса приватной IPv6-подсети не должно быть пустым!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nRet = RtlIpv6StringToAddress(
        sIPAddress,
        &pTerminator,
        &stIP6Address
        );
    if (NO_ERROR != nRet)
    {
        oRTSDDMessageBox.m_sMessageText = _T("Ошибка формата префикса приватной IPv6-подсети!");
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    spDispatch = spHTMLElementCollection->item(_variant_t(L"prefix_private_length"));
    hr = spDispatch->QueryInterface(&spInputText);
    hr = spDispatch->QueryInterface(&spIPElement2);
    sIPAddress = (LPCTSTR) spInputText->value;
    if (sIPAddress.IsEmpty())
    {
        oRTSDDMessageBox.m_sMessageText = L"Поле длины префикса приватной IPv6-подсети не должно быть пустым!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    nPrefixLength = _tstol(sIPAddress);
    if ((nPrefixLength < 1) || (nPrefixLength > 128))
    {
        oRTSDDMessageBox.m_sMessageText = L"Длина префикса приватной IPv6-подсети должна быть в диапазоне от 1 до 128!";
        nDialogRet = oRTSDDMessageBox.DoModal();
        hr = spIPElement2->focus();
        hr = spInputText->select();
        return S_OK;
    }
    oRTSDDMessageBox.m_sMessageText = _T("Формат приватной IPv6-подсети верен.");
    oRTSDDMessageBox.m_sMessageTypeImageSRC = _T("INFORMATION_ICON.PNG");
    nDialogRet = oRTSDDMessageBox.DoModal();
    return S_OK;
}
