server: Return multiple events in read_changes.
This commit is contained in:
parent
92ac7861f5
commit
b614a15328
|
@ -2902,49 +2902,72 @@ static void WINAPI read_changes_user_apc( void *arg, IO_STATUS_BLOCK *io, ULONG
|
|||
static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc )
|
||||
{
|
||||
struct read_changes_info *info = user;
|
||||
char path[PATH_MAX];
|
||||
NTSTATUS ret = STATUS_SUCCESS;
|
||||
int len, action, i;
|
||||
char data[PATH_MAX];
|
||||
NTSTATUS ret;
|
||||
int size;
|
||||
|
||||
SERVER_START_REQ( read_change )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( info->FileHandle );
|
||||
wine_server_set_reply( req, path, PATH_MAX );
|
||||
wine_server_set_reply( req, data, PATH_MAX );
|
||||
ret = wine_server_call( req );
|
||||
action = reply->action;
|
||||
len = wine_server_reply_size( reply );
|
||||
size = wine_server_reply_size( reply );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
if (ret == STATUS_SUCCESS && info->Buffer &&
|
||||
(info->BufferSize > (sizeof (FILE_NOTIFY_INFORMATION) + len*sizeof(WCHAR))))
|
||||
if (ret == STATUS_SUCCESS && info->Buffer)
|
||||
{
|
||||
PFILE_NOTIFY_INFORMATION pfni;
|
||||
PFILE_NOTIFY_INFORMATION pfni = info->Buffer;
|
||||
int i, left = info->BufferSize;
|
||||
DWORD *last_entry_offset = NULL;
|
||||
struct filesystem_event *event = (struct filesystem_event*)data;
|
||||
|
||||
pfni = info->Buffer;
|
||||
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] = '\\';
|
||||
|
||||
/* convert to an NT style path */
|
||||
for (i=0; i<len; i++)
|
||||
if (path[i] == '/')
|
||||
path[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;
|
||||
|
||||
len = ntdll_umbstowcs( 0, path, len, pfni->FileName,
|
||||
info->BufferSize - sizeof (*pfni) );
|
||||
if(pfni->FileNameLength == -1 || pfni->FileNameLength == -2)
|
||||
break;
|
||||
|
||||
pfni->NextEntryOffset = 0;
|
||||
pfni->Action = action;
|
||||
pfni->FileNameLength = len * sizeof (WCHAR);
|
||||
pfni->FileName[len] = 0;
|
||||
len = sizeof (*pfni) - sizeof (DWORD) + pfni->FileNameLength;
|
||||
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)
|
||||
{
|
||||
ret = STATUS_NOTIFY_ENUM_DIR;
|
||||
size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*last_entry_offset = 0;
|
||||
size = info->BufferSize - left;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = STATUS_NOTIFY_ENUM_DIR;
|
||||
len = 0;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
iosb->u.Status = ret;
|
||||
iosb->Information = len;
|
||||
iosb->Information = size;
|
||||
*apc = read_changes_user_apc;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -316,6 +316,14 @@ typedef struct
|
|||
unsigned short attr;
|
||||
} char_info_t;
|
||||
|
||||
|
||||
struct filesystem_event
|
||||
{
|
||||
int action;
|
||||
data_size_t len;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int low_part;
|
||||
|
@ -1879,9 +1887,7 @@ struct read_change_request
|
|||
struct read_change_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
int action;
|
||||
/* VARARG(name,string); */
|
||||
char __pad_12[4];
|
||||
/* VARARG(events,filesystem_event); */
|
||||
};
|
||||
|
||||
|
||||
|
@ -5519,6 +5525,6 @@ union generic_reply
|
|||
struct set_cursor_reply set_cursor_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 411
|
||||
#define SERVER_PROTOCOL_VERSION 412
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -123,9 +123,7 @@ static struct fd *inotify_fd;
|
|||
|
||||
struct change_record {
|
||||
struct list entry;
|
||||
int action;
|
||||
int len;
|
||||
char name[1];
|
||||
struct filesystem_event event;
|
||||
};
|
||||
|
||||
struct dir
|
||||
|
@ -616,13 +614,13 @@ static void inotify_do_change_notify( struct dir *dir, unsigned int action,
|
|||
if (dir->want_data)
|
||||
{
|
||||
size_t len = strlen(relpath);
|
||||
record = malloc( offsetof(struct change_record, name[len]) );
|
||||
record = malloc( offsetof(struct change_record, event.name[len]) );
|
||||
if (!record)
|
||||
return;
|
||||
|
||||
record->action = action;
|
||||
memcpy( record->name, relpath, len );
|
||||
record->len = len;
|
||||
record->event.action = action;
|
||||
memcpy( record->event.name, relpath, len );
|
||||
record->event.len = len;
|
||||
|
||||
list_add_tail( &dir->change_records, &record->entry );
|
||||
}
|
||||
|
@ -1145,21 +1143,54 @@ end:
|
|||
|
||||
DECL_HANDLER(read_change)
|
||||
{
|
||||
struct change_record *record;
|
||||
struct change_record *record, *next;
|
||||
struct dir *dir;
|
||||
struct list events;
|
||||
char *data, *event;
|
||||
int size = 0;
|
||||
|
||||
dir = get_dir_obj( current->process, req->handle, 0 );
|
||||
if (!dir)
|
||||
return;
|
||||
|
||||
if ((record = get_first_change_record( dir )) != NULL)
|
||||
list_init( &events );
|
||||
list_move_tail( &events, &dir->change_records );
|
||||
release_object( dir );
|
||||
|
||||
if (list_empty( &events ))
|
||||
{
|
||||
reply->action = record->action;
|
||||
set_reply_data( record->name, record->len );
|
||||
set_error( STATUS_NO_DATA_DETECTED );
|
||||
return;
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY( record, &events, struct change_record, entry )
|
||||
{
|
||||
size += (offsetof(struct filesystem_event, name[record->event.len])
|
||||
+ sizeof(int)-1) / sizeof(int) * sizeof(int);
|
||||
}
|
||||
|
||||
if (size > get_reply_max_size())
|
||||
set_error( STATUS_BUFFER_TOO_SMALL );
|
||||
else if ((data = mem_alloc( size )) != NULL)
|
||||
{
|
||||
event = data;
|
||||
LIST_FOR_EACH_ENTRY( record, &events, struct change_record, entry )
|
||||
{
|
||||
data_size_t len = offsetof( struct filesystem_event, name[record->event.len] );
|
||||
memcpy( event, &record->event, len );
|
||||
event += len;
|
||||
if (len % sizeof(int))
|
||||
{
|
||||
memset( event, 0, sizeof(int) - len % sizeof(int) );
|
||||
event += sizeof(int) - len % sizeof(int);
|
||||
}
|
||||
}
|
||||
set_reply_data_ptr( data, size );
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE( record, next, &events, struct change_record, entry )
|
||||
{
|
||||
list_remove( &record->entry );
|
||||
free( record );
|
||||
}
|
||||
else
|
||||
set_error( STATUS_NO_DATA_DETECTED );
|
||||
|
||||
release_object( dir );
|
||||
}
|
||||
|
|
|
@ -332,6 +332,14 @@ typedef struct
|
|||
unsigned short attr;
|
||||
} char_info_t;
|
||||
|
||||
/* structure returned in filesystem events */
|
||||
struct filesystem_event
|
||||
{
|
||||
int action;
|
||||
data_size_t len;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int low_part;
|
||||
|
@ -1448,8 +1456,7 @@ enum char_info_mode
|
|||
@REQ(read_change)
|
||||
obj_handle_t handle;
|
||||
@REPLY
|
||||
int action; /* type of change */
|
||||
VARARG(name,string); /* name of directory entry that changed */
|
||||
VARARG(events,filesystem_event); /* collected filesystem events */
|
||||
@END
|
||||
|
||||
|
||||
|
|
|
@ -1103,8 +1103,7 @@ C_ASSERT( FIELD_OFFSET(struct read_directory_changes_request, async) == 24 );
|
|||
C_ASSERT( sizeof(struct read_directory_changes_request) == 64 );
|
||||
C_ASSERT( FIELD_OFFSET(struct read_change_request, handle) == 12 );
|
||||
C_ASSERT( sizeof(struct read_change_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct read_change_reply, action) == 8 );
|
||||
C_ASSERT( sizeof(struct read_change_reply) == 16 );
|
||||
C_ASSERT( sizeof(struct read_change_reply) == 8 );
|
||||
C_ASSERT( FIELD_OFFSET(struct create_mapping_request, access) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct create_mapping_request, attributes) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct create_mapping_request, protect) == 20 );
|
||||
|
|
|
@ -991,6 +991,24 @@ static void dump_varargs_object_attributes( const char *prefix, data_size_t size
|
|||
fputc( '}', stderr );
|
||||
}
|
||||
|
||||
static void dump_varargs_filesystem_event( const char *prefix, data_size_t size )
|
||||
{
|
||||
fprintf( stderr,"%s{", prefix );
|
||||
while (size)
|
||||
{
|
||||
const struct filesystem_event *event = cur_data;
|
||||
data_size_t len = (offsetof( struct filesystem_event, name[event->len] ) + sizeof(int)-1)
|
||||
/ sizeof(int) * sizeof(int);
|
||||
if (size < len) break;
|
||||
fprintf( stderr, "{action=%x,len=%u,name=\"%.*s\"}",
|
||||
event->action, event->len, event->len, event->name );
|
||||
size -= len;
|
||||
remove_data( len );
|
||||
if (size)fputc( ',', stderr );
|
||||
}
|
||||
fputc( '}', stderr );
|
||||
}
|
||||
|
||||
typedef void (*dump_func)( const void *req );
|
||||
|
||||
/* Everything below this line is generated automatically by tools/make_requests */
|
||||
|
@ -1865,8 +1883,7 @@ static void dump_read_change_request( const struct read_change_request *req )
|
|||
|
||||
static void dump_read_change_reply( const struct read_change_reply *req )
|
||||
{
|
||||
fprintf( stderr, " action=%d", req->action );
|
||||
dump_varargs_string( ", name=", cur_size );
|
||||
dump_varargs_filesystem_event( " events=", cur_size );
|
||||
}
|
||||
|
||||
static void dump_create_mapping_request( const struct create_mapping_request *req )
|
||||
|
|
Loading…
Reference in New Issue