[Wine-patches] Add event to signal when should repeat get_add_device_request (eterbug #2726)

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Пн Окт 27 19:45:48 MSK 2008


----------- следующая часть -----------
From 63aaa40cac8acef5ac13233367e3283737f14ea5 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Mon, 27 Oct 2008 18:00:54 +0300
Subject: [PATCH] Add event to signal when should repeat get_add_device_request (eterbug #2726).

---
 programs/winedevice/device.c |    8 +++-
 server/device.c              |  109 ++++++++++++++++++++++++++++++++----------
 server/protocol.def          |    2 +
 3 files changed, 93 insertions(+), 26 deletions(-)

diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c
index 54ae128..bd11da9 100644
--- a/programs/winedevice/device.c
+++ b/programs/winedevice/device.c
@@ -297,16 +297,22 @@ static void WINAPI ServiceMain( DWORD argc, LPWSTR *argv )
 
             while (!reply_size)
             {
+                HANDLE event = NULL;
+
                 SERVER_START_REQ( get_add_device_request )
                 {
+                    req->event = event;
                     wine_server_add_data( req, drvname.Buffer, drvname.Length );
                     wine_server_set_reply( req, pdo_info, sizeof(pdo_info) );
                     ret = wine_server_call( req );
+                    event = reply->event;
                     if (STATUS_SUCCESS == ret)
                         reply_size = wine_server_reply_size( reply );
                 }
                 SERVER_END_REQ;
-                Sleep( 100 );
+
+                if (STATUS_PENDING == ret)
+                    WaitForSingleObject( event, INFINITE );
             }
 
             pdev_obj = __wine_usbhub_get_pdo( pdo_info );
diff --git a/server/device.c b/server/device.c
index eb1b593..d424db4 100644
--- a/server/device.c
+++ b/server/device.c
@@ -173,6 +173,7 @@ struct add_dev_request
 };
 
 static void add_dev_req_dump( struct object *obj, int verbose );
+static int add_dev_req_signaled( struct object *obj, struct thread *thread );
 static void add_dev_req_destroy( struct object *obj );
 
 static const struct object_ops add_dev_requests_ops =
@@ -180,9 +181,9 @@ static const struct object_ops add_dev_requests_ops =
     sizeof(struct add_dev_request),   /* size */
     add_dev_req_dump,                 /* dump */
     no_get_type,                      /* get_type */
-    no_add_queue,                     /* add_queue */
-    NULL,                             /* remove_queue */
-    NULL,                             /* signaled */
+    add_queue,                        /* add_queue */
+    remove_queue,                     /* remove_queue */
+    add_dev_req_signaled,             /* signaled */
     no_satisfied,                     /* satisfied */
     no_signal,                        /* signal */
     no_get_fd,                        /* get_fd */
@@ -461,6 +462,45 @@ static struct device_manager *create_device_manager(void)
 }
 
 
+static struct add_dev_request *create_add_dev_req( const struct unicode_str *drvname )
+{
+    struct add_dev_request *add_dev_req = NULL;
+    void *p;
+
+    p = mem_alloc( drvname->len );
+    if (p)
+    {
+        add_dev_req = alloc_object( &add_dev_requests_ops );
+        if (add_dev_req)
+        {
+            memcpy( p, drvname->str, drvname->len );
+            add_dev_req->drvname.len = drvname->len;
+            add_dev_req->drvname.str = p;
+            add_dev_req->data = NULL;
+            add_dev_req->size = 0;
+            list_add_tail( &add_dev_requests_list, &add_dev_req->entry );
+        }
+        else
+            free( p );
+    }
+    return add_dev_req;
+}
+
+static struct add_dev_request *get_add_dev_req( const struct unicode_str *drvname )
+{
+    struct add_dev_request *add_dev_req;
+    struct unicode_str *p;
+
+    LIST_FOR_EACH_ENTRY( add_dev_req, &add_dev_requests_list, struct add_dev_request, entry )
+    {
+        p = &add_dev_req->drvname;
+        if (p->len != drvname->len) continue;
+        if (!strncmpiW( drvname->str, p->str, p->len/sizeof(WCHAR) ))
+            return add_dev_req;
+    }
+    return NULL;
+}
+
 static void add_dev_req_dump( struct object *obj, int verbose )
 {
     struct add_dev_request *add_dev_req = (struct add_dev_request *)obj;
@@ -472,13 +512,20 @@ static void add_dev_req_dump( struct object *obj, int verbose )
     fputc( '\n', stderr );
 }
 
