I'm trying to connect a share (let's say \server\folder) to my local device X:
[DllImport("Mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int WNetAddConnection2(
[In] NetResource lpNetResource,
string lpPassword,
string lpUsername,
int flags
);
public static bool Connect(string remoteName, string localName, bool persistent) {
if (!IsLocalPathValid(localName)) return false;
var r = new NetResource
{
dwScope = ResourceScope.RESOURCE_GLOBALNET,
dwType = ResourceType.RESOURCETYPE_ANY,
dwDisplayType = ResourceDisplayType.RESOURCEDISPLAYTYPE_SHARE,
dwUsage = ResourceUsage.RESOURCEUSAGE_CONNECTABLE,
lpRemoteName = remoteName,
lpLocalName = localName
};
return WNetAddConnection2(r, null, null, persistent ? 1 : 0) == 0;
}
[StructLayout(LayoutKind.Sequential)]
public class NetResource {
public ResourceScope dwScope;
public ResourceType dwType;
public ResourceDisplayType dwDisplayType;
public ResourceUsage dwUsage;
public string lpLocalName;
public string lpRemoteName;
public string lpComment;
public string lpProvider;
}
When calling
Connect(@"\\server\folder", "X:", true);
the function just returns false - the Error says 1200 (BAD_DEVICE). The NetResource looks like this:
lpRemoteName = "\\\\server\\folder";
lpProvider = null;
lpLocalName = "X:";
lpComment = null;
dwUsage = Connectable;
dwType = Any;
dwScope = GlobalNet;
dwDisplayType = Share;
I already checked with several snippets (PInvoke) put i can't see any difference. Maybe you can solve this mystery...
EDIT1
I finally did it.
I solved the issue by adding
[MarshalAs(UnmanagedType.LPWStr)]
Attribute to every string field inside my NetResource class. Unfortunately I don't know why this is solving the issue...
[StructLayout(LayoutKind.Sequential)]
That is where the problem started, the attribute does not specify the CharSet
property. The default is CharSet.Ansi, a bewildering choice that requires a trip in a time machine to make sense of, taking you back to 1998. So the code passes a struct with strings that get translated to 8-bit characters to a function that is explicitly uses the Unicode flavor of the function. Inevitably the implementation sees garbage.
You can force the marshaling of each individual string member with [MarshalAs]. But it is just simpler and logical to make the character types match. Fix:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With