WIN32_FIND_DATA structure
Moderator: jNizM
WIN32_FIND_DATA structure
Moin,
konnte auf der schnelle kein sinnvollen Eintrag hier im Forum dazu finden.
Hat jemand schon mal sich mit der WIN32_FIND_DATA structure auseinander gesetzt?
WIN32_FIND_DATAA structure & WIN32_FIND_DATAW structure
Wird hauptsächlich für InternetFindNextFileA /W / FtpFindFirstFileA / W und InternetFindNextFileA / W benutzt
Im Forum finde ich die diversesten Strukturgrößen (z.B. 1140 usw.), die alle eigtl nicht stimmen können.
Mit dem sizeofchecker bekomme ich fogendes zurück:
WIN32_FIND_DATAA -> 320
WIN32_FIND_DATAW -> 592
konnte auf der schnelle kein sinnvollen Eintrag hier im Forum dazu finden.
Hat jemand schon mal sich mit der WIN32_FIND_DATA structure auseinander gesetzt?
WIN32_FIND_DATAA structure & WIN32_FIND_DATAW structure
Wird hauptsächlich für InternetFindNextFileA /W / FtpFindFirstFileA / W und InternetFindNextFileA / W benutzt
Im Forum finde ich die diversesten Strukturgrößen (z.B. 1140 usw.), die alle eigtl nicht stimmen können.
Mit dem sizeofchecker bekomme ich fogendes zurück:
WIN32_FIND_DATAA -> 320
WIN32_FIND_DATAW -> 592
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: WIN32_FIND_DATA structure
Code: Select all
typedef struct _WIN32_FIND_DATAA {
DWORD dwFileAttributes; // UInt 4
FILETIME ftCreationTime; // Ptr -> UInt / UInt 8
FILETIME ftLastAccessTime; // Ptr -> UInt / UInt 8
FILETIME ftLastWriteTime; // Ptr -> UInt / UInt 8
DWORD nFileSizeHigh; // UInt 4
DWORD nFileSizeLow; // UInt 4
DWORD dwReserved0; // UInt 4
DWORD dwReserved1; // UInt 4
_Field_z_ CHAR cFileName[ MAX_PATH ]; // Char 260
_Field_z_ CHAR cAlternateFileName[ 14 ]; // Char 14
#ifdef _MAC
DWORD dwFileType;
DWORD dwCreatorType;
WORD wFinderFlags;
#endif
} WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
Code: Select all
typedef struct _WIN32_FIND_DATAW {
DWORD dwFileAttributes; // UInt 4
FILETIME ftCreationTime; // Ptr -> UInt / UInt 8
FILETIME ftLastAccessTime; // Ptr -> UInt / UInt 8
FILETIME ftLastWriteTime; // Ptr -> UInt / UInt 8
DWORD nFileSizeHigh; // UInt 4
DWORD nFileSizeLow; // UInt 4
DWORD dwReserved0; // UInt 4
DWORD dwReserved1; // UInt 4
_Field_z_ WCHAR cFileName[ MAX_PATH ]; // UShort 260 * 2
_Field_z_ WCHAR cAlternateFileName[ 14 ]; // UShort 14 * 2
#ifdef _MAC
DWORD dwFileType;
DWORD dwCreatorType;
WORD wFinderFlags;
#endif
} WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW;
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: WIN32_FIND_DATA structure
Code: Select all
_WIN32_FIND_DATAA
{
[ 0] UInt dwFileAttributes
[ 4] UInt ftCreationTime.dwLowDateTime
[ 8] UInt ftCreationTime.dwHighDateTime
[ 12] UInt ftLastAccessTime.dwLowDateTime
[ 16] UInt ftLastAccessTime.dwHighDateTime
[ 20] UInt ftLastWriteTime.dwLowDateTime
[ 24] UInt ftLastWriteTime.dwHighDateTime
[ 28] UInt nFileSizeHigh
[ 32] UInt nFileSizeLow
[ 36] UInt dwReserved0
[ 40] UInt dwReserved1
[ 44] Char cFileName[ 260 ]
[304] Char cAlternateFileName[ 14 ]
[318] Char paddingbytes[ 2 ]
}
Re: WIN32_FIND_DATA structure
Moin,
nur ein ergänzender Hinweis:
Die FILETIME Struktur enthält zwei DWORD / UInt Felder a 4 Bytes. Das ergibt zwar mit 8 Bytes auf 64-Bit Systemen zusammen einen Speicherbereich in Pointergröße, es ist aber kein Ptr Typ. (Die Ausrichtung lässt grüßen!)
Die Werte aus Deinem sizeofchecker stimmen (siehe swagfag's paddingbytes).
Viel Spaß noch!
nur ein ergänzender Hinweis:
Die FILETIME Struktur enthält zwei DWORD / UInt Felder a 4 Bytes. Das ergibt zwar mit 8 Bytes auf 64-Bit Systemen zusammen einen Speicherbereich in Pointergröße, es ist aber kein Ptr Typ. (Die Ausrichtung lässt grüßen!)
Die Werte aus Deinem sizeofchecker stimmen (siehe swagfag's paddingbytes).
Viel Spaß noch!
Re: WIN32_FIND_DATA structure
Moin,
soweit habe ich das zzt. nur sind die Rüggabewerte noch etwas mau. Muss noch mehr testen.
soweit habe ich das zzt. nur sind die Rüggabewerte noch etwas mau. Muss noch mehr testen.
Code: Select all
...
FindFirstFile(hConnect, ByRef hFind, SearchFile := "*.*", TimeFormat := "system", SizeFormat := "auto", SizeSuffix := false)
{
VarSetCapacity(WIN32_FIND_DATA, (A_IsUnicode ? 592 : 320), 0)
if (hFind := DllCall("wininet\FtpFindFirstFile", "ptr", hConnect, "str", SearchFile, "ptr", &WIN32_FIND_DATA, "uint", 0, "uint*", 0))
return this.FindData(&WIN32_FIND_DATA, TimeFormat, SizeFormat, SizeSuffix)
VarSetCapacity(WIN32_FIND_DATA, 0)
return false
}
FindNextFile(hFind)
{
VarSetCapacity(WIN32_FIND_DATA, (A_IsUnicode ? 592 : 320), 0)
if (DllCall("wininet\InternetFindNextFile", "ptr", hFind, "ptr", &WIN32_FIND_DATA))
return this.FindData(&WIN32_FIND_DATA, TimeFormat, SizeFormat, SizeSuffix)
VarSetCapacity(WIN32_FIND_DATA, 0)
return false
}
FindData(WIN32_FIND_DATA, TimeFormat := "system", SizeFormat := "auto", SizeSuffix := false)
{
static MAX_PATH := 260
static MAXDWORD := 0xffffffff
addr := &WIN32_FIND_DATA
FIND_DATA := []
FIND_DATA["FileAttributes"] := "test"
FIND_DATA["CreationTime"] := this.FileTime( NumGet(addr + 4, "uint") << 32 | NumGet(addr + 8, "uint"), TimeFormat)
FIND_DATA["LastAccessTime"] := this.FileTime( NumGet(addr + 12, "uint") << 32 | NumGet(addr + 16, "uint"), TimeFormat)
FIND_DATA["LastWriteTime"] := this.FileTime( NumGet(addr + 20, "uint") << 32 | NumGet(addr + 24, "uint"), TimeFormat)
FIND_DATA["FileSize"] := this.FormatBytes((NumGet(addr + 28, "uint") * (MAXDWORD + 1)) + NumGet(addr + 32, "uint"), SizeFormat, SizeSuffix)
FIND_DATA["FileName"] := StrGet(addr + 44, "utf-16")
FIND_DATA["AlternateFileName"] := StrGet(addr + 44 + MAX_PATH * (A_IsUnicode ? 2 : 1), "utf-16")
return FIND_DATA
}
FileTime(FileTime, TimeFormat := "system")
{
addr := 0
if (TimeFormat = "system")
addr := this.FileTimeToSystemTime(FileTime)
else if (TimeFormat = "local")
addr := this.FileTimeToLocalFileTime(FileTime)
else
return false
if (addr)
{
return Format("{:04}{:02}{:02}{:02}{:02}{:02}"
, NumGet(addr, 0, "ushort")
, NumGet(addr, 2, "ushort")
, NumGet(addr, 6, "ushort")
, NumGet(addr, 8, "ushort")
, NumGet(addr, 10, "ushort")
, NumGet(addr, 12, "ushort"))
}
return false
}
FileTimeToSystemTime(FileTime)
{
VarSetCapacity(SystemTime, 16, 0)
if (DllCall("FileTimeToSystemTime", "ptr", &FileTime, "ptr", &SystemTime))
return &SystemTime
return false
}
FileTimeToLocalFileTime(FileTime)
{
VarSetCapacity(LocalTime, 16, 0)
if (DllCall("FileTimeToLocalFileTime", "ptr", &FileTime, "ptr", &LocalTime))
return &LocalTime
return false
}
SystemTimeToTzSpecificLocalTime(SystemTime)
{
VarSetCapacity(LocalTime, 16, 0)
if (DllCall("SystemTimeToTzSpecificLocalTime", "ptr", 0, "ptr", &SystemTime, "ptr", &LocalTime))
return &LocalTime
return false
}
FormatBytes(bytes, SizeFormat := "auto", suffix := false)
{
static SFBS_FLAGS_ROUND_TO_NEAREST_DISPLAYED_DIGIT := 0x0001
static SFBS_FLAGS_TRUNCATE_UNDISPLAYED_DECIMAL_DIGITS := 0x0002
static S_OK := 0
if (SizeFormat = "auto")
{
size := VarSetCapacity(buf, 1024, 0)
if (DllCall("shlwapi\StrFormatByteSizeEx", "int64", bytes, "int", SFBS_FLAGS_ROUND_TO_NEAREST_DISPLAYED_DIGIT, "str", buf, "uint", size) = S_OK)
output := buf
}
else if (SizeFormat = "kilobytes" || SizeFormat = "kb")
output := Round(bytes / 1024, 2) . (suffix ? " KB" : "")
else if (SizeFormat = "megabytes" || SizeFormat = "mb")
output := Round(bytes / 1024**2, 2) . (suffix ? " MB" : "")
else if (SizeFormat = "gigabytes" || SizeFormat = "gb")
output := Round(bytes / 1024**3, 2) . (suffix ? " GB" : "")
else if (SizeFormat = "terabytes" || SizeFormat = "tb")
output := Round(bytes / 1024**4, 2) . (suffix ? " TB" : "")
else
output := Round(bytes, 2) . (suffix ? " Bytes" : "")
return output
}
...
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: WIN32_FIND_DATA structure
- using the wrong pointer
- UB: accessing out of scope local variables
Re: WIN32_FIND_DATA structure
First one is done and works.
But for the "FILETIME" I still get strange outputs. Even if its in the same function
But for the "FILETIME" I still get strange outputs. Even if its in the same function
Code: Select all
FindFirstFile(hConnect, ByRef hFind, SearchFile := "*.*", TimeFormat := "system", SizeFormat := "auto", SizeSuffix := false)
{
VarSetCapacity(WIN32_FIND_DATA, (A_IsUnicode ? 592 : 320), 0)
if (hFind := DllCall("wininet\FtpFindFirstFile", "ptr", hConnect, "str", SearchFile, "ptr", &WIN32_FIND_DATA, "uint", 0, "uint*", 0))
{
;MsgBox % FileTime := NumGet(&WIN32_FIND_DATA + 4, "uint")
VarSetCapacity(FileTime, 8)
DllCall("RtlMoveMemory", "str", FileTime, "uint", &WIN32_FIND_DATA + 4, "uint", 8)
;VarSetCapacity(LocalTime, 16, 0)
;DllCall("FileTimeToLocalFileTime", "ptr", &FileTime, "ptr", &LocalTime)
VarSetCapacity(SystemTime, 16, 0)
DllCall("FileTimeToSystemTime", "ptr", &FileTime, "ptr", &SystemTime)
MsgBox % NumGet(SystemTime, 0, "ushort")
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: WIN32_FIND_DATA structure
Code: Select all
DllCall("RtlMoveMemory", "str", FileTime, "uint", &WIN32_FIND_DATA + 4, "uint", 8)
Code: Select all
DllCall("RtlMoveMemory", "Ptr", &FileTime, "Ptr", &WIN32_FIND_DATA + 4, "Ptr", 8)
Code: Select all
;VarSetCapacity(LocalTime, 16, 0)
;DllCall("FileTimeToLocalFileTime", "ptr", &FileTime, "ptr", &LocalTime)
thats as far as syntax goes. any other errors can only be attributed to other(unseen) syntax error or incorrect api usage. what does "strange outputs for FILETIME" mean?
Code: Select all
;MsgBox % FileTime := NumGet(&WIN32_FIND_DATA + 4, "uint")
Re: WIN32_FIND_DATA structure
Selbst wenn ich mich an den im Forum bereits versuchten Klassen / Funktionen halte, bekomme ich trotzdem immer falsche werte zurück.
Even if I stick to the classes / functions already tried in the forum, I still always get wrong values back.
while FileSize works perfect
i still stuck with FileTime. I tried every thing I found on this forum about WIN32_FIND_DATA
I don't know if I'm on the tube or just blind to see the error.
(sounds better in german: Keine Ahnung ob ich auf dem Schlauch stehe oder einfach nur Blind bin, den Fehler zu sehen.)
Even if I stick to the classes / functions already tried in the forum, I still always get wrong values back.
while FileSize works perfect
Code: Select all
FileSize := (NumGet(&WIN32_FIND_DATA + 28, "uint") * (MAXDWORD + 1)) + NumGet(&WIN32_FIND_DATA + 32, "uint")
MsgBox % FileSize ; -> 6 (bytes)
Code: Select all
;VarSetCapacity(FileTime, 8, 0)
;FileTime := NumGet(&WIN32_FIND_DATA + 4, "uint") << 32 | NumGet(&WIN32_FIND_DATA + 8, "uint") ; -> returns 1601
;FileTime := NumGet(&WIN32_FIND_DATA + 4, "ptr") ; -> returns 1601
;DllCall("RtlMoveMemory", "ptr", &FileTime, "ptr", &WIN32_FIND_DATA + 4, "uptr", 8) ; -> returns 1601
;DllCall("RtlMoveMemory", "ptr", FileTime, "ptr", &WIN32_FIND_DATA + 4, "uptr", 8) ; -> returns 1601
VarSetCapacity(SystemTime, 16, 0)
DllCall("FileTimeToSystemTime", "ptr", &FileTime, "ptr", &SystemTime)
MsgBox % NumGet(SystemTime, 0, "ushort") ; -> should be 2020 (Year)
(sounds better in german: Keine Ahnung ob ich auf dem Schlauch stehe oder einfach nur Blind bin, den Fehler zu sehen.)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: WIN32_FIND_DATA structure
Uff.. I got it...
My focus was too much on "CreationTime"... which still returns 1601. Also "LastAccessTime" returns 1601.
But "LastWriteTime" returns now 2020
Code: Select all
VarSetCapacity(FileTime, 8, 0)
DllCall("RtlMoveMemory", "ptr", &FileTime, "ptr", &WIN32_FIND_DATA + 20, "uptr", 8)
VarSetCapacity(SystemTime, 16, 0)
DllCall("FileTimeToSystemTime", "ptr", &FileTime, "ptr", &SystemTime)
MsgBox % "Year: " NumGet(SystemTime, 0, "ushort")
But "LastWriteTime" returns now 2020
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: WIN32_FIND_DATA structure
Atueller Stand des Projekts -> https://www.autohotkey.com/boards/viewtopic.php?f=6&p=344854#p344854
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: WIN32_FIND_DATA structure
Moin,
die Funktion FileTimeToSystemTime erwartet ja zwei Pointer:
1. einen Pointer auf eine FILETIME-Struktur,
2. einen Pointer auf eine SYSTEMTIME-Struktur.
Der Wert des Pointers auf die FILETIME-Struktur(ren) ist &WIN32_FIND_DATA + 4/12/20. Diesen Wert kannst Du der Funktion direkt übergeben. Das Auslesen und Zwischenspeichern des Inhalts brauchst Du dafür nicht.
Wenn Du den Wert in eine eigene Variable legen willst, sollte Folgendes funktionieren:
(Der Speicherbereich einer FILETIME-Struktur ist wie der eines Int64-Werts aufgebaut.)
die Funktion FileTimeToSystemTime erwartet ja zwei Pointer:
1. einen Pointer auf eine FILETIME-Struktur,
2. einen Pointer auf eine SYSTEMTIME-Struktur.
Der Wert des Pointers auf die FILETIME-Struktur(ren) ist &WIN32_FIND_DATA + 4/12/20. Diesen Wert kannst Du der Funktion direkt übergeben. Das Auslesen und Zwischenspeichern des Inhalts brauchst Du dafür nicht.
Wenn Du den Wert in eine eigene Variable legen willst, sollte Folgendes funktionieren:
Code: Select all
VarSetCapacity(FileTime, 8, 0)
NumPut(NumGet(&WIN32_FIND_DATA + 20, "UInt64"), FileTime, "UInt64")
VarSetCapacity(SystemTime, 16, 0)
DllCall("FileTimeToSystemTime", "Ptr", &FileTime, "Ptr", &SystemTime)
; -------------------------------------------------------------------
; oder alternativ
; -------------------------------------------------------------------
FileTime := NumGet(&WIN32_FIND_DATA + 20, "UInt64")
VarSetCapacity(SystemTime, 16, 0)
DllCall("FileTimeToSystemTime", "Int64P", FileTime, "Ptr", &SystemTime)
Re: WIN32_FIND_DATA structure
Danke euch beide. Habe es an der "alternative" angepasst.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: WIN32_FIND_DATA structure
Moin,
erweckt sehr stark den Anschein, dass in addr ein Pointer und kein Wert übergeben wird. Und genau so hatte ich mir das auch vorgestellt:
Für FtpFindFirstFile gibt es eine möglicherweise interessante Anmerkung:
Code: Select all
FileTime(addr)
{
this.FileTimeToSystemTime(addr, SystemTime)
...
}
Code: Select all
FindData(ByRef WIN32_FIND_DATA, SizeFormat := "auto", SizeSuffix := false)
{
...
FIND_DATA["CreationTime"] := this.FileTime(addr + 4)
FIND_DATA["LastAccessTime"] := this.FileTime(addr + 12)
FIND_DATA["LastWriteTime"] := this.FileTime(addr + 20)
...
}
...
FileTime(addr)
{
this.FileTimeToSystemTime(addr, SystemTime)
this.SystemTimeToTzSpecificLocalTime(&SystemTime, LocalTime)
...
}
...
FileTimeToSystemTime(FileTimePtr, ByRef SystemTime)
{
VarSetCapacity(SystemTime, 16, 0)
if (DllCall("FileTimeToSystemTime", "ptr", FileTimePtr, "ptr", &SystemTime))
return true
return false
}
Remarks
For FtpFindFirstFile, file times returned in the WIN32_FIND_DATA structure are in the local time zone, not in a coordinated universal time (UTC) format.