Invalid enumerator when trying to add a filter using WFP by C#

Asked

Viewed 63 times

1

I’m trying to bear a code of c++ to c#. My goal is to block a website using WFP. After translating the code, I seem to have missed something because when adding a filter I get the message "An enumerator is not Valid" (FWP_E_INVALID_ENUMERATOR).

I’ve checked the code several times, including debugging along with the original code and I can’t find what’s wrong. The code is very long because it contains structure statements, Enumerators and call methods to the windows api. So I leave below just the snippet that is launching the Exception. The full code can be found in the Pastebin from of this link.

var filterConditions = new List<FWPM_FILTER_CONDITION0_>();
filterConditions.Add(new FWPM_FILTER_CONDITION0_ {
    fieldKey = FWPM_CONDITION_IP_REMOTE_ADDRESS,
    matchType = FWP_MATCH_TYPE_.FWP_MATCH_EQUAL,
    conditionValue = new FWP_CONDITION_VALUE0_
    {
        type = FWP_DATA_TYPE_.FWP_V4_ADDR_MASK,
        v4AddrMask = site.ToIntPtr() // site é um objeto do tipo FWP_V4_ADDR_AND_MASK_
    }
});

var filterIn = new FWPM_FILTER0_ {
    subLayerKey = _subLayerGuid,
    layerKey = FWPM_LAYER_INBOUND_IPPACKET_V4,
    displayData = new FWPM_DISPLAY_DATA0_ { name = "Filter Name" },
    action = new FWPM_ACTION0_ { type = NativeConstants.FWP_ACTION_BLOCK },
    filterCondition = filterConditions.ToIntPtr(),
    numFilterConditions = (uint)filterConditions.Count,
    weight = new FWP_VALUE0_
    {
        type = FWP_DATA_TYPE_.FWP_UINT8,
        uint8 = 0x00
    }
};

var hr = NativeMethods.FwpmEngineOpen0(null, RPC_C_AUTHN_WINNT, IntPtr.Zero, IntPtr.Zero, ref _engineHandle);
Marshal.ThrowExceptionForHR((int)hr);

hr = NativeMethods.FwpmSubLayerAdd0(_engineHandle, ref subLayer, IntPtr.Zero);
Marshal.ThrowExceptionForHR((int)hr);

hr = NativeMethods.FwpmFilterAdd0(_engineHandle, ref filterIn, IntPtr.Zero, ref filterIn.filterId);
Marshal.ThrowExceptionForHR((int)hr); // aqui recebo a exception FWP_E_INVALID_ENUMERATOR

I’ve had this problem for days. I posted a question on stackoverflow in English and I received some downvotes so know that I researched a lot to port this code (you do not have the necessary references in pinvoke.net) and, if something is not clear, please comment that I add any necessary information.

  • But that’s not the function of Marshal.ThrowExceptionForHR?

  • Its function is to actually launch Exception if hr is different from 0. I’m trying to figure out why hr is different from 0. I’m suspicious that there’s something wrong with my struct + Union translation, but I still haven’t found the right way to do it.

1 answer

0

At the end of the day, I figured out what it was. The problem was in translating the structs containing Union. An example is the struct below:

typedef struct FWP_VALUE0_ {
  FWP_DATA_TYPE type;
  union {
    ;      // case(FWP_EMPTY)
    UINT8                 uint8;
    UINT16                uint16;
    UINT32                uint32;
    UINT64                *uint64;
    INT8                  int8;
    INT16                 int16;
    INT32                 int32;
    INT64                 *int64;
    float                 float32;
    double                *double64;
    FWP_BYTE_ARRAY16      *byteArray16;
    FWP_BYTE_BLOB         *byteBlob;
    SID                   *sid;
    FWP_BYTE_BLOB         *sd;
    FWP_TOKEN_INFORMATION *tokenInformation;
    FWP_BYTE_BLOB         *tokenAccessInformation;
    LPWSTR                unicodeString;
    FWP_BYTE_ARRAY6       *byteArray6;
  };
} FWP_VALUE0;

When translating it, I simply ignored Union. Getting the code in C# like this:

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct FWP_VALUE0_
{
    public FWP_DATA_TYPE_ type;
    public byte uint8;
    public ushort uint16;
    public uint uint32;
    public System.IntPtr uint64;
    public byte int8;
    public short int16;
    public int int32;
    public System.IntPtr int64;
    public float float32;
    public System.IntPtr double64;
    public System.IntPtr byteArray16;
    public System.IntPtr byteBlob;
    public System.IntPtr sid;
    public System.IntPtr sd;
    public System.IntPtr tokenInformation;
    public System.IntPtr tokenAccessInformation;
    public System.IntPtr unicodeString;
    public System.IntPtr byteArray6;
}

The problem is, from what I understand, by doing this I’m putting each of the values in sequence into memory. Union allows all values within it to occupy the same position, which consequently only allows me to use one of the values. This way, the correct translation would look like this:

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)]
public struct UnionType
{
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public byte uint8;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public ushort uint16;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public uint uint32;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr uint64;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public byte int8;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public short int16;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public int int32;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr int64;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public float float32;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr double64;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr byteArray16;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr byteBlob;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr sid;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr sd;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr tokenInformation;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr tokenAccessInformation;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr unicodeString;
    [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
    public System.IntPtr byteArray6;
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct FWP_VALUE0_
{
    public FWP_DATA_TYPE_ type;
    public UnionType Union1;
}

Note the Structlayout attribute in Uniontype as Explicit. This forces me to speak the offset of each of the values. And then, all values have the same offset (0) which makes everyone occupy the same position.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.