In my ASP.NET Application, I must access file share on a remote server by its UNC path, i.e., \\server\folder\subfolder\, using specific username and password.
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.IO;
namespace RemoteCredentials
{
class MainClass
{
[DllImport( "advapi32.dll", SetLastError = true )]
private static extern bool LogonUser( string
lpszUsername, string lpszDomain, string lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken );
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private unsafe static extern int FormatMessage(int
dwFlags, ref IntPtr lpSource,
int dwMessageId, int dwLanguageId, ref String lpBuffer,
int nSize, IntPtr *arguments);
[DllImport( "kernel32.dll", CharSet = CharSet.Auto,
SetLastError = true )]
private static extern bool CloseHandle( IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public extern static bool DuplicateToken( IntPtr
existingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL,
ref IntPtr duplicateTokenHandle );
// logon types
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
// logon providers
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_PROVIDER_WINNT50 = 3;
const int LOGON32_PROVIDER_WINNT40 = 2;
const int LOGON32_PROVIDER_WINNT35 = 1;
///
/// The main entry point for the application.
///
[STAThread]
static void Main(string[] args)
{
IntPtr token = IntPtr.Zero;
IntPtr dupToken = IntPtr.Zero;
bool isSuccess = LogonUser(
"userId", "192.168.1.1", "password",
LOGON32_LOGON_NEW_CREDENTIALS,
LOGON32_PROVIDER_DEFAULT, ref token );
if( !isSuccess )
{
RaiseLastError();
}
isSuccess = DuplicateToken( token, 2, ref dupToken );
if( !isSuccess )
{
RaiseLastError();
}
WindowsIdentity newIdentity = new WindowsIdentity( dupToken );
WindowsImpersonationContext impersonatedUser
= newIdentity.Impersonate();
DirectoryInfo dirInfo = new DirectoryInfo(
@"\\192.19.12.46\sharedfolder" );
FileInfo[] files = dirInfo.GetFiles();
impersonatedUser.Undo();
foreach( FileInfo file in files )
{
Console.WriteLine( file.FullName );
}
isSuccess = CloseHandle( token );
if( !isSuccess )
{
RaiseLastError();
}
}
// GetErrorMessage formats and returns an error message
// corresponding to the input errorCode.
public unsafe static string GetErrorMessage( int errorCode )
{
int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
int messageSize = 255;
string lpMsgBuf = "";
int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS;
IntPtr ptrlpSource = IntPtr.Zero;
IntPtr ptrArguments = IntPtr.Zero;
int retVal = FormatMessage(
dwFlags, ref ptrlpSource, errorCode, 0,
ref lpMsgBuf, messageSize, &ptrArguments);
if( retVal == 0 )
{
throw new ApplicationException(
string.Format(
"Failed to format message for error code '{0}'."
, errorCode ) );
}
return lpMsgBuf;
}
private static void RaiseLastError()
{
int errorCode = Marshal.GetLastWin32Error();
string errorMessage = GetErrorMessage(errorCode );
throw new ApplicationException( errorMessage);
}
}
}