1

I have file paths which are very long, so can be handled only using SafeFileHandle.
Want to get creation datetime.
When tried getting millies and then converted in DateTime then it is 1600 years less.

Code:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool GetFileTime(SafeFileHandle hFile, ref long lpCreationTime, ref long lpLastAccessTime, ref long lpLastWriteTime);

void fnc(String file){
    var filePath = @"\\?\" + file;
    var fileObj = CreateFile(filePath, Constants.SafeFile.GENERIC_READ, 0, IntPtr.Zero, Constants.SafeFile.OPEN_EXISTING, 0, IntPtr.Zero);
    long millies = 0, l1 = 0, l2 = 0;

    if(GetFileTime(fileObj, ref millies, ref l1, ref l2))
    {
        DateTime creationTime = new DateTime(millies, DateTimeKind.Local);

Above creationTime is 1600 years less. Instead of year 2019, its 0419.

Then I had to do this

        DateTime creationTime = new DateTime(millies, DateTimeKind.Local).AddYears(1600);
    }
}

Above creationTime is correct as I have added 1600 years.

What makes date 1600 years less?
Am I doing anything wrong?

Prem
  • 316
  • 1
  • 5
  • 23
  • The FILETIME structure returned by GetFileTime returns the number of 100 nanosecond intervals starting from January 1st 1601: https://learn.microsoft.com/en-gb/windows/win32/api/minwinbase/ns-minwinbase-filetime – theduck Jul 31 '19 at 10:54
  • 1
    I believe you can use DateTime.FromFileTime() to convert safely – theduck Jul 31 '19 at 10:58

2 Answers2

2

This is entirely by design when working with file times.

The basis for the returned file time is a counter from 01/01/1601:

A file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC).

Reference the official documentation.

Martin
  • 16,093
  • 1
  • 29
  • 48
1

The FILETIME structure returned by GetFileTime returns the number of 100 nanosecond intervals starting from January 1st 1601. You can see the documentation for this here: Microsoft docs

Rather than adding 1600 years there is a built in .net function that converts for you - DateTime.FromFileTime(). In your example the code would be:

if (GetFileTime(fileObj, ref millies, ref l1, ref l2))
{
    DateTime creationTime = DateTime.FromFileTime(millies);
}

I would also change the variable name from millies as that is a bit misleading (GetFileTime does not return milliseconds).

theduck
  • 2,589
  • 13
  • 17
  • 23