WNetAddConnection2 returns Error 1200 - Local name is valid
Asked Answered
M

2

6

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

Variables when trying to map the drive

Mismatch answered 27/7, 2017 at 5:58 Comment(2)
Does the map drive work if you don't give a local name ? i.e., make localName an empty string. This may give some clue whether there is any other problem. Error code 1200 means that there is something not right with your "X:\" -- is there any extra space (please see - #31138379)Retarded
Unfortunately not - the Error 1200 persists, even without a local drive specified (empty string). See my Edit1 for further NetResource details. (I had to clear the server name out, sorry.Mismatch
S
5
[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)]
Slavism answered 31/7, 2017 at 8:51 Comment(0)
M
1

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...

Mismatch answered 31/7, 2017 at 4:59 Comment(1)
With 'LPWStr' your specifying that it's a pointer to a null-terminated array of Unicode characters. If you don't specify it explicitly, it may be defaulting to some other value. More details on this here: Default marshalling for strings.Robet

© 2022 - 2024 — McMap. All rights reserved.