Alexandre Julliard : ntdll: Fix handling of async cancellation for directory changes.

Alexandre Julliard julliard at wine.codeweavers.com
Thu May 7 09:01:44 CDT 2015


Module: wine
Branch: master
Commit: 193667ecd7e8543d48d6c2f16cfd0abca818c3c8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=193667ecd7e8543d48d6c2f16cfd0abca818c3c8

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu May  7 16:02:26 2015 +0900

ntdll: Fix handling of async cancellation for directory changes.

---

 dlls/ntdll/file.c         | 113 ++++++++++++++++++++++++----------------------
 dlls/ntdll/tests/change.c |  10 ++--
 server/change.c           |   2 +-
 3 files changed, 65 insertions(+), 60 deletions(-)

diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 4c6b1b7..43e52c6 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -1805,73 +1805,78 @@ static NTSTATUS read_changes_apc( void *user, IO_STATUS_BLOCK *iosb,
                                   NTSTATUS status, void **apc, void **arg )
 {
     struct read_changes_fileio *fileio = user;
-    NTSTATUS ret;
-    int size;
+    int size = 0;
 
-    SERVER_START_REQ( read_change )
-    {
-        req->handle = wine_server_obj_handle( fileio->io.handle );
-        wine_server_set_reply( req, fileio->data, fileio->data_size );
-        ret = wine_server_call( req );
-        size = wine_server_reply_size( reply );
-    }
-    SERVER_END_REQ;
-
-    if (ret == STATUS_SUCCESS && fileio->buffer)
+    if (status == STATUS_ALERTED)
     {
-        FILE_NOTIFY_INFORMATION *pfni = fileio->buffer;
-        int i, left = fileio->buffer_size;
-        DWORD *last_entry_offset = NULL;
-        struct filesystem_event *event = (struct filesystem_event*)fileio->data;
-
-        while (size && left >= sizeof(*pfni))
+        SERVER_START_REQ( read_change )
         {
-            /* convert to an NT style path */
-            for (i=0; i<event->len; i++)
-                if (event->name[i] == '/') event->name[i] = '\\';
-
-            pfni->Action = event->action;
-            pfni->FileNameLength = ntdll_umbstowcs( 0, event->name, event->len, pfni->FileName,
-                    (left - offsetof(FILE_NOTIFY_INFORMATION, FileName)) / sizeof(WCHAR));
-            last_entry_offset = &pfni->NextEntryOffset;
-
-            if (pfni->FileNameLength == -1 || pfni->FileNameLength == -2) break;
-
-            i = offsetof(FILE_NOTIFY_INFORMATION, FileName[pfni->FileNameLength]);
-            pfni->FileNameLength *= sizeof(WCHAR);
-            pfni->NextEntryOffset = i;
-            pfni = (FILE_NOTIFY_INFORMATION*)((char*)pfni + i);
-            left -= i;
-
-            i = (offsetof(struct filesystem_event, name[event->len])
-                    + sizeof(int)-1) / sizeof(int) * sizeof(int);
-            event = (struct filesystem_event*)((char*)event + i);
-            size -= i;
+            req->handle = wine_server_obj_handle( fileio->io.handle );
+            wine_server_set_reply( req, fileio->data, fileio->data_size );
+            status = wine_server_call( req );
+            size = wine_server_reply_size( reply );
         }
+        SERVER_END_REQ;
 
-        if (size)
+        if (status == STATUS_SUCCESS && fileio->buffer)
         {
-            ret = STATUS_NOTIFY_ENUM_DIR;
-            size = 0;
+            FILE_NOTIFY_INFORMATION *pfni = fileio->buffer;
+            int i, left = fileio->buffer_size;
+            DWORD *last_entry_offset = NULL;
+            struct filesystem_event *event = (struct filesystem_event*)fileio->data;
+
+            while (size && left >= sizeof(*pfni))
+            {
+                /* convert to an NT style path */
+                for (i = 0; i < event->len; i++)
+                    if (event->name[i] == '/') event->name[i] = '\\';
+
+                pfni->Action = event->action;
+                pfni->FileNameLength = ntdll_umbstowcs( 0, event->name, event->len, pfni->FileName,
+                             (left - offsetof(FILE_NOTIFY_INFORMATION, FileName)) / sizeof(WCHAR));
+                last_entry_offset = &pfni->NextEntryOffset;
+
+                if (pfni->FileNameLength == -1 || pfni->FileNameLength == -2) break;
+
+                i = offsetof(FILE_NOTIFY_INFORMATION, FileName[pfni->FileNameLength]);
+                pfni->FileNameLength *= sizeof(WCHAR);
+                pfni->NextEntryOffset = i;
+                pfni = (FILE_NOTIFY_INFORMATION*)((char*)pfni + i);
+                left -= i;
+
+                i = (offsetof(struct filesystem_event, name[event->len])
+                     + sizeof(int)-1) / sizeof(int) * sizeof(int);
+                event = (struct filesystem_event*)((char*)event + i);
+                size -= i;
+            }
+
+            if (size)
+            {
+                status = STATUS_NOTIFY_ENUM_DIR;
+                size = 0;
+            }
+            else
+            {
+                if (last_entry_offset) *last_entry_offset = 0;
+                size = fileio->buffer_size - left;
+            }
         }
         else
         {
-            *last_entry_offset = 0;
-            size = fileio->buffer_size - left;
+            status = STATUS_NOTIFY_ENUM_DIR;
+            size = 0;
         }
     }
-    else
+
+    if (status != STATUS_PENDING)
     {
-        ret = STATUS_NOTIFY_ENUM_DIR;
-        size = 0;
+        iosb->u.Status = status;
+        iosb->Information = size;
+        *apc = fileio->io.apc;
+        *arg = fileio->io.apc_arg;
+        release_fileio( &fileio->io );
     }
-
-    iosb->u.Status = ret;
-    iosb->Information = size;
-    *apc = fileio->io.apc;
-    *arg = fileio->io.apc_arg;
-    release_fileio( &fileio->io );
-    return ret;
+    return status;
 }
 
 #define FILE_NOTIFY_ALL        (  \
