C# - NetUseAdd from NetApi32.dll on Windows Server 2008 and IIS7

c#, iis-7, interop, winapi

Solution

The reason is:

You pulled the p/invoke signature off pinvoke.net and you didn't verify it. The fool who initially wrote this p/invoke sample code had no idea what he was doing and created one that "works" on 32-bit systems but does not work on 64-bit systems. He somehow turned a very simple p/invoke signature into some amazingly complicated mess and it spread like wildfire on the net.

The correct signature is:

    [DllImport( "NetApi32.dll", SetLastError = true, CharSet = CharSet.Unicode )]
    public static extern uint NetUseAdd(
         string UncServerName,
         UInt32 Level,
         ref USE_INFO_2 Buf,
         out UInt32 ParmError
        );

    [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Unicode )]
    public struct USE_INFO_2
    {
        public string ui2_local;
        public string ui2_remote;
        public string ui2_password;
        public UInt32 ui2_status;
        public UInt32 ui2_asg_type;
        public UInt32 ui2_refcount;
        public UInt32 ui2_usecount;
        public string ui2_username;
        public string ui2_domainname;
    }

And your code should read:

USE_INFO_2 info = new USE_INFO_2();   
info.ui2_local = null;   
info.ui2_asg_type = 0xFFFFFFFF;   
info.ui2_remote = remoteUNC;   
info.ui2_username = username;   
info.ui2_password = password;
info.ui2_domainname = domainName;      

uint paramErrorIndex;   
uint returnCode = NetUseAdd(null, 2, ref info, out paramErrorIndex);   

if (returnCode != 0)   
{   
    throw new Win32Exception((int)returnCode);   
}

Hope this was of some help. I just spent half a day knee deep remote debugging someone elses trash code trying to figure out what was going on and it was this.

Problem

I am attemping to use NetUseAdd to add a share that is needed by an application. My code looks like this. ``` [DllImport("NetApi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] internal static extern uint NetUseAdd( string UncServerName, uint Level, IntPtr Buf, out uint ParmError); ``` ... ``` USE_INFO_2 info = new USE_INFO_2(); info.ui2_local = null; info.ui2_asg_type = 0xFFFFFFFF; info.ui2_remote = remoteUNC; info.ui2_username = username; info.ui2_password = Marshal.StringToHGlobalAuto(password); info.ui2_domainname = domainName; IntPtr buf = Marshal.AllocHGlobal(Marshal.SizeOf(info)); try { Marshal.StructureToPtr(info, buf, true); uint paramErrorIndex; uint returnCode = NetUseAdd(null, 2, buf, out paramErrorIndex); if (returnCode != 0) { throw new Win32Exception((int)returnCode); } } finally { Marshal.FreeHGlobal(buf); } ``` This works fine on our server 2003 boxes. But in attempting to move over to Server 2008 and IIS7 this doesnt work any more. Through liberal logging i have found that it hangs on the line `Marshal.StructureToPtr(info, buf, true);` I have absolutely no idea why this is can anyone shed any light on it for tell me where i might look for more information?

Original source