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

📄 npipe.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
BOOL STDCALL
GetNamedPipeHandleStateW(HANDLE hNamedPipe,
			 LPDWORD lpState,
			 LPDWORD lpCurInstances,
			 LPDWORD lpMaxCollectionCount,
			 LPDWORD lpCollectDataTimeout,
			 LPWSTR lpUserName,
			 DWORD nMaxUserNameSize)
{
  IO_STATUS_BLOCK StatusBlock;
  NTSTATUS Status;

  if (lpState != NULL)
  {
    FILE_PIPE_INFORMATION PipeInfo;

    Status = NtQueryInformationFile(hNamedPipe,
                                    &StatusBlock,
                                    &PipeInfo,
                                    sizeof(FILE_PIPE_INFORMATION),
                                    FilePipeInformation);
    if (!NT_SUCCESS(Status))
    {
      SetLastErrorByStatus(Status);
      return FALSE;
    }

    *lpState = ((PipeInfo.CompletionMode != FILE_PIPE_QUEUE_OPERATION) ? PIPE_NOWAIT : PIPE_WAIT);
    *lpState |= ((PipeInfo.ReadMode != FILE_PIPE_BYTE_STREAM_MODE) ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
  }

  if(lpCurInstances != NULL)
  {
    FILE_PIPE_LOCAL_INFORMATION LocalInfo;

    Status = NtQueryInformationFile(hNamedPipe,
                                    &StatusBlock,
                                    &LocalInfo,
                                    sizeof(FILE_PIPE_LOCAL_INFORMATION),
                                    FilePipeLocalInformation);
    if(!NT_SUCCESS(Status))
    {
      SetLastErrorByStatus(Status);
      return FALSE;
    }

    *lpCurInstances = min(LocalInfo.CurrentInstances, PIPE_UNLIMITED_INSTANCES);
  }

  if(lpMaxCollectionCount != NULL || lpCollectDataTimeout != NULL)
  {
    FILE_PIPE_REMOTE_INFORMATION RemoteInfo;

    Status = NtQueryInformationFile(hNamedPipe,
                                    &StatusBlock,
                                    &RemoteInfo,
                                    sizeof(FILE_PIPE_REMOTE_INFORMATION),
                                    FilePipeRemoteInformation);
    if(!NT_SUCCESS(Status))
    {
      SetLastErrorByStatus(Status);
      return FALSE;
    }

    if(lpMaxCollectionCount != NULL)
    {
      *lpMaxCollectionCount = RemoteInfo.MaximumCollectionCount;
    }

    if(lpCollectDataTimeout != NULL)
    {
      /* FIXME */
      *lpCollectDataTimeout = 0;
    }
  }

  if(lpUserName != NULL)
  {
    /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
               retreive the user name with GetUserName(), revert the impersonation
               and finally restore the thread token */
  }

  return TRUE;
}


/*
 * @implemented
 */
BOOL STDCALL
GetNamedPipeHandleStateA(HANDLE hNamedPipe,
			 LPDWORD lpState,
			 LPDWORD lpCurInstances,
			 LPDWORD lpMaxCollectionCount,
			 LPDWORD lpCollectDataTimeout,
			 LPSTR lpUserName,
			 DWORD nMaxUserNameSize)
{
  UNICODE_STRING UserNameW = {0};
  ANSI_STRING UserNameA;
  BOOL Ret;

  if(lpUserName != NULL)
  {
    UserNameW.MaximumLength = nMaxUserNameSize * sizeof(WCHAR);
    UserNameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW.MaximumLength);
    if (UserNameW.Buffer == NULL)
    {
      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
      return FALSE;
    }

    UserNameA.Buffer = lpUserName;
    UserNameA.Length = 0;
    UserNameA.MaximumLength = nMaxUserNameSize;
  }

  Ret = GetNamedPipeHandleStateW(hNamedPipe,
                                 lpState,
                                 lpCurInstances,
                                 lpMaxCollectionCount,
                                 lpCollectDataTimeout,
                                 UserNameW.Buffer,
                                 nMaxUserNameSize);

  if(Ret && lpUserName != NULL)
  {
    NTSTATUS Status;

    RtlInitUnicodeString(&UserNameW, UserNameW.Buffer);
    Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
    if(!NT_SUCCESS(Status))
    {
      SetLastErrorByStatus(Status);
      Ret = FALSE;
    }
  }

  if(UserNameW.Buffer != NULL)
  {
    RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW.Buffer);
  }

  return Ret;
}


