I am trying to use a Windows API .dll called netapi32.dll
to manipulate DFS shares. We are using DFS on Windows Server 2008 R2, and I am using .NET 4.0. I've never used something like this before in .NET, but I am having trouble understanding what is failing.
I am using DllImport
to call NetDfsGetInfo to test getting information about a DFS share. I had to create structures for the level of information I wanted to receive from the function.
public struct DFS_INFO_3
{
[MarshalAs(UnmanagedType.LPWStr)]
public string EntryPath;
[MarshalAs(UnmanagedType.LPWStr)]
public string Comment;
public UInt32 State;
public UInt32 NumberOfStorages;
public IntPtr Storage;
}
public struct DFS_STORAGE_INFO
{
public ulong State;
[MarshalAs(UnmanagedType.LPWStr)]
public string ServerName;
[MarshalAs(UnmanagedType.LPWStr)]
public string ShareName;
}
I used the following code to get and read the result:
[DllImport("netapi32", CallingConvention = CallingConvention.Winapi)]
public static extern int NetDfsGetInfo(
[MarshalAs(UnmanagedType.LPWStr)] string DfsEntryPath,
[MarshalAs(UnmanagedType.LPWStr)]string ServerName,
[MarshalAs(UnmanagedType.LPWStr)]string ShareName,
int Level,
out IntPtr Buffer);
public void GetInfo() {
IntPtr buffer;
string dfsPath = "\\\\server\\share";
int result = NetDfsGetInfo(EntryPath, null, null, 3, out buffer);
if (result == 0) { //0 is Success
DFS_INFO_3 info = (DFS_INFO_3)Marshal.PtrToStructure(buffer, typeof(DFS_INFO_3));
DFS_STORAGE_INFO storage = (DFS_STORAGE_INFO)Marshal.PtrToStructure(info.Storage, typeof(DFS_STORAGE_INFO)); //Error
Console.WriteLine("{0}, {1}, {2} ", storage.ServerName, storage.ShareName, storage.State);
}
}
Everything goes fine until it goes to read the storage
line.
I sometimes get an error that says:
The runtime has encountered a fatal error. The address of the error was at 0x626ac91c, on thread 0x1d44. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
The error type is fatalExecutionEngineError, which isn't a .NET Exception, so I can't catch it. It doesn't happen every time, but I'd say about 50% of the time I get this error. Looking up Windows error codes, I'm seeing that 5 is "Access Denied". Being only intro-level Comp Sci proficient, I understand a bit about pointers (which is what the IntPtr
object is), and that the pointer may have spilled over into a piece of the result that it wasn't supposed to? I still don't understand why this error would occur only some of the time.
How do I understand/avoid this error?
Your definition of DFS_STORAGE_INFO
is incorrect. In .NET a long/ulong
is 64 bits while in unmanaged Win32 it's only 32 bits (the same as an int/uint)
public struct DFS_STORAGE_INFO
{
public UInt32 State;
[MarshalAs(UnmanagedType.LPWStr)]
public string ServerName;
[MarshalAs(UnmanagedType.LPWStr)]
public string ShareName;
}
When you marshal the DFS_STORAGE_INFO
you would be reading 4 bytes past the end of the structure - which may or may not work depending on what is after the structure.