⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rw.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
				Status = STATUS_PENDING;
				goto done;
			}
		}
	}

	while (1)
	{
		Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
		Information = Irp->IoStatus.Information;
		Length = IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length;
		ASSERT (Information <= Length);
		Buffer = (PVOID)((ULONG_PTR)Buffer + Information);
		Length -= Information;
		Status = STATUS_SUCCESS;

		while (1)
		{
			if (Ccb->ReadDataAvailable == 0)
			{
				if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
				{
					ASSERT(Ccb->OtherSide != NULL);
					KeSetEvent(&Ccb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
				}
				if (Information > 0 &&
					(Ccb->Fcb->ReadMode != FILE_PIPE_BYTE_STREAM_MODE ||
					Ccb->PipeState != FILE_PIPE_CONNECTED_STATE))
				{
					break;
				}
				if (Ccb->PipeState != FILE_PIPE_CONNECTED_STATE)
				{
					DPRINT("PipeState: %x\n", Ccb->PipeState);
					Status = STATUS_PIPE_BROKEN;
					break;
				}
				ExReleaseFastMutex(&Ccb->DataListLock);
				if (IoIsOperationSynchronous(Irp))
				{
					/* Wait for ReadEvent to become signaled */

					DPRINT("Waiting for readable data (%wZ)\n", &Ccb->Fcb->PipeName);
					Status = KeWaitForSingleObject(&Ccb->ReadEvent,
						UserRequest,
						KernelMode,
						FALSE,
						NULL);
					DPRINT("Finished waiting (%wZ)! Status: %x\n", &Ccb->Fcb->PipeName, Status);
					ExAcquireFastMutex(&Ccb->DataListLock);
				}
				else
				{
					Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;

					Context->WaitEvent = &Ccb->ReadEvent;
					Status = NpfsAddWaitingReadWriteRequest(DeviceObject, Irp);

					if (NT_SUCCESS(Status))
					{
						Status = STATUS_PENDING;
					}
					ExAcquireFastMutex(&Ccb->DataListLock);
					break;
				}
			}
			ASSERT(IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL);
			if (Ccb->Fcb->ReadMode == FILE_PIPE_BYTE_STREAM_MODE)
			{
				DPRINT("Byte stream mode\n");
				/* Byte stream mode */
				while (Length > 0 && Ccb->ReadDataAvailable > 0)
				{
					CopyLength = min(Ccb->ReadDataAvailable, Length);
					if ((ULONG_PTR)Ccb->ReadPtr + CopyLength <= (ULONG_PTR)Ccb->Data + Ccb->MaxDataLength)
					{
						memcpy(Buffer, Ccb->ReadPtr, CopyLength);
						Ccb->ReadPtr = (PVOID)((ULONG_PTR)Ccb->ReadPtr + CopyLength);
						if (Ccb->ReadPtr == (PVOID)((ULONG_PTR)Ccb->Data + Ccb->MaxDataLength))
						{
							Ccb->ReadPtr = Ccb->Data;
						}
					}
					else
					{
						TempLength = (ULONG)((ULONG_PTR)Ccb->Data + Ccb->MaxDataLength - (ULONG_PTR)Ccb->ReadPtr);
						memcpy(Buffer, Ccb->ReadPtr, TempLength);
						memcpy((PVOID)((ULONG_PTR)Buffer + TempLength), Ccb->Data, CopyLength - TempLength);
						Ccb->ReadPtr = (PVOID)((ULONG_PTR)Ccb->Data + CopyLength - TempLength);
					}

					Buffer = (PVOID)((ULONG_PTR)Buffer + CopyLength);
					Length -= CopyLength;
					Information += CopyLength;

					Ccb->ReadDataAvailable -= CopyLength;
					Ccb->WriteQuotaAvailable += CopyLength;
				}

				if (Length == 0)
				{
					if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
					{
						KeSetEvent(&Ccb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
					}
					KeResetEvent(&Ccb->ReadEvent);
					break;
				}
			}
			else
			{
				DPRINT("Message mode\n");

				/* Message mode */
				if (Ccb->ReadDataAvailable)
				{
					/* Truncate the message if the receive buffer is too small */
					CopyLength = min(Ccb->ReadDataAvailable, Length);
					memcpy(Buffer, Ccb->Data, CopyLength);

#ifndef NDEBUG
					DPRINT("Length %d Buffer %x\n",CopyLength,Buffer);
					HexDump((PUCHAR)Buffer, CopyLength);
#endif

					Information = CopyLength;

					if (Ccb->ReadDataAvailable > Length)
					{
						memmove(Ccb->Data, (PVOID)((ULONG_PTR)Ccb->Data + Length),
							Ccb->ReadDataAvailable - Length);
						Ccb->ReadDataAvailable -= Length;
						Status = STATUS_MORE_ENTRIES;
					}
					else
					{
						KeResetEvent(&Ccb->ReadEvent);
						if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
						{
							KeSetEvent(&Ccb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
						}
						Ccb->ReadDataAvailable = 0;
						Ccb->WriteQuotaAvailable = Ccb->MaxDataLength;
					}
				}

				if (Information > 0)
				{
					break;
				}
			}
		}
		Irp->IoStatus.Information = Information;
		Irp->IoStatus.Status = Status;

		ASSERT(IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL);

		if (IoIsOperationSynchronous(Irp))
		{
			RemoveEntryList(&Context->ListEntry);
			if (!IsListEmpty(&Ccb->ReadRequestListHead))
			{
				Context = CONTAINING_RECORD(Ccb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry);
				KeSetEvent(Context->WaitEvent, IO_NO_INCREMENT, FALSE);
			}
			ExReleaseFastMutex(&Ccb->DataListLock);
			IoCompleteRequest(Irp, IO_NO_INCREMENT);

			DPRINT("NpfsRead done (Status %lx)\n", Status);
			return Status;
		}
		else
		{
			if (IsOriginalRequest)
			{
				IsOriginalRequest = FALSE;
				OriginalStatus = Status;
			}
			if (Status == STATUS_PENDING)
			{
				ExReleaseFastMutex(&Ccb->DataListLock);
				DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus);
				return OriginalStatus;
			}
			RemoveEntryList(&Context->ListEntry);
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			if (IsListEmpty(&Ccb->ReadRequestListHead))
			{
				ExReleaseFastMutex(&Ccb->DataListLock);
				DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus);
				return OriginalStatus;
			}
			Context = CONTAINING_RECORD(Ccb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry);
			Irp = CONTAINING_RECORD(Context, IRP, Tail.Overlay.DriverContext);
		}
	}

done:
	Irp->IoStatus.Status = Status;

	if (Status != STATUS_PENDING)
	{
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
	}
	DPRINT("NpfsRead done (Status %lx)\n", Status);

	return Status;
}

