Winapi Pascal-Win32api SYSTEMTIME结构wYear始终为97

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

我有一个返回SYSTEMTIME的函数

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。没关系。雷米的第二个答案并没有真正回答你提出的问题。它回答了这个问题