Пример #1
0
/*
 * @implemented
 */
HANDLE
WINAPI
RegisterWaitForSingleObjectEx(IN HANDLE hObject,
                              IN WAITORTIMERCALLBACK Callback,
                              IN PVOID Context,
                              IN ULONG dwMilliseconds,
                              IN ULONG dwFlags)
{
    NTSTATUS Status;
    HANDLE hNewWaitObject;

    /* Get real handle */
    hObject = TranslateStdHandle(hObject);

    /* Check for console handle */
    if ((IsConsoleHandle(hObject)) && (VerifyConsoleIoHandle(hObject)))
    {
        /* Get the real wait handle */
        hObject = GetConsoleInputWaitHandle();
    }

    /* Register the wait */
    Status = RtlRegisterWait(&hNewWaitObject,
                             hObject,
                             Callback,
                             Context,
                             dwMilliseconds,
                             dwFlags);
    if (!NT_SUCCESS(Status))
    {
        /* Return failure */
        BaseSetLastNTError(Status);
        return NULL;
    }

    /* Return the object */
    return hNewWaitObject;
}
Пример #2
0
/*
 * @implemented
 */
BOOL
WINAPI
GetHandleInformation(IN HANDLE hObject,
                     OUT LPDWORD lpdwFlags)
{
    OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo;
    ULONG BytesWritten;
    NTSTATUS Status;
    DWORD Flags;

    hObject = TranslateStdHandle(hObject);

    if (IsConsoleHandle(hObject))
    {
        /* FIXME: GetConsoleHandleInformation required */
        UNIMPLEMENTED;
        BaseSetLastNTError(STATUS_NOT_IMPLEMENTED);
        return FALSE;
    }

    Status = NtQueryObject(hObject,
                           ObjectHandleFlagInformation,
                           &HandleInfo,
                           sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION),
                           &BytesWritten);
    if (!NT_SUCCESS(Status))
    {
        BaseSetLastNTError(Status);
        return FALSE;
    }

    Flags = 0;
    if (HandleInfo.Inherit) Flags |= HANDLE_FLAG_INHERIT;
    if (HandleInfo.ProtectFromClose) Flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
    *lpdwFlags = Flags;
    return TRUE;
}
Пример #3
0
int
rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
            struct timeval *timeout)
