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.

189 lines
4.4 KiB

  1. /****************************************************************************
  2. * (c) Copyright 1993 Micro Computer Systems, Inc. All rights reserved.
  3. *****************************************************************************
  4. *
  5. * Title: IPX/SPX WinSock Helper DLL for Windows NT
  6. *
  7. * Module: ipx/sockhelp/wshutil.c
  8. *
  9. * Version: 1.00.00
  10. *
  11. * Date: 04-08-93
  12. *
  13. * Author: Brian Walker
  14. *
  15. *****************************************************************************
  16. *
  17. * Change Log:
  18. *
  19. * Date DevSFC Comment
  20. * -------- ------ -------------------------------------------------------
  21. *
  22. *****************************************************************************
  23. *
  24. * Functional Description:
  25. *
  26. ****************************************************************************/
  27. #include <nt.h>
  28. #include <ntrtl.h>
  29. #include <nturtl.h>
  30. #include <windef.h>
  31. #include <winbase.h>
  32. #include <tdi.h>
  33. #include <winsock.h>
  34. #include <wsahelp.h>
  35. #include <isnkrnl.h>
  36. /*page*******************************************************
  37. d o _ t d i _ a c t i o n
  38. Generate a TDI_ACTION down to the streams
  39. driver.
  40. Arguments - fd = Handle to send on
  41. cmd = Command to send down
  42. optbuf = Ptr to options buffer
  43. optlen = Ptr to options length
  44. addrflag = TRUE = This is for DG/STREAM socket on addr handle
  45. FALSE = This is for conn handle
  46. Returns - A WinSock error code (NO_ERROR = OK)
  47. ************************************************************/
  48. INT do_tdi_action(HANDLE fd, ULONG cmd, PUCHAR optbuf, INT optlen, BOOLEAN addrflag, PHANDLE eventhandle OPTIONAL)
  49. {
  50. NTSTATUS status;
  51. PSTREAMS_TDI_ACTION tdibuf;
  52. ULONG tdilen;
  53. IO_STATUS_BLOCK iostat;
  54. HANDLE event;
  55. /** If the eventhandle is passed, it also means that the **/
  56. /** NWLINK_ACTION header is pre-allocated in the buffer, **/
  57. /** although we still have to fill the header in here. **/
  58. if (eventhandle == NULL) {
  59. /** Get the length of the buffer we need to allocate **/
  60. tdilen = FIELD_OFFSET(STREAMS_TDI_ACTION,Buffer) + sizeof(ULONG) + optlen;
  61. /** Allocate a buffer to use for the action **/
  62. tdibuf = RtlAllocateHeap(RtlProcessHeap(), 0, tdilen);
  63. if (tdibuf == NULL) {
  64. return WSAENOBUFS;
  65. }
  66. } else {
  67. tdilen = optlen;
  68. tdibuf = (PSTREAMS_TDI_ACTION)optbuf;
  69. }
  70. /** Set the datagram option **/
  71. RtlMoveMemory(&tdibuf->Header.TransportId, "MISN", 4);
  72. tdibuf->DatagramOption = addrflag;
  73. /**
  74. Fill out the buffer, the buffer looks like this:
  75. ULONG cmd
  76. data passed.
  77. **/
  78. memcpy(tdibuf->Buffer, &cmd, sizeof(ULONG));
  79. if (eventhandle == NULL) {
  80. tdibuf->BufferLength = sizeof(ULONG) + optlen;
  81. RtlMoveMemory(tdibuf->Buffer + sizeof(ULONG), optbuf, optlen);
  82. /** Create an event to wait on **/
  83. status = NtCreateEvent(
  84. &event,
  85. EVENT_ALL_ACCESS,
  86. NULL,
  87. SynchronizationEvent,
  88. FALSE);
  89. /** If no event - then return error **/
  90. if (!NT_SUCCESS(status)) {
  91. RtlFreeHeap(RtlProcessHeap(), 0, tdibuf);
  92. return WSAENOBUFS;
  93. }
  94. } else {
  95. tdibuf->BufferLength = sizeof(ULONG) + optlen - FIELD_OFFSET (NWLINK_ACTION, Data[0]);
  96. /** Use the event handle passed in **/
  97. event = *eventhandle;
  98. }
  99. /** **/
  100. status = NtDeviceIoControlFile(
  101. fd,
  102. event,
  103. NULL,
  104. NULL,
  105. &iostat,
  106. IOCTL_TDI_ACTION,
  107. NULL,
  108. 0,
  109. tdibuf,
  110. tdilen);
  111. if (eventhandle == NULL) {
  112. /** If pending - wait for it to finish **/
  113. if (status == STATUS_PENDING) {
  114. status = NtWaitForSingleObject(event, FALSE, NULL);
  115. ASSERT(status == 0);
  116. status = iostat.Status;
  117. }
  118. /** Close the event **/
  119. NtClose(event);
  120. }
  121. /** If we get an error - return it **/
  122. if (!NT_SUCCESS(status)) {
  123. if (eventhandle == NULL) {
  124. RtlFreeHeap(RtlProcessHeap(), 0, tdibuf);
  125. }
  126. return WSAEINVAL;
  127. }
  128. if (eventhandle == NULL) {
  129. /** Copy the returned back to optbuf if needed */
  130. if (optlen) {
  131. RtlMoveMemory (optbuf, tdibuf->Buffer + sizeof(ULONG), optlen);
  132. }
  133. RtlFreeHeap(RtlProcessHeap(), 0, tdibuf);
  134. }
  135. /** Return OK **/
  136. return NO_ERROR;
  137. }