/*++

Module Name:

    public.h

Abstract:

    This module contains the common declarations shared by driver
    and user applications.

Environment:

    user and kernel

--*/

#pragma once

#define DNSFIREWALL_DEVICE_NAME   L"\\Device\\DNSFIREWALL"
#define DNSFIREWALL_SYMBOLIC_NAME L"\\DosDevices\\Global\\DNSFIREWALL"
#define DNSFIREWALL_DOS_NAME      L"\\\\.\\DNSFIREWALL"

#define	DNSFIREWALL_IOCTL_INIT_FILTERS            CTL_CODE(FILE_DEVICE_NETWORK, 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_WAIT_FOR_RESTART        CTL_CODE(FILE_DEVICE_NETWORK, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_RELEASE_RESORCE         CTL_CODE(FILE_DEVICE_NETWORK, 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_GET_FIREWALL_CONFIG     CTL_CODE(FILE_DEVICE_NETWORK, 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_SET_FIREWALL_CONFIG     CTL_CODE(FILE_DEVICE_NETWORK, 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define	DNSFIREWALL_IOCTL_WAIT_FLOW_DONE          CTL_CODE(FILE_DEVICE_NETWORK, 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_WAIT_DNS_QUERY          CTL_CODE(FILE_DEVICE_NETWORK, 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_READ_UDP_QUERY          CTL_CODE(FILE_DEVICE_NETWORK, 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_WAIT_UDP_QUERY2         CTL_CODE(FILE_DEVICE_NETWORK, 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_APPROVAL_UDP_QUERY      CTL_CODE(FILE_DEVICE_NETWORK, 0x0A, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_WAIT_UDP_SET_FILTER     CTL_CODE(FILE_DEVICE_NETWORK, 0x0B, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_READ_UDP_QUERY2         CTL_CODE(FILE_DEVICE_NETWORK, 0x0C, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_APPROVAL_UDP_QUERY2     CTL_CODE(FILE_DEVICE_NETWORK, 0x0D, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_GET_FLOW_STATUS         CTL_CODE(FILE_DEVICE_NETWORK, 0x0E, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_READ_TCP_QUERY          CTL_CODE(FILE_DEVICE_NETWORK, 0x0F, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_WAIT_TCP_RESPONCE       CTL_CODE(FILE_DEVICE_NETWORK, 0x10, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_APPROVAL_TCP_QUERY      CTL_CODE(FILE_DEVICE_NETWORK, 0x11, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_INJECT_TCP_QUERY        CTL_CODE(FILE_DEVICE_NETWORK, 0x12, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_READ_TCP_RESPONCE       CTL_CODE(FILE_DEVICE_NETWORK, 0x13, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_WAIT_TCP_NEW_MESSAGE    CTL_CODE(FILE_DEVICE_NETWORK, 0x14, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_APPROVAL_TCP_RESPONCE   CTL_CODE(FILE_DEVICE_NETWORK, 0x15, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define	DNSFIREWALL_IOCTL_INJECT_TCP_RESPONCE     CTL_CODE(FILE_DEVICE_NETWORK, 0x16, METHOD_BUFFERED, FILE_ANY_ACCESS)

// {87F99024-7A3C-4E43-A449-96B869FF2D8E}
DEFINE_GUID(DNS_FIREWALL_INBOUND_TRANSPORT_CALLOUT_V4,
    0x87f99024, 0x7a3c, 0x4e43, 0xa4, 0x49, 0x96, 0xb8, 0x69, 0xff, 0x2d, 0x8e);
// {80E80087-674E-4EC4-A7F4-5CA2636C4CDD}
DEFINE_GUID(DNS_FIREWALL_INBOUND_TRANSPORT_CALLOUT_V6,
    0x80e80087, 0x674e, 0x4ec4, 0xa7, 0xf4, 0x5c, 0xa2, 0x63, 0x6c, 0x4c, 0xdd);
// {C98A438A-01F2-49C9-8143-99B56AB6B57F}
DEFINE_GUID(DNS_FIREWALL_ALE_ACCEPT_RECV_CALLOUT_V4,
    0xc98a438a, 0x1f2, 0x49c9, 0x81, 0x43, 0x99, 0xb5, 0x6a, 0xb6, 0xb5, 0x7f);
