Mike McCormack : kernel32: ReadDirectoryChangesW fixes.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Feb 7 09:57:37 CST 2006


Module: wine
Branch: refs/heads/master
Commit: 0790f955897d5664997d7263fbd3e42165eda548
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=0790f955897d5664997d7263fbd3e42165eda548

Author: Mike McCormack <mike at codeweavers.com>
Date:   Tue Feb  7 16:50:36 2006 +0100

kernel32: ReadDirectoryChangesW fixes.
ReadDirectoryChangesW remembers whether it's recording changes or not.
Don't initialize overlapped->InternalHigh.
The hEvent is cleared when ReadDirectoryChanges is called.

---

 dlls/kernel/change.c           |   14 +++++++++++++-
 dlls/ntdll/directory.c         |    1 +
 include/wine/server_protocol.h |    3 ++-
 server/change.c                |   36 +++++++++++++++++++++++-------------
 server/protocol.def            |    1 +
 server/trace.c                 |    1 +
 6 files changed, 41 insertions(+), 15 deletions(-)

diff --git a/dlls/kernel/change.c b/dlls/kernel/change.c
index 235ac58..7c5eb92 100644
--- a/dlls/kernel/change.c
+++ b/dlls/kernel/change.c
@@ -132,6 +132,19 @@ BOOL WINAPI FindCloseChangeNotification(
     return CloseHandle( handle );
 }
 
+/****************************************************************************
+ *		ReadDirectoryChangesW (KERNEL32.@)
+ *
+ * NOTES
+ *
+ *  The filter is remember from the first run and ignored on successive runs.
+ *
+ *  If there's no output buffer on the first run, it's ignored successive runs
+ *   and STATUS_NOTIFY_ENUM_DIRECTORY is returned with an empty buffer.
+ *
+ *  If a NULL overlapped->hEvent is passed, the directory handle is used
+ *   for signalling.
+ */
 BOOL WINAPI ReadDirectoryChangesW( HANDLE handle, LPVOID buffer, DWORD len, BOOL subtree,
                                    DWORD filter, LPDWORD returned, LPOVERLAPPED overlapped,
                                    LPOVERLAPPED_COMPLETION_ROUTINE completion )
@@ -155,7 +168,6 @@ BOOL WINAPI ReadDirectoryChangesW( HANDL
 
     ios = (PIO_STATUS_BLOCK) pov;
     ios->Status = STATUS_PENDING;
-    ios->Information = 0;
 
     status = NtNotifyChangeDirectoryFile( handle, pov->hEvent, NULL, NULL,
                                           ios, buffer, len, filter, subtree );
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index 84e01af..af29057 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -1899,6 +1899,7 @@ NtNotifyChangeDirectoryFile( HANDLE File
         req->handle     = FileHandle;
         req->event      = Event;
         req->filter     = CompletionFilter;
+        req->want_data  = (Buffer != NULL);
         req->io_apc     = read_changes_apc;
         req->io_sb      = IoStatusBlock;
         req->io_user    = info;
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 8a061ed..9f9150c 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1401,6 +1401,7 @@ struct read_directory_changes_request
     obj_handle_t handle;
     obj_handle_t event;
     unsigned int filter;
+    int          want_data;
     void*        io_apc;
     void*        io_sb;
     void*        io_user;
@@ -4363,6 +4364,6 @@ union generic_reply
     struct query_symlink_reply query_symlink_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 224
+#define SERVER_PROTOCOL_VERSION 225
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/change.c b/server/change.c
index d6213fe..c35a82c 100644
--- a/server/change.c
+++ b/server/change.c
@@ -141,6 +141,7 @@ struct dir
     struct event  *event;
     unsigned int   filter;   /* notification filter */
     int            notified; /* SIGIO counter */
+    int            want_data; /* return change data */
     long           signaled; /* the file changed */
     struct fd     *inotify_fd; /* inotify file descriptor */
     int            wd;       /* inotify watch descriptor */
@@ -254,6 +255,7 @@ struct object *create_dir_obj( struct fd
     dir->filter = 0;
     dir->notified = 0;
     dir->signaled = 0;
+    dir->want_data = 0;
     dir->inotify_fd = NULL;
     dir->wd = -1;
     grab_object( fd );
@@ -412,20 +414,23 @@ static void inotify_do_change_notify( st
 {
     struct change_record *record;
 
-    record = malloc( sizeof (*record) + ie->len - 1 ) ;
-    if (!record)
-        return;
-
-    if( ie->mask & IN_CREATE )
-        record->action = FILE_ACTION_ADDED;
-    else if( ie->mask & IN_DELETE )
-        record->action = FILE_ACTION_REMOVED;
-    else
-        record->action = FILE_ACTION_MODIFIED;
-    memcpy( record->name, ie->name, ie->len );
-    record->len = strlen( ie->name );
+    if (dir->want_data)
+    {
+        record = malloc( sizeof (*record) + ie->len - 1 ) ;
+        if (!record)
+            return;
+
+        if( ie->mask & IN_CREATE )
+            record->action = FILE_ACTION_ADDED;
+        else if( ie->mask & IN_DELETE )
+            record->action = FILE_ACTION_REMOVED;
+        else
+            record->action = FILE_ACTION_MODIFIED;
+        memcpy( record->name, ie->name, ie->len );
+        record->len = strlen( ie->name );
 
-    list_add_tail( &dir->change_records, &record->entry );
+        list_add_tail( &dir->change_records, &record->entry );
+    }
 
     if (!list_empty( &dir->change_q ))
         async_terminate_head( &dir->change_q, STATUS_ALERTED );
@@ -551,12 +556,17 @@ DECL_HANDLER(read_directory_changes)
     {
         insert_change( dir );
         dir->filter = req->filter;
+        dir->want_data = req->want_data;
     }
 
     /* remove any notifications */
     if (dir->signaled>0)
         dir->signaled--;
 
+    /* clear the event */
+    if (event)
+        reset_event( event );
+
     /* setup the real notification */
 #ifdef USE_INOTIFY
     if (!inotify_adjust_changes( dir ))
diff --git a/server/protocol.def b/server/protocol.def
index 2b3a587..986a595 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1045,6 +1045,7 @@ enum char_info_mode
     obj_handle_t handle;        /* handle to the directory */
     obj_handle_t event;         /* handle to the event */
     unsigned int filter;        /* notification filter */
+    int          want_data;     /* flag indicating whether change data should be collected */
     void*        io_apc;        /* APC routine to queue upon end of async */
     void*        io_sb;         /* I/O status block (unique across all async on this handle) */
     void*        io_user;       /* data to pass back to caller */
diff --git a/server/trace.c b/server/trace.c
index e1ed879..05f4bb6 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1449,6 +1449,7 @@ static void dump_read_directory_changes_
     fprintf( stderr, " handle=%p,", req->handle );
     fprintf( stderr, " event=%p,", req->event );
     fprintf( stderr, " filter=%08x,", req->filter );
+    fprintf( stderr, " want_data=%d,", req->want_data );
     fprintf( stderr, " io_apc=%p,", req->io_apc );
     fprintf( stderr, " io_sb=%p,", req->io_sb );
     fprintf( stderr, " io_user=%p", req->io_user );




More information about the wine-cvs mailing list