Pascal - Win32api SYSTEMTIME struct wYear总是97

时间:2012-09-06 21:23:46

标签: 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, 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年。 为什么呢?

1 个答案:

答案 0 :(得分:3)

那段代码是无稽之谈,我很惊讶它完全可以编译。你声明了三个指针变量,但是你从不让它们指向任何东西。您将指向这些变量的指针传递给API函数,但这些API函数不会指向指向它们的类型的指针。

FileTimeToLocalFileTime预计会收到两个FILETIME指针。您已将FileTimeFileTimeReturn声明为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.