// {3EE579A2-193D-45A1-8431-F014C04BAE55}
DEFINE_GUID(DNS_FIREWALL_ALE_ACCEPT_RECV_CALLOUT_V6,
    0x3ee579a2, 0x193d, 0x45a1, 0x84, 0x31, 0xf0, 0x14, 0xc0, 0x4b, 0xae, 0x55);
// {8342DDA5-47FF-4A27-84D1-2DC1663C5540}
DEFINE_GUID(DNS_FIREWALL_ALE_FLOW_ESTABLISHED_CALLOUT_V4,
    0x8342dda5, 0x47ff, 0x4a27, 0x84, 0xd1, 0x2d, 0xc1, 0x66, 0x3c, 0x55, 0x40);
// {28F84F90-0212-495E-977A-B558C91C1E36}
DEFINE_GUID(DNS_FIREWALL_ALE_FLOW_ESTABLISHED_CALLOUT_V6,
    0x28f84f90, 0x212, 0x495e, 0x97, 0x7a, 0xb5, 0x58, 0xc9, 0x1c, 0x1e, 0x36);
// {9B8F3D7C-05B0-4D1C-BD6C-54D1990C858B}
DEFINE_GUID(DSN_FIREWALL_STREAM_CALLOUT_V4,
    0x9b8f3d7c, 0x5b0, 0x4d1c, 0xbd, 0x6c, 0x54, 0xd1, 0x99, 0xc, 0x85, 0x8b);
// {0B6B9C51-9598-4F6B-AE01-EBC85FE9B6FF}
DEFINE_GUID(DSN_FIREWALL_STREAM_CALLOUT_V6,
    0xb6b9c51, 0x9598, 0x4f6b, 0xae, 0x1, 0xeb, 0xc8, 0x5f, 0xe9, 0xb6, 0xff);
// {755EF8EA-644A-4FAC-A889-C0A360396577}
DEFINE_GUID(DSN_FIREWALL_DATAGRAM_DATA_CALLOUT_V4,
    0x755ef8ea, 0x644a, 0x4fac, 0xa8, 0x89, 0xc0, 0xa3, 0x60, 0x39, 0x65, 0x77);
// {CD7E301A-E50F-4861-B29B-96BD57B32487}
DEFINE_GUID(DSN_FIREWALL_DATAGRAM_DATA_CALLOUT_V6,
    0xcd7e301a, 0xe50f, 0x4861, 0xb2, 0x9b, 0x96, 0xbd, 0x57, 0xb3, 0x24, 0x87);