#undef timeval
{
  static struct timeval tv0;
  static HANDLE hEvent;
  HANDLE h, handle_array[FD_SETSIZE + 2];
  fd_set handle_rfds, handle_wfds, handle_xfds;
  struct bitset rbits, wbits, xbits;
  unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
  DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
  MSG msg;
  int i, fd, rc;

  if (nfds > FD_SETSIZE)
    nfds = FD_SETSIZE;

  if (!timeout)
    wait_timeout = INFINITE;
  else
    {
      wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;

      /* select is also used as a portable usleep.  */
      if (!rfds && !wfds && !xfds)
        {
          Sleep (wait_timeout);
          return 0;
        }
    }

  if (!hEvent)
    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);

  handle_array[0] = hEvent;
  nhandles = 1;
  nsock = 0;

  /* Copy descriptors to bitsets.  At the same time, eliminate
     bits in the "wrong" direction for console input buffers
     and screen buffers, because screen buffers are waitable
     and they will block until a character is available.  */
  memset (&rbits, 0, sizeof (rbits));
  memset (&wbits, 0, sizeof (wbits));
  memset (&xbits, 0, sizeof (xbits));
  memset (anyfds_in, 0, sizeof (anyfds_in));
  if (rfds)
    for (i = 0; i < rfds->fd_count; i++)
      {
        fd = rfds->fd_array[i];
        h = (HANDLE) _get_osfhandle (fd);
        if (IsConsoleHandle (h)
            && !GetNumberOfConsoleInputEvents (h, &nbuffer))
          continue;

        rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
      }
  else
    rfds = (fd_set *) alloca (sizeof (fd_set));

  if (wfds)
    for (i = 0; i < wfds->fd_count; i++)
      {
        fd = wfds->fd_array[i];
        h = (HANDLE) _get_osfhandle (fd);
        if (IsConsoleHandle (h)
            && GetNumberOfConsoleInputEvents (h, &nbuffer))
          continue;

        wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
      }
  else
    wfds = (fd_set *) alloca (sizeof (fd_set));

  if (xfds)
    for (i = 0; i < xfds->fd_count; i++)
      {
        fd = xfds->fd_array[i];
        xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
      }
  else
    xfds = (fd_set *) alloca (sizeof (fd_set));

  /* Zero all the fd_sets, including the application's.  */
  FD_ZERO (rfds);
  FD_ZERO (wfds);
  FD_ZERO (xfds);
  FD_ZERO (&handle_rfds);
  FD_ZERO (&handle_wfds);
  FD_ZERO (&handle_xfds);

  /* Classify handles.  Create fd sets for sockets, poll the others. */
  for (i = 0; i < nfds; i++)
    {
      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
        continue;

      h = (HANDLE) _get_osfhandle (i);
      if (!h)
        {
          errno = EBADF;
          return -1;
        }

      if (IsSocketHandle (h))
        {
          int requested = FD_CLOSE;

          /* See above; socket handles are mapped onto select, but we
             need to map descriptors to handles.  */
          if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            {
              requested |= FD_READ | FD_ACCEPT;
              FD_SET ((SOCKET) h, rfds);
              FD_SET ((SOCKET) h, &handle_rfds);
            }
          if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            {
              requested |= FD_WRITE | FD_CONNECT;
              FD_SET ((SOCKET) h, wfds);
              FD_SET ((SOCKET) h, &handle_wfds);
            }
          if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            {
              requested |= FD_OOB;
              FD_SET ((SOCKET) h, xfds);
              FD_SET ((SOCKET) h, &handle_xfds);
            }

          WSAEventSelect ((SOCKET) h, hEvent, requested);
          nsock++;
        }
      else
        {
          handle_array[nhandles++] = h;

          /* Poll now.  If we get an event, do not wait below.  */
          if (wait_timeout != 0
              && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
            wait_timeout = 0;
        }
    }

  /* Place a sentinel at the end of the array.  */
  handle_array[nhandles] = NULL;

restart:
  if (wait_timeout == 0 || nsock == 0)
    rc = 0;
  else
    {
      /* See if we need to wait in the loop below.  If any select is ready,
         do MsgWaitForMultipleObjects anyway to dispatch messages, but
         no need to call select again.  */
      rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
      if (rc == 0)
        {
          /* Restore the fd_sets for the other select we do below.  */
          memcpy (&handle_rfds, rfds, sizeof (fd_set));
          memcpy (&handle_wfds, wfds, sizeof (fd_set));
          memcpy (&handle_xfds, xfds, sizeof (fd_set));
        }
      else
        wait_timeout = 0;
    }

  for (;;)
    {
      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
                                       wait_timeout, QS_ALLINPUT);

      if (ret == WAIT_OBJECT_0 + nhandles)
        {
          /* new input of some other kind */
          BOOL bRet;
          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
            {
              TranslateMessage (&msg);
              DispatchMessage (&msg);
            }
        }
      else
        break;
    }

  /* If we haven't done it yet, check the status of the sockets.  */
  if (rc == 0 && nsock > 0)
    rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);

  if (nhandles > 1)
    {
      /* Count results that are not counted in the return value of select.  */
      nhandles = 1;
      for (i = 0; i < nfds; i++)
        {
          if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
            continue;

          h = (HANDLE) _get_osfhandle (i);
          if (h == handle_array[nhandles])
            {
              /* Not a socket.  */
              nhandles++;
              windows_poll_handle (h, i, &rbits, &wbits, &xbits);
              if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
                  || wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
                  || xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
                rc++;
            }
        }

      if (rc == 0 && wait_timeout == INFINITE)
        {
          /* Sleep 1 millisecond to avoid busy wait and retry with the
             original fd_sets.  */
          memcpy (&handle_rfds, rfds, sizeof (fd_set));
          memcpy (&handle_wfds, wfds, sizeof (fd_set));
          memcpy (&handle_xfds, xfds, sizeof (fd_set));
          SleepEx (1, TRUE);
          goto restart;
        }
    }

  /* Now fill in the results.  */
  FD_ZERO (rfds);
  FD_ZERO (wfds);
  FD_ZERO (xfds);
  nhandles = 1;
  for (i = 0; i < nfds; i++)
    {
      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
        continue;

      h = (HANDLE) _get_osfhandle (i);
      if (h != handle_array[nhandles])
        {
          /* Perform handle->descriptor mapping.  */
          WSAEventSelect ((SOCKET) h, NULL, 0);
          if (FD_ISSET (h, &handle_rfds))
            FD_SET (i, rfds);
          if (FD_ISSET (h, &handle_wfds))
            FD_SET (i, wfds);
          if (FD_ISSET (h, &handle_xfds))
            FD_SET (i, xfds);
        }
      else
        {
          /* Not a socket.  */
          nhandles++;
          if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            FD_SET (i, rfds);
          if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            FD_SET (i, wfds);
          if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            FD_SET (i, xfds);
        }
    }

  return rc;
}
Пример #4
0
static int
windows_poll_handle (HANDLE h, int fd,
                     struct bitset *rbits,
                     struct bitset *wbits,
                     struct bitset *xbits)
{
  BOOL read, write, except;
  int i, ret;
  INPUT_RECORD *irbuffer;
  DWORD avail, nbuffer;
  BOOL bRet;
  IO_STATUS_BLOCK iosb;
  FILE_PIPE_LOCAL_INFORMATION fpli;
  static PNtQueryInformationFile NtQueryInformationFile;
  static BOOL once_only;

