Possible help or direction to build Win to Linux pass through device - resent

Pavel Pisa pisa at cmp.felk.cvut.cz
Thu Jul 4 06:44:04 CDT 2013


Hello all,

thanks much for replies.

On Tuesday 02 of July 2013 18:15:28 Vincent Povirk wrote:
> > What others have suggested in similar situations is to build a Linux
> > application that speaks to the device driver directly, and provides a
> > socket interface, then use sockets from the Windows program to talk to
> > the device.
>
> I didn't think of that. A winelib dll providing an API for directly
> accessing your devices (which you can use from a normal Windows
> program) might be simpler than a separate process if you're willing to
> modify the application.

Do you mean by winelib dll that the wine/Liunux native .so style DLL
is built which is linked/imported through fakedlib to the application?
That looks like feasible solution and I would consider this solution
if there is interrest in the application in Linux community
and not enough resource is find  to port it as full Linux native
version.

How is it with wine version dependency if the wine .so style DLL uses
only bunch of Linux calls (open, close, read, write, ioctl) and exports
some small set of the functions to the application?

Another suggestion to use socket is also reasonable. In the fact we have
support for indirect uLAN access over TCP/IP implemented in other
utilities and programs but for this actual application it is missing
and would require more intrusive modifications. Its design is quite old
but it provides still valuable services to many old and new users.

I have done some more search to find narrow passes which limits
my initial idea of the driver based solution. I am sending my dump
there because it can be usesfull to somebody else (or even to me
if I find time one day and return to the problem).

The driver is run by Wine in the separate process.
This process calls get_next_device_request which is processed
on the Wine Server side in

wine-git/server/device.c:                                                             
/* retrieve the next pending device ioctl request */
DECL_HANDLER(get_next_device_request)

Even that name suggest that it is processing generic requests,
actual implementation is really minimal and allows only to encode
simple IOCTLs which use BUFFERED method to pass data.

But extension to more complete version is possible. It is questionable
if more fields and operations codes should be added or if the better
way to achieve complete functionality is to provide mechanism
to pass whole IRP from wine server to the service tasks.
This would be more close to the real Windows implementation
and original idea of microkernel based OS. But whole IRP
is quite huge and some mechanism to pass it and associated data
through shared memory would be probably much faster.

In both cases, there should be maintained/exchanged at least
value of the fields

StackPtr->FileObject->FsContext
StackPtr->FileObject->FsContext2

where drivers can store their context specific for each
device open instance (IRP_MJ_CREATE). It has to be stored
and read again from the HANDLE structure created/associated
with file in wine/server/directory.c.

Next operations needs to be propagated for our driver
(and probably would cover needs of significant range of other drivers too)

    ulan_driver = driver;
    driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ulan_dispatch;
    driver->MajorFunction[IRP_MJ_CREATE] = ulan_dispatch;
    driver->MajorFunction[IRP_MJ_CLOSE] = ulan_dispatch;
    driver->MajorFunction[IRP_MJ_READ] = ulan_dispatch;
    driver->MajorFunction[IRP_MJ_WRITE] = ulan_dispatch;
    driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ulan_dispatch;
    driver->MajorFunction[IRP_MJ_CLEANUP] = ulan_dispatch;


The analysis of the side of the started service

C:\windows\system32\winedevice.exe uL_Drv

wine/programs/winedevice/device.c:ServiceMain()
   wine_ntoskrnl_main_loop( stop_event );

wine/dlls/ntoskrnl.exe/ntoskrnl.c:
   wine_ntoskrnl_main_loop( HANDLE stop_event )
   
     SERVER_START_REQ( get_next_device_request )

   process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff, ULONG in_size,
                               void *out_buff, ULONG *out_size )
			       
   PDRIVER_DISPATCH dispatch = device->DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];

   Pointer irpStack->FileObject is filled with 0x66666666.

Good source of information how full IRP setup should work can be found
in React OS sources

reactos/reactos/reactos/ntoskrnl/io/iomgr/irp.c

and

reactos/reactos/reactos/ntoskrnl/io/iomgr/iofunc.c:IopDeviceFsIoControl
  including FileObject
  
    /* Setup the IRP */
    Irp->UserIosb = IoStatusBlock;
    Irp->UserEvent = EventObject;
    Irp->Overlay.AsynchronousParameters.UserApcRoutine = UserApcRoutine;
    Irp->Overlay.AsynchronousParameters.UserApcContext = UserApcContext;
    Irp->Cancel = FALSE;
    Irp->CancelRoutine = NULL;
    Irp->PendingReturned = FALSE;
    Irp->RequestorMode = PreviousMode;
    Irp->MdlAddress = NULL;
    Irp->AssociatedIrp.SystemBuffer = NULL;
    Irp->Flags = 0;
    Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();

    /* Set stack location settings */
    StackPtr = IoGetNextIrpStackLocation(Irp);
    StackPtr->FileObject = FileObject;
    StackPtr->MajorFunction = IsDevIoCtl ?
                              IRP_MJ_DEVICE_CONTROL :
                              IRP_MJ_FILE_SYSTEM_CONTROL;
    StackPtr->MinorFunction = 0; /* Minor function 0 is IRP_MN_USER_FS_REQUEST */
    StackPtr->Control = 0;
    StackPtr->Flags = 0;
    StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = NULL;

    /* Set the IOCTL Data */
    StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
    StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
    StackPtr->Parameters.DeviceIoControl.OutputBufferLength =
        OutputBufferLength;

This is example for IOCTL. The other operations need again similar but individual
setup.

So I hope that this information could be usesfull for somebody.

May it be that even my skeleton of the "native" driver extracted from Wine
sources can be usesfull for somebody who needs to substitute functionality
of some simpler driver which functionality is fully implemented in IOCTL
and without per open context.

 http://cmp.felk.cvut.cz/~pisa/ulan/wine/

Thanks again for advises and your work,

                Pavel



More information about the wine-devel mailing list