diff --git a/dlls/kernel/change.c b/dlls/kernel/change.c index 177c61652a1..d899f274b3b 100644 --- a/dlls/kernel/change.c +++ b/dlls/kernel/change.c @@ -65,7 +65,7 @@ HANDLE WINAPI FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtr if (!RtlDosPathNameToNtPathName_U( lpPathName, &nt_name, NULL, NULL )) { SetLastError( ERROR_PATH_NOT_FOUND ); - return INVALID_HANDLE_VALUE; + return ret; } attr.Length = sizeof(attr); @@ -75,27 +75,28 @@ HANDLE WINAPI FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtr attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; - status = NtOpenFile( &file, 0, &attr, &io, 0, + status = NtOpenFile( &file, SYNCHRONIZE, &attr, &io, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); RtlFreeUnicodeString( &nt_name ); if (status != STATUS_SUCCESS) { SetLastError( RtlNtStatusToDosError(status) ); - return INVALID_HANDLE_VALUE; + return ret; } - SERVER_START_REQ( create_change_notification ) + SERVER_START_REQ( read_directory_changes ) { - req->access = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE; - req->attributes = 0; req->handle = file; - req->subtree = bWatchSubtree; + req->event = NULL; req->filter = dwNotifyFilter; - if (!wine_server_call_err( req )) ret = reply->handle; + status = wine_server_call( req ); + if (status == STATUS_PENDING) + ret = file; } SERVER_END_REQ; - CloseHandle( file ); + return ret; } @@ -104,16 +105,28 @@ HANDLE WINAPI FindFirstChangeNotificationW( LPCWSTR lpPathName, BOOL bWatchSubtr */ BOOL WINAPI FindNextChangeNotification( HANDLE handle ) { - BOOL ret; + BOOL ret = FALSE; + NTSTATUS status; TRACE("%p\n",handle); - SERVER_START_REQ( next_change_notification ) + if (!handle) { - req->handle = handle; - ret = !wine_server_call_err( req ); + SetLastError( ERROR_INVALID_HANDLE ); + return ret; + } + + SERVER_START_REQ( read_directory_changes ) + { + req->handle = handle; + req->event = NULL; + req->filter = FILE_NOTIFY_CHANGE_SIZE; /* valid but ignored */ + status = wine_server_call( req ); + if (status == STATUS_PENDING) + ret = TRUE; } SERVER_END_REQ; + return ret; } diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index a86b9a4f7b8..b07174dd126 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -1778,6 +1778,16 @@ done: return status; } +#define FILE_NOTIFY_ALL ( \ + FILE_NOTIFY_CHANGE_FILE_NAME | \ + FILE_NOTIFY_CHANGE_DIR_NAME | \ + FILE_NOTIFY_CHANGE_ATTRIBUTES | \ + FILE_NOTIFY_CHANGE_SIZE | \ + FILE_NOTIFY_CHANGE_LAST_WRITE | \ + FILE_NOTIFY_CHANGE_LAST_ACCESS | \ + FILE_NOTIFY_CHANGE_CREATION | \ + FILE_NOTIFY_CHANGE_SECURITY ) + /****************************************************************************** * NtNotifyChangeDirectoryFile [NTDLL.@] */ @@ -1787,8 +1797,30 @@ NtNotifyChangeDirectoryFile( HANDLE FileHandle, HANDLE Event, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG BufferSize, ULONG CompletionFilter, BOOLEAN WatchTree ) { - FIXME("%p %p %p %p %p %p %lu %lu %d\n", + NTSTATUS status; + + TRACE("%p %p %p %p %p %p %lu %lu %d\n", FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, Buffer, BufferSize, CompletionFilter, WatchTree ); - return STATUS_NOT_IMPLEMENTED; + + if (!IoStatusBlock) + return STATUS_ACCESS_VIOLATION; + + if (CompletionFilter == 0 || (CompletionFilter & ~FILE_NOTIFY_ALL)) + return STATUS_INVALID_PARAMETER; + + if (ApcRoutine || ApcContext || Buffer || BufferSize || WatchTree) + FIXME("parameters ignored %p %p %p %lu %d\n", + ApcRoutine, ApcContext, Buffer, BufferSize, WatchTree ); + + SERVER_START_REQ( read_directory_changes ) + { + req->handle = FileHandle; + req->event = Event; + req->filter = CompletionFilter; + status = wine_server_call( req ); + } + SERVER_END_REQ; + + return status; } diff --git a/dlls/ntdll/tests/change.c b/dlls/ntdll/tests/change.c index 7ba527b0a3b..d07cb841a12 100644 --- a/dlls/ntdll/tests/change.c +++ b/dlls/ntdll/tests/change.c @@ -64,10 +64,8 @@ static void test_ntncdf(void) r = CreateDirectoryW(path, NULL); ok( r == TRUE, "failed to create directory\n"); - todo_wine { r = pNtNotifyChangeDirectoryFile(NULL,NULL,NULL,NULL,NULL,NULL,0,0,0); ok(r==STATUS_ACCESS_VIOLATION, "should return access violation\n"); - } fflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED; hdir = CreateFileW(path, GENERIC_READ|SYNCHRONIZE, FILE_SHARE_READ, NULL, @@ -76,7 +74,6 @@ static void test_ntncdf(void) hEvent = CreateEvent( NULL, 0, 0, NULL ); - todo_wine { r = pNtNotifyChangeDirectoryFile(hdir,NULL,NULL,NULL,&iosb,NULL,0,0,0); ok(r==STATUS_INVALID_PARAMETER, "should return invalid parameter\n"); @@ -93,31 +90,28 @@ static void test_ntncdf(void) filter |= FILE_NOTIFY_CHANGE_SECURITY; r = pNtNotifyChangeDirectoryFile(hdir,hEvent,NULL,NULL,&iosb,buffer,sizeof buffer,filter,0); - ok(r==STATUS_PENDING, "should return invalid parameter\n"); - } + ok(r==STATUS_PENDING, "should return status pending\n"); r = WaitForSingleObject( hEvent, 0 ); - ok( r == STATUS_TIMEOUT, "event ready\n" ); + ok( r == STATUS_TIMEOUT, "event shouldn't be ready\n" ); r = CreateDirectoryW( subdir, NULL ); ok( r == TRUE, "failed to create directory\n"); - todo_wine { r = WaitForSingleObject( hEvent, 0 ); - ok( r == WAIT_OBJECT_0, "event ready\n" ); + ok( r == WAIT_OBJECT_0, "event wasn't ready\n" ); r = pNtNotifyChangeDirectoryFile(hdir,0,NULL,NULL,&iosb,NULL,0,filter,0); - ok(r==STATUS_PENDING, "should return invalid parameter\n"); + ok(r==STATUS_PENDING, "should return status pending\n"); r = WaitForSingleObject( hdir, 0 ); - ok( r == STATUS_TIMEOUT, "event ready\n" ); - } + ok( r == STATUS_TIMEOUT, "event shouldn't be ready\n" ); r = RemoveDirectoryW( subdir ); ok( r == TRUE, "failed to remove directory\n"); r = WaitForSingleObject( hdir, 0 ); - ok( r == WAIT_OBJECT_0, "event ready\n" ); + ok( r == WAIT_OBJECT_0, "event wasn't ready\n" ); todo_wine { r = RemoveDirectoryW( path ); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index f5562153a3c..1be70aed531 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1396,34 +1396,20 @@ struct send_console_signal_reply -struct create_change_notification_request +struct read_directory_changes_request { struct request_header __header; - unsigned int access; - unsigned int attributes; obj_handle_t handle; - int subtree; + obj_handle_t event; unsigned int filter; }; -struct create_change_notification_reply -{ - struct reply_header __header; - obj_handle_t handle; -}; - - - -struct next_change_notification_request -{ - struct request_header __header; - obj_handle_t handle; -}; -struct next_change_notification_reply +struct read_directory_changes_reply { struct reply_header __header; }; + struct create_mapping_request { struct request_header __header; @@ -3782,8 +3768,7 @@ enum request REQ_read_console_output, REQ_move_console_output, REQ_send_console_signal, - REQ_create_change_notification, - REQ_next_change_notification, + REQ_read_directory_changes, REQ_create_mapping, REQ_open_mapping, REQ_get_mapping_info, @@ -4001,8 +3986,7 @@ union generic_request struct read_console_output_request read_console_output_request; struct move_console_output_request move_console_output_request; struct send_console_signal_request send_console_signal_request; - struct create_change_notification_request create_change_notification_request; - struct next_change_notification_request next_change_notification_request; + struct read_directory_changes_request read_directory_changes_request; struct create_mapping_request create_mapping_request; struct open_mapping_request open_mapping_request; struct get_mapping_info_request get_mapping_info_request; @@ -4218,8 +4202,7 @@ union generic_reply struct read_console_output_reply read_console_output_reply; struct move_console_output_reply move_console_output_reply; struct send_console_signal_reply send_console_signal_reply; - struct create_change_notification_reply create_change_notification_reply; - struct next_change_notification_reply next_change_notification_reply; + struct read_directory_changes_reply read_directory_changes_reply; struct create_mapping_reply create_mapping_reply; struct open_mapping_reply open_mapping_reply; struct get_mapping_info_reply get_mapping_info_reply; @@ -4362,6 +4345,6 @@ union generic_reply struct query_symlink_reply query_symlink_reply; }; -#define SERVER_PROTOCOL_VERSION 221 +#define SERVER_PROTOCOL_VERSION 222 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/change.c b/server/change.c index b3fead1d618..ca78093437a 100644 --- a/server/change.c +++ b/server/change.c @@ -2,6 +2,7 @@ * Server-side change notification management * * Copyright (C) 1998 Alexandre Julliard + * Copyright (C) 2006 Mike McCormack * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -51,35 +52,50 @@ #endif #endif -struct change +struct dir { struct object obj; /* object header */ struct fd *fd; /* file descriptor to the directory */ struct list entry; /* entry in global change notifications list */ - int subtree; /* watch all the subtree */ + struct event *event; unsigned int filter; /* notification filter */ int notified; /* SIGIO counter */ long signaled; /* the file changed */ }; -static void change_dump( struct object *obj, int verbose ); -static int change_signaled( struct object *obj, struct thread *thread ); -static void change_destroy( struct object *obj ); +static struct fd *dir_get_fd( struct object *obj ); +static unsigned int dir_map_access( struct object *obj, unsigned int access ); +static void dir_dump( struct object *obj, int verbose ); +static void dir_destroy( struct object *obj ); +static int dir_signaled( struct object *obj, struct thread *thread ); -static const struct object_ops change_ops = +static const struct object_ops dir_ops = { - sizeof(struct change), /* size */ - change_dump, /* dump */ + sizeof(struct dir), /* size */ + dir_dump, /* dump */ add_queue, /* add_queue */ remove_queue, /* remove_queue */ - change_signaled, /* signaled */ + dir_signaled, /* signaled */ no_satisfied, /* satisfied */ no_signal, /* signal */ - no_get_fd, /* get_fd */ - no_map_access, /* map_access */ + dir_get_fd, /* get_fd */ + dir_map_access, /* map_access */ no_lookup_name, /* lookup_name */ no_close_handle, /* close_handle */ - change_destroy /* destroy */ + dir_destroy /* destroy */ +}; + +static int dir_get_poll_events( struct fd *fd ); +static int dir_get_info( struct fd *fd ); + +static const struct fd_ops dir_fd_ops = +{ + dir_get_poll_events, /* get_poll_events */ + default_poll_event, /* poll_event */ + no_flush, /* flush */ + dir_get_info, /* get_file_info */ + default_fd_queue_async, /* queue_async */ + default_fd_cancel_async /* cancel_async */ }; static struct list change_list = LIST_INIT(change_list); @@ -113,77 +129,61 @@ static void adjust_changes( int fd, unsigned int filter ) } /* insert change in the global list */ -static inline void insert_change( struct change *change ) +static inline void insert_change( struct dir *dir ) { sigset_t sigset; sigemptyset( &sigset ); sigaddset( &sigset, SIGIO ); sigprocmask( SIG_BLOCK, &sigset, NULL ); - list_add_head( &change_list, &change->entry ); + list_add_head( &change_list, &dir->entry ); sigprocmask( SIG_UNBLOCK, &sigset, NULL ); } /* remove change from the global list */ -static inline void remove_change( struct change *change ) +static inline void remove_change( struct dir *dir ) { sigset_t sigset; sigemptyset( &sigset ); sigaddset( &sigset, SIGIO ); sigprocmask( SIG_BLOCK, &sigset, NULL ); - list_remove( &change->entry ); + list_remove( &dir->entry ); sigprocmask( SIG_UNBLOCK, &sigset, NULL ); } -static struct change *create_change_notification( struct fd *fd, int subtree, unsigned int filter ) +struct object *create_dir_obj( struct fd *fd ) { - struct change *change; - struct stat st; - int unix_fd = get_unix_fd( fd ); + struct dir *dir; - if (unix_fd == -1) return NULL; - - if (fstat( unix_fd, &st ) == -1 || !S_ISDIR(st.st_mode)) - { - set_error( STATUS_NOT_A_DIRECTORY ); + dir = alloc_object( &dir_ops ); + if (!dir) return NULL; - } + + dir->event = NULL; + dir->filter = 0; + dir->notified = 0; + dir->signaled = 0; + grab_object( fd ); + dir->fd = fd; + set_fd_user( fd, &dir_fd_ops, &dir->obj ); - if ((change = alloc_object( &change_ops ))) - { - change->fd = (struct fd *)grab_object( fd ); - change->subtree = subtree; - change->filter = filter; - change->notified = 0; - change->signaled = 0; - insert_change( change ); - adjust_changes( unix_fd, filter ); - } - return change; + return &dir->obj; } -static void change_dump( struct object *obj, int verbose ) +static void dir_dump( struct object *obj, int verbose ) { - struct change *change = (struct change *)obj; - assert( obj->ops == &change_ops ); - fprintf( stderr, "Change notification fd=%p sub=%d filter=%08x\n", - change->fd, change->subtree, change->filter ); + struct dir *dir = (struct dir *)obj; + assert( obj->ops == &dir_ops ); + fprintf( stderr, "Dirfile fd=%p event=%p filter=%08x\n", + dir->fd, dir->event, dir->filter ); } -static int change_signaled( struct object *obj, struct thread *thread ) +static int dir_signaled( struct object *obj, struct thread *thread ) { - struct change *change = (struct change *)obj; - - return change->signaled != 0; -} - -static void change_destroy( struct object *obj ) -{ - struct change *change = (struct change *)obj; - - release_object( change->fd ); - remove_change( change ); + struct dir *dir = (struct dir *)obj; + assert (obj->ops == &dir_ops); + return (dir->event == NULL) && dir->signaled; } /* enter here directly from SIGIO signal handler */ @@ -194,9 +194,9 @@ void do_change_notify( int unix_fd ) /* FIXME: this is O(n) ... probably can be improved */ LIST_FOR_EACH( ptr, &change_list ) { - struct change *change = LIST_ENTRY( ptr, struct change, entry ); - if (get_unix_fd( change->fd ) != unix_fd) continue; - interlocked_xchg_add( &change->notified, 1 ); + struct dir *dir = LIST_ENTRY( ptr, struct dir, entry ); + if (get_unix_fd( dir->fd ) != unix_fd) continue; + interlocked_xchg_add( &dir->notified, 1 ); break; } } @@ -208,46 +208,113 @@ void sigio_callback(void) LIST_FOR_EACH( ptr, &change_list ) { - struct change *change = LIST_ENTRY( ptr, struct change, entry ); - long count = interlocked_xchg( &change->notified, 0 ); + struct dir *dir = LIST_ENTRY( ptr, struct dir, entry ); + long count = interlocked_xchg( &dir->notified, 0 ); if (count) { - change->signaled += count; - if (change->signaled == count) /* was it 0? */ - wake_up( &change->obj, 0 ); + dir->signaled += count; + if (dir->signaled == count) /* was it 0? */ + { + if (dir->event) + set_event( dir->event ); + else + wake_up( &dir->obj, 0 ); + } } } } -/* create a change notification */ -DECL_HANDLER(create_change_notification) +static struct fd *dir_get_fd( struct object *obj ) { - struct change *change; - struct file *file; - struct fd *fd; - - if (!(file = get_file_obj( current->process, req->handle, 0 ))) return; - fd = get_obj_fd( (struct object *)file ); - release_object( file ); - if (!fd) return; - - if ((change = create_change_notification( fd, req->subtree, req->filter ))) - { - reply->handle = alloc_handle( current->process, change, req->access, req->attributes ); - release_object( change ); - } - release_object( fd ); + struct dir *dir = (struct dir *)obj; + assert( obj->ops == &dir_ops ); + return (struct fd *)grab_object( dir->fd ); } -/* move to the next change notification */ -DECL_HANDLER(next_change_notification) +static unsigned int dir_map_access( struct object *obj, unsigned int access ) { - struct change *change; - - if ((change = (struct change *)get_handle_obj( current->process, req->handle, - 0, &change_ops ))) - { - if (change->signaled > 0) change->signaled--; - release_object( change ); - } + if (access & GENERIC_READ) access |= FILE_GENERIC_READ; + if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE; + if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE; + if (access & GENERIC_ALL) access |= FILE_ALL_ACCESS; + return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL); +} + +static void dir_destroy( struct object *obj ) +{ + struct dir *dir = (struct dir *)obj; + assert (obj->ops == &dir_ops); + + if (dir->filter) + remove_change( dir ); + + if (dir->event) + { + set_event( dir->event ); + release_object( dir->event ); + } + release_object( dir->fd ); +} + +static struct dir * +get_dir_obj( struct process *process, obj_handle_t handle, unsigned int access ) +{ + return (struct dir *)get_handle_obj( process, handle, access, &dir_ops ); +} + +static int dir_get_poll_events( struct fd *fd ) +{ + return 0; +} + +static int dir_get_info( struct fd *fd ) +{ + return 0; +} + +/* enable change notifications for a directory */ +DECL_HANDLER(read_directory_changes) +{ + struct event *event = NULL; + struct dir *dir; + + if (!req->filter) + { + set_error(STATUS_INVALID_PARAMETER); + return; + } + + dir = get_dir_obj( current->process, req->handle, 0 ); + if (!dir) + return; + + /* possibly send changes through an event flag */ + if (req->event) + { + event = get_event_obj( current->process, req->event, EVENT_MODIFY_STATE ); + if (!event) + goto end; + } + + /* discard the current data, and move onto the next event */ + if (dir->event) release_object( dir->event ); + dir->event = event; + + /* assign it once */ + if (!dir->filter) + { + insert_change( dir ); + dir->filter = req->filter; + } + + /* remove any notifications */ + if (dir->signaled>0) + dir->signaled--; + + adjust_changes( get_unix_fd( dir->fd ), dir->filter ); + + set_error(STATUS_PENDING); + +end: + release_object( dir ); } diff --git a/server/file.c b/server/file.c index f488c554367..ac48e55fb20 100644 --- a/server/file.c +++ b/server/file.c @@ -172,7 +172,9 @@ static struct object *create_file( const char *nameptr, size_t len, unsigned int fd = open_fd( name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options ); if (!fd) goto done; - if (S_ISCHR(mode) && is_serial_fd( fd )) + if (S_ISDIR(mode)) + obj = create_dir_obj( fd ); + else if (S_ISCHR(mode) && is_serial_fd( fd )) obj = create_serial( fd, options ); else obj = create_file_obj( fd, access, options ); diff --git a/server/file.h b/server/file.h index 5b139af0bde..2769c501bbe 100644 --- a/server/file.h +++ b/server/file.h @@ -109,6 +109,7 @@ extern void file_set_error(void); extern void do_change_notify( int unix_fd ); extern void sigio_callback(void); +extern struct object *create_dir_obj( struct fd *fd ); /* serial port functions */ diff --git a/server/protocol.def b/server/protocol.def index e717dd2785d..6df0784bcba 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1041,23 +1041,14 @@ enum char_info_mode @END -/* Create a change notification */ -@REQ(create_change_notification) - unsigned int access; /* wanted access rights */ - unsigned int attributes; /* object attributes */ +/* enable directory change notifications */ +@REQ(read_directory_changes) obj_handle_t handle; /* handle to the directory */ - int subtree; /* watch all the subtree */ + obj_handle_t event; /* handle to the event */ unsigned int filter; /* notification filter */ -@REPLY - obj_handle_t handle; /* handle to the change notification */ @END -/* Move to the next change notification */ -@REQ(next_change_notification) - obj_handle_t handle; /* handle to the change notification */ -@END - /* Create a file mapping */ @REQ(create_mapping) unsigned int access; /* wanted access rights */ diff --git a/server/request.h b/server/request.h index 91b314fe1b3..cad86c865c0 100644 --- a/server/request.h +++ b/server/request.h @@ -180,8 +180,7 @@ DECL_HANDLER(fill_console_output); DECL_HANDLER(read_console_output); DECL_HANDLER(move_console_output); DECL_HANDLER(send_console_signal); -DECL_HANDLER(create_change_notification); -DECL_HANDLER(next_change_notification); +DECL_HANDLER(read_directory_changes); DECL_HANDLER(create_mapping); DECL_HANDLER(open_mapping); DECL_HANDLER(get_mapping_info); @@ -398,8 +397,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_read_console_output, (req_handler)req_move_console_output, (req_handler)req_send_console_signal, - (req_handler)req_create_change_notification, - (req_handler)req_next_change_notification, + (req_handler)req_read_directory_changes, (req_handler)req_create_mapping, (req_handler)req_open_mapping, (req_handler)req_get_mapping_info, diff --git a/server/trace.c b/server/trace.c index fc5f4f35871..7467b9ece6a 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1445,25 +1445,13 @@ static void dump_send_console_signal_request( const struct send_console_signal_r fprintf( stderr, " group_id=%04x", req->group_id ); } -static void dump_create_change_notification_request( const struct create_change_notification_request *req ) +static void dump_read_directory_changes_request( const struct read_directory_changes_request *req ) { - fprintf( stderr, " access=%08x,", req->access ); - fprintf( stderr, " attributes=%08x,", req->attributes ); fprintf( stderr, " handle=%p,", req->handle ); - fprintf( stderr, " subtree=%d,", req->subtree ); + fprintf( stderr, " event=%p,", req->event ); fprintf( stderr, " filter=%08x", req->filter ); } -static void dump_create_change_notification_reply( const struct create_change_notification_reply *req ) -{ - fprintf( stderr, " handle=%p", req->handle ); -} - -static void dump_next_change_notification_request( const struct next_change_notification_request *req ) -{ - fprintf( stderr, " handle=%p", req->handle ); -} - static void dump_create_mapping_request( const struct create_mapping_request *req ) { fprintf( stderr, " access=%08x,", req->access ); @@ -3286,8 +3274,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_read_console_output_request, (dump_func)dump_move_console_output_request, (dump_func)dump_send_console_signal_request, - (dump_func)dump_create_change_notification_request, - (dump_func)dump_next_change_notification_request, + (dump_func)dump_read_directory_changes_request, (dump_func)dump_create_mapping_request, (dump_func)dump_open_mapping_request, (dump_func)dump_get_mapping_info_request, @@ -3501,7 +3488,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_read_console_output_reply, (dump_func)0, (dump_func)0, - (dump_func)dump_create_change_notification_reply, (dump_func)0, (dump_func)dump_create_mapping_reply, (dump_func)dump_open_mapping_reply, @@ -3716,8 +3702,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "read_console_output", "move_console_output", "send_console_signal", - "create_change_notification", - "next_change_notification", + "read_directory_changes", "create_mapping", "open_mapping", "get_mapping_info",