[PATCH 5/8] server: Notify client about freed object so that it may free associated kernel object.

Jacek Caban jacek at codeweavers.com
Fri Mar 15 13:19:16 CDT 2019


On 3/15/19 5:50 PM, Zebediah Figura wrote:
> On 03/15/2019 09:58 AM, Jacek Caban wrote:
>> Long term, we may consider making interface between server and device
>> manager more generic so that it could be used for messages other than IRPs.
>>
>> Signed-off-by: Jacek Caban <jacek at codeweavers.com>
>> ---
>>   dlls/ntoskrnl.exe/ntoskrnl.c | 14 +++++++++++++-
>>   server/device.c              | 15 +++++++++++++++
>>   server/protocol.def          |  6 ++++++
>>   3 files changed, 34 insertions(+), 1 deletion(-)
>>
>>
>>
>>
>>
> Sorry if this is a dumb question, but why do we need this (and then, by
> extension, the whole infrastructure involving server changes)?


Generally speaking, it's meant to allow kernel objects implementation. 
The main part in my consideration was ObReferenceObjectByHandle. 
Although we could have more hacks around it without server support, 
there are limitations to what's possible to hack. If we want to return 
exactly the same object for given actual object (implemented usually in 
server in Wine case), we need server involved in handle to object mapping.


Once we have that, there is another problem with object life time. 
Driver may release its reference to the object, but an other process may 
still have open handles. On Windows, those handles would keep object 
reference count of the object, but on Wine that count is in server, not 
ntoskrnl.exe. It means that only server knows when the object is 
actually destroyed. If we don't want to leak in ntoskrnl.exe, we need 
some mechanism to be notified about object being freed.


Also such kernel object reflecting a server object may be used as an 
argument for other functions, like KeSetEvent. Unlike events initialized 
with KeInitializeEvent, we don't have much control over such event. MRAC 
does that: it creates an event, passes it by handle in ioctl(), driver 
uses ObReferenceObjectByHandle and then KeSetEvent on this even. So we 
need a way to implement such functions on top of kernel object pointers. 
I tried storing handles on client side, but it had more problems as I 
noted in [1]. Instead, we may just get a handle whenever we need them 
and that's all we need to implement KeSetEvent on top of NtSetEvent.


In case of MRAC, it also needs FILE_OBJECT and PETHREAD. For 
FILE_OBJECT, it checks some of its fields. I didn't debug details yet, 
but found that some fake values satisfied its checks. PETHREAD follows 
the pattern of bug 46205, where ObReferenceObjectByHandle needs to 
return an object that we will be able to wait on later. On top of this 
series, all we need is something similar to [2]. And once we have that, 
KeGetCurrentThread (which you were interested in), would be a matter of 
calling ObReferenceObjectByHandle with current thread handle (and 
probably caching the result in TEB; also server would know thread client 
pointer, so it could just pass it directly in get_next_device_request 
when needed).


So there are multiple problems to solve. Some may be worked around 
without server support, others not. I tried to make it generic enough to 
fit all those requirements and allow using it for all objects. Note that 
server already has limited mechanism for mapping device files and 
devices to user pointers, which could also use the generic mechanism 
instead.


Jacek


[1] https://source.winehq.org/patches/data/159405

[2] https://source.winehq.org/patches/data/161002




More information about the wine-devel mailing list