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

📄 rw.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 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);

	  ExAcquireFastMutex(&ReaderCcb->DataListLock);
	  /*
	   * 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;
	    }
	}

      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 + -