typedef enum _context_state
{
    csNotRun = 0,                       // 00
    csWaitFlowDoneStarted,              // 01
    csUdpWaitQuery2Started,             // 02
    csUdpWaitSetFilterStarted,          // 03
    csWaitQueryStarted,                 // 04
    csUdpWaitAcceptRecv,                // 05
    csUdpAcceptedRecv,                  // 06
    csUdpFlowEstablishing,              // 07
    csUdpFlowCancel,                    // 08
    csUdpFlowSetFirewallEvent,          // 09
    csUdpInboundPended,                 // 10
    csUdpFlowEstablishPended,           // 11
    csUdpFlowEstablished,               // 12
    csUdpWaitReadQuery,                 // 13
    csUdpQueryDiscarded,                // 14
    csUdpWaitApprovalQuery,             // 15
    csUdpWaitReplaceQuery,              // 16
    csUdpPermitQueryPended,             // 17
    csUdpWaitPermitQuery,               // 18
    csUdpIllegalOutbound,               // 19
    csUdpPermitQueryDone,               // 20
    csUdpFlowBreak,                     // 21
    csUdpWaitResponce1Pended,           // 22
    csUdpWaitResponce1,                 // 23
    csUdpFlow1Done,                     // 24
    csUdpIllegalInbound,                // 25
    csUdpWaitReadQuery2,                // 26
    csUdpWaitApprovalQuery2,            // 27
    csUdpQuery2Discarded,               // 28
    csUdpWaitReplaceQuery2,             // 29
    csUdpPermitQuery2Pended,            // 30
    csUdpWaitPermitQuery2,              // 31
    csUdpPermitQuery2Done,              // 32
    csUdpWaitResponce2Pended,           // 33
    csUdpWaitResponce2,                 // 34
    csUdpSetFilterEvent,                // 35
    csUdpFlowDone,                      // 36
    csTcpFlowEstablished,               // 37
    csTcpQueryMoreData01,               // 38
    csTcpQueryMoreData02,               // 39
    csTcpWaitReadQuery,                 // 40
    csTcpWaitApprovalQuery,             // 41
    csTcpWaitResponceStarted,           // 42
    csTcpWaitReplaceQuery,              // 43
    csTcpQueryDiscarded,                // 44
    csTcpPermitQueryPended,             // 45
    csTcpWaitPermitQuery,               // 46
    csTcpPermitQueryDone,               // 47
    csTcpWaitQueryInjectDone,           // 48
    csTcpReplaceQueryPended,            // 49
    csTcpWaitReplaceQueryDone,          // 50
    csTcpReplaceQueryDone,              // 51
    csTcpWaitReadResponce,              // 52
    csTcpResponceMoreData01,            // 53
    csTcpResponceMoreData02,            // 54
    csTcpResponceMoreData03,            // 55
    csTcpIllegalInbound,                // 56
    csTcpWaitApprovalResponce,          // 57
    csTcpPermitResponcePended,          // 58
    csTcpWaitPermitResponce,            // 59
    csTcpPermitResponceDone,            // 60
    csTcpWaitResponceInjectDone,        // 61
    csTcpWaitReplaceResponce,           // 62
    csTcpResponceDiscarded,             // 63
    csTcpWaitNewMessageStarted,         // 64
    csTcpReplaceResponcePended,         // 65
    csTcpWaitReplaceResponceDone,       // 66
    csTcpReplaceResponceDone,           // 67
    csTcpClientDisconnect,              // 68
    csTcpServerDisconnect,              // 69
    csFlowDeleted,                      // 70
    csFileClosed,                       // 71
    csDnsError,                         // 72
    csUdpFiltersChangeInProgress,       // 73
    csMaxValue                          // 74
}
context_state;

typedef enum _flow_data_owner
{
    foNoOwner = 0,                      // 00
    foFreeFileList,                     // 01
    foWaitForDoneFileList,              // 02
    foWaitForQuery2FileList,            // 03
    foWaitForSetFilterFileList,         // 04
    foAcceptableList,                   // 05
    foUdpInboundList,                   // 06
    foUdpALEAcceptRecvList,             // 07
    foUdpAcceptNotifyList,              // 08
    foUdpALEAcceptPendedList,           // 09
    foUdpALEFlowEstablishList,          // 10
    foFlowedFileList,                   // 11
    foMaxValue                          // 12
} flow_data_owner;

