Move a file with ImpersonateLoggedOnUser

2019-05-10 09:38发布

问题:

I am trying to move a file, but gives this error:

System.UnauthorizedAccessException: Access to the path is denied..
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.__Error.WinIOError()
at System.IO.FileInfo.MoveTo(String destFileName)

To move the file, I have this code:

public void MssFile_Move (string ssPath, string ssDestinationDirectoryPath, string ssDomain, string ssUsername, string ssPassword, out string ssError_message) {
        IntPtr admin_token = IntPtr.Zero;
        ssError_message = "";

        try
        {
            DoImpersonateLoggedOnUser(  ssDomain
                          , ssUsername
                          , ssPassword
                          , out ssError_message
                          , out admin_token);                   


            FileInfo fi = new FileInfo(ssPath);
            //Destination Directory does not exist ?
            if ( !Directory.Exists(Path.GetDirectoryName(ssDestinationDirectoryPath)))
                    Directory.CreateDirectory(Path.GetDirectoryName(
                    ssDestinationDirectoryPath));
            fi.MoveTo (ssDestinationDirectoryPath);

            DoRevertToSelf(ssDomain);

        }
        catch (System.Exception se)
        {
            int ret = Marshal.GetLastWin32Error();
            ssError_message += "Win32Error: " + ret + "\n";
            ssError_message += se.ToString();
        }
        finally
        {
            if (admin_token != IntPtr.Zero)
                CloseHandle(admin_token);
        }                   
    }

To impersonate I have:

[DllImport("advapi32.DLL", SetLastError = true)]
        public static extern int LogonUser(string lpszUsername, string lpszDomain,
            string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
        [DllImport("advapi32.DLL")]
        public static extern bool ImpersonateLoggedOnUser(IntPtr hToken); //handle to token for logged-on user


public void DoImpersonateLoggedOnUser (     string ssDomain
                                            ,   string ssUsername
                                            ,   string ssPassword
                                            ,   out string ssError_message
                                            ,   out IntPtr admin_token)
    {
        IntPtr phToken = IntPtr.Zero;
        admin_token = IntPtr.Zero;
        ssError_message = "";

        if (ssDomain != "")
        {
            if (LogonUser(ssUsername, ssDomain, ssPassword, 9, 0, out phToken) != 0)
            {
                ImpersonateLoggedOnUser(phToken);           
            }
            else
            {
                int nErrorCode = Marshal.GetLastWin32Error();

                ssError_message = "Operation Failed, error: " + nErrorCode;
            }
            admin_token = phToken;
        }           
    }

If I set the folder /file to permissions everyone, it works, but I don't want that. What am I doing wrong?

回答1:

Done it sucessfull with this code.

[DllImport("advapi32.DLL", SetLastError = true)]
public static extern int LogonUser(
    string lpszUsername, 
    string lpszDomain,
    string lpszPassword, 
    int dwLogonType, 
    int dwLogonProvider, 
    out IntPtr phToken);

[DllImport("advapi32.DLL")]
public static extern bool ImpersonateLoggedOnUser(IntPtr hToken); //handle to token for logged-on user

[DllImport("advapi32.DLL")]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll")]
public extern static bool CloseHandle(IntPtr hToken);

enum LogonType
{
    Interactive = 2,
    Network = 3,
    Batch = 4,
    Service = 5,
    Unlock = 7,
    NetworkClearText = 8,
    NewCredentials = 9
}

enum LogonProvider
{
     Default = 0,
     WinNT35 = 1,
     WinNT40 = 2,
     WinNT50 = 3
}

int valid = LogonUser(
    ssUsername,
    ssDomain,
    ssPassword,
    (int)LogonType.Interactive,
    (int)LogonProvider.WinNT50,
    out admin_token);

if (valid != 0)
{
    using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(admin_token))
    {
        CloseHandle(admin_token);
        FileInfo fi = new FileInfo(ssPath);

        //Destination Directory does not exist ?
        if (!Directory.Exists(Path.GetDirectoryName(ssDestinationDirectoryPath)))
            Directory.CreateDirectory(Path.GetDirectoryName(ssDestinationDirectoryPath));

        fi.CopyTo(ssDestinationDirectoryPath);
        fi.Delete();
    }
}


回答2:

there are two possible conflicts: is the impersonated use allowed to delete the source-file ?

is the user allowed to see the full path down to ssDestinationDirectoryPath ?

I've got much trouble with file-moves, so please try to copy and then delete.