  read = write = except = FALSE;
  switch (GetFileType (h))
    {
    case FILE_TYPE_DISK:
      read = TRUE;
      write = TRUE;
      break;

    case FILE_TYPE_PIPE:
      if (!once_only)
        {
          NtQueryInformationFile = (PNtQueryInformationFile)
            GetProcAddress (GetModuleHandle ("ntdll.dll"),
                            "NtQueryInformationFile");
          once_only = TRUE;
        }

      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
        {
          if (avail)
            read = TRUE;
        }
      else if (GetLastError () == ERROR_BROKEN_PIPE)
        ;

      else
        {
          /* It was the write-end of the pipe.  Check if it is writable.
             If NtQueryInformationFile fails, optimistically assume the pipe is
             writable.  This could happen on Windows 9x, where
             NtQueryInformationFile is not available, or if we inherit a pipe
             that doesn't permit FILE_READ_ATTRIBUTES access on the write end
             (I think this should not happen since Windows XP SP2; WINE seems
             fine too).  Otherwise, ensure that enough space is available for
             atomic writes.  */
          memset (&iosb, 0, sizeof (iosb));
          memset (&fpli, 0, sizeof (fpli));

          if (!NtQueryInformationFile
              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
                                         FilePipeLocalInformation)
              || fpli.WriteQuotaAvailable >= PIPE_BUF
              || (fpli.OutboundQuota < PIPE_BUF &&
                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))
            write = TRUE;
        }
      break;

    case FILE_TYPE_CHAR:
      write = TRUE;
      if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
        break;

      ret = WaitForSingleObject (h, 0);
      if (ret == WAIT_OBJECT_0)
        {
          if (!IsConsoleHandle (h))
            {
              read = TRUE;
              break;
            }

          nbuffer = avail = 0;
          bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);

          /* Screen buffers handles are filtered earlier.  */
          assert (bRet);
          if (nbuffer == 0)
            {
              except = TRUE;
              break;
            }

          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
          if (!bRet || avail == 0)
            {
              except = TRUE;
              break;
            }

          for (i = 0; i < avail; i++)
            if (irbuffer[i].EventType == KEY_EVENT)
              read = TRUE;
        }
      break;

    default:
      ret = WaitForSingleObject (h, 0);
      write = TRUE;
      if (ret == WAIT_OBJECT_0)
        read = TRUE;

      break;
    }

  ret = 0;
  if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
    {
      rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
      ret++;
    }

  if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
    {
      wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
      ret++;
    }

  if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
    {
      xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
      ret++;
    }

  return ret;
}
Пример #5
0
/*
 * @implemented
 */