+static int add_dev_req_signaled( struct object *obj, struct thread *thread )
+{
+    struct add_dev_request *add_dev_req = (struct add_dev_request *)obj;
+
+    return add_dev_req->size;
+}
+
 static void add_dev_req_destroy( struct object *obj )
 {
     struct add_dev_request *add_dev_req = (struct add_dev_request *)obj;
 
     list_remove( &add_dev_req->entry );
-    /* data and drvname.str are in the same memory block pointed to by drvname.str */
     free( (void *)add_dev_req->drvname.str );
+    free( add_dev_req->data );
 }
 
 
@@ -618,23 +665,28 @@ DECL_HANDLER(call_add_device)
     void *p;
     struct add_dev_request *add_dev_req;
     data_size_t size;
+    struct unicode_str drvname;
 
-    size = get_req_data_size();
+    drvname.str = get_req_data();
+    drvname.len = req->drvname_len;
+    size = get_req_data_size() - req->drvname_len;
     p = mem_alloc( size );
     if (p)
     {
-        add_dev_req = alloc_object( &add_dev_requests_ops );
-        if (add_dev_req)
+        add_dev_req = get_add_dev_req( &drvname );
+        if (!add_dev_req)
         {
-            memcpy( p, get_req_data(), size );
-            add_dev_req->drvname.len = req->drvname_len;
-            add_dev_req->drvname.str = p;
-            add_dev_req->data = (char *)p + req->drvname_len;
-            add_dev_req->size = size - req->drvname_len;
-            list_add_tail( &add_dev_requests_list, &add_dev_req->entry );
+            add_dev_req = create_add_dev_req( &drvname );
+            if (!add_dev_req)
+            {
+                free( p );
+                return;
+            }
         }
-        else
-            free( p );
+        memcpy( p, (char *)get_req_data() + req->drvname_len, size );
+        add_dev_req->data = p;
+        add_dev_req->size = size;
+        wake_up( &add_dev_req->obj, 0 );
     }
 }
 
@@ -643,25 +695,32 @@ DECL_HANDLER(get_add_device_request)
 {
     struct unicode_str drvname;
     struct add_dev_request *add_dev_req;
-    int found = 0;
+
+    if (req->event)
+        close_handle( current->process, req->event );
 
     get_req_unicode_str( &drvname );
-    LIST_FOR_EACH_ENTRY( add_dev_req, &add_dev_requests_list, struct add_dev_request, entry )
-    {
-        struct unicode_str *p = &add_dev_req->drvname;
+    add_dev_req = get_add_dev_req( &drvname );
 
-        if (p->len != drvname.len) continue;
-        if (!strncmpiW( drvname.str, p->str, p->len/sizeof(WCHAR) ))
+    if (!add_dev_req)
+    {
+        add_dev_req = create_add_dev_req( &drvname );
+        if (!add_dev_req)
         {
-            found = 1;
-            break;
+            reply->event = NULL;
+            return;
         }
     }
-    if (found)
+
+    if (add_dev_req->size)
     {
         set_reply_data( add_dev_req->data, add_dev_req->size );
         release_object( add_dev_req );
     }
     else
-        set_reply_data( NULL, 0 );
+    {
+        reply->event = alloc_handle( current->process, add_dev_req, SYNCHRONIZE, 0 );
+        if (reply->event)
+            set_error( STATUS_PENDING );
+    }
 }
diff --git a/server/protocol.def b/server/protocol.def
index 959d782..9fc5645 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3077,8 +3077,10 @@ enum message_type
 
 /* Check if it should call AddDevice function */
 @REQ(get_add_device_request)
+    obj_handle_t    event;        /* old event */
     VARARG(drvname,unicode_str);  /* driver name */
 @REPLY
+    obj_handle_t    event;        /* event to signal when should repeat this request */
     VARARG(data,bytes);           /* driver specific data */
 @END
 
-- 
1.5.6.5.GIT



Подробная информация о списке рассылки Wine-patches