ntdll: Fix handling of async cancellation for directory changes.
This commit is contained in:
parent
38b7c8839c
commit
193667ecd7
|
@ -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 )
|
||||
if (status == STATUS_ALERTED)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
ret = STATUS_NOTIFY_ENUM_DIR;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
iosb->u.Status = ret;
|
||||
iosb->Information = size;
|
||||
*apc = fileio->io.apc;
|
||||
*arg = fileio->io.apc_arg;
|
||||
release_fileio( &fileio->io );
|
||||
return ret;
|
||||
if (status != STATUS_PENDING)
|
||||
{
|
||||
iosb->u.Status = status;
|
||||
iosb->Information = size;
|
||||
*apc = fileio->io.apc;
|
||||
*arg = fileio->io.apc_arg;
|
||||
release_fileio( &fileio->io );
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#define FILE_NOTIFY_ALL ( \
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue