See the question and my original answer on StackOverflow

This kind of structure is of variable size (because of the last member). You must call the API once to get the size, and a second time with the properly allocated buffer.

Here is a definition that works:

int size = 0;
if (!SetupGetInfInformation(@"D:\TestDriverFile\intcoed.inf", INFINFO_INF_NAME_IS_ABSOLUTE,
    IntPtr.Zero, 0, ref size)) // pass NULL the first time
    throw new Win32Exception(Marshal.GetLastWin32Error());

// now, size contains the required buffer size
var ptr = Marshal.AllocHGlobal(size);
if (!SetupGetInfInformation(@"D:\TestDriverFile\intcoed.inf", INFINFO_INF_NAME_IS_ABSOLUTE,
    ptr, size, ref size))
    throw new Win32Exception(Marshal.GetLastWin32Error());

// now, ptr contains a pointer to a SP_INF_INFORMATION structure
var InfStyle = Marshal.ReadInt32(ptr);
var InfCount = Marshal.ReadInt32(ptr, 4);
... etc...

[DllImport("setupapi.dll", SetLastError = true)]
internal static extern bool SetupGetInfInformation(
    string InfSpec,
    int SearchControl,
    IntPtr ReturnBuffer,
    int ReturnBufferSize,
    ref int RequiredSize
    );