diff --git a/dlls/ntdll/tests/change.c b/dlls/ntdll/tests/change.c
index 84e281c..0e76fb5 100644
--- a/dlls/ntdll/tests/change.c
+++ b/dlls/ntdll/tests/change.c
@@ -99,19 +99,19 @@ static void test_ntncdf(void)
     r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0);
     ok(r==STATUS_PENDING, "should return status pending\n");
 
-    r = WaitForSingleObject( hEvent, 0 );
+    r = WaitForSingleObject( hEvent, 100 );
     ok( r == STATUS_TIMEOUT, "should timeout\n" );
 
-    r = WaitForSingleObject( hdir, 0 );
+    r = WaitForSingleObject( hdir, 100 );
     ok( r == STATUS_TIMEOUT, "should timeout\n" );
 
     r = CreateDirectoryW( subdir, NULL );
     ok( r == TRUE, "failed to create directory\n");
 
-    r = WaitForSingleObject( hdir, 0 );
+    r = WaitForSingleObject( hdir, 100 );
     ok( r == STATUS_TIMEOUT, "should timeout\n" );
 
-    r = WaitForSingleObject( hEvent, 0 );
+    r = WaitForSingleObject( hEvent, 100 );
     ok( r == WAIT_OBJECT_0, "event should be ready\n" );
 
     ok( U(iosb).Status == STATUS_SUCCESS, "information wrong\n");
@@ -299,7 +299,7 @@ static void test_ntncdf_async(void)
     CloseHandle(hdir);
 
     ok(U(iosb).Status == STATUS_SUCCESS, "status wrong\n");
-    todo_wine ok(U(iosb2).Status == STATUS_CANCELLED, "status wrong\n");
+    ok(U(iosb2).Status == STATUS_CANCELLED, "status wrong %x\n",U(iosb2).Status);
 
     ok(iosb.Information == 0, "info wrong\n");
     ok(iosb2.Information == 0, "info wrong\n");
diff --git a/server/change.c b/server/change.c
index 08cee9b..11d9b93 100644
--- a/server/change.c
+++ b/server/change.c
@@ -272,7 +272,7 @@ void sigio_callback(void)
     LIST_FOR_EACH_ENTRY( dir, &change_list, struct dir, entry )
     {
         if (interlocked_xchg( &dir->notified, 0 ))
-            fd_async_wake_up( dir->fd, ASYNC_TYPE_WAIT, STATUS_NOTIFY_ENUM_DIR );
+            fd_async_wake_up( dir->fd, ASYNC_TYPE_WAIT, STATUS_ALERTED );
     }
 }
 




More information about the wine-cvs mailing list