Winapi Pascal-Win32api SYSTEMTIME结构wYear始终为97
我有一个返回SYSTEMTIME的函数Winapi Pascal-Win32api SYSTEMTIME结构wYear始终为97,winapi,pascal,systemtime,Winapi,Pascal,Systemtime,我有一个返回SYSTEMTIME的函数 function GetFileDate : SYSTEMTIME; //Stdcall; var CheckFile: Long; FileTime: LPFILETIME; FileTimeReturn: LPFILETIME; SystemTimeReturn: LPSYSTEMTIME; begin CheckFile := CreateFile(PChar('main.dll'), GENERIC_READ
function GetFileDate : SYSTEMTIME; //Stdcall;
var
CheckFile: Long;
FileTime: LPFILETIME;
FileTimeReturn: LPFILETIME;
SystemTimeReturn: LPSYSTEMTIME;
begin
CheckFile := CreateFile(PChar('main.dll'), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
GetFileTime(CheckFile, @FileTime, NIL, NIL);
FileTimeToLocalFileTime(@FileTime, @FileTimeReturn);
FileTimeToSystemTime(@FileTime, @SystemTimeReturn);
GetFileDate := SystemTimeReturn^;
end;
对于2012年和2006年的文件以及其他任何文件,它总是返回97。
为什么?这段代码毫无意义,我很惊讶它居然能编译。您声明了三个指针变量,但从不让它们指向任何东西。您将指向这些变量的指针传递给API函数,但这些API函数并不期望指向您提供给它们的类型的指针
FileTimeToLocalFileTime
希望收到两个FILETIME
指针。您已经声明了FileTime
和FileTimeReturn
作为FileTime
值的指针,但是当您对它们应用@
运算符时,您会得到指向FileTime
值指针的指针。更好的代码应该如下所示:
function GetFileDate : SYSTEMTIME; //Stdcall;
var
CheckFile: Long;
FileTime: FILETIME;
FileTimeReturn: FILETIME;
SystemTimeReturn: SYSTEMTIME;
begin
CheckFile := CreateFile(PChar('main.dll'), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
GetFileTime(CheckFile, @FileTime, NIL, NIL);
FileTimeToLocalFileTime(@FileTime, @FileTimeReturn);
FileTimeToSystemTime(@FileTime, @SystemTimeReturn);
GetFileDate := SystemTimeReturn;
end;
注意,我已经从类型名中删除了LP
前缀,并且从最后一行中删除了取消引用
正确的代码将检查每个API函数的返回值,以确保在调用下一个函数之前成功
这就是为什么你会看到意想不到的结果。
FILETIME
是一个64位的值。如果使用32位系统,则LPFILETIME
变量的宽度仅为32位。API需要一个指向64位宽缓冲区的指针,但您给它一个指向32位空间的指针。当API将64位信息写入32位空间时,我们无法确定额外的32位存储在哪里
您传递了一个指向
SystemTimeReturn
的指针,它是一个LPSYSTEMTIME
。API将其写入该空间,就好像它是一个SYSTEMTIME
。然后,您的函数取消了对它假定为LPSYSTEMTIME
的引用,但它实际上包含SYSTEMTIME
类型的值。您取消了对时间的引用,而不是对指针的引用。您得到的时间恰巧看起来像一个有效地址,而驻留在该“地址”上的值恰巧是97。该代码毫无意义,我很惊讶它居然能编译。您声明了三个指针变量,但从不让它们指向任何东西。您将指向这些变量的指针传递给API函数,但这些API函数并不期望指向您提供给它们的类型的指针
FileTimeToLocalFileTime
希望收到两个FILETIME
指针。您已经声明了FileTime
和FileTimeReturn
作为FileTime
值的指针,但是当您对它们应用@
运算符时,您会得到指向FileTime
值指针的指针。更好的代码应该如下所示:
function GetFileDate : SYSTEMTIME; //Stdcall;
var
CheckFile: Long;
FileTime: FILETIME;
FileTimeReturn: FILETIME;
SystemTimeReturn: SYSTEMTIME;
begin
CheckFile := CreateFile(PChar('main.dll'), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
GetFileTime(CheckFile, @FileTime, NIL, NIL);
FileTimeToLocalFileTime(@FileTime, @FileTimeReturn);
FileTimeToSystemTime(@FileTime, @SystemTimeReturn);
GetFileDate := SystemTimeReturn;
end;
注意,我已经从类型名中删除了LP
前缀,并且从最后一行中删除了取消引用
正确的代码将检查每个API函数的返回值,以确保在调用下一个函数之前成功
这就是为什么你会看到意想不到的结果。
FILETIME
是一个64位的值。如果使用32位系统,则LPFILETIME
变量的宽度仅为32位。API需要一个指向64位宽缓冲区的指针,但您给它一个指向32位空间的指针。当API将64位信息写入32位空间时,我们无法确定额外的32位存储在哪里
您传递了一个指向
SystemTimeReturn
的指针,它是一个LPSYSTEMTIME
。API将其写入该空间,就好像它是一个SYSTEMTIME
。然后,您的函数取消了对它假定为LPSYSTEMTIME
的引用,但它实际上包含SYSTEMTIME
类型的值。您取消了对时间的引用,而不是对指针的引用。您得到的时间恰巧看起来像一个有效地址,而该“地址”上的值恰巧是97。购买苹果股票。几年后它会有价值;)PS:带有“LP”的类型通常表示“长指针”;i、 e.32位地址。您可能需要一个“FILETIME”或“SYSTEMTIME”记录;不是“LPFILETIME”;)如果您看到的是的最新答案,您将首先看到此代码的错误,并找到此问题的修复方法。(有一个原因会通知你问题的新内容-这样你就可以检查内容。):-)多么尴尬。对不起,买苹果股票。几年后它会有价值;)PS:带有“LP”的类型通常表示“长指针”;i、 e.32位地址。您可能需要一个“FILETIME”或“SYSTEMTIME”记录;不是“LPFILETIME”;)如果您看到的是的最新答案,您将首先看到此代码的错误,并找到此问题的修复方法。(有一个原因会通知你问题的新内容-这样你就可以检查内容。):-)多么尴尬。对不起。请参阅此海报的最后一个问题-Remy Lebeau也在那里纠正了此问题,但显然SuperDisk没有检查新内容。:-)@肯怀特:每当我提出这个问题时,他都没有发布编辑。抱歉,如果所有这些Pascal Winapi的东西听起来像是完全的白痴,我只是想了解Pascal。没关系。雷米的第二个答案并没有真正回答你提出的问题。它回答了你在这里提出的问题,这与你以前提出的问题完全不同。一个是编译器错误,另一个是运行时错误。你提出这个问题是对的;您不需要在另一个问题中发布函数体,因为它与编译器错误无关。+1。请参阅此海报的最后一个问题-Remy Lebeau也在那里纠正了此问题,但显然SuperDisk没有检查新内容。:-)@肯怀特:每当我提出这个问题时,他都没有发布编辑。抱歉,如果所有这些Pascal Winapi的东西听起来像是完全的白痴,我只是想了解Pascal。没关系。雷米的第二个答案并没有真正回答你提出的问题。它回答了这个问题