BOOL WINAPI
WriteFile(IN HANDLE hFile,
          IN LPCVOID lpBuffer,
          IN DWORD nNumberOfBytesToWrite OPTIONAL,
          OUT LPDWORD lpNumberOfBytesWritten OPTIONAL,
          IN LPOVERLAPPED lpOverlapped OPTIONAL)
{
    NTSTATUS Status;

    TRACE("WriteFile(hFile %p)\n", hFile);

    if (lpNumberOfBytesWritten != NULL) *lpNumberOfBytesWritten = 0;

    hFile = TranslateStdHandle(hFile);

    if (IsConsoleHandle(hFile))
    {
        return WriteConsoleA(hFile,
                             lpBuffer,
                             nNumberOfBytesToWrite,
                             lpNumberOfBytesWritten,
                             lpOverlapped);
    }

    if (lpOverlapped != NULL)
    {
        LARGE_INTEGER Offset;
        PVOID ApcContext;

        Offset.u.LowPart = lpOverlapped->Offset;
        Offset.u.HighPart = lpOverlapped->OffsetHigh;
        lpOverlapped->Internal = STATUS_PENDING;
        ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);

        Status = NtWriteFile(hFile,
                             lpOverlapped->hEvent,
                             NULL,
                             ApcContext,
                             (PIO_STATUS_BLOCK)lpOverlapped,
                             (PVOID)lpBuffer,
                             nNumberOfBytesToWrite,
                             &Offset,
                             NULL);

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

        if (lpNumberOfBytesWritten != NULL)
            *lpNumberOfBytesWritten = lpOverlapped->InternalHigh;
    }
    else
    {
        IO_STATUS_BLOCK Iosb;

        Status = NtWriteFile(hFile,
                             NULL,
                             NULL,
                             NULL,
                             &Iosb,
                             (PVOID)lpBuffer,
                             nNumberOfBytesToWrite,
                             NULL,
                             NULL);

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

        if (NT_SUCCESS(Status))
        {
            /*
             * lpNumberOfBytesWritten must not be NULL here, in fact Win doesn't
             * check that case either and crashes (only after the operation
             * completed).
             */
            *lpNumberOfBytesWritten = Iosb.Information;
        }
        else
        {
            BaseSetLastNTError(Status);
            return FALSE;
        }
    }

    TRACE("WriteFile() succeeded\n");
    return TRUE;
}
Пример #6
0
/*
 * @implemented
 */
BOOL WINAPI
ReadFile(IN HANDLE hFile,
         IN LPVOID lpBuffer,
         IN DWORD nNumberOfBytesToRead,
         OUT LPDWORD lpNumberOfBytesRead OPTIONAL,
         IN LPOVERLAPPED lpOverlapped OPTIONAL)
{
    NTSTATUS Status;

    TRACE("ReadFile(hFile %p)\n", hFile);

    if (lpNumberOfBytesRead != NULL) *lpNumberOfBytesRead = 0;
    if (!nNumberOfBytesToRead) return TRUE;

    hFile = TranslateStdHandle(hFile);

    if (IsConsoleHandle(hFile))
    {
        if (ReadConsoleA(hFile,
                         lpBuffer,
                         nNumberOfBytesToRead,
                         lpNumberOfBytesRead,
                         NULL))
        {
            DWORD dwMode;
            GetConsoleMode(hFile, &dwMode);
            if ((dwMode & ENABLE_PROCESSED_INPUT) && *(PCHAR)lpBuffer == 0x1a)
            {
                /* EOF character entered; simulate end-of-file */
                *lpNumberOfBytesRead = 0;
            }
            return TRUE;
        }
        return FALSE;
    }

    if (lpOverlapped != NULL)
    {
        LARGE_INTEGER Offset;
        PVOID ApcContext;

        Offset.u.LowPart = lpOverlapped->Offset;
        Offset.u.HighPart = lpOverlapped->OffsetHigh;
        lpOverlapped->Internal = STATUS_PENDING;
        ApcContext = (((ULONG_PTR)lpOverlapped->hEvent & 0x1) ? NULL : lpOverlapped);

        Status = NtReadFile(hFile,
                            lpOverlapped->hEvent,
                            NULL,
                            ApcContext,
                            (PIO_STATUS_BLOCK)lpOverlapped,
                            lpBuffer,
                            nNumberOfBytesToRead,
                            &Offset,
                            NULL);

        /* return FALSE in case of failure and pending operations! */
        if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)
        {
            if (Status == STATUS_END_OF_FILE && lpNumberOfBytesRead != NULL)
                *lpNumberOfBytesRead = 0;

            BaseSetLastNTError(Status);
            return FALSE;
        }

        if (lpNumberOfBytesRead != NULL)
            *lpNumberOfBytesRead = lpOverlapped->InternalHigh;
    }
    else
    {
        IO_STATUS_BLOCK Iosb;

        Status = NtReadFile(hFile,
                            NULL,
                            NULL,
                            NULL,
                            &Iosb,
                            lpBuffer,
                            nNumberOfBytesToRead,
                            NULL,
                            NULL);

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

        if (Status == STATUS_END_OF_FILE)
        {
            /*
             * lpNumberOfBytesRead must not be NULL here, in fact Win doesn't
             * check that case either and crashes (only after the operation
             * completed).
             */
            *lpNumberOfBytesRead = 0;
            return TRUE;
        }

        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).
             */
            *lpNumberOfBytesRead = Iosb.Information;
        }
        else
        {
            BaseSetLastNTError(Status);
            return FALSE;
        }
    }

    TRACE("ReadFile() succeeded\n");
    return TRUE;
}
Пример #7
0
/*
 * @implemented
 */
