[PATCH 1/4] Handle FSCTL in NtDeviceIoControlFile.

Alex Xu (Hello71) alex_y_xu at yahoo.ca
Thu Jul 29 13:30:00 CDT 2021

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.

> 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.


More information about the wine-devel mailing list