wineserver is a daemon process that provides to Wine roughly the same services that the Windows kernel provides on Windows. It is normally launched automatically when starting Wine, so you shouldn't have to worry about it. In some cases however, it can be useful to start wineserver explicitly.

Server communication takes place via a simple, custom RPC protocol that is defined at {{{server/protocol.def}}} in the Wine SourceCode. This file is used to automatically generate others during the build process, and each time the regeneration process takes place the protocol version is bumped. Wine will refuse to start if the client and server protocol versions don't match so of you modify the protocol, you have to do a full tree rebuild. To see what a wineserver call looks like in the source code, grep for SERVER_START_REQ.

Some of the things the wineserver does include:

  • message routing
  • handling the registry
  • the debugging API
  • sync primitives
  • some window management
  • thread tracking
  • region manipulation...

and in the future, it will probably do even more (the windows kernel does a lot of stuff).

For more information on invoking the wineserver, run man wineserver from a terminal.

Help to create a server request

Charles Davis explained that quite well in this thread on wine-devel. He wrote:

To add a new request to the server, you first add a definition to server/protocol.def . This file is processed by the make_requests tool, which generates a bunch of other files from it. The syntax of the server protocol definition file is somewhat like Objective-C (if you've ever used or seen that). A typical server request definition looks like this:

    /* input parameters go here */
    int input;
    obj_handle_t handle; /* don't use Windows types */
    /* output values go here */
    int output;

As with all generated files, the files generated by make_requests shouldn't be included in your patch.

After defining a new server call, you define the handler in the server like so:

    /* implicit parameters: req, reply */
    /* use the 'current' global to refer to the process and thread that made the request */
    if (req->handle != ((obj_handle_t)-1))
        reply->output = do_something(req->input, req->handle);
        set_error(STATUS_UNSUCCESSFUL); /* NTSTATUS is returned to client */
    /* no return value */

Then, in the client DLLs, you make server calls like this:

SERVER_START_REQ( request_name )
    /* implicit variables: req, reply */
    req->input = 1;
    req->handle = wine_server_obj_handle( handle ); /* converts Windows HANDLE to a server obj_handle_t */
    if (wine_server_call( req ) != STATUS_SUCCESS)
        /* SetLastError(), return error code, etc. */

There's lots of examples throughout Wine of this in action, especially in lower-level DLLs like ntdll and kernel32; I encourage you to look at them. (That's how I figured all this out, after all.)

See Also

This page was last edited on 22 August 2020, at 23:16.