typedef struct _FLOW_DATA
{
    struct _FLOW_DATA*  pThis;
    int                 nFileIndex;
    int                 nThreadIndex;
    LIST_ENTRY          listEntry;
    LIST_ENTRY          threadListEntry;
    WDFFILEOBJECT       wdfFlowFileObject;
    WDFQUEUE            wdfFlowQueue;
    WDFQUEUE            wdfWaitFlowDoneQueue;
    WDFQUEUE            wdfWaitUdpQuery2Queue;
    WDFQUEUE            wdfWaitUdpSetFirewallFilterQueue;
    WDFQUEUE            wdfWaitDnsQueryQueue;
    WDFQUEUE            wdfUdpQueryPermitQueue;
    WDFQUEUE            wdfUdpQuery2PermitQueue;
    WDFQUEUE            wdfWaitTcpNewMessageQueue;
    WDFQUEUE            wdfWaitTcpResponceQueue;
    WDFQUEUE            wdfTcpQueryPermitQueue;
    WDFQUEUE            wdfTcpQueryInjectQueue;
    WDFQUEUE            wdfTcpResponcePermitQueue;
    WDFQUEUE            wdfTcpResponceInjectQueue;
    IPPROTO             enIpProto;
    UINT32              nRemoteAddressV4;
    UINT32              nRemoteAddressV4N;
    UINT16              usRemotePort;
    UINT64              flowHandle;
    HANDLE              hAleAuthRecvAcceptCompletionHandle;
    HANDLE              hAleAuthRecvAcceptContext;
    context_state       enContextState;
    context_state       arContextStateStack[16];
    flow_data_owner     enFlowDataOwner;
    flow_data_owner     arFlowDataOwnerStack[16];
    FWP_BYTE_ARRAY16    stRemoteAddressV6;
    FWP_DIRECTION       enPacketDirection;
    PNET_BUFFER_LIST    pUdpQueryBufferList;
    PNET_BUFFER_LIST    pUdpQueryCloneBufferList;
    PNET_BUFFER_LIST    pUdpQuery2BufferList;
    PNET_BUFFER_LIST    pUdpQuery2CloneBufferList;
    PNET_BUFFER_LIST    pTcpQueryBufferList;
    PNET_BUFFER_LIST    pTcpQueryInjectBufferList;
    PNET_BUFFER_LIST    pTcpResponceBufferList;
    PNET_BUFFER_LIST    pTcpResponceInjectBufferList;
    PNET_BUFFER_LIST    pUdpResponceBufferList;
    PNET_BUFFER_LIST    pUdpResponceCloneBufferList;
    PNET_BUFFER_LIST    pUdpResponce2BufferList;
    PNET_BUFFER_LIST    pUdpResponce2CloneBufferList;
    PMDL                pTcpQueryMdl;
    PMDL                pTcpResponceMdl;
    UINT32              ulUdpQueryIpHeaderSize;
    UINT32              ulUdpQuery2IpHeaderSize;
    UINT32              ulUdpQueryTransportHeaderSize;
    UINT32              ulUdpQuery2TransportHeaderSize;
    UINT32              ulUdpQueryBufferSize;
    UINT32              ulUdpQueryDataOffset;
    UINT32              ulUdpQueryPacketOffset;
    UINT32              ulUdpQueryDataLength;
    UINT32              ulUdpQuery2BufferSize;
    UINT32              ulUdpQuery2DataOffset;
    UINT32              ulUdpQuery2PacketOffset;
    UINT32              ulUdpQuery2DataLength;
    UINT32              ulUdpResponceBufferSize;
    UINT32              ulUdpResponceDataOffset;
    UINT32              ulUdpResponceIpHeaderSize;
    UINT32              ulUdpResponceTransportHeaderSize;
    UINT32              ulUdpResponce2BufferSize;
    UINT32              ulUdpResponce2DataOffset;
    UINT32              ulUdpResponce2IpHeaderSize;
    UINT32              ulUdpResponce2TransportHeaderSize;
    UINT32              ulUdpQueryCount;
    COMPARTMENT_ID      enUdpQueryCompartmentID;
    COMPARTMENT_ID      enUdpQuery2CompartmentID;
    COMPARTMENT_ID      enUdpResponceCompartmentID;
    COMPARTMENT_ID      enUdpResponce2CompartmentID;
    IF_INDEX            interfaceIndex;
    IF_INDEX            subInterfaceIndex;
    UINT64              hTcpQueryFlowID;
    UINT64              hTcpResponceFlowID;
    UINT64              hUdpResponceEndpointHandle;
    UINT64              hUdpInjectEndpointHandle;
    UINT64              hUdpResponce2EndpointHandle;
    UINT64              hUdpInject2EndpointHandle;
    SIZE_T              nTcpQueryLength;
    SIZE_T              nTcpQueryInjectDataSize;
    SIZE_T              nTcpResponceLength;
    SIZE_T              nTcpResponceInjectDataSize;
    SIZE_T              nUdpResponceDataLength;
    SIZE_T              nUdpResponce2DataLength;
    FWPS_TRANSPORT_SEND_PARAMS stUdpResponceSendParams;
    FWPS_TRANSPORT_SEND_PARAMS stUdpResponce2SendParams;
    BOOLEAN             bIPv6;
    BOOLEAN             bQuery2Pended;
    BOOLEAN             bFilterGhangePended;
    BOOLEAN             bUdpFlow1Done;
    BOOLEAN             bUdpQuery1Discarded;
    BOOLEAN             bUdpQueryClassifyPended;
    BOOLEAN             bUdpResponceClassifyPended;
    BOOLEAN             bUdpQuery2Reestablish;
    BOOLEAN             bUdpNotifyQuery;
    BOOLEAN             bUdpNotInboundTransport;
} FLOW_DATA, *PFLOW_DATA;

