[Bug 7876] CPU-Z cannot load cpu-z.sys due to missing ntoskrnl implementation

Wine Bugs wine-bugs at winehq.org
Fri May 25 09:43:10 CDT 2007


http://bugs.winehq.org/show_bug.cgi?id=7876





------- Additional Comments From focht at gmx.net  2007-25-05 09:43 -------
Hello,

due to some stall (read: hit-the-wall) in other kmode projects, I gave this one
a shot with my current ntoskrnl impl.
After adding MmMapIoSpace() and MmUnmapIoSpace() impl to ntoskrnl the usermode
part issues a lot of device ioctls.
This consists of direct i/o port reads, gathering peripherals (ACPI ..), chipset
info, timing/calibration loops and the like.

There is a showstopper for now and probably forever due to the way wine is
currently designed.
In short: user mode pointers hidden in ioctl input buffers are passed from user
mode to kernel mode.

Now lets go into details...

--- snip relevant trace ---
...
003c:Call ntdll.RtlAllocateHeap(00610000,00000000,0000000c) ret=00460fa4
003c:Ret  ntdll.RtlAllocateHeap() retval=00b6b768 ret=00460fa4
003c:Call ntdll.RtlAllocateHeap(00610000,00000000,00000014) ret=00460fa4
003c:Ret  ntdll.RtlAllocateHeap() retval=00b6b780 ret=00460fa4
003c:Call ntdll.RtlAllocateHeap(00610000,00000000,00000404) ret=00460fa4
003c:Ret  ntdll.RtlAllocateHeap() retval=00b6b7a0 ret=00460fa4
003c:Call
KERNEL32.DeviceIoControl(00000074,9c402420,0034f494,0000000c,0034f4a0,00000008,0034f4cc,00000000)
ret=0047548e
0043:Ret  KERNEL32.WaitForMultipleObjects() retval=00000001 ret=603194a9
0043:Call ntdll.RtlFreeHeap(00110000,00000000,00188d68) ret=603190c2
0043:Ret  ntdll.RtlFreeHeap() retval=00000001 ret=603190c2
0043:Call ntdll.RtlAllocateHeap(00110000,00000000,0000000c) ret=603190e8
0043:Ret  ntdll.RtlAllocateHeap() retval=00188d68 ret=603190e8
0043:Call ntdll.RtlFreeHeap(00110000,00000000,00188d80) ret=60319149
0043:Ret  ntdll.RtlFreeHeap() retval=00000001 ret=60319149
0043:Call ntdll.RtlAllocateHeap(00110000,00000000,00000008) ret=60319183
0043:Ret  ntdll.RtlAllocateHeap() retval=00188d80 ret=60319183
0043:trace:ntoskrnl:process_ioctl ioctl 9c402420 device 0x188ca0 in_size 12
out_size 8
0043:trace:ntoskrnl:process_ioctl 0x188d68 0x188d80
0043:Call ntdll.NtGetTickCount() ret=60318920
0043:Ret  ntdll.NtGetTickCount() retval=005e6933 ret=60318920
0043:Call driver dispatch 0x350480 (device=0x188ca0,irp=0x6095c7a4)
0043:Call KERNEL32.GetEnvironmentVariableW(6032276e
L"DebugBreak",6095c434,00000104) ret=60318afd
0043:Ret  KERNEL32.GetEnvironmentVariableW() retval=00000000 ret=60318afd
0043:Call ntoskrnl.exe.MmMapIoSpace(00000000,00000000,00000400,00000000)
ret=00350716
0043:fixme:ntoskrnl:MmMapIoSpace stub: 0x0 1024 0
0043:Call ntdll.RtlAllocateHeap(00110000,00000000,00000400) ret=60318f13
0043:Ret  ntdll.RtlAllocateHeap() retval=0018ca68 ret=60318f13
0043:Ret  ntoskrnl.exe.MmMapIoSpace() retval=0018ca68 ret=00350716
0043:trace:seh:raise_exception code=c0000005 flags=0 addr=0x350733
0043:trace:seh:raise_exception  info[0]=00000001
0043:trace:seh:raise_exception  info[1]=00b6b7a0
0043:trace:seh:raise_exception  eax=00b6b740 ebx=00000400 ecx=00b6b7a0
edx=ff6212c8 esi=00188d68 edi=6095c7a4
0043:trace:seh:raise_exception  ebp=6095c748 esp=6095c6c4 cs=0073 ds=007b
es=007b fs=0033 gs=003b flags=00010283 
--- snip relevant trace ---

So whats going on...

ioctl code 9c402420 decodes as follows: 

device: 0xc40 (cpu-z ring0 driver)
function: 0x908
access: FILE_ANY_ACCESS
method: METHOD_BUFFERED

The client (usermode) allocates 2 buffers (RtlAllocateHeap preceeding the
ioctl), with input buffer size = 0xc and output buffer size = 0x8.
It passes data in input buffer, specific to function code, which is used in
kernel driver for further operations.

- ioctl in/out buffers get copied in wineserver (see RtlAllocateHeap() after ioctl).
- IRP gets constructed and passed to the drivers ioctl handler.

The temporary buffers are assigned to IRP:

(1)   irp.AssociatedIrp.SystemBuffer = in_buff;
      irp.UserBuffer = out_buff;
      ...
      irpsp.Parameters.DeviceIoControl.Type3InputBuffer = in_buff;

---

The kernel driver accesses the input buffer to extract data.
In this case the buffer contains parameters which are used for driver functions.

FIRST error: the Type3InputBuffer is accessed to extract parameters.
This is not allowed in kernel mode drivers when the METHOD_BUFFERED flag is
passed using ioctl.
With METHOD_BUFFERED, the input buffer is in Irp->AssociatedIrp.SystemBuffer.
This is a general rule for kernel driver developers ... but well :-)

Though wine "corrects" this error, by associating the input buffer pointer to
both locations, see (1)

Now it gets interesting.
The following is memory dump of input buffer (Type3InputBuffer, 3x4 DWORDs ->
size 0xC):

offset+0:  00000000
offset+4:  00000400
offset+8   00b6b7a0

The first DWORD is the physical address and the second one is length in bytes
used for MmMapIoSpace().
The driver maps physical memory into nonpaged area to access it.
This direct access is used to dump data from peripherals, like the memory
controller hub (MCHBAR) and others.

The real problem is the third parameter.
This is actually a user mode pointer, allocated before the ioctl call (look for
0x00b6b7a0 address in trace).
This buffer is used as target buffer to hold the data copied from physical space.

Wine doesnt know about this data, because it only sees the device ioctl input
and output buffers as "whole" data block.
So it cannot translate any contained pointers automatically to a valid user
space address.
Remember: the kernel driver runs in winedevice process, while the user mode
client runs in another address space.

Dang. Lost.
The driver would have to run in same address space as the usermode client which
breaks the whole design...

Hope you enjoyed this little analysis ... and sorry, this problem can't be
possibly fixed. :-(

Regards


-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.



More information about the wine-bugs mailing list