Leaked source code of windows server 2003
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.

203 lines
5.8 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. s_getmsg.c
  5. Abstract:
  6. This module implements the STREAMS api, getmsg().
  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. int
  15. getmsg(
  16. IN HANDLE fd,
  17. IN OUT struct strbuf *ctrlptr OPTIONAL,
  18. IN OUT struct strbuf *dataptr OPTIONAL,
  19. IN OUT int *flagsp
  20. )
  21. /*++
  22. Routine Description:
  23. This procedure is called to receive a STREAMS message.
  24. Arguments:
  25. fd - NT file handle
  26. ctrlptr - pointer to the control portion of the STREAMS message
  27. dataptr - pointer to the data portion of the STREAMS message
  28. flagsp - pointer to the flags argument, which may be RS_HIPRI
  29. Return Value:
  30. 0, MORECTL and/or MOREDATA bits set if successful, -1 otherwise.
  31. --*/
  32. {
  33. char *tmp;
  34. int chunksz;
  35. NTSTATUS status;
  36. PSTRM_ARGS_OUT oparm;
  37. IO_STATUS_BLOCK iosb;
  38. PGETMSG_ARGS_INOUT chunk;
  39. int retval;
  40. //
  41. // marshall the arguments into one contiguous chunk, laid out as:
  42. //
  43. // typedef struct _GETMSG_ARGS_INOUT_ {
  44. // int a_retval; // ignored for input
  45. // long a_flags; // 0 or RS_HIPRI
  46. // struct strbuf a_ctlbuf; // (required)
  47. // struct strbuf a_databuf; // (required)
  48. // char a_stuff[1]; // a_ctlbuf.buf (optional)
  49. // // a_databuf.buf (optional)
  50. // } GETMSG_ARGS_INOUT, *PGETMSG_ARGS_INOUT;
  51. //
  52. //
  53. chunksz = sizeof(GETMSG_ARGS_INOUT) - 1 +
  54. ((ctrlptr && (ctrlptr->maxlen > 0)) ? ctrlptr->maxlen : 0) +
  55. ((dataptr && (dataptr->maxlen > 0)) ? dataptr->maxlen : 0);
  56. if (!(chunk = (PGETMSG_ARGS_INOUT) LocalAlloc(LMEM_FIXED, chunksz))) {
  57. SetLastError(ENOSPC);
  58. return(-1);
  59. }
  60. chunk->a_flags = (long) *flagsp;
  61. memset(&(chunk->a_ctlbuf), 0, 2 * sizeof(struct strbuf));
  62. if (ctrlptr) {
  63. chunk->a_ctlbuf = *ctrlptr; // structure copy
  64. }
  65. if (dataptr) {
  66. chunk->a_databuf = *dataptr; // structure copy
  67. }
  68. status = NtDeviceIoControlFile(
  69. fd, // Handle
  70. NULL, // Event
  71. NULL, // ApcRoutine
  72. NULL, // ApcContext
  73. &iosb, // IoStatusBlock
  74. IOCTL_STREAMS_GETMSG, // IoControlCode
  75. (PVOID) chunk, // InputBuffer
  76. chunksz, // InputBufferSize
  77. (PVOID) chunk, // OutputBuffer
  78. chunksz); // OutputBufferSize
  79. if (status == STATUS_PENDING) {
  80. status = NtWaitForSingleObject(
  81. fd, // Handle
  82. TRUE, // Alertable
  83. NULL); // Timeout
  84. }
  85. if (status != STATUS_SUCCESS) {
  86. LocalFree(chunk);
  87. SetLastError(MapNtToPosixStatus(status));
  88. return(-1);
  89. }
  90. //
  91. // sampa
  92. //
  93. #if 0
  94. if (status == STATUS_PENDING)
  95. {
  96. TimeOut.LowPart = 30L; // 30 second
  97. TimeOut.HighPart = 0L;
  98. TimeOut = RtlExtendedIntegerMultiply(TimeOut, 1000000L);
  99. status =
  100. NtWaitForSingleObject(
  101. fd,
  102. TRUE,
  103. NULL);
  104. if (status != STATUS_SUCCESS) {
  105. SetLastError(MapNtToPosixStatus(status));
  106. LocalFree((HANDLE) chunk);
  107. return(-1);
  108. }
  109. }
  110. #endif
  111. //
  112. // if there was an error, the return parameters from the Stream Head
  113. // Driver are laid out as:
  114. //
  115. // typedef struct _STRM_ARGS_OUT_ { // generic return parameters
  116. // int a_retval; // return value
  117. // int a_errno; // errno if retval == -1
  118. //
  119. // } STRM_ARGS_OUT, *PSTRM_ARGS_OUT;
  120. //
  121. //
  122. oparm = (PSTRM_ARGS_OUT) chunk;
  123. if (oparm->a_retval == -1) {
  124. SetLastError(oparm->a_errno);
  125. retval = oparm->a_retval;
  126. LocalFree(chunk);
  127. return(retval);
  128. }
  129. // otherwise, the return parameters from the Stream Head Driver are laid
  130. // out as:
  131. //
  132. // typedef struct _GETMSG_ARGS_INOUT_ {
  133. // int a_retval; // ignored for input
  134. // long a_flags; // 0 or RS_HIPRI
  135. // struct strbuf a_ctlbuf; // (required)
  136. // struct strbuf a_databuf; // (required)
  137. // char a_stuff[1]; // a_ctlbuf.buf (optional)
  138. // // a_databuf.buf (optional)
  139. // } GETMSG_ARGS_INOUT, *PGETMSG_ARGS_INOUT;
  140. //
  141. //
  142. *flagsp = chunk->a_flags;
  143. tmp = chunk->a_stuff;
  144. if (ctrlptr) {
  145. ctrlptr->len = chunk->a_ctlbuf.len;
  146. if (ctrlptr->len > 0) {
  147. assert(ctrlptr->len <= ctrlptr->maxlen);
  148. memcpy(ctrlptr->buf, tmp, ctrlptr->len);
  149. tmp += ctrlptr->len;
  150. }
  151. }
  152. if (dataptr) {
  153. dataptr->len = chunk->a_databuf.len;
  154. if (dataptr->len > 0) {
  155. assert(dataptr->len <= dataptr->maxlen);
  156. memcpy(dataptr->buf, tmp, dataptr->len);
  157. }
  158. }
  159. retval = chunk->a_retval;
  160. LocalFree(chunk);
  161. return(retval);
  162. } // getmsg