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.

164 lines
4.5 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. s_putmsg.c
  5. Abstract:
  6. This module implements the STREAMS APIs, ioctl(I_FDINSERT) and
  7. putmsg().
  8. Author:
  9. Eric Chin (ericc) July 26, 1991
  10. Revision History:
  11. Sam Patton (sampa) August 13, 1991
  12. changed errno to {get|set}lasterror
  13. --*/
  14. #include "common.h"
  15. int
  16. putmsg(
  17. IN HANDLE fd,
  18. IN struct strbuf *ctrlptr OPTIONAL,
  19. IN struct strbuf *dataptr OPTIONAL,
  20. IN int flags
  21. )
  22. /*++
  23. Routine Description:
  24. This function is called to send a STREAMS message downstream.
  25. This function is synchronous, in the NT sense: it blocks until the API
  26. completes.
  27. Arguments:
  28. fd - NT file handle
  29. ctrlptr - pointer to the control portion of the STREAMS message
  30. dataptr - pointer to the data portion of the STREAMS message
  31. flags - 0 or RS_HIPRI
  32. Return Value:
  33. 0 if successful, -1 otherwise.
  34. --*/
  35. {
  36. char *tmp;
  37. int chunksz;
  38. NTSTATUS status;
  39. IO_STATUS_BLOCK iosb;
  40. PSTRM_ARGS_OUT oparm;
  41. PPUTMSG_ARGS_IN chunk;
  42. int retval;
  43. //
  44. // marshall the arguments into one contiguous chunk. However, for
  45. // commonality with ioctl(I_FDINSERT), we arrange the input arguments
  46. // as below:
  47. //
  48. // typedef struct _PUTMSG_ARGS_IN_ {
  49. // int a_iocode; // 0
  50. // long a_flags; // 0 | RS_HIPRI
  51. // struct strbuf a_ctlbuf; // (required)
  52. // struct strbuf a_databuf; // (required)
  53. // HANDLE a_insert.i_fildes; // -1
  54. // int a_offset; // 0
  55. // char a_stuff[1]; // s_ctlbuf.buf (optional)
  56. // // s_databuf.buf (optional)
  57. // } PUTMSG_ARGS_IN, *PPUTMSG_ARGS_IN;
  58. //
  59. //
  60. chunksz = sizeof(PUTMSG_ARGS_IN) - 1 +
  61. ((ctrlptr && (ctrlptr->len > 0)) ? ctrlptr->len : 0) +
  62. ((dataptr && (dataptr->len > 0)) ? dataptr->len : 0);
  63. if (!(chunk = (PPUTMSG_ARGS_IN) LocalAlloc(LMEM_FIXED, chunksz))) {
  64. SetLastError(ENOSPC);
  65. return(-1);
  66. }
  67. chunk->a_iocode = 0;
  68. chunk->a_flags = (long) flags;
  69. tmp = (char *) chunk->a_stuff;
  70. if (ctrlptr && ctrlptr->buf && (ctrlptr->len >= 0)) {
  71. chunk->a_ctlbuf = *ctrlptr; // structure copy
  72. memcpy(tmp, ctrlptr->buf, ctrlptr->len);
  73. tmp += ctrlptr->len;
  74. }
  75. else {
  76. chunk->a_ctlbuf.len = -1;
  77. }
  78. if (dataptr && dataptr->buf && (dataptr->len >= 0)) {
  79. chunk->a_databuf = *dataptr; // structure copy
  80. memcpy(tmp, dataptr->buf, dataptr->len);
  81. tmp += dataptr->len;
  82. }
  83. else {
  84. chunk->a_databuf.len = -1;
  85. }
  86. chunk->a_insert.i_fildes = INVALID_HANDLE_VALUE;
  87. chunk->a_offset = 0;
  88. ASSERT(chunksz >= sizeof(STRM_ARGS_OUT));
  89. status = NtDeviceIoControlFile(
  90. fd, // Handle
  91. NULL, // Event
  92. NULL, // ApcRoutine
  93. NULL, // ApcContext
  94. &iosb, // IoStatusBlock
  95. IOCTL_STREAMS_PUTMSG, // IoControlCode
  96. (PVOID) chunk, // InputBuffer
  97. chunksz, // InputBufferSize
  98. (PVOID) chunk, // OutputBuffer
  99. chunksz); // OutputBufferSize
  100. if (status == STATUS_PENDING) {
  101. status = NtWaitForSingleObject(
  102. fd, // Handle
  103. TRUE, // Alertable
  104. NULL); // Timeout
  105. }
  106. if (!NT_SUCCESS(status)) {
  107. LocalFree(chunk);
  108. SetLastError(MapNtToPosixStatus(status));
  109. return(-1);
  110. }
  111. //
  112. // the return parameters from the Stream Head Driver are laid out as:
  113. //
  114. // typedef struct _STRM_ARGS_OUT_ { // generic return parameters
  115. // int a_retval; // return value
  116. // int a_errno; // errno if retval == -1
  117. //
  118. // } STRM_ARGS_OUT, *PSTRM_ARGS_OUT;
  119. //
  120. oparm = (PSTRM_ARGS_OUT) chunk;
  121. if (oparm->a_retval == -1) {
  122. SetLastError(oparm->a_errno);
  123. }
  124. retval = oparm->a_retval;
  125. LocalFree(chunk);
  126. return(retval);
  127. } // putmsg