typedef enum _dns_approval_action
{
    aaPermit,
    aaModify,
    aaDiscard
}
dns_approval_action;
typedef struct _UDP_QUERY_APPROVAL
{
    dns_approval_action _enApprovalAction;
}
UDP_QUERY_APPROVAL, *PUDP_QUERY_APPROVAL;
typedef struct _UDP_RESPONCE_APPROVAL
{
    dns_approval_action _enApprovalAction;
}
UDP_RESPONCE_APPROVAL, *PUDP_RESPONCE_APPROVAL;
typedef struct _DNS_INJECT_CONFIG
{
    UINT32      m_nDataSize;
} DNS_INJECT_CONFIG, *PDNS_INJECT_CONFIG;
typedef struct _TCP_INJECT_OUTPUT
{
    DNS_INJECT_CONFIG   m_stInjectConfig;
    WORD                m_wMessageLength;
    BYTE                m_pData[65534];
} TCP_INJECT_OUTPUT, *PTCP_INJECT_OUTPUT;

typedef struct _IP4ADDR_RANGE_STRUCT
{
    UINT32 _ulLowValue;
    UINT32 _ulHighValue;
}
IP4ADDR_RANGE_STRUCT, *PIP4ADDR_RANGE_STRUCT;

typedef struct _IP4SUBNET_STRUCT
{
    UINT32 _ulIpAddr;
    UINT32 _ulIpMask;
}
IP4SUBNET_STRUCT, *PIP4SUBNET_STRUCT;

typedef struct _IPV6_ADDRESS_STRUCT
{
    UINT8   _IPv6Addr[16];
    UINT32  _PrefixLength;
}IPV6_ADDRESS_STRUCT, *PIPV6_ADDRESS_STRUCT;

typedef struct _ADDRESSES_DESCRIPTOR
{
    int m_nPublicIpCount;
    UINT32* m_pPublicIpArray;
    int m_nPrivateIpCount;
    UINT32* m_pPrivateIpArray;
    int m_nPublicRangeCount;
    PIP4ADDR_RANGE_STRUCT m_pPublicRangeArray;
    int m_nPrivateRangeCount;
    PIP4ADDR_RANGE_STRUCT m_pPrivateRangeArray;
    int m_nPublicSubnetCount;
    PIP4SUBNET_STRUCT m_pPublicSubnetArray;
    int m_nPrivateSubnetCount;
    PIP4SUBNET_STRUCT m_pPrivateSubnetArray;
    int m_nPublicIPV6AddrCount;
    PIPV6_ADDRESS_STRUCT m_pPublicIPV6AddrArray;
    int m_nPrivateIPV6AddrCount;
    PIPV6_ADDRESS_STRUCT m_pPrivateIPV6AddrArray;
    PBYTE m_pDataArray;
} ADDRESSES_DESCRIPTOR, *PADDRESSES_DESCRIPTOR;

static const FWP_BYTE_ARRAY16 c_aIPv6MaskArray [] = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //   0
    { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //   1
    { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //   2
    { 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //   3
    { 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //   4
    { 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //   5
    { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //   6
    { 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //   7
    { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //   8
    { 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //   9
    { 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  10
    { 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  11
    { 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  12
    { 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  13
    { 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  14
    { 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  15
    { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  16
    { 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  17
    { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  18
    { 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  19
    { 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  20
    { 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  21
    { 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  22
    { 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  23
    { 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  24
    { 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  25
    { 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  26
    { 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  27
    { 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  28
    { 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  29
    { 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  30
    { 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  31
    { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  32
    { 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  33
    { 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  34
    { 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  35
    { 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  36
    { 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  37
    { 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  38
    { 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  39
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  40
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  41
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  42
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  43
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  44
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  45
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  46
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  47
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  48
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  49
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  50
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  51
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  52
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  53
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  54
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  55
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  56
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  57
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  58
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  59
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  60
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  61
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  62
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  63
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  64
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  65
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  66
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  67
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  68
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  69
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  70
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  71
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  72
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  73
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  74
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  75
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  76
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  77
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  78
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  79
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  80
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  81
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  82
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  83
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  84
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  85
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  86
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  87
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 }, //  88
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00 }, //  89
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00 }, //  90
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00 }, //  91
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00 }, //  92
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00 }, //  93
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00 }, //  94
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00 }, //  95
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }, //  96
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00 }, //  97
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00 }, //  98
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00 }, //  99
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00 }, // 100
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00 }, // 101
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00 }, // 102
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00 }, // 103
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00 }, // 104
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00 }, // 105
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00 }, // 106
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00 }, // 107
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00 }, // 108
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00 }, // 109
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00 }, // 110
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00 }, // 111
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }, // 112
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00 }, // 113
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 }, // 114
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00 }, // 115
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00 }, // 116
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00 }, // 117
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00 }, // 118
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00 }, // 119
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }, // 120
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 }, // 121
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0 }, // 122
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0 }, // 123
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0 }, // 124
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8 }, // 125
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc }, // 126
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe }, // 127
    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, // 128
};

