Module: wine Branch: refs/heads/master Commit: 0790f955897d5664997d7263fbd3e42165eda548 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=0790f955897d5664997d7263...
Author: Mike McCormack mike@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 );