NTSTATUS STDCALL
NpfsWrite(PDEVICE_OBJECT DeviceObject,
		  PIRP Irp)
{
	PIO_STACK_LOCATION IoStack;
	PFILE_OBJECT FileObject;
	PNPFS_FCB Fcb = NULL;
	PNPFS_CCB Ccb = NULL;
	PNPFS_CCB ReaderCcb;
	PUCHAR Buffer;
	NTSTATUS Status = STATUS_SUCCESS;
	ULONG Length;
	ULONG Offset;
	ULONG Information;
	ULONG CopyLength;
	ULONG TempLength;

	DPRINT("NpfsWrite()\n");

	IoStack = IoGetCurrentIrpStackLocation(Irp);
	FileObject = IoStack->FileObject;
	DPRINT("FileObject %p\n", FileObject);
	DPRINT("Pipe name %wZ\n", &FileObject->FileName);

	Ccb = FileObject->FsContext2;
	ReaderCcb = Ccb->OtherSide;
	Fcb = Ccb->Fcb;

	Length = IoStack->Parameters.Write.Length;
	Offset = IoStack->Parameters.Write.ByteOffset.u.LowPart;
	Information = 0;

	if (Irp->MdlAddress == NULL)
	{
		DPRINT("Irp->MdlAddress == NULL\n");
		Status = STATUS_UNSUCCESSFUL;
		Length = 0;
		goto done;
	}

	if (ReaderCcb == NULL)
	{
		DPRINT("Pipe is NOT connected!\n");
		if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
			Status = STATUS_PIPE_LISTENING;
		else if (Ccb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
			Status = STATUS_PIPE_DISCONNECTED;
		else
			Status = STATUS_UNSUCCESSFUL;
		Length = 0;
		goto done;
	}

	if (ReaderCcb->Data == NULL)
	{
		DPRINT("Pipe is NOT writable!\n");
		Status = STATUS_UNSUCCESSFUL;
		Length = 0;
		goto done;
	}

	Status = STATUS_SUCCESS;
	Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);

	ExAcquireFastMutex(&ReaderCcb->DataListLock);
#ifndef NDEBUG
	DPRINT("Length %d Buffer %x Offset %x\n",Length,Buffer,Offset);
	HexDump(Buffer, Length);
#endif

	while(1)
	{
		if (ReaderCcb->WriteQuotaAvailable == 0)
		{
			KeSetEvent(&ReaderCcb->ReadEvent, IO_NO_INCREMENT, FALSE);
			if (Ccb->PipeState != FILE_PIPE_CONNECTED_STATE)
			{
				Status = STATUS_PIPE_BROKEN;
				ExReleaseFastMutex(&ReaderCcb->DataListLock);
				goto done;
			}
			ExReleaseFastMutex(&ReaderCcb->DataListLock);

			DPRINT("Waiting for buffer space (%S)\n", Fcb->PipeName.Buffer);
			Status = KeWaitForSingleObject(&Ccb->WriteEvent,
				UserRequest,
				KernelMode,
				FALSE,
				NULL);
			DPRINT("Finished waiting (%S)! Status: %x\n", Fcb->PipeName.Buffer, Status);

			/*
			* It's possible that the event was signaled because the
			* other side of pipe was closed.
			*/
			if (Ccb->PipeState != FILE_PIPE_CONNECTED_STATE)
			{
				DPRINT("PipeState: %x\n", Ccb->PipeState);
				Status = STATUS_PIPE_BROKEN;
				// ExReleaseFastMutex(&ReaderCcb->DataListLock);
				goto done;
			}

			ExAcquireFastMutex(&ReaderCcb->DataListLock);
		}

		if (Fcb->WriteMode == FILE_PIPE_BYTE_STREAM_MODE)
		{
			DPRINT("Byte stream mode\n");
			while (Length > 0 && ReaderCcb->WriteQuotaAvailable > 0)
			{
				CopyLength = min(Length, ReaderCcb->WriteQuotaAvailable);
				if ((ULONG_PTR)ReaderCcb->WritePtr + CopyLength <= (ULONG_PTR)ReaderCcb->Data + ReaderCcb->MaxDataLength)
				{
					memcpy(ReaderCcb->WritePtr, Buffer, CopyLength);
					ReaderCcb->WritePtr = (PVOID)((ULONG_PTR)ReaderCcb->WritePtr + CopyLength);
					if ((ULONG_PTR)ReaderCcb->WritePtr == (ULONG_PTR)ReaderCcb->Data + ReaderCcb->MaxDataLength)
					{
						ReaderCcb->WritePtr = ReaderCcb->Data;
					}
				}
				else
				{
					TempLength = (ULONG)((ULONG_PTR)ReaderCcb->Data + ReaderCcb->MaxDataLength - (ULONG_PTR)ReaderCcb->WritePtr);
					memcpy(ReaderCcb->WritePtr, Buffer, TempLength);
					memcpy(ReaderCcb->Data, Buffer + TempLength, CopyLength - TempLength);
					ReaderCcb->WritePtr = (PVOID)((ULONG_PTR)ReaderCcb->Data + CopyLength - TempLength);
				}

				Buffer += CopyLength;
				Length -= CopyLength;
				Information += CopyLength;

				ReaderCcb->ReadDataAvailable += CopyLength;
				ReaderCcb->WriteQuotaAvailable -= CopyLength;
			}

			if (Length == 0)
			{
				KeSetEvent(&ReaderCcb->ReadEvent, IO_NO_INCREMENT, FALSE);
				KeResetEvent(&Ccb->WriteEvent);
				break;
			}
		}
		else
		{
			DPRINT("Message mode\n");
			if (Length > 0)
			{
				CopyLength = min(Length, ReaderCcb->WriteQuotaAvailable);
				memcpy(ReaderCcb->Data, Buffer, CopyLength);

				Information = CopyLength;
				ReaderCcb->ReadDataAvailable = CopyLength;
				ReaderCcb->WriteQuotaAvailable = 0;
			}

			if (Information > 0)
			{
				KeSetEvent(&ReaderCcb->ReadEvent, IO_NO_INCREMENT, FALSE);
				KeResetEvent(&Ccb->WriteEvent);
				break;
			}
		}
	}

	ExReleaseFastMutex(&ReaderCcb->DataListLock);

done:
	Irp->IoStatus.Status = Status;
	Irp->IoStatus.Information = Information;

	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	DPRINT("NpfsWrite done (Status %lx)\n", Status);

	return Status;
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -