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.

225 lines
5.6 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. action.c
  5. Abstract:
  6. This module contains code which implements the TDI action
  7. dispatch routines.
  8. Environment:
  9. Kernel mode
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. typedef struct _NB_ACTION_GET_COUNTS {
  15. USHORT MaximumNicId; // returns maximum NIC ID
  16. USHORT NicIdCounts[32]; // session counts for first 32 NIC IDs
  17. } NB_ACTION_GET_COUNTS, *PNB_ACTION_GET_COUNTS;
  18. NTSTATUS
  19. NbiTdiAction(
  20. IN PDEVICE Device,
  21. IN PREQUEST Request
  22. )
  23. /*++
  24. Routine Description:
  25. This routine handles action requests.
  26. Arguments:
  27. Device - The netbios device.
  28. Request - The request describing the action.
  29. Return Value:
  30. NTSTATUS - status of operation.
  31. --*/
  32. {
  33. NTSTATUS Status;
  34. PADDRESS_FILE AddressFile;
  35. PCONNECTION Connection;
  36. UINT BufferLength;
  37. UINT DataLength;
  38. PNDIS_BUFFER NdisBuffer;
  39. CTELockHandle LockHandle;
  40. union {
  41. PNB_ACTION_GET_COUNTS GetCounts;
  42. } u;
  43. PNWLINK_ACTION NwlinkAction = NULL;
  44. UINT i;
  45. static UCHAR BogusId[4] = { 0x01, 0x00, 0x00, 0x00 }; // old nwrdr uses this
  46. //
  47. // To maintain some compatibility with the NWLINK streams-
  48. // based transport, we use the streams header format for
  49. // our actions. The old transport expected the action header
  50. // to be in InputBuffer and the output to go in OutputBuffer.
  51. // We follow the TDI spec, which states that OutputBuffer
  52. // is used for both input and output. Since IOCTL_TDI_ACTION
  53. // is method out direct, this means that the output buffer
  54. // is mapped by the MDL chain; for action the chain will
  55. // only have one piece so we use it for input and output.
  56. //
  57. NdisBuffer = REQUEST_NDIS_BUFFER(Request);
  58. if (NdisBuffer == NULL) {
  59. return STATUS_INVALID_PARAMETER;
  60. }
  61. NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request),(PVOID *)&NwlinkAction,&BufferLength,HighPagePriority);
  62. if (!NwlinkAction)
  63. {
  64. return (STATUS_INSUFFICIENT_RESOURCES);
  65. }
  66. //
  67. // Make sure we have enough room for just the header not
  68. // including the data.
  69. // (This will also include verification of buffer space for the TransportId) Bug# 171837
  70. //
  71. if (BufferLength < (UINT)(FIELD_OFFSET(NWLINK_ACTION, Data[0]))) {
  72. NB_DEBUG (QUERY, ("Nwlink action failed, buffer too small\n"));
  73. return STATUS_BUFFER_TOO_SMALL;
  74. }
  75. DataLength = BufferLength - FIELD_OFFSET(NWLINK_ACTION, Data[0]);
  76. if ((!RtlEqualMemory ((PVOID)(&NwlinkAction->Header.TransportId), "MISN", 4)) &&
  77. (!RtlEqualMemory ((PVOID)(&NwlinkAction->Header.TransportId), "MIPX", 4)) &&
  78. (!RtlEqualMemory ((PVOID)(&NwlinkAction->Header.TransportId), "XPIM", 4)) &&
  79. (!RtlEqualMemory ((PVOID)(&NwlinkAction->Header.TransportId), BogusId, 4))) {
  80. return STATUS_NOT_SUPPORTED;
  81. }
  82. //
  83. // Make sure that the correct file object is being used.
  84. //
  85. if (NwlinkAction->OptionType == NWLINK_OPTION_ADDRESS) {
  86. if (REQUEST_OPEN_TYPE(Request) != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
  87. NB_DEBUG (QUERY, ("Nwlink action failed, not address file\n"));
  88. return STATUS_INVALID_HANDLE;
  89. }
  90. AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
  91. if ((AddressFile->Size != sizeof (ADDRESS_FILE)) ||
  92. (AddressFile->Type != NB_ADDRESSFILE_SIGNATURE)) {
  93. NB_DEBUG (QUERY, ("Nwlink action failed, bad address file\n"));
  94. return STATUS_INVALID_HANDLE;
  95. }
  96. } else if (NwlinkAction->OptionType != NWLINK_OPTION_CONTROL) {
  97. NB_DEBUG (QUERY, ("Nwlink action failed, option type %d\n", NwlinkAction->OptionType));
  98. return STATUS_NOT_SUPPORTED;
  99. }
  100. //
  101. // Handle the requests based on the action code. For these
  102. // requests ActionHeader->ActionCode is 0, we use the
  103. // Option field in the streams header instead.
  104. //
  105. Status = STATUS_SUCCESS;
  106. switch (NwlinkAction->Option) {
  107. case (I_MIPX | 351):
  108. //
  109. // A request for details on every binding.
  110. //
  111. if (DataLength < sizeof(NB_ACTION_GET_COUNTS)) {
  112. return STATUS_BUFFER_TOO_SMALL;
  113. }
  114. u.GetCounts = (PNB_ACTION_GET_COUNTS)(NwlinkAction->Data);
  115. u.GetCounts->MaximumNicId = NbiDevice->MaximumNicId;
  116. for (i = 0; i < 32 ; i++) {
  117. u.GetCounts->NicIdCounts[i] = 0;
  118. }
  119. for (i = 0; i < CONNECTION_HASH_COUNT; i++) {
  120. NB_GET_LOCK (&Device->Lock, &LockHandle);
  121. Connection = Device->ConnectionHash[i].Connections;
  122. while (Connection != NULL) {
  123. #if defined(_PNP_POWER)
  124. if ((Connection->State == CONNECTION_STATE_ACTIVE) &&
  125. (Connection->LocalTarget.NicHandle.NicId < 32)) {
  126. ++u.GetCounts->NicIdCounts[Connection->LocalTarget.NicHandle.NicId];
  127. }
  128. #else
  129. if ((Connection->State == CONNECTION_STATE_ACTIVE) &&
  130. (Connection->LocalTarget.NicId < 32)) {
  131. ++u.GetCounts->NicIdCounts[Connection->LocalTarget.NicId];
  132. }
  133. #endif _PNP_POWER
  134. Connection = Connection->NextConnection;
  135. }
  136. NB_FREE_LOCK (&Device->Lock, LockHandle);
  137. }
  138. break;
  139. //
  140. // The Option was not supported, so fail.
  141. //
  142. default:
  143. Status = STATUS_NOT_SUPPORTED;
  144. break;
  145. } // end of the long switch on NwlinkAction->Option
  146. #if DBG
  147. if (!NT_SUCCESS(Status)) {
  148. NB_DEBUG (QUERY, ("Nwlink action %lx failed, status %lx\n", NwlinkAction->Option, Status));
  149. }
  150. #endif
  151. return Status;
  152. } /* NbiTdiAction */