/*
 * @implemented
 */
BOOL STDCALL
GetNamedPipeInfo(HANDLE hNamedPipe,
		 LPDWORD lpFlags,
		 LPDWORD lpOutBufferSize,
		 LPDWORD lpInBufferSize,
		 LPDWORD lpMaxInstances)
{
  FILE_PIPE_LOCAL_INFORMATION PipeLocalInformation;
  IO_STATUS_BLOCK StatusBlock;
  NTSTATUS Status;

  Status = NtQueryInformationFile(hNamedPipe,
				  &StatusBlock,
				  &PipeLocalInformation,
				  sizeof(FILE_PIPE_LOCAL_INFORMATION),
				  FilePipeLocalInformation);
  if (!NT_SUCCESS(Status))
    {
      SetLastErrorByStatus(Status);
      return(FALSE);
    }

  if (lpFlags != NULL)
    {
      *lpFlags = (PipeLocalInformation.NamedPipeEnd == FILE_PIPE_SERVER_END) ? PIPE_SERVER_END : PIPE_CLIENT_END;
      *lpFlags |= (PipeLocalInformation.NamedPipeType == 1) ? PIPE_TYPE_MESSAGE : PIPE_TYPE_BYTE;
    }

  if (lpOutBufferSize != NULL)
    *lpOutBufferSize = PipeLocalInformation.OutboundQuota;

  if (lpInBufferSize != NULL)
    *lpInBufferSize = PipeLocalInformation.InboundQuota;

  if (lpMaxInstances != NULL)
    {
      if (PipeLocalInformation.MaximumInstances >= 255)
	*lpMaxInstances = PIPE_UNLIMITED_INSTANCES;
      else
	*lpMaxInstances = PipeLocalInformation.MaximumInstances;
    }

  return(TRUE);
}

/*
 * @implemented
 */
