Help to create a server request

Charles Davis cdavis5x at gmail.com
Thu Aug 29 20:38:59 CDT 2013


On Aug 29, 2013, at 6:43 PM, Bruno Jesus wrote:

> Hi all, I need some help to continue my current wine work.
> 
> In order to implement SO_PROTOCOL_INFO for getsockopt I need to
> retrieve some information from the socket like its family and
> protocol.
> 
> I have searched for a few days and ended up with a solution I dislike
> so I had a better idea (at least I hope I did).
> 
> Instead of using non-portable SO_DOMAIN and SO_PROTOCOL/SO_PROTOTYPE
> to retrieve the socket family and protocol or using non-reliable
> guessing using only the socket type I thought it would be better to
> ask the server for this information. Using a request just like is used
> for several other information in ws2_32 (operation which will work on
> every OS).
> 
> So, all I need is a server request that based on the socket fd will
> return the socket family, type and protocol. I tried to understand how
> requests work but I failed completely.
> 
> Maybe this request can be later improved to return the connection time
> so we can finally fix SO_CONNECT_TIME option.
> 
> The current solution is attached, since I sent the tests separated and
> they were commited the patch will not apply, it's only for reference.
> The idea is to remove the functions get_sock_[family|protocol|type] to
> a single server request.
> 
> So, is this a good idea?
There's no way I know of to get this information directly on at least Mac OS, so I'd say go for it. (But I can't speak for anyone else on this list, so...)
> If yes, how can I create and use the request?
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:

@REQ(request_name)
    /* input parameters go here */
    int input;
    obj_handle_t handle; /* don't use Windows types */
@REPLY
    /* output values go here */
    int output;
@END

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:

DECL_HANDLER(request_name)
{
    /* 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);
    }
    else
    {
        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. */
    }
    do_something(reply->output);
}
SERVER_END_REQ;

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.) If you have any more questions (and not just because you were too lazy to even look ;), feel free to ask.

Chip




More information about the wine-devel mailing list