On 7/29/21 1:30 PM, Alex Xu (Hello71) wrote:
Excerpts from Zebediah Figura (she/her)'s message of July 26, 2021 12:36 pm:
On 7/26/21 9:13 AM, Alex Xu (Hello71) wrote:
Excerpts from Chip Davis's message of July 25, 2021 4:06 pm:
Needs tests showing that FSCTLs do indeed work with NtDeviceIoControlFile().
Chip
Yes, I see your point.
It looks like it should be simple to add NtDeviceIoControlFile in dlls/ntdll/tests/file.c, but I was wondering: there don't seem to be any tests already, and it seems like it should make more sense to add a test for DeviceIoControl instead (since that is what most applications will care about).
However, looking at that, there are two implementations of DeviceIoControl, in kernelbase and kernel32. Why doesn't the kernel32 one forward to kernelbase like most kernel32 functions? Also, why is the kernelbase function different from the kernel32 function? I don't know anything about VxDs, but it seems odd that the kernel32 one uses Information only for non-overlapped IO, but kernelbase uses it for overlapped too. Actually, looking at dlls/ntdll, it doesn't seem like InternalHigh is actually used for anything? It seems like it might happen to work on little-endian machines by chance due to alignment of OVERLAPPED and IO_STATUS_BLOCK, but this doesn't seem like a reliable method.
I checked git history, seems like InternalHigh should actually be Information everywhere? Thoughts?
No, this was done intentionally by Microsoft. OVERLAPPED is a documented user API; IO_STATUS_BLOCK is not (although now it is a documented kernel API). The fields of IO_STATUS_BLOCK are handled at the kernel32/kernelbase level but this handling is obscured in the user API by calling them "Internal" and "InternalHigh". The fields in the two structures match regardless of endianness.
How is this done in Wine? IO_STATUS_BLOCK in include/winternl.h has Status then Information, and include/winbase.h has InternalHigh then Internal for WORDS_BIGENDIAN, and reversed if not. Seems to me like InternalHigh is Information on LE, and Status/Pointer on BE.
I think Windows probably won't actually support BE CPUs in the future, considering they are becoming less and less popular, and looks like MinGW does not support it, but why should we intentionally write to Information and then read from InternalHigh? It seems unnecessarily confusing. The only value explicitly stored in InternalHigh in Wine appears to be 0; all other values are aliased.
Actually, I think our definition is wrong, and the ordering of Internal and InternalHigh shouldn't depend on endianness. It was added in [1], but I think that commit incorrectly assumed that InternalHigh was a "high" part of Internal in any meaningful way, which it is not.
For that matter, is the Offset/OffsetHigh part correct? I'm not sure there are any places where we alias those members with a LARGE_INTEGER.
[Did Windows *ever* support BE CPUs? I know that early versions of NT supported Alpha, MIPS, PowerPC (and current version support ARM), but my research tells me that even at the time all were bi-endian and that Windows ran them in LE.]
[1] https://www.winehq.org/pipermail/wine-patches/2005-March/016419.html
I'm not sure why we don't load VXD drivers in kernelbase; there doesn't seem to be any obvious reason why we can't, but we don't anyway.
I guess maybe the logic is that Win9x-era programs should use kernel32, not kernelbase? kernelbase DeviceIoControl is only 1.5 years old, maybe Julliard remembers?
I think current VxD behavior is basically "non-standard Wine extension" nowadays anyways; as long as programs work with no VxDs installed I don't see the issue either way.
There aren't any generic tests for NtDeviceIoControlFile and NtFsControlFile because all of the tests are rather specific to the different ioctls used. I'd recommend finding any place in the tests where one is used and testing the other as well. It wouldn't surprise me if both are identical nowadays.
OK, sounds good.
Regards, Alex.