Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 lines
4.0 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. s_poll.c
  5. Abstract:
  6. This module implements the STREAMS api, poll()
  7. Author:
  8. Eric Chin (ericc) July 26, 1991
  9. Revision History:
  10. Sam Patton (sampa) August 13, 1991
  11. changed errno to {get|set}lasterror
  12. --*/
  13. #include "common.h"
  14. /*
  15. * BUGBUG
  16. * Confirm that the following is a sane number.
  17. */
  18. #define MAX_FDS NPOLLFILE /* max handles to poll */
  19. int
  20. poll(
  21. IN OUT struct pollfd *fds OPTIONAL,
  22. IN unsigned int nfds,
  23. IN int timeout
  24. )
  25. /*++
  26. Routine Description:
  27. This procedure is called to poll a set of stream descriptors.
  28. Arguments:
  29. fds - pointer to a array of poll structures
  30. nfds - number of poll structures pointed to by fds
  31. timeout - 0, INFTIM (-1), or timeout in milliseconds.
  32. Return Value:
  33. no of stream descriptors selected, or -1 if failure.
  34. --*/
  35. {
  36. char *chunk;
  37. NTSTATUS status;
  38. IO_STATUS_BLOCK iosb;
  39. int chunksz, selected;
  40. struct pollfd *overlay;
  41. HANDLE hijack = INVALID_HANDLE_VALUE;
  42. if (!fds || (nfds <= 0) || (nfds > MAX_FDS)) {
  43. SetLastError(EINVAL);
  44. return(-1);
  45. }
  46. /*
  47. * hijack a handle to the Stream Head driver.
  48. *
  49. * BUGBUG:
  50. * In Unix, the user can set pollfd.fd to less than 0 to indicate that
  51. * the entry should be ignored. On NT, that isn't possible:
  52. * INVALID_HANDLE_VALUE must be used.
  53. */
  54. for (overlay = fds; overlay < &fds[nfds]; overlay++) {
  55. if (overlay->fd != INVALID_HANDLE_VALUE) {
  56. hijack = overlay->fd;
  57. break;
  58. }
  59. }
  60. if (hijack == INVALID_HANDLE_VALUE) {
  61. SetLastError(EINVAL);
  62. return(-1);
  63. }
  64. chunksz = sizeof(nfds) + nfds * sizeof(*fds) + sizeof(timeout);
  65. if (!(chunk = (char *) LocalAlloc(LMEM_FIXED, chunksz))) {
  66. SetLastError(EAGAIN);
  67. return(-1);
  68. }
  69. /*
  70. * marshall the arguments into one contiguous chunk, laid out as:
  71. *
  72. * nfds (required)
  73. * timeout (required)
  74. * struct fds[nfds] (required)
  75. */
  76. * ((size_t *) chunk) = nfds;
  77. * (int *) (chunk + sizeof(nfds)) = timeout;
  78. overlay = (struct pollfd *) (chunk +
  79. sizeof(nfds) + sizeof(timeout));
  80. memcpy(overlay, fds, nfds * sizeof(*fds));
  81. status = NtDeviceIoControlFile(
  82. hijack,
  83. NULL, // Event
  84. NULL, // ApcRoutine
  85. NULL, // ApcContext
  86. &iosb, // IoStatusBlock
  87. IOCTL_STREAMS_POLL, // IoControlCode
  88. (PVOID) chunk, // InputBuffer
  89. chunksz, // InputBufferSize
  90. (PVOID) chunk, // OutputBuffer
  91. chunksz); // OutputBufferSize
  92. if (status == STATUS_PENDING) {
  93. status =
  94. NtWaitForSingleObject(
  95. hijack,
  96. TRUE,
  97. NULL);
  98. }
  99. if (!NT_SUCCESS(status)) {
  100. SetLastError(MapNtToPosixStatus(status));
  101. LocalFree((HANDLE) chunk);
  102. return(-1);
  103. }
  104. /*
  105. * the Stream Head Driver marshalled the return parameters into one
  106. * contiguous chunk, laid out as:
  107. *
  108. * return value (required)
  109. * errno (required)
  110. * struct fds[nfds] (required)
  111. */
  112. if ((selected = * (int *) chunk) == -1) {
  113. SetLastError(* (int *) (chunk + sizeof(nfds)));
  114. LocalFree((HANDLE) chunk);
  115. return(selected);
  116. }
  117. overlay = (struct pollfd *) (chunk + sizeof(nfds) + sizeof(timeout));
  118. while (nfds--) {
  119. fds[nfds].revents = overlay[nfds].revents;
  120. }
  121. LocalFree((HANDLE) chunk);
  122. return(selected);
  123. }