BOOL
WINAPI
PeekNamedPipe(HANDLE hNamedPipe,
              LPVOID lpBuffer,
              DWORD nBufferSize,
              LPDWORD lpBytesRead,
              LPDWORD lpTotalBytesAvail,
              LPDWORD lpBytesLeftThisMessage)
{
    PFILE_PIPE_PEEK_BUFFER Buffer;
    IO_STATUS_BLOCK Iosb;
    ULONG BufferSize;
    NTSTATUS Status;

    /* Calculate the buffer space that we'll need and allocate it */
    BufferSize = nBufferSize + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]);
    Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
    if (Buffer == NULL)
    {
        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
        return FALSE;
    }

    /* Tell the driver to seek */
    Status = NtFsControlFile(hNamedPipe,
                             NULL,
                             NULL,
                             NULL,
                             &Iosb,
                             FSCTL_PIPE_PEEK,
                             NULL,
                             0,
                             Buffer,
                             BufferSize);
    if (Status == STATUS_PENDING)
    {
        /* Wait for npfs to be done, and update the status */
        Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
        if (NT_SUCCESS(Status)) Status = Iosb.Status;
    }

    /* Overflow is success for us */
    if (Status == STATUS_BUFFER_OVERFLOW) Status = STATUS_SUCCESS;

    /* If we failed */
    if (!NT_SUCCESS(Status))
    {
        /* Free the buffer and return failure */
        RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
        SetLastErrorByStatus(Status);
        return FALSE;
    }

    /* Check if caller requested bytes available */
    if (lpTotalBytesAvail) *lpTotalBytesAvail = Buffer->ReadDataAvailable;

    /* Check if caller requested bytes read */
    if (lpBytesRead)
    {
        /* Calculate the bytes returned, minus our structure overhead */
        *lpBytesRead = (ULONG)(Iosb.Information -
                               FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
    }

    /* Check if caller requested bytes left */
    if (lpBytesLeftThisMessage)
    {
        /* Calculate total minus what we returned and our structure overhead */
        *lpBytesLeftThisMessage = Buffer->MessageLength -
                                  (ULONG)(Iosb.Information -
                                          FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
    }

    /* Check if the caller wanted to see the actual data */
    if (lpBuffer)
    {
        /* Give him what he wants */
        RtlCopyMemory(lpBuffer,
                      Buffer->Data,
	                  Iosb.Information -
                      FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
    }

    /* Free the buffer and return success */
    RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
    return TRUE;
}

/*
 * @implemented
 */
BOOL STDCALL
TransactNamedPipe(IN HANDLE hNamedPipe,
                  IN LPVOID lpInBuffer,
                  IN DWORD nInBufferSize,
                  OUT LPVOID lpOutBuffer,
                  IN DWORD nOutBufferSize,
                  OUT LPDWORD lpBytesRead  OPTIONAL,
                  IN LPOVERLAPPED lpOverlapped  OPTIONAL)
{
   NTSTATUS Status;

   if (lpBytesRead != NULL)
     {
        *lpBytesRead = 0;
     }

   if (lpOverlapped != NULL)
     {
        PVOID ApcContext;

        ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);
        lpOverlapped->Internal = STATUS_PENDING;

        Status = NtFsControlFile(hNamedPipe,
                                 lpOverlapped->hEvent,
                                 NULL,
                                 ApcContext,
                                 (PIO_STATUS_BLOCK)lpOverlapped,
                                 FSCTL_PIPE_TRANSCEIVE,
                                 lpInBuffer,
                                 nInBufferSize,
                                 lpOutBuffer,
                                 nOutBufferSize);

        /* return FALSE in case of failure and pending operations! */
        if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
          {
             SetLastErrorByStatus(Status);
             return FALSE;
          }

        if (lpBytesRead != NULL)
          {
             *lpBytesRead = lpOverlapped->InternalHigh;
          }
     }
   else
     {
#if 0 /* We don't implement FSCTL_PIPE_TRANSCEIVE yet */
        IO_STATUS_BLOCK Iosb;

        Status = NtFsControlFile(hNamedPipe,
                                 NULL,
                                 NULL,
                                 NULL,
                                 &Iosb,
                                 FSCTL_PIPE_TRANSCEIVE,
                                 lpInBuffer,
                                 nInBufferSize,
                                 lpOutBuffer,
                                 nOutBufferSize);

        /* wait in case operation is pending */
        if (Status == STATUS_PENDING)
          {
             Status = NtWaitForSingleObject(hNamedPipe,
                                            FALSE,
                                            NULL);
             if (NT_SUCCESS(Status))
               {
                  Status = Iosb.Status;
               }
          }

        if (NT_SUCCESS(Status))
          {
             /* lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
                check that case either and crashes (only after the operation
                completed) */
             *lpBytesRead = Iosb.Information;
          }
        else
          {
             SetLastErrorByStatus(Status);
             return FALSE;
          }
#else /* Workaround while FSCTL_PIPE_TRANSCEIVE not available */
        DWORD nActualBytes;

        while (0 != nInBufferSize &&
               WriteFile(hNamedPipe, lpInBuffer, nInBufferSize, &nActualBytes,
                         NULL))
          {
             lpInBuffer = (LPVOID)((char *) lpInBuffer + nActualBytes);
             nInBufferSize -= nActualBytes;
          }
        if (0 != nInBufferSize)
          {
             /* Must have dropped out of the while 'cause WriteFile failed */
             return FALSE;
          }
        if (! ReadFile(hNamedPipe, lpOutBuffer, nOutBufferSize, &nActualBytes,
                       NULL))
          {
             return FALSE;
          }
        if (NULL != lpBytesRead)
          {
            *lpBytesRead = nActualBytes;
          }
#endif
     }

   return TRUE;
}

/* EOF */

⌨️ 快捷键说明

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