DWORD
WINAPI
WaitForMultipleObjectsEx(IN DWORD nCount,
                         IN CONST HANDLE *lpHandles,
                         IN BOOL bWaitAll,
                         IN DWORD dwMilliseconds,
                         IN BOOL bAlertable)
{
    PLARGE_INTEGER TimePtr;
    LARGE_INTEGER Time;
    PHANDLE HandleBuffer;
    HANDLE Handle[8];
    DWORD i;
    NTSTATUS Status;
    RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx;

    /* APCs must execute with the default activation context */
    if (bAlertable)
    {
        /* Setup the frame */
        RtlZeroMemory(&ActCtx, sizeof(ActCtx));
        ActCtx.Size = sizeof(ActCtx);
        ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER;
        RtlActivateActivationContextUnsafeFast(&ActCtx, NULL);
    }

    /* Check if we have more handles then we locally optimize */
    if (nCount > 8)
    {
        /* Allocate a buffer for them */
        HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
                                       0,
                                       nCount * sizeof(HANDLE));
        if (!HandleBuffer)
        {
            /* No buffer, fail the wait */
            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
            if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx);
            return WAIT_FAILED;
        }
    }
    else
    {
        /* Otherwise, use our local buffer */
        HandleBuffer = Handle;
    }

    /* Copy the handles into our buffer and loop them all */
    RtlCopyMemory(HandleBuffer, (LPVOID)lpHandles, nCount * sizeof(HANDLE));
    for (i = 0; i < nCount; i++)
    {
        /* Check what kind of handle this is */
        HandleBuffer[i] = TranslateStdHandle(HandleBuffer[i]);

        /* Check for console handle */
        if ((IsConsoleHandle(HandleBuffer[i])) &&
            (VerifyConsoleIoHandle(HandleBuffer[i])))
        {
            /* Get the real wait handle */
            HandleBuffer[i] = GetConsoleInputWaitHandle();
        }
    }

    /* Convert the timeout */
    TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds);

    /* Start wait loop */
    do
    {
        /* Do the wait */
        Status = NtWaitForMultipleObjects(nCount,
                                          HandleBuffer,
                                          bWaitAll ? WaitAll : WaitAny,
                                          (BOOLEAN)bAlertable,
                                          TimePtr);
        if (!NT_SUCCESS(Status))
        {
            /* Wait failed */
            BaseSetLastNTError(Status);
            Status = WAIT_FAILED;
        }
    } while ((Status == STATUS_ALERTED) && (bAlertable));

    /* Check if we didn't use our local buffer */
    if (HandleBuffer != Handle)
    {
        /* Free the allocated one */
        RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer);
    }

    /* Cleanup the activation context */
    if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx);

    /* Return wait status */
    return Status;
}
Пример #8
0
INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
{
    INT len;
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    TCHAR szOut[OUTPUT_BUFFER_SIZE];
    DWORD dwWritten;
    HANDLE hOutput = GetStdHandle(nStdHandle);

    /* used to count number of lines since last pause */
    static int LineCount = 0;

    /* used to see how big the screen is */
    int ScreenLines = 0;

    /* chars since start of line */
    int CharSL;

    int from = 0, i = 0;

    if (NewPage == TRUE)
        LineCount = 0;

    /* rest LineCount and return if no string have been given */
    if (szFormat == NULL)
        return 0;

    /* Get the size of the visual screen that can be printed too */
    if (!IsConsoleHandle(hOutput) || !GetConsoleScreenBufferInfo(hOutput, &csbi))
    {
        /* We assume it's a file handle */
        ConPrintf(szFormat, arg_ptr, nStdHandle);
        return 0;
    }
    /* Subtract 2 to account for "press any key..." and for the blank line at the end of PagePrompt() */
    ScreenLines = (csbi.srWindow.Bottom  - csbi.srWindow.Top) - 4;
    CharSL = csbi.dwCursorPosition.X;

    /* Make sure they didn't make the screen to small */
    if (ScreenLines < 4)
    {
        ConPrintf(szFormat, arg_ptr, nStdHandle);
        return 0;
    }

    len = _vstprintf(szOut, szFormat, arg_ptr);

    while (i < len)
    {
        /* Search until the end of a line is reached */
        if (szOut[i++] != _T('\n') && ++CharSL < csbi.dwSize.X)
            continue;

        LineCount++;
        CharSL=0;

        if (LineCount >= ScreenLines)
        {
            WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
            from = i;

            if (PagePrompt() != PROMPT_YES)
            {
                return 1;
            }
            /* Reset the number of lines being printed */
            LineCount = 0;
        }
    }

    WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);

    return 0;
}
Пример #9
0
static VOID ConWrite(TCHAR *str, DWORD len, DWORD nStdHandle)
{
    DWORD dwWritten;
    HANDLE hOutput = GetStdHandle(nStdHandle);
    PVOID p;

    /* Check whether we are writing to a console and if so, write to it */
    if (IsConsoleHandle(hOutput))
    {
        if (WriteConsole(hOutput, str, len, &dwWritten, NULL))
            return;
    }

    /* We're writing to a file or pipe instead of the console. Convert the
     * string from TCHARs to the desired output format, if the two differ */
    if (bUnicodeOutput)
    {
#ifndef _UNICODE
        WCHAR *buffer = cmd_alloc(len * sizeof(WCHAR));
        if (!buffer)
        {
            error_out_of_memory();
            return;
        }
        len = (DWORD)MultiByteToWideChar(OutputCodePage, 0, str, (INT)len, buffer, (INT)len);
        str = (PVOID)buffer;
#endif
        /*
         * Find any newline character in the buffer,
         * send the part BEFORE the newline, then send
         * a carriage-return + newline, and then send
         * the remaining part of the buffer.
         *
         * This fixes output in files and serial console.
         */
        while (str && *(PWCHAR)str && len > 0)
        {
            p = wcspbrk((PWCHAR)str, L"\r\n");
            if (p)
            {
                len -= ((PWCHAR)p - (PWCHAR)str) + 1;
                WriteFile(hOutput, str, ((PWCHAR)p - (PWCHAR)str) * sizeof(WCHAR), &dwWritten, NULL);
                WriteFile(hOutput, L"\r\n", 2 * sizeof(WCHAR), &dwWritten, NULL);
                str = (PVOID)((PWCHAR)p + 1);
            }
            else
            {
                WriteFile(hOutput, str, len * sizeof(WCHAR), &dwWritten, NULL);
                break;
            }
        }

        // WriteFile(hOutput, str, len * sizeof(WCHAR), &dwWritten, NULL);
#ifndef _UNICODE
        cmd_free(buffer);
#endif
    }
    else
    {
#ifdef _UNICODE
        CHAR *buffer = cmd_alloc(len * MB_LEN_MAX * sizeof(CHAR));
        if (!buffer)
        {
            error_out_of_memory();
            return;
        }
        len = WideCharToMultiByte(OutputCodePage, 0, str, len, buffer, len * MB_LEN_MAX, NULL, NULL);
        str = (PVOID)buffer;
#endif
        /*
         * Find any newline character in the buffer,
         * send the part BEFORE the newline, then send
         * a carriage-return + newline, and then send
         * the remaining part of the buffer.
         *
         * This fixes output in files and serial console.
         */
        while (str && *(PCHAR)str && len > 0)
        {
            p = strpbrk((PCHAR)str, "\r\n");
            if (p)
            {
                len -= ((PCHAR)p - (PCHAR)str) + 1;
                WriteFile(hOutput, str, ((PCHAR)p - (PCHAR)str), &dwWritten, NULL);
                WriteFile(hOutput, "\r\n", 2, &dwWritten, NULL);
                str = (PVOID)((PCHAR)p + 1);
            }
            else
            {
                WriteFile(hOutput, str, len, &dwWritten, NULL);
                break;
            }
        }

        // WriteFile(hOutput, str, len, &dwWritten, NULL);
#ifdef _UNICODE
        cmd_free(buffer);
#endif
    }
}
Пример #10
0
static int
windows_compute_revents (HANDLE h, int *p_sought)
{
  int i, ret, happened;
  INPUT_RECORD *irbuffer;
  DWORD avail, nbuffer;
  BOOL bRet;
  IO_STATUS_BLOCK iosb;
  FILE_PIPE_LOCAL_INFORMATION fpli;
  static PNtQueryInformationFile NtQueryInformationFile;
  static BOOL once_only;

  switch (GetFileType (h))
    {
    case FILE_TYPE_PIPE:
      if (!once_only)
        {
          NtQueryInformationFile = (PNtQueryInformationFile)
            GetProcAddress (GetModuleHandle ("ntdll.dll"),
                            "NtQueryInformationFile");
          once_only = TRUE;
        }

      happened = 0;
      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
        {
          if (avail)
            happened |= *p_sought & (POLLIN | POLLRDNORM);
        }
      else if (GetLastError () == ERROR_BROKEN_PIPE)
        happened |= POLLHUP;

      else
        {
          /* It was the write-end of the pipe.  Check if it is writable.
             If NtQueryInformationFile fails, optimistically assume the pipe is
             writable.  This could happen on Windows 9x, where
             NtQueryInformationFile is not available, or if we inherit a pipe
             that doesn't permit FILE_READ_ATTRIBUTES access on the write end
             (I think this should not happen since Windows XP SP2; WINE seems
             fine too).  Otherwise, ensure that enough space is available for
             atomic writes.  */
          memset (&iosb, 0, sizeof (iosb));
          memset (&fpli, 0, sizeof (fpli));

          if (!NtQueryInformationFile
              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
                                         FilePipeLocalInformation)
              || fpli.WriteQuotaAvailable >= PIPE_BUF
              || (fpli.OutboundQuota < PIPE_BUF &&
                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))
            happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
        }
      return happened;

    case FILE_TYPE_CHAR:
      ret = WaitForSingleObject (h, 0);
      if (!IsConsoleHandle (h))
        return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;

      nbuffer = avail = 0;
      bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
      if (bRet)
        {
          /* Input buffer.  */
          *p_sought &= POLLIN | POLLRDNORM;
          if (nbuffer == 0)
            return POLLHUP;
          if (!*p_sought)
            return 0;

          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
          if (!bRet || avail == 0)
            return POLLHUP;

          for (i = 0; i < avail; i++)
            if (irbuffer[i].EventType == KEY_EVENT)
              return *p_sought;
          return 0;
        }
      else
        {
          /* Screen buffer.  */
          *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;
          return *p_sought;
        }

    default:
      ret = WaitForSingleObject (h, 0);
      if (ret == WAIT_OBJECT_0)
        return *p_sought & ~(POLLPRI | POLLRDBAND);

      return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
    }
}