SetFileTime returns error code 5

I'm trying to P / Invoke SetFileTime but I can't seem to get it to work. It always returns error code 5 for me (access denied) and I'm not sure why. Here is the code I'm using:

void Main()
{
    var pointer = CreateFile(@"C:\Users\User\Desktop\New folder\New Text Document.txt", FileAccess.ReadWrite, FileShare.None, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);
    Console.WriteLine(pointer);
    var now = DateTime.Now.ToFileTime();
    long lpCreationTime = now;
    long lpLastAccessTime = now;
    long lpLastWriteTime = now;
    if (!SetFileTime(pointer, ref lpCreationTime, ref lpLastAccessTime, ref lpLastWriteTime))
        Console.WriteLine(GetLastError());
    CloseHandle(pointer);
}

[DllImport("kernel32.dll")]
static extern UInt32 GetLastError();

[DllImport("kernel32.dll", SetLastError = true)]
static extern Boolean SetFileTime(IntPtr hFile, ref long lpCreationTime, ref long lpLastAccessTime, ref long lpLastWriteTime);

[DllImport("kernel32.dll", SetLastError = true)]
static extern Boolean CloseHandle(IntPtr hObject);

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern IntPtr CreateFile(String fileName, [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess, [MarshalAs(UnmanagedType.U4)] FileShare fileShare, IntPtr securityAttributes, [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, [MarshalAs(UnmanagedType.U4)] FileAttributes flags, IntPtr template);

      

My pointer is valid (2376), but I can see that SetFileTime failed and returned error code 5 (access denied). I have now ensured that I am running as an administrator and that my account has permissions to this path, but still no cigar. Anyone have any ideas why this is happening?

Update

Marshal.GetLastWin32Error()

also returns 5 after the call SetFileTime

. Also, my need to make this call works so that I can SetFileTime

support long paths on Windows CreateFile

, but the current .NET file libraries do not support long paths on Windows.

+3


source to share


2 answers


From the documentation SetFileTime

:

A handle to a file or directory. The handle must be created using the CreateFile function with FILE_WRITE_ATTRIBUTES access.

Your code cannot do this. The .net enumeration is FileAccess

incompatible with Win32 access flags. You will need to specify an enum specifically for use with CreateFile

. Similarly, you use FileShare

and FileMode

incorrect.

This p / invoke declaration should suffice: http://www.pinvoke.net/default.aspx/kernel32.createfile




As Alexei said, don't name GetLastError

because you can choose an error code to call the structure rather than the true error. Use SetLastError = true

and Marshal.GetLastWin32Error()

.

You also cannot check for errors in the return value if CreateFile

.

+4


source


Thanks to all the help I was able to achieve my goals using the following (FileAccess.ReadWrite translates to 0x3 and FILE_WRITE_ATTRIBUTES translates to 0x100):



[DllImport("kernel32.dll", SetLastError = true)]
static extern Boolean SetFileTime(SafeFileHandle hFile, ref long lpCreationTime, ref long lpLastAccessTime, ref long lpLastWriteTime);

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern SafeFileHandle CreateFile(String fileName, uint fileAccess, [MarshalAs(UnmanagedType.U4)] FileShare fileShare, IntPtr securityAttributes, [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, [MarshalAs(UnmanagedType.U4)] FileAttributes flags, IntPtr template);

static void Main(string[] args)
{
    var handle = CreateFile(@"C:\Users\User\Desktop\FileTimeTest.txt", (uint)(0x3 | 0x100), FileShare.None, IntPtr.Zero, FileMode.Create, FileAttributes.Normal, IntPtr.Zero);
    if (!handle.IsInvalid)
    {
        using (var stream = new FileStream(handle, FileAccess.ReadWrite))
        using (var writer = new StreamWriter(stream))
        {
            writer.WriteLine("Hello, world.");
            var now = DateTime.MaxValue.ToFileTime();
            if (!SetFileTime(handle, ref now, ref now, ref now))
                Console.WriteLine(Marshal.GetLastWin32Error());
        }
    }
}

      

+1


source







All Articles