diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 4c6b1b70f61..43e52c6a0ae 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 ) + 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; ilen; 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 ( \ diff --git a/dlls/ntdll/tests/change.c b/dlls/ntdll/tests/change.c index 84e281c0235..0e76fb5635a 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 08cee9b7145..11d9b936ac4 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 ); } }