2

I'm having some difficulties using a struct to call some Windows kernel32 function. I'm trying to call the function FindFirstStreamW, which return, among others, a WIN32_FIND_STREAM_DATA struct.

I use this struct in C# to represent it :

[StructLayout(LayoutKind.Sequential)]
public unsafe struct WIN32_FIND_STREAM_DATA
{
    public long StreamSize;
    public fixed char StreamName [MAX_PATH + 32];
}

But I have problems using the StreamName afterward. After a call to the function, the StreamName buffer seems to contains a semicolon (which is expected) and then only random data.

I experimented by replacing the fixed buffer by consecutives char such as s1, s2, s3 etc... and it worked (s1 contained ':', then s2 '$' etc... all correct !).

[StructLayout(LayoutKind.Sequential)]
public unsafe struct WIN32_FIND_STREAM_DATA
{
    public long StreamSize;
    public char s1;
    public char s2;
    public char s3;
}

I must therefore miss something but can't find what and after 8 firefox windows filled with google researches, I'm pretty desperate.

Here is my DLLImport :

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindFirstStreamW(
    [MarshalAs(UnmanagedType.LPTStr)] string filename,
    StreamInfoLevels infoLevel,
    out WIN32_FIND_STREAM_DATA data,
    int reserved = 0
    );

And there is my test code :

WIN32_FIND_STREAM_DATA data = default(WIN32_FIND_STREAM_DATA);
IntPtr search = FindFirstStreamW(D_TMP_TESTHANDLE_TXT, StreamInfoLevels.FindStreamInfoStandard, out data);
Debug.WriteLine(data.StreamSize);
Debug.WriteLine(new string(data.StreamName));
FindClose(search); 

Thanks in advance for your help.

2
  • You are corrupting the stack with this declaration, it has a, cough, interesting affect on the fixed buffer. +32 needs to be +36. And you need to use CharSet = CharSet.Unicode in the [StructLayout] attribute. Commented Dec 20, 2015 at 17:38
  • Can you explain where is the stack corrupted please ? Commented Dec 20, 2015 at 18:13

1 Answer 1

1

The problem with your struct - compared to the variant where you actually have distinct characters - is probably that it does not get marshalled as expected because arrays are by reference and not by value by default when using .NET.

Read this MSDN article about string marshalling for more information.

So I'd try it with something like this:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct WIN32_FIND_STREAM_DATA
{
    public long StreamSize;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH+36)]
    public string StreamName;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I was assuming that a fixed-size buffer was indeed the same as individual sequential characters, specially since the size of the resulting struct was the same.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.