static const PUINT64 c_aQWMaskArray = (PUINT64) c_aIPv6MaskArray;
static const IPV6_ADDRESS_STRUCT c_stGlobalIPv6Subnet =
{
    { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
    3
};
static const PIPV6_ADDRESS_STRUCT c_pGlobalIPv6Subnet = (const PIPV6_ADDRESS_STRUCT) &c_stGlobalIPv6Subnet;
static const FWP_BYTE_ARRAY16 c_stIPv6LocalAdddess =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };

__inline BOOLEAN bfIsIPv6AddressesEqual(
    const FWP_BYTE_ARRAY16*   pIPv6Address1,
    const FWP_BYTE_ARRAY16*   pIPv6Address2
    )
{
    const PUINT64   pDoubleQword1 = (PUINT64) pIPv6Address1;
    const PUINT64   pDoubleQword2 = (PUINT64) pIPv6Address2;
    BOOLEAN         bReturn;
    bReturn = (pDoubleQword1[0] == pDoubleQword2[0]);
    bReturn = bReturn && (pDoubleQword1[1] == pDoubleQword2[1]);
    return bReturn;
}

__inline BOOLEAN bfIPv6AddressInIPv6Subnet(
    const FWP_BYTE_ARRAY16*    pIPv6Address,
    const PIPV6_ADDRESS_STRUCT pIPv6Subnet
    )
{
    const UINT32    nMaskIndex = (pIPv6Subnet->_PrefixLength << 1);
    const PUINT64   pDoubleQword = (PUINT64) pIPv6Address;
    const PUINT64   aIPv6SubnetArray = (PUINT64) pIPv6Subnet;
    UINT64          aIPv6Address[2];
    BOOLEAN         bReturn;
    aIPv6Address[0] = pDoubleQword[0];
    aIPv6Address[1] = pDoubleQword[1];
    aIPv6Address[0] &= c_aQWMaskArray[nMaskIndex];
    aIPv6Address[1] &= c_aQWMaskArray[nMaskIndex + 1];
    bReturn = (aIPv6SubnetArray[0] == aIPv6Address[0]);
    bReturn = bReturn && (aIPv6SubnetArray[1] == aIPv6Address[1]);
    return bReturn;
}

__inline void IPv6CopyAddress(
    FWP_BYTE_ARRAY16*       pDestAddress,
    const FWP_BYTE_ARRAY16* pSrcAddress
    )
{
    const PUINT64   pDoubleQwordSrc = (PUINT64) pSrcAddress;
    PUINT64         pDoubleQwordDest = (PUINT64) pDestAddress;
    pDoubleQwordDest[0] = pDoubleQwordSrc[0];
    pDoubleQwordDest[1] = pDoubleQwordSrc[1];
}

typedef struct _FIREWALL_CONFIG__
{
    UINT32              nBlackListLength;
    UINT32              aBlackListArray[128];
    HANDLE              aBlackListTimers[128];
    UINT32              nBlackSubnetListLength;
    IP4SUBNET_STRUCT    aBlackSubnetList[32];
    HANDLE              aBlackSubnetTimers[32];
    UINT32              nBlackListV6Length;
    FWP_BYTE_ARRAY16    aBlackListV6Array[128];
    HANDLE              aBlackListV6Timers[128];
    HANDLE              hEternalClientBlockedTimer;
    BOOLEAN             bExternalClientBlocked;
} FIREWALL_CONFIG, *PFIREWALL_CONFIG;

typedef struct _TCP_QUERY_APPROVAL
{
    dns_approval_action _enApprovalAction;
}
TCP_QUERY_APPROVAL, *PTCP_QUERY_APPROVAL;

typedef struct _TCP_RESPONCE_APPROVAL
{
    dns_approval_action _enApprovalAction;
}
TCP_RESPONCE_APPROVAL, *PTCP_RESPONCE_APPROVAL;
