Archive: System.dll: FILETIME Convertion


System.dll: FILETIME Convertion
Could someone help me to figure out the syntax I need to use to get the system time as "filetime" and then convert it to a long (INT64)?

I found the following code in Win32 Dev Help:

FILETIME ft;
SYSTEMTIME st;

GetLocalTime(&st);
SystemTimeToFileTime(&st,&ft);
Does anyone know how to change the FILETIME to a INT64 and back again at a later stage?

Vytautas

Extra information from the help file about the functions and structures they use.

Definitions of structures:

typedef struct _FILETIME { // ft  
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME;
typedef struct _SYSTEMTIME {  // st  
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME;

Definitions of functions:
VOID GetLocalTime(

LPSYSTEMTIME lpSystemTime // address of system time structure
);
BOOL SystemTimeToFileTime(

CONST SYSTEMTIME *lpSystemTime, // address of system time to convert
LPFILETIME lpFileTime // address of buffer for converted file time
);

Also in the help file they mention
Copy the resulting FILETIME structure to a LARGE_INTEGER structure.
Vytautas

get the latest beta or cvs, look at contrib\system directory.
You need the sysfunc.nsh, look thru the function systemGetFileSysTime.


OK so far I've got these functions

  System::Call '*(&i2, &i2, &i2, &i2, &i2, &i2, &i2, &i2) i .r1'
System::Call '*(&i2, &i2) l .r0'
System::Call 'kernel32::GetLocalTime(i) i(r1)'
System::Call 'kernel32::SystemTimeToFileTime(i, l) l(r1, r0)'
MessageBox MB_OK $0
However when I execute this code it always shows "1508792", which i think is probably only the HIGH order of the Int64. How should I modify the function to return the whole Int64 figure?

Vytautas :cry:

After doing some more testing in VC++ i found that "1508792" is the lower order value before it is initialized and it varies from machine to machine. Could anyone help me sort out the problems with these functions?

Thanks,
Vytautas


Doesn't the smGetFileSysTime macro from System.nsh work for you?


Originally posted by kichik
Doesn't the smGetFileSysTime macro from System.nsh work for you?
Yes but I would like to get the current system time as FILETIME so that i can compare it, after modification, with the result from smGetFileSysTime.

Vytautas

OK, so the problem in the last script is that you're printing out the pointer and not it's content. Include System.nsh and use:

System::Call '*$0${stSYSTEMTIME}(i .r1, i .r2)'

to get the high order DWORD into $2 and the low order DWORD into $1.

BTW, when allocating, why did you define every int to be a short? They should all be 4 bytes ints.


I'm not exacly sure where I am supposed to put this line "System::Call '*$0${stSYSTEMTIME}(i .r1, i .r2)'" and if you are refering to the "&i2" in the definitions I got those from the script on this page.

Vytautas


The *$0 line should come after the call to SystemTimeToFileTime.

The defintion in that page is for SYSTEMTIME structure which uses WORDs and not DWORDS. A DWORDS has 4 bytes, not 2 so the second line in your script should be:

System::Call '*(i, i) l .r0'


Thanks this does seem to work, I'll have to test it further but at least the numbers seem to be changing everytime i run the installer. However is there a way to copy that structure to an INT64 as mentioned in the MS Help file?

Vytautas


I think the following code achieves what I needed

  System::Call '*(stSYSTEMTIME) i .r1'
System::Call '*(i, i) l .r0'
System::Call 'kernel32::GetLocalTime(i) i(r1)'
System::Call 'kernel32::SystemTimeToFileTime(i, l) l(r1, r0)'
System::Call '*$0${stSYSTEMTIME}(l .r1)'
MessageBox MB_OK "$1"
Thanks for all your help kichik and brainsucker.

Vytautas

Both are wrong. It should be:

System::Call '*$0(i .r1, i .r2)'

without the ${stSYSTEMTIME} part that I have forgot to remove.

The complete INT64 is both of the numbers combined ($1 * (2^32) + $2). You can use System::Int64Op to work with this number. But it'll be enough to just compare the two parts alone as done with NSIS's GetFileTime.


Originally posted by kichik
The complete INT64 is both of the numbers combined ($1 * (2^32) + $2). You can use System::Int64Op to work with this number.
Thanks but you mixed up $1 and $2. I think the following code should work
  System::Call '*(stSYSTEMTIME) i .r1'
System::Call '*(i, i) l .r0'
System::Call 'kernel32::GetLocalTime(i) i(r1)'
System::Call 'kernel32::SystemTimeToFileTime(i, l) l(r1, r0)'
System::Call '*$0(i .r1, i .r2)'
System::Int64Op $2 * 4294967296
pop $3
System::Int64Op $3 + $1
pop $4
MessageBox MB_OK $4
BTW Do I have to use 4294967296 instead of 2^32 since Int64Op did not seem to work with 2^32?

Vytautas

Yep, right, this code should work.

Int64Op doesn't support expressions inside expression so you'll have to either use the current method, 0x100000000 or use Int64Op to get the number.