From 3d5ac6b2be51f4de75d455f7d7e745095928cad7 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Sat, 5 Mar 2005 00:21:38 +0000 Subject: [PATCH 1/5] Added comments about systemHandleInfo. svn path=/trunk/; revision=13822 --- reactos/ntoskrnl/ob/handle.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/reactos/ntoskrnl/ob/handle.c b/reactos/ntoskrnl/ob/handle.c index 58250750a72..dcc90efd882 100644 --- a/reactos/ntoskrnl/ob/handle.c +++ b/reactos/ntoskrnl/ob/handle.c @@ -1089,6 +1089,11 @@ ObpGetNextHandleByProcessCount(PSYSTEM_HANDLE_TABLE_ENTRY_INFO pshi, // pshi->HandleValue; +/* + This will never work with ROS! M$, I guess uses 0 -> 65535. + Ros uses 0 -> 4294967295! + */ + P = (ULONG) Process->UniqueProcessId; pshi->UniqueProcessId = (USHORT) P; From 594c2c424b9db583c8e2ba6bd63975fa543a2f55 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sat, 5 Mar 2005 11:27:15 +0000 Subject: [PATCH 2/5] - Implement NtCancelIoFile. - Queue the IRP to correct thread in IoQueueThreadIrp. - Cancel I/O requests when thread is about to be terminated. - Do not queue close requests to thread IRP list. svn path=/trunk/; revision=13824 --- reactos/ntoskrnl/include/internal/io.h | 5 + reactos/ntoskrnl/io/cancel.c | 177 ++++++++++++++++++++++++- reactos/ntoskrnl/io/iomgr.c | 23 +++- reactos/ntoskrnl/io/irp.c | 27 ++-- reactos/ntoskrnl/ps/kill.c | 3 + 5 files changed, 213 insertions(+), 22 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index 823c153c197..b23f6121742 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -426,6 +426,11 @@ IopBootLog(PUNICODE_STRING DriverName, BOOLEAN Success); VOID IopSaveBootLogToFile(VOID); +/* cancel.c */ + +VOID STDCALL +IoCancelThreadIo(PETHREAD Thread); + /* errlog.c */ NTSTATUS diff --git a/reactos/ntoskrnl/io/cancel.c b/reactos/ntoskrnl/io/cancel.c index f5c4312eeb9..1ce6919fb34 100644 --- a/reactos/ntoskrnl/io/cancel.c +++ b/reactos/ntoskrnl/io/cancel.c @@ -20,12 +20,181 @@ static KSPIN_LOCK CancelSpinLock; /* FUNCTIONS *****************************************************************/ +/** + * @name NtCancelIoFile + * + * Cancel all pending I/O operations in the current thread for specified + * file object. + * + * @param FileHandle + * Handle to file object to cancel requests for. No specific + * access rights are needed. + * @param IoStatusBlock + * Pointer to status block which is filled with final completition + * status on successful return. + * + * @return Status. + * + * @implemented + */ + NTSTATUS STDCALL -NtCancelIoFile (IN HANDLE FileHandle, - OUT PIO_STATUS_BLOCK IoStatusBlock) +NtCancelIoFile( + IN HANDLE FileHandle, + OUT PIO_STATUS_BLOCK IoStatusBlock) { - UNIMPLEMENTED; - return(STATUS_NOT_IMPLEMENTED); + NTSTATUS Status; + PFILE_OBJECT FileObject; + PETHREAD Thread; + PLIST_ENTRY IrpEntry; + PIRP Irp; + KIRQL OldIrql; + BOOLEAN OurIrpsInList = FALSE; + LARGE_INTEGER Interval; + + if ((ULONG_PTR)IoStatusBlock >= MmUserProbeAddress && + KeGetPreviousMode() == UserMode) + return STATUS_ACCESS_VIOLATION; + + Status = ObReferenceObjectByHandle(FileHandle, 0, IoFileObjectType, + KeGetPreviousMode(), (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + return Status; + + /* IRP cancellations are synchronized at APC_LEVEL. */ + OldIrql = KfRaiseIrql(APC_LEVEL); + + /* + * Walk the list of active IRPs and cancel the ones that belong to + * our file object. + */ + + Thread = PsGetCurrentThread(); + for (IrpEntry = Thread->IrpList.Flink; + IrpEntry != &Thread->IrpList; + IrpEntry = IrpEntry->Flink) + { + Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry); + if (Irp->Tail.Overlay.OriginalFileObject == FileObject) + { + IoCancelIrp(Irp); + /* Don't break here, we want to cancel all IRPs for the file object. */ + OurIrpsInList = TRUE; + } + } + + KfLowerIrql(OldIrql); + + while (OurIrpsInList) + { + OurIrpsInList = FALSE; + + /* Wait a short while and then look if all our IRPs were completed. */ + Interval.QuadPart = -1000000; /* 100 milliseconds */ + KeDelayExecutionThread(KernelMode, FALSE, &Interval); + + OldIrql = KfRaiseIrql(APC_LEVEL); + + /* + * Look in the list if all IRPs for the specified file object + * are completed (or cancelled). If someone sends a new IRP + * for our file object while we're here we can happily loop + * forever. + */ + + for (IrpEntry = Thread->IrpList.Flink; + IrpEntry != &Thread->IrpList; + IrpEntry = IrpEntry->Flink) + { + Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry); + if (Irp->Tail.Overlay.OriginalFileObject == FileObject) + { + OurIrpsInList = TRUE; + break; + } + } + + KfLowerIrql(OldIrql); + } + + _SEH_TRY + { + IoStatusBlock->Status = STATUS_SUCCESS; + IoStatusBlock->Information = 0; + Status = STATUS_SUCCESS; + } + _SEH_HANDLE + { + Status = STATUS_UNSUCCESSFUL; + } + _SEH_END; + + ObDereferenceObject(FileObject); + + return Status; +} + +/** + * @name IoCancelThreadIo + * + * Cancel all pending I/O request associated with specified thread. + * + * @param Thread + * Thread to cancel requests for. + */ + +VOID STDCALL +IoCancelThreadIo(PETHREAD Thread) +{ + PLIST_ENTRY IrpEntry; + PIRP Irp; + KIRQL OldIrql; + ULONG Retries = 3000; + LARGE_INTEGER Interval; + + OldIrql = KfRaiseIrql(APC_LEVEL); + + /* + * Start by cancelling all the IRPs in the current thread queue. + */ + + for (IrpEntry = Thread->IrpList.Flink; + IrpEntry != &Thread->IrpList; + IrpEntry = IrpEntry->Flink) + { + Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry); + IoCancelIrp(Irp); + } + + /* + * Wait till all the IRPs are completed or cancelled. + */ + + while (!IsListEmpty(&Thread->IrpList)) + { + KfLowerIrql(OldIrql); + + /* Wait a short while and then look if all our IRPs were completed. */ + Interval.QuadPart = -1000000; /* 100 milliseconds */ + KeDelayExecutionThread(KernelMode, FALSE, &Interval); + + /* + * Don't stay here forever if some broken driver doesn't complete + * the IRP. + */ + + if (Retries-- == 0) + { + /* FIXME: Handle this gracefully. */ + DPRINT1("Thread with dead IRPs!"); + ASSERT(FALSE); + } + + OldIrql = KfRaiseIrql(APC_LEVEL); + } + + KfLowerIrql(OldIrql); } /* diff --git a/reactos/ntoskrnl/io/iomgr.c b/reactos/ntoskrnl/io/iomgr.c index 81852d21362..eff2a12bcc0 100644 --- a/reactos/ntoskrnl/io/iomgr.c +++ b/reactos/ntoskrnl/io/iomgr.c @@ -105,15 +105,24 @@ IopDeleteFile(PVOID ObjectBody) UserMode); #endif KeResetEvent( &FileObject->Event ); - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_CLOSE, - FileObject->DeviceObject, - NULL, - 0, - NULL, - &FileObject->Event, - NULL); + + Irp = IoAllocateIrp(FileObject->DeviceObject->StackSize, TRUE); + if (Irp == NULL) + { + /* + * FIXME: This case should eventually be handled. We should wait + * until enough memory is available to allocate the IRP. + */ + ASSERT(FALSE); + } + + Irp->UserEvent = &FileObject->Event; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); Irp->Flags |= IRP_CLOSE_OPERATION; + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_CLOSE; + StackPtr->DeviceObject = FileObject->DeviceObject; StackPtr->FileObject = FileObject; Status = IoCallDriver(FileObject->DeviceObject, Irp); diff --git a/reactos/ntoskrnl/io/irp.c b/reactos/ntoskrnl/io/irp.c index d898dc4f1c8..ed98e86d973 100644 --- a/reactos/ntoskrnl/io/irp.c +++ b/reactos/ntoskrnl/io/irp.c @@ -268,7 +268,6 @@ IoAllocateIrp(CCHAR StackSize, return(NULL); } - RtlZeroMemory(Irp, IoSizeOfIrp(StackSize)); IoInitializeIrp(Irp, IoSizeOfIrp(StackSize), StackSize); @@ -364,6 +363,9 @@ IofCompleteRequest(PIRP Irp, ULONG MasterIrpCount; PIRP MasterIrp = Irp->AssociatedIrp.MasterIrp; + /* This should never happen! */ + ASSERT(IsListEmpty(&Irp->ThreadListEntry)); + MasterIrpCount = InterlockedDecrement(&MasterIrp->AssociatedIrp.IrpCount); while ((Mdl = Irp->MdlAddress)) { @@ -386,6 +388,9 @@ IofCompleteRequest(PIRP Irp, /* Windows NT File System Internals, page 165 */ if (Irp->Flags & (IRP_PAGING_IO|IRP_CLOSE_OPERATION)) { + /* This should never happen! */ + ASSERT(IsListEmpty(&Irp->ThreadListEntry)); + /* * If MDL_IO_PAGE_READ is set, then the caller is responsible * for deallocating of the mdl. @@ -582,19 +587,19 @@ IoGetTopLevelIrp(VOID) VOID STDCALL IoQueueThreadIrp(IN PIRP Irp) { -/* undefine this when (if ever) implementing irp cancellation */ -#if 0 - KIRQL oldIrql; + KIRQL OldIrql; - oldIrql = KfRaiseIrql(APC_LEVEL); + OldIrql = KfRaiseIrql(APC_LEVEL); - /* Synchronous irp's are queued to requestor thread. If they are not completed - when the thread exits, they are canceled (cleaned up). - -Gunnar */ - InsertTailList(&PsGetCurrentThread()->IrpList, &Irp->ThreadListEntry); + /* + * Synchronous irp's are queued to requestor thread. If they are not + * completed when the thread exits, they are canceled (cleaned up). + * - Gunnar + */ + + InsertTailList(&Irp->Tail.Overlay.Thread->IrpList, &Irp->ThreadListEntry); - KfLowerIrql(oldIrql); -#endif + KfLowerIrql(OldIrql); } diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index 1837f096b5a..acd9271c3e5 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -158,6 +158,9 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus) PsLockProcess(CurrentProcess, FALSE); + /* Cancel I/O for the thread. */ + IoCancelThreadIo(CurrentThread); + /* Remove the thread from the thread list of its process */ RemoveEntryList(&CurrentThread->ThreadListEntry); Last = IsListEmpty(&CurrentProcess->ThreadListHead); From 888cadd6ea7372626ad0021d32de78ee9804b2cc Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 5 Mar 2005 11:38:48 +0000 Subject: [PATCH 3/5] Fix calls to ReadFile and WriteFile for asynchronous I/O. svn path=/trunk/; revision=13825 --- reactos/lib/rpcrt4/rpc_message.c | 60 +++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/reactos/lib/rpcrt4/rpc_message.c b/reactos/lib/rpcrt4/rpc_message.c index 119af8cfab3..d10e56c9ab4 100644 --- a/reactos/lib/rpcrt4/rpc_message.c +++ b/reactos/lib/rpcrt4/rpc_message.c @@ -265,10 +265,15 @@ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, } /* transmit packet header */ - if (!WriteFile(Connection->conn, Header, hdr_size, &count, NULL)) { + ResetEvent(Connection->ovl.hEvent); + if (!WriteFile(Connection->conn, Header, hdr_size, &count, &Connection->ovl)) { WARN("WriteFile failed with error %ld\n", GetLastError()); return GetLastError(); } + if (!GetOverlappedResult(Connection->conn, &Connection->ovl, &count, TRUE)) { + WARN("GetOverlappedResult failed with error %ld\n", GetLastError()); + return GetLastError(); + } /* fragment consisted of header only and is the last one */ if (hdr_size == Header->common.frag_len && @@ -277,10 +282,15 @@ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, } /* send the fragment data */ - if (!WriteFile(Connection->conn, buffer_pos, Header->common.frag_len - hdr_size, &count, NULL)) { + ResetEvent(Connection->ovl.hEvent); + if (!WriteFile(Connection->conn, buffer_pos, Header->common.frag_len - hdr_size, &count, &Connection->ovl)) { WARN("WriteFile failed with error %ld\n", GetLastError()); return GetLastError(); } + if (!GetOverlappedResult(Connection->conn, &Connection->ovl, &count, TRUE)) { + WARN("GetOverlappedResult failed with error %ld\n", GetLastError()); + return GetLastError(); + } Header->common.flags &= ~RPC_FLG_FIRST; } @@ -309,9 +319,15 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, TRACE("(%p, %p, %p)\n", Connection, Header, pMsg); /* read packet common header */ - if (!ReadFile(Connection->conn, &common_hdr, sizeof(common_hdr), &dwRead, NULL)) { + ResetEvent(Connection->ovl.hEvent); + if (!ReadFile(Connection->conn, &common_hdr, sizeof(common_hdr), &dwRead, &Connection->ovl)) { + WARN("ReadFile failed with error %ld\n", GetLastError()); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + if (!GetOverlappedResult(Connection->conn, &Connection->ovl, &dwRead, TRUE)) { if (GetLastError() != ERROR_MORE_DATA) { - WARN("ReadFile failed with error %ld\n", GetLastError()); + WARN("GetOverlappedResult failed with error %ld\n", GetLastError()); status = RPC_S_PROTOCOL_ERROR; goto fail; } @@ -339,10 +355,16 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, memcpy(*Header, &common_hdr, sizeof(common_hdr)); /* read the rest of packet header */ + ResetEvent(Connection->ovl.hEvent); if (!ReadFile(Connection->conn, &(*Header)->common + 1, - hdr_length - sizeof(common_hdr), &dwRead, NULL)) { + hdr_length - sizeof(common_hdr), &dwRead, &Connection->ovl)) { + WARN("ReadFile failed with error %ld\n", GetLastError()); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + if (!GetOverlappedResult(Connection->conn, &Connection->ovl, &dwRead, TRUE)) { if (GetLastError() != ERROR_MORE_DATA) { - WARN("ReadFile failed with error %ld\n", GetLastError()); + WARN("GetOverlappedResult failed with error %ld\n", GetLastError()); status = RPC_S_PROTOCOL_ERROR; goto fail; } @@ -352,6 +374,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, goto fail; } + /* read packet body */ switch (common_hdr.ptype) { case PKT_RESPONSE: @@ -379,13 +402,20 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, goto fail; } - if (data_length == 0) dwRead = 0; else - if (!ReadFile(Connection->conn, buffer_ptr, data_length, &dwRead, NULL)) { - if (GetLastError() != ERROR_MORE_DATA) { + if (data_length == 0) dwRead = 0; else { + ResetEvent(Connection->ovl.hEvent); + if (!ReadFile(Connection->conn, buffer_ptr, data_length, &dwRead, &Connection->ovl)) { WARN("ReadFile failed with error %ld\n", GetLastError()); status = RPC_S_PROTOCOL_ERROR; goto fail; } + if (!GetOverlappedResult(Connection->conn, &Connection->ovl, &dwRead, TRUE)) { + if (GetLastError() != ERROR_MORE_DATA) { + WARN("GetOverlappedResult failed with error %ld\n", GetLastError()); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + } } if (dwRead != data_length) { status = RPC_S_PROTOCOL_ERROR; @@ -403,10 +433,16 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, TRACE("next header\n"); /* read the header of next packet */ - if (!ReadFile(Connection->conn, *Header, hdr_length, &dwRead, NULL)) { + ResetEvent(Connection->ovl.hEvent); + if (!ReadFile(Connection->conn, *Header, hdr_length, &dwRead, &Connection->ovl)) { + WARN("ReadFile failed with error %ld\n", GetLastError()); + status = GetLastError(); + goto fail; + } + if (!GetOverlappedResult(Connection->conn, &Connection->ovl, &dwRead, TRUE)) { if (GetLastError() != ERROR_MORE_DATA) { - WARN("ReadFile failed with error %ld\n", GetLastError()); - status = GetLastError(); + WARN("GetOverlappedResult failed with error %ld\n", GetLastError()); + status = RPC_S_PROTOCOL_ERROR; goto fail; } } From 8027ba84c5b65c88dbca7cacc70375d07f878c7e Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 5 Mar 2005 12:08:50 +0000 Subject: [PATCH 4/5] Support asynchronous (aka overlapped) connect, read and write requests. svn path=/trunk/; revision=13826 --- reactos/drivers/fs/np/create.c | 50 ++++++++++++++---- reactos/drivers/fs/np/fsctrl.c | 95 ++++++++++++++++++++++++++-------- reactos/drivers/fs/np/npfs.h | 9 ++++ reactos/drivers/fs/np/rw.c | 21 ++++++-- 4 files changed, 138 insertions(+), 37 deletions(-) diff --git a/reactos/drivers/fs/np/create.c b/reactos/drivers/fs/np/create.c index cda16fe846a..106c511cdc0 100644 --- a/reactos/drivers/fs/np/create.c +++ b/reactos/drivers/fs/np/create.c @@ -48,17 +48,18 @@ static PNPFS_FCB NpfsFindListeningServerInstance(PNPFS_PIPE Pipe) { PLIST_ENTRY CurrentEntry; - PNPFS_FCB ServerFcb; + PNPFS_WAITER_ENTRY Waiter; - CurrentEntry = Pipe->ServerFcbListHead.Flink; - while (CurrentEntry != &Pipe->ServerFcbListHead) + CurrentEntry = Pipe->WaiterListHead.Flink; + while (CurrentEntry != &Pipe->WaiterListHead) { - ServerFcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, FcbListEntry); - if (ServerFcb->PipeState == FILE_PIPE_LISTENING_STATE) + Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry); + if (Waiter->Fcb->PipeState == FILE_PIPE_LISTENING_STATE) { - DPRINT("Server found! Fcb %p\n", ServerFcb); - return ServerFcb; + DPRINT("Server found! Fcb %p\n", Waiter->Fcb); + return Waiter->Fcb; } + CurrentEntry = CurrentEntry->Flink; } @@ -66,6 +67,35 @@ NpfsFindListeningServerInstance(PNPFS_PIPE Pipe) } +static VOID +NpfsSignalAndRemoveListeningServerInstance(PNPFS_PIPE Pipe, + PNPFS_FCB Fcb) +{ + PLIST_ENTRY CurrentEntry; + PNPFS_WAITER_ENTRY Waiter; + + CurrentEntry = Pipe->WaiterListHead.Flink; + while (CurrentEntry != &Pipe->WaiterListHead) + { + Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry); + if (Waiter->Fcb == Fcb) + { + DPRINT("Server found! Fcb %p\n", Waiter->Fcb); + + KeSetEvent(Waiter->Irp->UserEvent, 0, FALSE); + Waiter->Irp->UserIosb->Status = FILE_PIPE_CONNECTED_STATE; + Waiter->Irp->UserIosb->Information = 0; + IoCompleteRequest(Waiter->Irp, IO_NO_INCREMENT); + + RemoveEntryList(&Waiter->Entry); + ExFreePool(Waiter); + return; + } + CurrentEntry = CurrentEntry->Flink; + } +} + + NTSTATUS STDCALL NpfsCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp) @@ -206,9 +236,8 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject, ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE; ServerFcb->PipeState = FILE_PIPE_CONNECTED_STATE; - /* Wake server thread */ - DPRINT("Setting the ConnectEvent for %x\n", ServerFcb); - KeSetEvent(&ServerFcb->ConnectEvent, 0, FALSE); + /* Signal the server thread and remove it from the waiter list */ + NpfsSignalAndRemoveListeningServerInstance(Pipe, ServerFcb); } KeUnlockMutex(&Pipe->FcbListLock); @@ -318,6 +347,7 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, InitializeListHead(&Pipe->ServerFcbListHead); InitializeListHead(&Pipe->ClientFcbListHead); + InitializeListHead(&Pipe->WaiterListHead); KeInitializeMutex(&Pipe->FcbListLock, 0); Pipe->PipeType = Buffer->NamedPipeType; diff --git a/reactos/drivers/fs/np/fsctrl.c b/reactos/drivers/fs/np/fsctrl.c index f245fdfe75c..815198974ad 100644 --- a/reactos/drivers/fs/np/fsctrl.c +++ b/reactos/drivers/fs/np/fsctrl.c @@ -18,8 +18,66 @@ /* FUNCTIONS *****************************************************************/ +static VOID +NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PNPFS_WAITER_ENTRY Waiter; + + DPRINT1("NpfsListeningCancelRoutine() called\n"); + /* FIXME: Not tested. */ + + Waiter = Irp->Tail.Overlay.DriverContext[0]; + + RemoveEntryList(&Waiter->Entry); + ExFreePool(Waiter); + + IoReleaseCancelSpinLock(Irp->CancelIrql); + + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); +} + + static NTSTATUS -NpfsConnectPipe(PNPFS_FCB Fcb) +NpfsAddListeningServerInstance(PIRP Irp, + PNPFS_FCB Fcb) +{ + PNPFS_WAITER_ENTRY Entry; + KIRQL OldIrql; + + Entry = ExAllocatePool(NonPagedPool, sizeof(NPFS_WAITER_ENTRY)); + if (Entry == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + Entry->Irp = Irp; + Entry->Fcb = Fcb; + InsertTailList(&Fcb->Pipe->WaiterListHead, &Entry->Entry); + + IoAcquireCancelSpinLock(&OldIrql); + if (!Irp->Cancel) + { + Irp->Tail.Overlay.DriverContext[0] = Entry; + IoMarkIrpPending(Irp); + IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine); + IoReleaseCancelSpinLock(OldIrql); + return STATUS_PENDING; + } + /* IRP has already been cancelled */ + IoReleaseCancelSpinLock(OldIrql); + + DPRINT1("FIXME: Remove waiter entry!\n"); + RemoveEntryList(&Entry->Entry); + ExFreePool(Entry); + + return STATUS_CANCELLED; +} + + +static NTSTATUS +NpfsConnectPipe(PIRP Irp, + PNPFS_FCB Fcb) { PNPFS_PIPE Pipe; PLIST_ENTRY current_entry; @@ -88,29 +146,18 @@ NpfsConnectPipe(PNPFS_FCB Fcb) current_entry = current_entry->Flink; } - KeUnlockMutex(&Pipe->FcbListLock); - /* no listening client fcb found */ DPRINT("No listening client fcb found -- waiting for client\n"); Fcb->PipeState = FILE_PIPE_LISTENING_STATE; - Status = KeWaitForSingleObject(&Fcb->ConnectEvent, - UserRequest, - KernelMode, - FALSE, - NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("KeWaitForSingleObject() failed (Status %lx)\n", Status); - return Status; - } + Status = NpfsAddListeningServerInstance(Irp, Fcb); - Fcb->PipeState = FILE_PIPE_CONNECTED_STATE; + KeUnlockMutex(&Pipe->FcbListLock); - DPRINT("Client Fcb: %p\n", Fcb->OtherSide); + DPRINT("NpfsConnectPipe() done (Status %lx)\n", Status); - return STATUS_PIPE_CONNECTED; + return Status; } @@ -327,7 +374,6 @@ NpfsPeekPipe(PIRP Irp, } - NTSTATUS STDCALL NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) @@ -366,7 +412,7 @@ NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, case FSCTL_PIPE_LISTEN: DPRINT("Connecting pipe %wZ\n", &Pipe->PipeName); - Status = NpfsConnectPipe(Fcb); + Status = NpfsConnectPipe(Irp, Fcb); break; case FSCTL_PIPE_PEEK: @@ -439,12 +485,15 @@ NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject, Status = STATUS_UNSUCCESSFUL; } - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; + if (Status != STATUS_PENDING) + { + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return(Status); + return Status; } diff --git a/reactos/drivers/fs/np/npfs.h b/reactos/drivers/fs/np/npfs.h index effd44d332d..1038411e2fb 100644 --- a/reactos/drivers/fs/np/npfs.h +++ b/reactos/drivers/fs/np/npfs.h @@ -19,6 +19,7 @@ typedef struct _NPFS_PIPE KMUTEX FcbListLock; LIST_ENTRY ServerFcbListHead; LIST_ENTRY ClientFcbListHead; + LIST_ENTRY WaiterListHead; ULONG PipeType; ULONG ReadMode; ULONG WriteMode; @@ -52,6 +53,14 @@ typedef struct _NPFS_FCB KSPIN_LOCK DataListLock; /* Data queue lock */ } NPFS_FCB, *PNPFS_FCB; +typedef struct _NPFS_WAITER_ENTRY +{ + LIST_ENTRY Entry; + PIRP Irp; + PNPFS_PIPE Pipe; + PNPFS_FCB Fcb; +} NPFS_WAITER_ENTRY, *PNPFS_WAITER_ENTRY; + extern NPAGED_LOOKASIDE_LIST NpfsPipeDataLookasideList; diff --git a/reactos/drivers/fs/np/rw.c b/reactos/drivers/fs/np/rw.c index c52403b8e69..5338323c555 100644 --- a/reactos/drivers/fs/np/rw.c +++ b/reactos/drivers/fs/np/rw.c @@ -101,7 +101,6 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, /* FIXME: check if in blocking mode */ if (Fcb->ReadDataAvailable == 0) { - KeResetEvent(&Fcb->Event); if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE) { KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE); @@ -167,6 +166,7 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, if (Length == 0) { KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE); + KeResetEvent(&Fcb->Event); break; } } @@ -187,8 +187,19 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, #endif Information = CopyLength; - Fcb->ReadDataAvailable = 0; - Fcb->WriteQuotaAvailable = Fcb->MaxDataLength; + + if (Fcb->ReadDataAvailable > Length) + { + memmove(Fcb->Data, Fcb->Data + Length, + Fcb->ReadDataAvailable - Length); + Fcb->ReadDataAvailable -= Length; + Status = STATUS_MORE_ENTRIES; + } + else + { + Fcb->ReadDataAvailable = 0; + Fcb->WriteQuotaAvailable = Fcb->MaxDataLength; + } } if (Information > 0) @@ -197,6 +208,7 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, { KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE); } + KeResetEvent(&Fcb->Event); break; } } @@ -291,7 +303,6 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject, { if (ReaderFcb->WriteQuotaAvailable == 0) { - KeResetEvent(&Fcb->Event); KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE); KeReleaseSpinLock(&ReaderFcb->DataListLock, OldIrql); if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE) @@ -355,6 +366,7 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject, if (Length == 0) { KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE); + KeResetEvent(&Fcb->Event); break; } } @@ -374,6 +386,7 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject, if (Information > 0) { KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE); + KeResetEvent(&Fcb->Event); break; } } From a0acd5386b696e8a8f2ae854df99ffb39611533d Mon Sep 17 00:00:00 2001 From: Martin Fuchs Date: Sat, 5 Mar 2005 17:27:21 +0000 Subject: [PATCH 5/5] install ibrowser.exe in system32 dir svn path=/trunk/; revision=13829 --- reactos/bootdata/packages/reactos.dff | 1 + reactos/subsys/system/ibrowser/Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/reactos/bootdata/packages/reactos.dff b/reactos/bootdata/packages/reactos.dff index 3bc14dbc6fa..2a3248c017e 100755 --- a/reactos/bootdata/packages/reactos.dff +++ b/reactos/bootdata/packages/reactos.dff @@ -146,6 +146,7 @@ subsys\system\cmd\cmd.exe 1 subsys\system\explorer\explorer.exe 4 subsys\system\explorer\explorer-cfg-template.xml 4 subsys\system\explorer\notifyhook\notifyhook.dll 1 +subsys\system\ibrowser\ibrowser.exe 1 subsys\system\format\format.exe 1 subsys\system\notepad\notepad.exe 1 subsys\system\regedit\regedit.exe 4 diff --git a/reactos/subsys/system/ibrowser/Makefile b/reactos/subsys/system/ibrowser/Makefile index fccef8fc2eb..1abc8a1356a 100644 --- a/reactos/subsys/system/ibrowser/Makefile +++ b/reactos/subsys/system/ibrowser/Makefile @@ -12,7 +12,7 @@ TARGET_APPTYPE := windows TARGET_NAME := ibrowser -TARGET_INSTALLDIR := . +TARGET_INSTALLDIR := system32 TARGET_CFLAGS := \ -D__USE_W32API -DWIN32 -D_ROS_ \