- NSIS Discussion
- System.dll: FILETIME Convertion
Archive: System.dll: FILETIME Convertion
Vytautas
2nd July 2003 01:26 UTC
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
Vytautas
2nd July 2003 03:47 UTC
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
brainsucker
2nd July 2003 14:15 UTC
get the latest beta or cvs, look at contrib\system directory.
You need the sysfunc.nsh, look thru the function systemGetFileSysTime.
Vytautas
3rd July 2003 14:14 UTC
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:
Vytautas
4th July 2003 04:01 UTC
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
kichik
4th July 2003 17:22 UTC
Doesn't the smGetFileSysTime macro from System.nsh work for you?
Vytautas
5th July 2003 07:26 UTC
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
kichik
5th July 2003 11:29 UTC
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.
Vytautas
5th July 2003 13:39 UTC
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
kichik
5th July 2003 13:46 UTC
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'
Vytautas
5th July 2003 14:00 UTC
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
Vytautas
5th July 2003 14:33 UTC
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
kichik
5th July 2003 15:33 UTC
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.
Vytautas
5th July 2003 16:36 UTC
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
kichik
5th July 2003 16:44 UTC
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.