Alexandre Julliard : ntdll: Fix handling of async cancellation for directory changes.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu May 7 09:01:44 CDT 2015
Module: wine
Branch: master
Commit: 193667ecd7e8543d48d6c2f16cfd0abca818c3c8
URL: http://source.winehq.org/git/wine.git/?a=commit;h=193667ecd7e8543d48d6c2f16cfd0abca818c3c8
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu May 7 16:02:26 2015 +0900
ntdll: Fix handling of async cancellation for directory changes.
---
dlls/ntdll/file.c | 113 ++++++++++++++++++++++++----------------------
dlls/ntdll/tests/change.c | 10 ++--
server/change.c | 2 +-
3 files changed, 65 insertions(+), 60 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 4c6b1b7..43e52c6 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -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 )
- {
- 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)
+ if (status == STATUS_ALERTED)
{
- 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
+
+ if (status != STATUS_PENDING)
{
- ret = STATUS_NOTIFY_ENUM_DIR;
- size = 0;
+ iosb->u.Status = status;
+ iosb->Information = size;
+ *apc = fileio->io.apc;
+ *arg = fileio->io.apc_arg;
+ release_fileio( &fileio->io );
}
-
- iosb->u.Status = ret;
- iosb->Information = size;
- *apc = fileio->io.apc;
- *arg = fileio->io.apc_arg;
- release_fileio( &fileio->io );
- return ret;
+ return status;
}
#define FILE_NOTIFY_ALL ( \
diff --git a/dlls/ntdll/tests/change.c b/dlls/ntdll/tests/change.c
index 84e281c..0e76fb5 100644
--- a/dlls/ntdll/tests/change.c
+++ b/dlls/ntdll/tests/change.c
@@ -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");
diff --git a/server/change.c b/server/change.c
index 08cee9b..11d9b93 100644
--- a/server/change.c
+++ b/server/change.c
@@ -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 );
}
}
More information about the wine-cvs
mailing list