C# Access a (untrusted) network share

Date: 2020-01-21

Source: https://stackoverflow.com/a/14870774

Note:
The share path must NOT end with a \ (backslash)
or it will result in the exception: The network path was not found

public static class NetworkShareConsts
{
	public const int RESOURCE_CONNECTED = 0x00000001;
	public const int RESOURCE_GLOBALNET = 0x00000002;
	public const int RESOURCE_REMEMBERED = 0x00000003;

	public const int RESOURCETYPE_ANY = 0x00000000;
	public const int RESOURCETYPE_DISK = 0x00000001;
	public const int RESOURCETYPE_PRINT = 0x00000002;

	public const int RESOURCEDISPLAYTYPE_GENERIC = 0x00000000;
	public const int RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001;
	public const int RESOURCEDISPLAYTYPE_SERVER = 0x00000002;
	public const int RESOURCEDISPLAYTYPE_SHARE = 0x00000003;
	public const int RESOURCEDISPLAYTYPE_FILE = 0x00000004;
	public const int RESOURCEDISPLAYTYPE_GROUP = 0x00000005;

	public const int RESOURCEUSAGE_CONNECTABLE = 0x00000001;
	public const int RESOURCEUSAGE_CONTAINER = 0x00000002;

	public const int CONNECT_INTERACTIVE = 0x00000008;
	public const int CONNECT_PROMPT = 0x00000010;
	public const int CONNECT_REDIRECT = 0x00000080;
	public const int CONNECT_UPDATE_PROFILE = 0x00000001;
	public const int CONNECT_COMMANDLINE = 0x00000800;
	public const int CONNECT_CMD_SAVECRED = 0x00001000;

	public const int CONNECT_LOCALDRIVE = 0x00000100;

	/// Errors
	public const int NO_ERROR = 0;

	public const int ERROR_ACCESS_DENIED = 5;
	public const int ERROR_ALREADY_ASSIGNED = 85;
	public const int ERROR_BAD_DEVICE = 1200;
	public const int ERROR_BAD_NET_NAME = 67;
	public const int ERROR_BAD_PROVIDER = 1204;
	public const int ERROR_CANCELLED = 1223;
	public const int ERROR_EXTENDED_ERROR = 1208;
	public const int ERROR_INVALID_ADDRESS = 487;
	public const int ERROR_INVALID_PARAMETER = 87;
	public const int ERROR_INVALID_PASSWORD = 1216;
	public const int ERROR_MORE_DATA = 234;
	public const int ERROR_NO_MORE_ITEMS = 259;
	public const int ERROR_NO_NET_OR_BAD_PATH = 1203;
	public const int ERROR_NO_NETWORK = 1222;

	public const int ERROR_BAD_PROFILE = 1206;
	public const int ERROR_CANNOT_OPEN_PROFILE = 1205;
	public const int ERROR_DEVICE_IN_USE = 2404;
	public const int ERROR_NOT_CONNECTED = 2250;
	public const int ERROR_OPEN_FILES = 2401;
}
public class NetworkShareConnection : IDisposable
{
	public string UncPath { get; private set; }
	public string UserName { get; private set; }
	public string Password { get; private set; }

	#region PInvoke Signatures
	[DllImport("Mpr.dll")]
	private static extern int WNetUseConnection(IntPtr hwndOwner, NETRESOURCE lpNetResource,
		string lpPassword, string lpUserID, int dwFlags, string lpAccessName, string lpBufferSize, string lpResult);

	[DllImport("Mpr.dll")]
	private static extern int WNetCancelConnection2(string lpName, int dwFlags, bool fForce);

	[StructLayout(LayoutKind.Sequential)]
	private class NETRESOURCE
	{
		public int dwScope = 0;
		public int dwType = 0;
		public int dwDisplayType = 0;
		public int dwUsage = 0;
		public string lpLocalName = "";
		public string lpRemoteName = "";
		public string lpComment = "";
		public string lpProvider = "";
	}
	#endregion

	public NetworkShareConnection(string uncPath, string userName, string password)
	{
		UncPath = uncPath;
		UserName = userName;
		Password = password;
		ConnectToShare(UncPath, UserName, Password, false);
	}

	private void ConnectToShare(string remoteUnc, string username, string password, bool promptUser)
	{
		NETRESOURCE nr = new NETRESOURCE { dwType = NetworkShareConsts.RESOURCETYPE_DISK, lpRemoteName = remoteUnc };
		int result;
		if (promptUser)
		{
			result = WNetUseConnection(IntPtr.Zero, nr, "", "", NetworkShareConsts.CONNECT_INTERACTIVE | NetworkShareConsts.CONNECT_PROMPT, null, null, null);
		}
		else
		{
			result = WNetUseConnection(IntPtr.Zero, nr, password, username, 0, null, null, null);
		}
		if (result != NetworkShareConsts.NO_ERROR)
		{
			throw new Win32Exception(result);
		}
	}

	private void DisconnectFromShare(string remoteUnc)
	{
		int result = WNetCancelConnection2(remoteUnc, NetworkShareConsts.CONNECT_UPDATE_PROFILE, false);
		if (result != NetworkShareConsts.NO_ERROR)
		{
			throw new Win32Exception(result);
		}
	}

	public void Dispose()
	{
		DisconnectFromShare(UncPath);
	}
}

Example:

public string GetNetworkShare(string networkPath)
{
	var regEx = new Regex(@"(\\\\.*?\\[^\\]*)");
	return regEx.Match(networkPath)?.Groups[0]?.Value;
}
var networkPath = @"\\192.168.0.10\C$\test";
var filePath = Path.Combine(networkPath, fileName);
using (new NetworkShareConnection(GetNetworkShare(networkPath), userName, password))
{
        if (!Directory.Exists(networkPath))
                Directory.CreateDirectory(networkPath);
	using (var fs = File.OpenWrite(filePath))
	{
		data.CopyTo(fs);
	}
}
31640cookie-checkC# Access a (untrusted) network share