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.

3517 lines
94 KiB

  1. /*++
  2. Copyright (c) 1989, 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. info.c
  5. Abstract:
  6. This module contains code which performs the following TDI services:
  7. o TdiQueryInformation
  8. o TdiSetInformation
  9. Author:
  10. David Beaver (dbeaver) 1-July-1991
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. //
  18. // Only the following routine is active in this module. All is is commented
  19. // out waiting for the definition of Get/Set info in TDI version 2.
  20. //
  21. //
  22. // Useful macro to obtain the total length of an MDL chain.
  23. //
  24. #define NbfGetMdlChainLength(Mdl, Length) { \
  25. PMDL _Mdl = (Mdl); \
  26. *(Length) = 0; \
  27. while (_Mdl) { \
  28. *(Length) += MmGetMdlByteCount(_Mdl); \
  29. _Mdl = _Mdl->Next; \
  30. } \
  31. }
  32. //
  33. // Local functions used to satisfy various requests.
  34. //
  35. VOID
  36. NbfStoreProviderStatistics(
  37. IN PDEVICE_CONTEXT DeviceContext,
  38. IN PTDI_PROVIDER_STATISTICS ProviderStatistics
  39. );
  40. VOID
  41. NbfStoreAdapterStatus(
  42. IN PDEVICE_CONTEXT DeviceContext,
  43. IN PUCHAR SourceRouting,
  44. IN UINT SourceRoutingLength,
  45. IN PVOID StatusBuffer
  46. );
  47. VOID
  48. NbfStoreNameBuffers(
  49. IN PDEVICE_CONTEXT DeviceContext,
  50. IN PVOID Buffer,
  51. IN ULONG BufferLength,
  52. IN ULONG NamesToSkip,
  53. OUT PULONG NamesWritten,
  54. OUT PULONG TotalNameCount OPTIONAL,
  55. OUT PBOOLEAN Truncated
  56. );
  57. NTSTATUS
  58. NbfTdiQueryInformation(
  59. IN PDEVICE_CONTEXT DeviceContext,
  60. IN PIRP Irp
  61. )
  62. /*++
  63. Routine Description:
  64. This routine performs the TdiQueryInformation request for the transport
  65. provider.
  66. Arguments:
  67. Irp - the Irp for the requested operation.
  68. Return Value:
  69. NTSTATUS - status of operation.
  70. --*/
  71. {
  72. NTSTATUS status;
  73. PIO_STACK_LOCATION irpSp;
  74. PVOID adapterStatus;
  75. PTDI_REQUEST_KERNEL_QUERY_INFORMATION query;
  76. PTA_NETBIOS_ADDRESS broadcastAddress;
  77. PTDI_PROVIDER_STATISTICS ProviderStatistics;
  78. PTDI_CONNECTION_INFO ConnectionInfo;
  79. ULONG TargetBufferLength;
  80. PFIND_NAME_HEADER FindNameHeader;
  81. LARGE_INTEGER timeout = {0,0};
  82. PTP_REQUEST tpRequest;
  83. PTP_CONNECTION Connection;
  84. PTP_ADDRESS_FILE AddressFile;
  85. PTP_ADDRESS Address;
  86. ULONG NamesWritten, TotalNameCount, BytesWritten;
  87. BOOLEAN Truncated;
  88. BOOLEAN RemoteAdapterStatus;
  89. TDI_ADDRESS_NETBIOS * RemoteAddress;
  90. struct {
  91. ULONG ActivityCount;
  92. TA_NETBIOS_ADDRESS TaAddressBuffer;
  93. } AddressInfo;
  94. PTRANSPORT_ADDRESS TaAddress;
  95. TDI_DATAGRAM_INFO DatagramInfo;
  96. BOOLEAN UsedConnection;
  97. PLIST_ENTRY p;
  98. KIRQL oldirql;
  99. ULONG BytesCopied;
  100. //
  101. // what type of status do we want?
  102. //
  103. irpSp = IoGetCurrentIrpStackLocation (Irp);
  104. query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&irpSp->Parameters;
  105. switch (query->QueryType) {
  106. #if 0
  107. case 0x12345678:
  108. {
  109. typedef struct _NBF_CONNECTION_STATUS {
  110. UCHAR LocalName[16];
  111. UCHAR RemoteName[16];
  112. BOOLEAN SendActive;
  113. BOOLEAN ReceiveQueued;
  114. BOOLEAN ReceiveActive;
  115. BOOLEAN ReceiveWakeUp;
  116. ULONG Flags;
  117. ULONG Flags2;
  118. } NBF_CONNECTION_STATUS, *PNBF_CONNECTION_STATUS;
  119. PNBF_CONNECTION_STATUS CurStatus;
  120. ULONG TotalStatus;
  121. ULONG AllowedStatus;
  122. PLIST_ENRY q;
  123. CurStatus = MmGetSystemAddressForMdl (Irp->MdlAddress);
  124. TotalStatus = 0;
  125. AllowedStatus = MmGetMdlByteCount (Irp->MdlAddress) / sizeof(NBF_CONNECTION_STATUS);
  126. for (p = DeviceContext->AddressDatabase.Flink;
  127. p != &DeviceContext->AddressDatabase;
  128. p = p->Flink) {
  129. Address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
  130. if ((Address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
  131. continue;
  132. }
  133. for (q = Address->ConnectionDatabase.Flink;
  134. q != &Address->ConnectionDatabase;
  135. q = q->Flink) {
  136. Connection = CONTAINING_RECORD (q, TP_CONNECTION, AddressList);
  137. if ((Connection->Flags & CONNECTION_FLAGS_READY) == 0) {
  138. continue;
  139. }
  140. if (TotalStatus >= AllowedStatus) {
  141. continue;
  142. }
  143. RtlMoveMemory (CurStatus->LocalName, Address->NetworkName->NetbiosName, 16);
  144. RtlMoveMemory (CurStatus->RemoteName, Connection->RemoteName, 16);
  145. CurStatus->Flags = Connection->Flags;
  146. CurStatus->Flags2 = Connection->Flags2;
  147. CurStatus->SendActive = (BOOLEAN)(!IsListEmpty(&Connection->SendQueue));
  148. CurStatus->ReceiveQueued = (BOOLEAN)(!IsListEmpty(&Connection->ReceiveQueue));
  149. CurStatus->ReceiveActive = (BOOLEAN)((Connection->Flags & CONNECTION_FLAGS_ACTIVE_RECEIVE) != 0);
  150. CurStatus->ReceiveWakeUp = (BOOLEAN)((Connection->Flags & CONNECTION_FLAGS_RECEIVE_WAKEUP) != 0);
  151. ++CurStatus;
  152. ++TotalStatus;
  153. }
  154. }
  155. Irp->IoStatus.Information = TotalStatus * sizeof(NBF_CONNECTION_STATUS);
  156. status = STATUS_SUCCESS;
  157. }
  158. break;
  159. #endif
  160. case TDI_QUERY_CONNECTION_INFO:
  161. //
  162. // Connection info is queried on a connection,
  163. // verify this.
  164. //
  165. if (irpSp->FileObject->FsContext2 != (PVOID) TDI_CONNECTION_FILE) {
  166. return STATUS_INVALID_CONNECTION;
  167. }
  168. Connection = irpSp->FileObject->FsContext;
  169. status = NbfVerifyConnectionObject (Connection);
  170. if (!NT_SUCCESS (status)) {
  171. #if DBG
  172. NbfPrint2 ("TdiQueryInfo: Invalid Connection %lx Irp %lx\n", Connection, Irp);
  173. #endif
  174. return status;
  175. }
  176. ConnectionInfo = ExAllocatePoolWithTag (
  177. NonPagedPool,
  178. sizeof (TDI_CONNECTION_INFO),
  179. NBF_MEM_TAG_TDI_CONNECTION_INFO);
  180. if (ConnectionInfo == NULL) {
  181. PANIC ("NbfQueryInfo: Cannot allocate connection info!\n");
  182. NbfWriteResourceErrorLog(
  183. DeviceContext,
  184. EVENT_TRANSPORT_RESOURCE_POOL,
  185. 6,
  186. sizeof(TDI_CONNECTION_INFO),
  187. 0);
  188. status = STATUS_INSUFFICIENT_RESOURCES;
  189. } else if ((Connection->Flags & CONNECTION_FLAGS_READY) == 0) {
  190. status = STATUS_INVALID_CONNECTION;
  191. ExFreePool (ConnectionInfo);
  192. } else {
  193. PTP_LINK Link = Connection->Link;
  194. RtlZeroMemory ((PVOID)ConnectionInfo, sizeof(TDI_CONNECTION_INFO));
  195. //
  196. // Get link delay and throughput.
  197. //
  198. if (Link->Delay == 0xffffffff) {
  199. //
  200. // If delay is not known, assume 0.
  201. //
  202. ConnectionInfo->Delay.HighPart = 0;
  203. ConnectionInfo->Delay.LowPart = 0;
  204. } else {
  205. //
  206. // Copy the delay as an NT relative time.
  207. //
  208. ConnectionInfo->Delay.HighPart = -1L;
  209. ConnectionInfo->Delay.LowPart = (ULONG)-((LONG)(Link->Delay));
  210. }
  211. if (DeviceContext->MacInfo.MediumAsync) {
  212. ULONG PacketsSent;
  213. ULONG PacketsResent;
  214. ULONG MultiplyFactor;
  215. //
  216. // Calculate the packets sent and resent since the
  217. // last time the throughput was queried.
  218. //
  219. PacketsSent = Link->PacketsSent - Connection->LastPacketsSent;
  220. PacketsResent = Link->PacketsResent - Connection->LastPacketsResent;
  221. //
  222. // Save these for next time.
  223. //
  224. Connection->LastPacketsSent = Link->PacketsSent;
  225. Connection->LastPacketsResent = Link->PacketsResent;
  226. //
  227. // To convert exactly from 100 bits-per-second to
  228. // bytes-per-second, we need to multiply by 12.5.
  229. // Using lower numbers will give worse throughput.
  230. // If there have been no errors we use 12, if there
  231. // have been 20% or more errors we use 1, and in
  232. // between we subtract 11 * (error%/20%) from 12
  233. // and use that.
  234. //
  235. if (PacketsResent == 0 || PacketsSent <= 10) {
  236. MultiplyFactor = 12;
  237. } else if ((PacketsSent / PacketsResent) <= 5) {
  238. MultiplyFactor = 1;
  239. } else {
  240. //
  241. // error%/20% is error%/(1/5), which is 5*error%,
  242. // which is 5 * (resent/send).
  243. //
  244. ASSERT (((11 * 5 * PacketsResent) / PacketsSent) <= 11);
  245. MultiplyFactor = 12 - ((11 * 5 * PacketsResent) / PacketsSent);
  246. }
  247. ConnectionInfo->Throughput.QuadPart =
  248. UInt32x32To64(DeviceContext->MediumSpeed, MultiplyFactor);
  249. } else if (!Link->ThroughputAccurate) {
  250. //
  251. // If throughput is not known, then guess. We
  252. // have MediumSpeed in units of 100 bps; we
  253. // return four times that number as the throughput,
  254. // which corresponds to about 1/3 of the
  255. // maximum bandwidth expressed in bytes/sec.
  256. //
  257. ConnectionInfo->Throughput.QuadPart =
  258. UInt32x32To64(DeviceContext->MediumSpeed, 4);
  259. } else {
  260. //
  261. // Throughput is accurate, return it.
  262. //
  263. ConnectionInfo->Throughput = Link->Throughput;
  264. }
  265. //
  266. // Calculate reliability using the sent/resent ratio,
  267. // if there has been enough activity to make it
  268. // worthwhile. >10% resent is unreliable.
  269. //
  270. if ((Link->PacketsResent > 0) &&
  271. (Link->PacketsSent > 20)) {
  272. ConnectionInfo->Unreliable =
  273. ((Link->PacketsSent / Link->PacketsResent) < 10);
  274. } else {
  275. ConnectionInfo->Unreliable = FALSE;
  276. }
  277. ConnectionInfo->TransmittedTsdus = Connection->TransmittedTsdus;
  278. ConnectionInfo->ReceivedTsdus = Connection->ReceivedTsdus;
  279. ConnectionInfo->TransmissionErrors = Connection->TransmissionErrors;
  280. ConnectionInfo->ReceiveErrors = Connection->ReceiveErrors;
  281. status = TdiCopyBufferToMdl (
  282. (PVOID)ConnectionInfo,
  283. 0L,
  284. sizeof(TDI_CONNECTION_INFO),
  285. Irp->MdlAddress,
  286. 0,
  287. &BytesCopied);
  288. Irp->IoStatus.Information = BytesCopied;
  289. ExFreePool (ConnectionInfo);
  290. }
  291. NbfDereferenceConnection ("query connection info", Connection, CREF_BY_ID);
  292. break;
  293. case TDI_QUERY_ADDRESS_INFO:
  294. if (irpSp->FileObject->FsContext2 == (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
  295. AddressFile = irpSp->FileObject->FsContext;
  296. status = NbfVerifyAddressObject(AddressFile);
  297. if (!NT_SUCCESS (status)) {
  298. #if DBG
  299. NbfPrint2 ("TdiQueryInfo: Invalid AddressFile %lx Irp %lx\n", AddressFile, Irp);
  300. #endif
  301. return status;
  302. }
  303. UsedConnection = FALSE;
  304. } else if (irpSp->FileObject->FsContext2 == (PVOID)TDI_CONNECTION_FILE) {
  305. Connection = irpSp->FileObject->FsContext;
  306. status = NbfVerifyConnectionObject (Connection);
  307. if (!NT_SUCCESS (status)) {
  308. #if DBG
  309. NbfPrint2 ("TdiQueryInfo: Invalid Connection %lx Irp %lx\n", Connection, Irp);
  310. #endif
  311. return status;
  312. }
  313. AddressFile = Connection->AddressFile;
  314. UsedConnection = TRUE;
  315. } else {
  316. return STATUS_INVALID_ADDRESS;
  317. }
  318. Address = AddressFile->Address;
  319. TdiBuildNetbiosAddress(
  320. Address->NetworkName->NetbiosName,
  321. (BOOLEAN)(Address->Flags & ADDRESS_FLAGS_GROUP ? TRUE : FALSE),
  322. &AddressInfo.TaAddressBuffer);
  323. //
  324. // Count the active addresses.
  325. //
  326. AddressInfo.ActivityCount = 0;
  327. ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
  328. for (p = Address->AddressFileDatabase.Flink;
  329. p != &Address->AddressFileDatabase;
  330. p = p->Flink) {
  331. ++AddressInfo.ActivityCount;
  332. }
  333. RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
  334. status = TdiCopyBufferToMdl (
  335. &AddressInfo,
  336. 0,
  337. sizeof(ULONG) + sizeof(TA_NETBIOS_ADDRESS),
  338. Irp->MdlAddress,
  339. 0,
  340. &BytesCopied);
  341. Irp->IoStatus.Information = BytesCopied;
  342. if (UsedConnection) {
  343. NbfDereferenceConnection ("query address info", Connection, CREF_BY_ID);
  344. } else {
  345. NbfDereferenceAddress ("query address info", Address, AREF_VERIFY);
  346. }
  347. break;
  348. case TDI_QUERY_BROADCAST_ADDRESS:
  349. //
  350. // for this provider, the broadcast address is a zero byte name,
  351. // contained in a Transport address structure.
  352. //
  353. broadcastAddress = ExAllocatePoolWithTag (
  354. NonPagedPool,
  355. sizeof (TA_NETBIOS_ADDRESS),
  356. NBF_MEM_TAG_TDI_QUERY_BUFFER);
  357. if (broadcastAddress == NULL) {
  358. PANIC ("NbfQueryInfo: Cannot allocate broadcast address!\n");
  359. NbfWriteResourceErrorLog(
  360. DeviceContext,
  361. EVENT_TRANSPORT_RESOURCE_POOL,
  362. 2,
  363. sizeof(TA_NETBIOS_ADDRESS),
  364. 0);
  365. status = STATUS_INSUFFICIENT_RESOURCES;
  366. } else {
  367. broadcastAddress->TAAddressCount = 1;
  368. broadcastAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  369. broadcastAddress->Address[0].AddressLength = 0;
  370. Irp->IoStatus.Information =
  371. sizeof (broadcastAddress->TAAddressCount) +
  372. sizeof (broadcastAddress->Address[0].AddressType) +
  373. sizeof (broadcastAddress->Address[0].AddressLength);
  374. BytesCopied = (ULONG)Irp->IoStatus.Information;
  375. status = TdiCopyBufferToMdl (
  376. (PVOID)broadcastAddress,
  377. 0L,
  378. BytesCopied,
  379. Irp->MdlAddress,
  380. 0,
  381. &BytesCopied);
  382. Irp->IoStatus.Information = BytesCopied;
  383. ExFreePool (broadcastAddress);
  384. }
  385. break;
  386. case TDI_QUERY_PROVIDER_INFO:
  387. status = TdiCopyBufferToMdl (
  388. &(DeviceContext->Information),
  389. 0,
  390. sizeof (TDI_PROVIDER_INFO),
  391. Irp->MdlAddress,
  392. 0,
  393. &BytesCopied);
  394. Irp->IoStatus.Information = BytesCopied;
  395. break;
  396. case TDI_QUERY_PROVIDER_STATISTICS:
  397. //
  398. // This information is probablt available somewhere else.
  399. //
  400. NbfGetMdlChainLength (Irp->MdlAddress, &TargetBufferLength);
  401. if (TargetBufferLength < sizeof(TDI_PROVIDER_STATISTICS) + ((NBF_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS))) {
  402. Irp->IoStatus.Information = 0;
  403. status = STATUS_BUFFER_OVERFLOW;
  404. } else {
  405. ProviderStatistics = ExAllocatePoolWithTag(
  406. NonPagedPool,
  407. sizeof(TDI_PROVIDER_STATISTICS) +
  408. ((NBF_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS)),
  409. NBF_MEM_TAG_TDI_PROVIDER_STATS);
  410. if (ProviderStatistics == NULL) {
  411. PANIC ("NbfQueryInfo: Cannot allocate provider statistics!\n");
  412. NbfWriteResourceErrorLog(
  413. DeviceContext,
  414. EVENT_TRANSPORT_RESOURCE_POOL,
  415. 7,
  416. sizeof(TDI_PROVIDER_STATISTICS),
  417. 0);
  418. status = STATUS_INSUFFICIENT_RESOURCES;
  419. } else {
  420. NbfStoreProviderStatistics (DeviceContext, ProviderStatistics);
  421. status = TdiCopyBufferToMdl (
  422. (PVOID)ProviderStatistics,
  423. 0L,
  424. sizeof(TDI_PROVIDER_STATISTICS) +
  425. ((NBF_TDI_RESOURCES-1) * sizeof(TDI_PROVIDER_RESOURCE_STATS)),
  426. Irp->MdlAddress,
  427. 0,
  428. &BytesCopied);
  429. Irp->IoStatus.Information = BytesCopied;
  430. ExFreePool (ProviderStatistics);
  431. }
  432. }
  433. break;
  434. case TDI_QUERY_SESSION_STATUS:
  435. status = STATUS_NOT_IMPLEMENTED;
  436. break;
  437. case TDI_QUERY_ADAPTER_STATUS:
  438. NbfGetMdlChainLength (Irp->MdlAddress, &TargetBufferLength);
  439. //
  440. // Determine if this is a local or remote query. It is
  441. // local if there is no remote address specific at all,
  442. // or if it is equal to our reserved address.
  443. //
  444. RemoteAdapterStatus = FALSE;
  445. if (query->RequestConnectionInformation != NULL) {
  446. if (!NbfValidateTdiAddress(
  447. query->RequestConnectionInformation->RemoteAddress,
  448. query->RequestConnectionInformation->RemoteAddressLength)) {
  449. return STATUS_BAD_NETWORK_PATH;
  450. }
  451. RemoteAddress = NbfParseTdiAddress(query->RequestConnectionInformation->RemoteAddress, FALSE);
  452. if (!RemoteAddress) {
  453. return STATUS_BAD_NETWORK_PATH;
  454. }
  455. if (!RtlEqualMemory(
  456. RemoteAddress->NetbiosName,
  457. DeviceContext->ReservedNetBIOSAddress,
  458. NETBIOS_NAME_LENGTH)) {
  459. RemoteAdapterStatus = TRUE;
  460. }
  461. }
  462. if (RemoteAdapterStatus) {
  463. //
  464. // We need a request object to keep track of this TDI request.
  465. // Attach this request to the device context.
  466. //
  467. status = NbfCreateRequest (
  468. Irp, // IRP for this request.
  469. DeviceContext, // context.
  470. REQUEST_FLAGS_DC, // partial flags.
  471. Irp->MdlAddress, // the data to be received.
  472. TargetBufferLength, // length of the data.
  473. timeout, // do this ourselves here.
  474. &tpRequest);
  475. if (NT_SUCCESS (status)) {
  476. NbfReferenceDeviceContext ("Remote status", DeviceContext, DCREF_REQUEST);
  477. tpRequest->Owner = DeviceContextType;
  478. //
  479. // Allocate a temp buffer to hold our results.
  480. //
  481. tpRequest->ResponseBuffer = ExAllocatePoolWithTag(
  482. NonPagedPool,
  483. TargetBufferLength,
  484. NBF_MEM_TAG_TDI_QUERY_BUFFER);
  485. if (tpRequest->ResponseBuffer == NULL) {
  486. NbfWriteResourceErrorLog(
  487. DeviceContext,
  488. EVENT_TRANSPORT_RESOURCE_POOL,
  489. 12,
  490. TargetBufferLength,
  491. 0);
  492. NbfCompleteRequest (tpRequest, STATUS_INSUFFICIENT_RESOURCES, 0);
  493. } else {
  494. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql);
  495. if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) {
  496. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock,oldirql);
  497. NbfCompleteRequest (tpRequest, STATUS_DEVICE_NOT_READY, 0);
  498. } else {
  499. PUCHAR SingleSR;
  500. UINT SingleSRLength;
  501. InsertTailList (
  502. &DeviceContext->StatusQueryQueue,
  503. &tpRequest->Linkage);
  504. tpRequest->FrameContext = DeviceContext->UniqueIdentifier | 0x8000;
  505. ++DeviceContext->UniqueIdentifier;
  506. if (DeviceContext->UniqueIdentifier == 0x8000) {
  507. DeviceContext->UniqueIdentifier = 1;
  508. }
  509. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  510. //
  511. // The request is queued. Now send out the first packet and
  512. // start the timer.
  513. //
  514. tpRequest->Retries = DeviceContext->GeneralRetries;
  515. tpRequest->BytesWritten = 0;
  516. //
  517. // STATUS_QUERY frames go out as
  518. // single-route source routing.
  519. //
  520. MacReturnSingleRouteSR(
  521. &DeviceContext->MacInfo,
  522. &SingleSR,
  523. &SingleSRLength);
  524. NbfSendStatusQuery(
  525. DeviceContext,
  526. tpRequest,
  527. &DeviceContext->NetBIOSAddress,
  528. SingleSR,
  529. SingleSRLength);
  530. }
  531. }
  532. //
  533. // As long as the request is created, pend here.
  534. // The IRP will complete when the request completes.
  535. //
  536. status = STATUS_PENDING;
  537. }
  538. } else {
  539. //
  540. // Local.
  541. //
  542. adapterStatus = ExAllocatePoolWithTag (
  543. NonPagedPool,
  544. TargetBufferLength,
  545. NBF_MEM_TAG_TDI_QUERY_BUFFER);
  546. if (adapterStatus == NULL) {
  547. PANIC("NbfQueryInfo: PANIC! Could not allocate adapter status buffer\n");
  548. NbfWriteResourceErrorLog(
  549. DeviceContext,
  550. EVENT_TRANSPORT_RESOURCE_POOL,
  551. 3,
  552. TargetBufferLength,
  553. 0);
  554. return STATUS_INSUFFICIENT_RESOURCES;
  555. }
  556. NbfStoreAdapterStatus (
  557. DeviceContext,
  558. NULL,
  559. 0,
  560. adapterStatus);
  561. NbfStoreNameBuffers (
  562. DeviceContext,
  563. (PUCHAR)adapterStatus + sizeof(ADAPTER_STATUS),
  564. TargetBufferLength - sizeof(ADAPTER_STATUS),
  565. 0,
  566. &NamesWritten,
  567. &TotalNameCount,
  568. &Truncated);
  569. ((PADAPTER_STATUS)adapterStatus)->name_count = (WORD)TotalNameCount;
  570. BytesWritten = sizeof(ADAPTER_STATUS) + (NamesWritten * sizeof(NAME_BUFFER));
  571. status = TdiCopyBufferToMdl (
  572. adapterStatus,
  573. 0,
  574. BytesWritten,
  575. Irp->MdlAddress,
  576. 0,
  577. &BytesCopied);
  578. Irp->IoStatus.Information = BytesCopied;
  579. if (Truncated) {
  580. status = STATUS_BUFFER_OVERFLOW;
  581. }
  582. ExFreePool (adapterStatus);
  583. }
  584. break;
  585. case TDI_QUERY_FIND_NAME:
  586. NbfGetMdlChainLength (Irp->MdlAddress, &TargetBufferLength);
  587. //
  588. // Check that there is a valid Netbios remote address.
  589. //
  590. if (!NbfValidateTdiAddress(
  591. query->RequestConnectionInformation->RemoteAddress,
  592. query->RequestConnectionInformation->RemoteAddressLength)) {
  593. return STATUS_BAD_NETWORK_PATH;
  594. }
  595. RemoteAddress = NbfParseTdiAddress(query->RequestConnectionInformation->RemoteAddress, FALSE);
  596. if (!RemoteAddress) {
  597. return STATUS_BAD_NETWORK_PATH;
  598. }
  599. //
  600. // We need a request object to keep track of this TDI request.
  601. // Attach this request to the device context.
  602. //
  603. status = NbfCreateRequest (
  604. Irp, // IRP for this request.
  605. DeviceContext, // context.
  606. REQUEST_FLAGS_DC, // partial flags.
  607. Irp->MdlAddress, // the data to be received.
  608. TargetBufferLength, // length of the data.
  609. timeout, // do this ourselves here.
  610. &tpRequest);
  611. if (NT_SUCCESS (status)) {
  612. NbfReferenceDeviceContext ("Find name", DeviceContext, DCREF_REQUEST);
  613. tpRequest->Owner = DeviceContextType;
  614. //
  615. // Allocate a temp buffer to hold our results.
  616. //
  617. tpRequest->ResponseBuffer = ExAllocatePoolWithTag(
  618. NonPagedPool,
  619. TargetBufferLength,
  620. NBF_MEM_TAG_TDI_QUERY_BUFFER);
  621. if (tpRequest->ResponseBuffer == NULL) {
  622. NbfWriteResourceErrorLog(
  623. DeviceContext,
  624. EVENT_TRANSPORT_RESOURCE_POOL,
  625. 4,
  626. TargetBufferLength,
  627. 0);
  628. NbfCompleteRequest (tpRequest, STATUS_INSUFFICIENT_RESOURCES, 0);
  629. } else {
  630. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql);
  631. if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) {
  632. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock,oldirql);
  633. NbfCompleteRequest (tpRequest, STATUS_DEVICE_NOT_READY, 0);
  634. } else {
  635. InsertTailList (
  636. &DeviceContext->FindNameQueue,
  637. &tpRequest->Linkage);
  638. tpRequest->FrameContext = DeviceContext->UniqueIdentifier | 0x8000;
  639. ++DeviceContext->UniqueIdentifier;
  640. if (DeviceContext->UniqueIdentifier == 0x8000) {
  641. DeviceContext->UniqueIdentifier = 1;
  642. }
  643. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  644. //
  645. // The request is queued. Now send out the first packet and
  646. // start the timer.
  647. //
  648. // We fill in the FIND_NAME_HEADER in the buffer, but
  649. // set BytesWritten to 0; we don't include the header
  650. // in BytesWritten until we get a response, so that
  651. // a BytesWritten of 0 means "no response".
  652. //
  653. tpRequest->Retries = DeviceContext->GeneralRetries;
  654. tpRequest->BytesWritten = 0;
  655. FindNameHeader = (PFIND_NAME_HEADER)tpRequest->ResponseBuffer;
  656. FindNameHeader->node_count = 0;
  657. FindNameHeader->unique_group = NETBIOS_NAME_TYPE_UNIQUE;
  658. NbfSendQueryFindName (DeviceContext, tpRequest);
  659. }
  660. }
  661. //
  662. // As long as the request is created, pend here.
  663. // The IRP will complete when the request completes.
  664. //
  665. status = STATUS_PENDING;
  666. }
  667. break;
  668. case TDI_QUERY_DATA_LINK_ADDRESS:
  669. case TDI_QUERY_NETWORK_ADDRESS:
  670. TaAddress = (PTRANSPORT_ADDRESS)&AddressInfo.TaAddressBuffer;
  671. TaAddress->TAAddressCount = 1;
  672. TaAddress->Address[0].AddressLength = 6;
  673. if (query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS) {
  674. TaAddress->Address[0].AddressType =
  675. DeviceContext->MacInfo.MediumAsync ?
  676. NdisMediumWan : DeviceContext->MacInfo.MediumType;
  677. } else {
  678. TaAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_UNSPEC;
  679. }
  680. RtlCopyMemory (TaAddress->Address[0].Address, DeviceContext->LocalAddress.Address, 6);
  681. status = TdiCopyBufferToMdl (
  682. &AddressInfo.TaAddressBuffer,
  683. 0,
  684. sizeof(TRANSPORT_ADDRESS)+5,
  685. Irp->MdlAddress,
  686. 0,
  687. &BytesCopied);
  688. Irp->IoStatus.Information = BytesCopied;
  689. break;
  690. case TDI_QUERY_DATAGRAM_INFO:
  691. DatagramInfo.MaximumDatagramBytes = 0;
  692. DatagramInfo.MaximumDatagramCount = 0;
  693. status = TdiCopyBufferToMdl (
  694. &DatagramInfo,
  695. 0,
  696. sizeof(DatagramInfo),
  697. Irp->MdlAddress,
  698. 0,
  699. &BytesCopied);
  700. Irp->IoStatus.Information = BytesCopied;
  701. break;
  702. default:
  703. status = STATUS_INVALID_DEVICE_REQUEST;
  704. break;
  705. }
  706. return status;
  707. } /* NbfTdiQueryInformation */
  708. //
  709. // Quick macros, assumes DeviceContext and ProviderStatistics exist.
  710. //
  711. #define STORE_RESOURCE_STATS_1(_ResourceNum,_ResourceId,_ResourceName) \
  712. { \
  713. PTDI_PROVIDER_RESOURCE_STATS RStats = &ProviderStatistics->ResourceStats[_ResourceNum]; \
  714. RStats->ResourceId = (_ResourceId); \
  715. RStats->MaximumResourceUsed = DeviceContext->_ResourceName ## MaxInUse; \
  716. if (DeviceContext->_ResourceName ## Samples > 0) { \
  717. RStats->AverageResourceUsed = DeviceContext->_ResourceName ## Total / DeviceContext->_ResourceName ## Samples; \
  718. } else { \
  719. RStats->AverageResourceUsed = 0; \
  720. } \
  721. RStats->ResourceExhausted = DeviceContext->_ResourceName ## Exhausted; \
  722. }
  723. #define STORE_RESOURCE_STATS_2(_ResourceNum,_ResourceId,_ResourceName) \
  724. { \
  725. PTDI_PROVIDER_RESOURCE_STATS RStats = &ProviderStatistics->ResourceStats[_ResourceNum]; \
  726. RStats->ResourceId = (_ResourceId); \
  727. RStats->MaximumResourceUsed = DeviceContext->_ResourceName ## Allocated; \
  728. RStats->AverageResourceUsed = DeviceContext->_ResourceName ## Allocated; \
  729. RStats->ResourceExhausted = DeviceContext->_ResourceName ## Exhausted; \
  730. }
  731. VOID
  732. NbfStoreProviderStatistics(
  733. IN PDEVICE_CONTEXT DeviceContext,
  734. IN PTDI_PROVIDER_STATISTICS ProviderStatistics
  735. )
  736. /*++
  737. Routine Description:
  738. This routine writes the TDI_PROVIDER_STATISTICS structure
  739. from the device context into ProviderStatistics.
  740. Arguments:
  741. DeviceContext - a pointer to the device context.
  742. ProviderStatistics - The buffer that holds the result. It is assumed
  743. that it is long enough.
  744. Return Value:
  745. None.
  746. --*/
  747. {
  748. //
  749. // Copy all the statistics up to NumberOfResources
  750. // in one move.
  751. //
  752. RtlCopyMemory(
  753. ProviderStatistics,
  754. &DeviceContext->Statistics,
  755. FIELD_OFFSET (TDI_PROVIDER_STATISTICS, NumberOfResources));
  756. //
  757. // Calculate AverageSendWindow.
  758. //
  759. if (DeviceContext->SendWindowSamples > 0) {
  760. ProviderStatistics->AverageSendWindow =
  761. DeviceContext->SendWindowTotal / DeviceContext->SendWindowSamples;
  762. } else {
  763. ProviderStatistics->AverageSendWindow = 1;
  764. }
  765. //
  766. // Copy the resource statistics.
  767. //
  768. ProviderStatistics->NumberOfResources = NBF_TDI_RESOURCES;
  769. STORE_RESOURCE_STATS_1 (0, LINK_RESOURCE_ID, Link);
  770. STORE_RESOURCE_STATS_1 (1, ADDRESS_RESOURCE_ID, Address);
  771. STORE_RESOURCE_STATS_1 (2, ADDRESS_FILE_RESOURCE_ID, AddressFile);
  772. STORE_RESOURCE_STATS_1 (3, CONNECTION_RESOURCE_ID, Connection);
  773. STORE_RESOURCE_STATS_1 (4, REQUEST_RESOURCE_ID, Request);
  774. STORE_RESOURCE_STATS_2 (5, UI_FRAME_RESOURCE_ID, UIFrame);
  775. STORE_RESOURCE_STATS_2 (6, PACKET_RESOURCE_ID, Packet);
  776. STORE_RESOURCE_STATS_2 (7, RECEIVE_PACKET_RESOURCE_ID, ReceivePacket);
  777. STORE_RESOURCE_STATS_2 (8, RECEIVE_BUFFER_RESOURCE_ID, ReceiveBuffer);
  778. } /* NbfStoreProviderStatistics */
  779. VOID
  780. NbfStoreAdapterStatus(
  781. IN PDEVICE_CONTEXT DeviceContext,
  782. IN PUCHAR SourceRouting,
  783. IN UINT SourceRoutingLength,
  784. IN PVOID StatusBuffer
  785. )
  786. /*++
  787. Routine Description:
  788. This routine writes the ADAPTER_STATUS structure for the
  789. device context into StatusBuffer. The name_count field is
  790. initialized to zero; NbfStoreNameBuffers is used to write
  791. name buffers.
  792. Arguments:
  793. DeviceContext - a pointer to the device context.
  794. SourceRouting - If this is a remote request, the source
  795. routing information from the frame.
  796. SourceRoutingLength - The length of SourceRouting.
  797. StatusBuffer - The buffer that holds the result. It is assumed
  798. that it is at least sizeof(ADAPTER_STATUS) bytes long.
  799. Return Value:
  800. None.
  801. --*/
  802. {
  803. PADAPTER_STATUS AdapterStatus = (PADAPTER_STATUS)StatusBuffer;
  804. UINT MaxUserData;
  805. RtlZeroMemory ((PVOID)AdapterStatus, sizeof(ADAPTER_STATUS));
  806. RtlCopyMemory (AdapterStatus->adapter_address, DeviceContext->LocalAddress.Address, 6);
  807. AdapterStatus->rev_major = 0x03;
  808. switch (DeviceContext->MacInfo.MediumType) {
  809. case NdisMedium802_5: AdapterStatus->adapter_type = 0xff; break;
  810. default: AdapterStatus->adapter_type = 0xfe; break;
  811. }
  812. AdapterStatus->frmr_recv = (WORD)DeviceContext->FrmrReceived;
  813. AdapterStatus->frmr_xmit = (WORD)DeviceContext->FrmrTransmitted;
  814. AdapterStatus->recv_buff_unavail = (WORD)(DeviceContext->ReceivePacketExhausted + DeviceContext->ReceiveBufferExhausted);
  815. AdapterStatus->xmit_buf_unavail = (WORD)DeviceContext->PacketExhausted;
  816. AdapterStatus->xmit_success = (WORD)(DeviceContext->Statistics.DataFramesSent - DeviceContext->Statistics.DataFramesResent);
  817. AdapterStatus->recv_success = (WORD)DeviceContext->Statistics.DataFramesReceived;
  818. AdapterStatus->iframe_recv_err = (WORD)DeviceContext->Statistics.DataFramesRejected;
  819. AdapterStatus->iframe_xmit_err = (WORD)DeviceContext->Statistics.DataFramesResent;
  820. AdapterStatus->t1_timeouts = (WORD)DeviceContext->Statistics.ResponseTimerExpirations;
  821. AdapterStatus->ti_timeouts = (WORD)DeviceContext->TiExpirations;
  822. AdapterStatus->xmit_aborts = (WORD)0;
  823. AdapterStatus->free_ncbs = (WORD)0xffff;
  824. AdapterStatus->max_cfg_ncbs = (WORD)0xffff;
  825. AdapterStatus->max_ncbs = (WORD)0xffff;
  826. AdapterStatus->pending_sess = (WORD)DeviceContext->Statistics.OpenConnections;
  827. AdapterStatus->max_cfg_sess = (WORD)0xffff;
  828. AdapterStatus->max_sess = (WORD)0xffff;
  829. MacReturnMaxDataSize(
  830. &DeviceContext->MacInfo,
  831. NULL,
  832. 0,
  833. DeviceContext->MaxSendPacketSize,
  834. TRUE,
  835. &MaxUserData);
  836. AdapterStatus->max_dgram_size = (WORD)(MaxUserData - (sizeof(DLC_FRAME) + sizeof(NBF_HDR_CONNECTIONLESS)));
  837. MacReturnMaxDataSize(
  838. &DeviceContext->MacInfo,
  839. SourceRouting,
  840. SourceRoutingLength,
  841. DeviceContext->MaxSendPacketSize,
  842. FALSE,
  843. &MaxUserData);
  844. AdapterStatus->max_sess_pkt_size = (WORD)(MaxUserData - (sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION)));
  845. return;
  846. } /* NbfStoreAdapterStatus */
  847. VOID
  848. NbfStoreNameBuffers(
  849. IN PDEVICE_CONTEXT DeviceContext,
  850. IN PVOID Buffer,
  851. IN ULONG BufferLength,
  852. IN ULONG NamesToSkip,
  853. OUT PULONG NamesWritten,
  854. OUT PULONG TotalNameCount OPTIONAL,
  855. OUT PBOOLEAN Truncated
  856. )
  857. /*++
  858. Routine Description:
  859. This routine writes NAME_BUFFER structures for the
  860. device context into NameBuffer. It can skip a specified
  861. number of names at the beginning, and returns the number
  862. of names written into NameBuffer. If a name will only
  863. partially fit, it is not written.
  864. Arguments:
  865. DeviceContext - a pointer to the device context.
  866. NameBuffer - The buffer to write the names into.
  867. NameBufferLength - The length of NameBuffer.
  868. NamesToSkip - The number of names to skip.
  869. NamesWritten - Returns the number of names written.
  870. TotalNameCount - Returns the total number of names available,
  871. if specified.
  872. Truncated - More names are available than were written.
  873. Return Value:
  874. None.
  875. --*/
  876. {
  877. ULONG NameCount = 0;
  878. ULONG BytesWritten = 0;
  879. KIRQL oldirql;
  880. PLIST_ENTRY p;
  881. PNAME_BUFFER NameBuffer = (PNAME_BUFFER)Buffer;
  882. PTP_ADDRESS address;
  883. //
  884. // Spin through the address list for this device context.
  885. //
  886. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  887. p = DeviceContext->AddressDatabase.Flink;
  888. for (p = DeviceContext->AddressDatabase.Flink;
  889. p != &DeviceContext->AddressDatabase;
  890. p = p->Flink) {
  891. address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
  892. //
  893. // Ignore addresses that are shutting down.
  894. //
  895. if ((address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
  896. continue;
  897. }
  898. //
  899. // Ignore the broadcast address.
  900. //
  901. if (address->NetworkName == NULL) {
  902. continue;
  903. }
  904. //
  905. // Ignore the reserved address.
  906. //
  907. if ((address->NetworkName->NetbiosName[0] == 0) &&
  908. (RtlEqualMemory(
  909. address->NetworkName->NetbiosName,
  910. DeviceContext->ReservedNetBIOSAddress,
  911. NETBIOS_NAME_LENGTH))) {
  912. continue;
  913. }
  914. //
  915. // Check if we are still skipping.
  916. //
  917. if (NameCount < NamesToSkip) {
  918. ++NameCount;
  919. continue;
  920. }
  921. //
  922. // Make sure we still have room.
  923. //
  924. if (BytesWritten + sizeof(NAME_BUFFER) > BufferLength) {
  925. break;
  926. }
  927. RtlCopyMemory(
  928. NameBuffer->name,
  929. address->NetworkName->NetbiosName,
  930. NETBIOS_NAME_LENGTH);
  931. ++NameCount;
  932. NameBuffer->name_num = (UCHAR)NameCount;
  933. NameBuffer->name_flags = REGISTERED;
  934. if (address->Flags & ADDRESS_FLAGS_GROUP) {
  935. NameBuffer->name_flags |= GROUP_NAME;
  936. }
  937. // name_flags should be done more accurately.
  938. BytesWritten += sizeof(NAME_BUFFER);
  939. ++NameBuffer;
  940. }
  941. *NamesWritten = (ULONG)(NameBuffer - (PNAME_BUFFER)Buffer);
  942. if (p == &DeviceContext->AddressDatabase) {
  943. *Truncated = FALSE;
  944. if (ARGUMENT_PRESENT(TotalNameCount)) {
  945. *TotalNameCount = NameCount;
  946. }
  947. } else {
  948. *Truncated = TRUE;
  949. //
  950. // If requested, continue through the list and count
  951. // all the addresses.
  952. //
  953. if (ARGUMENT_PRESENT(TotalNameCount)) {
  954. for ( ;
  955. p != &DeviceContext->AddressDatabase;
  956. p = p->Flink) {
  957. address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
  958. //
  959. // Ignore addresses that are shutting down.
  960. //
  961. if ((address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
  962. continue;
  963. }
  964. //
  965. // Ignore the broadcast address.
  966. //
  967. if (address->NetworkName == NULL) {
  968. continue;
  969. }
  970. //
  971. // Ignore the reserved address, since we count it no matter what.
  972. //
  973. if ((address->NetworkName->NetbiosName[0] == 0) &&
  974. (RtlEqualMemory(
  975. address->NetworkName->NetbiosName,
  976. DeviceContext->ReservedNetBIOSAddress,
  977. NETBIOS_NAME_LENGTH))) {
  978. continue;
  979. }
  980. ++NameCount;
  981. }
  982. *TotalNameCount = NameCount;
  983. }
  984. }
  985. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  986. return;
  987. } /* NbfStoreNameBuffers */
  988. NTSTATUS
  989. NbfProcessStatusQuery(
  990. IN PDEVICE_CONTEXT DeviceContext,
  991. IN PTP_ADDRESS Address OPTIONAL,
  992. IN PNBF_HDR_CONNECTIONLESS UiFrame,
  993. IN PHARDWARE_ADDRESS SourceAddress,
  994. IN PUCHAR SourceRouting,
  995. IN UINT SourceRoutingLength
  996. )
  997. /*++
  998. Routine Description:
  999. This routine processes a STATUS.QUERY packet.
  1000. Arguments:
  1001. DeviceContext - a pointer to the device context the frame was received on.
  1002. Address - The address we are responding from, or NULL if the STATUS.QUERY
  1003. was sent to the reserved address.
  1004. UiFrame - The packet in question, starting at the Netbios header.
  1005. SourceAddress - The source hardware address of the packet.
  1006. SourceRouting - Source routing data in the query.
  1007. SourceRoutingLength - The length of SourceRouting.
  1008. Return Value:
  1009. NTSTATUS - status of operation.
  1010. --*/
  1011. {
  1012. NTSTATUS Status;
  1013. NDIS_STATUS NdisStatus;
  1014. PTP_UI_FRAME RawFrame;
  1015. PVOID ResponseBuffer;
  1016. UINT ResponseBufferLength;
  1017. ULONG NamesWritten, TotalNameCount;
  1018. ULONG BytesWritten;
  1019. UCHAR RequestType;
  1020. BOOLEAN Truncated, UsersBufferTooShort;
  1021. USHORT UsersBufferLength;
  1022. UINT HeaderLength;
  1023. UCHAR TempSR[MAX_SOURCE_ROUTING];
  1024. PUCHAR ResponseSR;
  1025. PNDIS_BUFFER NdisBuffer;
  1026. //
  1027. // Allocate a buffer to hold the status.
  1028. //
  1029. MacReturnMaxDataSize(
  1030. &DeviceContext->MacInfo,
  1031. SourceRouting,
  1032. SourceRoutingLength,
  1033. DeviceContext->CurSendPacketSize,
  1034. FALSE,
  1035. &ResponseBufferLength);
  1036. ResponseBufferLength -= (sizeof(DLC_FRAME) + sizeof(NBF_HDR_CONNECTIONLESS));
  1037. UsersBufferLength = (UiFrame->Data2High * 256) + UiFrame->Data2Low;
  1038. //
  1039. // See how big to make our buffer; if the amount remaining in the user's
  1040. // buffer is less than our max size, chop it down.
  1041. //
  1042. if (UiFrame->Data1 <= 1) {
  1043. //
  1044. // This is the initial request.
  1045. //
  1046. if (ResponseBufferLength > (UINT)UsersBufferLength) {
  1047. ResponseBufferLength = UsersBufferLength;
  1048. }
  1049. } else {
  1050. //
  1051. // Subsequent request; compensate for already-sent data.
  1052. //
  1053. UsersBufferLength -= (sizeof(ADAPTER_STATUS) + (UiFrame->Data1 * sizeof(NAME_BUFFER)));
  1054. if (ResponseBufferLength > (UINT)UsersBufferLength) {
  1055. ResponseBufferLength = UsersBufferLength;
  1056. }
  1057. }
  1058. //
  1059. // If the remote station is asking for no data, ignore this request.
  1060. // This prevents us from trying to allocate 0 bytes of pool.
  1061. //
  1062. if ( (LONG)ResponseBufferLength <= 0 ) {
  1063. return STATUS_ABANDONED;
  1064. }
  1065. ResponseBuffer = ExAllocatePoolWithTag(
  1066. NonPagedPool,
  1067. ResponseBufferLength,
  1068. NBF_MEM_TAG_TDI_QUERY_BUFFER);
  1069. if (ResponseBuffer == NULL) {
  1070. NbfWriteResourceErrorLog(
  1071. DeviceContext,
  1072. EVENT_TRANSPORT_RESOURCE_POOL,
  1073. 5,
  1074. ResponseBufferLength,
  1075. 0);
  1076. return STATUS_ABANDONED;
  1077. }
  1078. //
  1079. // Fill in the response buffer.
  1080. //
  1081. if (UiFrame->Data1 <= 1) {
  1082. //
  1083. // First request.
  1084. //
  1085. NbfStoreAdapterStatus (
  1086. DeviceContext,
  1087. SourceRouting,
  1088. SourceRoutingLength,
  1089. ResponseBuffer);
  1090. NbfStoreNameBuffers (
  1091. DeviceContext,
  1092. (PUCHAR)ResponseBuffer + sizeof(ADAPTER_STATUS),
  1093. ResponseBufferLength - sizeof(ADAPTER_STATUS),
  1094. 0,
  1095. &NamesWritten,
  1096. &TotalNameCount,
  1097. &Truncated);
  1098. BytesWritten = sizeof(ADAPTER_STATUS) + (NamesWritten * sizeof(NAME_BUFFER));
  1099. //
  1100. // If the data was truncated, but we are returning the maximum
  1101. // that the user requested, report that as "user's buffer
  1102. // too short" instead of "truncated".
  1103. //
  1104. if (Truncated && (ResponseBufferLength >= (UINT)UsersBufferLength)) {
  1105. Truncated = FALSE;
  1106. UsersBufferTooShort = TRUE;
  1107. } else {
  1108. UsersBufferTooShort = FALSE;
  1109. }
  1110. ((PADAPTER_STATUS)ResponseBuffer)->name_count = (WORD)TotalNameCount;
  1111. } else {
  1112. NbfStoreNameBuffers (
  1113. DeviceContext,
  1114. ResponseBuffer,
  1115. ResponseBufferLength,
  1116. UiFrame->Data1,
  1117. &NamesWritten,
  1118. NULL,
  1119. &Truncated);
  1120. BytesWritten = NamesWritten * sizeof(NAME_BUFFER);
  1121. if (Truncated && (ResponseBufferLength >= (UINT)UsersBufferLength)) {
  1122. Truncated = FALSE;
  1123. UsersBufferTooShort = TRUE;
  1124. } else {
  1125. UsersBufferTooShort = FALSE;
  1126. }
  1127. }
  1128. //
  1129. // Allocate a UI frame from the pool.
  1130. //
  1131. Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
  1132. if (!NT_SUCCESS (Status)) { // couldn't make frame.
  1133. ExFreePool (ResponseBuffer);
  1134. return STATUS_ABANDONED;
  1135. }
  1136. IF_NBFDBG (NBF_DEBUG_DEVCTX) {
  1137. NbfPrint2 ("NbfProcessStatusQuery: Sending Frame: %lx, NdisPacket: %lx\n",
  1138. RawFrame, RawFrame->NdisPacket);
  1139. }
  1140. //
  1141. // Build the MAC header. STATUS_RESPONSE frames go out as
  1142. // non-broadcast source routing.
  1143. //
  1144. if (SourceRouting != NULL) {
  1145. RtlCopyMemory(
  1146. TempSR,
  1147. SourceRouting,
  1148. SourceRoutingLength);
  1149. MacCreateNonBroadcastReplySR(
  1150. &DeviceContext->MacInfo,
  1151. TempSR,
  1152. SourceRoutingLength,
  1153. &ResponseSR);
  1154. } else {
  1155. ResponseSR = NULL;
  1156. }
  1157. MacConstructHeader (
  1158. &DeviceContext->MacInfo,
  1159. RawFrame->Header,
  1160. SourceAddress->Address,
  1161. DeviceContext->LocalAddress.Address,
  1162. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS) + BytesWritten,
  1163. ResponseSR,
  1164. SourceRoutingLength,
  1165. &HeaderLength);
  1166. //
  1167. // Build the DLC UI frame header.
  1168. //
  1169. NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
  1170. HeaderLength += sizeof(DLC_FRAME);
  1171. //
  1172. // Build the Netbios header.
  1173. //
  1174. switch (UiFrame->Data1) {
  1175. case 0: // pre 2.1 request
  1176. RequestType = (UCHAR)0;
  1177. break;
  1178. case 1: // 2.1, first request
  1179. RequestType = (UCHAR)NamesWritten;
  1180. break;
  1181. default: // 2.1, subsequent request
  1182. RequestType = (UCHAR)(UiFrame->Data1 + NamesWritten);
  1183. break;
  1184. }
  1185. ConstructStatusResponse (
  1186. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  1187. RequestType, // request type.
  1188. Truncated, // more data.
  1189. UsersBufferTooShort, // user's buffer too small
  1190. (USHORT)BytesWritten, // bytes in response
  1191. RESPONSE_CORR(UiFrame), // correlator
  1192. UiFrame->SourceName, // receiver permanent name
  1193. (ARGUMENT_PRESENT(Address)) ?
  1194. Address->NetworkName->NetbiosName :
  1195. DeviceContext->ReservedNetBIOSAddress); // source name
  1196. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  1197. //
  1198. // Munge the packet length (now, before we append the second
  1199. // buffer).
  1200. //
  1201. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  1202. //
  1203. // Now, if we have any name data, attach our buffer onto the frame.
  1204. // Note that it's possible at the end of the user's buffer for us
  1205. // to not have room for any names, and thus we'll have no data to
  1206. // send.
  1207. //
  1208. if ( BytesWritten != 0 ) {
  1209. RawFrame->DataBuffer = ResponseBuffer;
  1210. NdisAllocateBuffer(
  1211. &NdisStatus,
  1212. &NdisBuffer,
  1213. DeviceContext->NdisBufferPool,
  1214. ResponseBuffer,
  1215. BytesWritten);
  1216. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  1217. PANIC ("ConstructStatusResponse: NdisAllocateBuffer failed.\n");
  1218. NbfDestroyConnectionlessFrame (DeviceContext, RawFrame);
  1219. return STATUS_ABANDONED;
  1220. }
  1221. NdisChainBufferAtBack (RawFrame->NdisPacket, NdisBuffer);
  1222. } else {
  1223. RawFrame->DataBuffer = NULL;
  1224. }
  1225. NbfSendUIFrame (
  1226. DeviceContext,
  1227. RawFrame,
  1228. FALSE); // no loopback (MC frame)
  1229. return STATUS_ABANDONED;
  1230. } /* NbfProcessStatusQuery */
  1231. VOID
  1232. NbfSendQueryFindName(
  1233. IN PDEVICE_CONTEXT DeviceContext,
  1234. IN PTP_REQUEST Request
  1235. )
  1236. /*++
  1237. Routine Description:
  1238. This routine will send a FIND.NAME packet for the specified
  1239. find name request, and start the request timer.
  1240. Arguments:
  1241. DeviceContext - a pointer to the device context to send the find name on.
  1242. Request - The find name request.
  1243. Return Value:
  1244. None.
  1245. --*/
  1246. {
  1247. TDI_ADDRESS_NETBIOS * remoteAddress;
  1248. PIO_STACK_LOCATION irpSp;
  1249. NTSTATUS Status;
  1250. PTP_UI_FRAME RawFrame;
  1251. PUCHAR SingleSR;
  1252. UINT SingleSRLength;
  1253. UINT HeaderLength;
  1254. LARGE_INTEGER Timeout;
  1255. irpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket);
  1256. remoteAddress = NbfParseTdiAddress(
  1257. ((PTDI_REQUEST_KERNEL_QUERY_INFORMATION)(&irpSp->Parameters))->
  1258. RequestConnectionInformation->RemoteAddress, FALSE);
  1259. //
  1260. // Start the timer for this request.
  1261. //
  1262. Request->Flags |= REQUEST_FLAGS_TIMER; // there is a timeout on this request.
  1263. KeInitializeTimer (&Request->Timer); // set to not-signaled state.
  1264. NbfReferenceRequest ("Find Name: timer", Request, RREF_TIMER); // one for the timer
  1265. Timeout.LowPart = (ULONG)(-(LONG)DeviceContext->GeneralTimeout);
  1266. Timeout.HighPart = -1;
  1267. KeSetTimer (&Request->Timer, Timeout, &Request->Dpc);
  1268. //
  1269. // Allocate a UI frame from the pool.
  1270. //
  1271. Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
  1272. if (!NT_SUCCESS (Status)) { // couldn't make frame.
  1273. return;
  1274. }
  1275. IF_NBFDBG (NBF_DEBUG_DEVCTX) {
  1276. NbfPrint2 ("NbfSendFindNames: Sending Frame: %lx, NdisPacket: %lx\n",
  1277. RawFrame, RawFrame->NdisPacket);
  1278. }
  1279. //
  1280. // Build the MAC header. NAME_QUERY frames go out as
  1281. // single-route source routing.
  1282. //
  1283. MacReturnSingleRouteSR(
  1284. &DeviceContext->MacInfo,
  1285. &SingleSR,
  1286. &SingleSRLength);
  1287. MacConstructHeader (
  1288. &DeviceContext->MacInfo,
  1289. RawFrame->Header,
  1290. DeviceContext->NetBIOSAddress.Address,
  1291. DeviceContext->LocalAddress.Address,
  1292. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
  1293. SingleSR,
  1294. SingleSRLength,
  1295. &HeaderLength);
  1296. //
  1297. // Build the DLC UI frame header.
  1298. //
  1299. NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
  1300. HeaderLength += sizeof(DLC_FRAME);
  1301. //
  1302. // Build the Netbios header.
  1303. //
  1304. ConstructNameQuery (
  1305. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  1306. NETBIOS_NAME_TYPE_UNIQUE, // call from a unique name.
  1307. NAME_QUERY_LSN_FIND_NAME, // LSN
  1308. Request->FrameContext, // corr. in 1st NAME_RECOGNIZED.
  1309. DeviceContext->ReservedNetBIOSAddress,
  1310. (PNAME)remoteAddress->NetbiosName);
  1311. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  1312. //
  1313. // Munge the packet length.
  1314. //
  1315. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  1316. NbfSendUIFrame (
  1317. DeviceContext,
  1318. RawFrame,
  1319. FALSE); // no loopback (MC frame)
  1320. } /* NbfSendQueryFindName */
  1321. NTSTATUS
  1322. NbfProcessQueryNameRecognized(
  1323. IN PDEVICE_CONTEXT DeviceContext,
  1324. IN PUCHAR Packet,
  1325. PNBF_HDR_CONNECTIONLESS UiFrame
  1326. )
  1327. /*++
  1328. Routine Description:
  1329. This routine processes a NAME.RECOGNIZED request with a
  1330. correlator of 0, indicating it was a response to a previous
  1331. FIND.NAME packet.
  1332. Arguments:
  1333. DeviceContext - a pointer to the device context the frame was received on.
  1334. Packet - The packet in question, starting at the MAC header.
  1335. UiFrame - The packet, starting at the Netbios header.
  1336. Return Value:
  1337. NTSTATUS - status of operation.
  1338. --*/
  1339. {
  1340. KIRQL oldirql;
  1341. PTP_REQUEST Request;
  1342. PFIND_NAME_BUFFER FindNameBuffer;
  1343. PFIND_NAME_HEADER FindNameHeader;
  1344. PUCHAR DestinationAddress;
  1345. HARDWARE_ADDRESS SourceAddressBuffer;
  1346. PHARDWARE_ADDRESS SourceAddress;
  1347. PUCHAR SourceRouting;
  1348. UINT SourceRoutingLength;
  1349. PUCHAR TargetBuffer;
  1350. USHORT FrameContext;
  1351. PLIST_ENTRY p;
  1352. MacReturnDestinationAddress(
  1353. &DeviceContext->MacInfo,
  1354. Packet,
  1355. &DestinationAddress);
  1356. MacReturnSourceAddress(
  1357. &DeviceContext->MacInfo,
  1358. Packet,
  1359. &SourceAddressBuffer,
  1360. &SourceAddress,
  1361. NULL);
  1362. MacReturnSourceRouting(
  1363. &DeviceContext->MacInfo,
  1364. Packet,
  1365. &SourceRouting,
  1366. &SourceRoutingLength);
  1367. //
  1368. // Find the request that this is for, using the frame context.
  1369. //
  1370. FrameContext = TRANSMIT_CORR(UiFrame);
  1371. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  1372. for (p=DeviceContext->FindNameQueue.Flink;
  1373. p != &DeviceContext->FindNameQueue;
  1374. p=p->Flink) {
  1375. Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
  1376. if (Request->FrameContext == FrameContext) {
  1377. break;
  1378. }
  1379. }
  1380. if (p == &DeviceContext->FindNameQueue) {
  1381. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1382. return STATUS_SUCCESS;
  1383. }
  1384. NbfReferenceRequest ("Name Recognized", Request, RREF_FIND_NAME);
  1385. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1386. //
  1387. // Make sure that this physical address has not
  1388. // responded yet.
  1389. //
  1390. ACQUIRE_SPIN_LOCK (&Request->SpinLock, &oldirql);
  1391. //
  1392. // Make sure this request is not stopping.
  1393. //
  1394. if ((Request->Flags & REQUEST_FLAGS_STOPPING) != 0) {
  1395. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1396. NbfDereferenceRequest ("Stopping", Request, RREF_STATUS);
  1397. return STATUS_SUCCESS;
  1398. }
  1399. //
  1400. // If this is the first response, update BytesWritten to include
  1401. // the header that is already written in ResponseBuffer.
  1402. //
  1403. if (Request->BytesWritten == 0) {
  1404. Request->BytesWritten = sizeof(FIND_NAME_HEADER);
  1405. }
  1406. TargetBuffer = Request->ResponseBuffer;
  1407. FindNameBuffer = (PFIND_NAME_BUFFER)(TargetBuffer + sizeof(FIND_NAME_HEADER));
  1408. for ( ; FindNameBuffer < (PFIND_NAME_BUFFER)(TargetBuffer + Request->BytesWritten); FindNameBuffer++) {
  1409. if (RtlEqualMemory (FindNameBuffer->source_addr, SourceAddress->Address, 6)) {
  1410. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1411. NbfDereferenceRequest ("Duplicate NR", Request, RREF_FIND_NAME);
  1412. return STATUS_SUCCESS;
  1413. }
  1414. }
  1415. //
  1416. // This is a new address, update if there is room.
  1417. //
  1418. if ((Request->BytesWritten + sizeof(FIND_NAME_BUFFER)) >
  1419. Request->Buffer2Length) {
  1420. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1421. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql);
  1422. RemoveEntryList (&Request->Linkage);
  1423. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1424. NbfCompleteRequest (Request, STATUS_SUCCESS, Request->BytesWritten);
  1425. NbfDereferenceRequest ("No Buffer", Request, RREF_FIND_NAME);
  1426. return STATUS_SUCCESS;
  1427. }
  1428. FindNameHeader = (PFIND_NAME_HEADER)TargetBuffer;
  1429. FindNameHeader->unique_group = UiFrame->Data2High;
  1430. Request->BytesWritten += sizeof(FIND_NAME_BUFFER);
  1431. ++FindNameHeader->node_count;
  1432. RtlCopyMemory(FindNameBuffer->source_addr, SourceAddress->Address, 6);
  1433. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1434. RtlCopyMemory(FindNameBuffer->destination_addr, DestinationAddress, 6);
  1435. FindNameBuffer->length = 14;
  1436. if (DeviceContext->MacInfo.MediumType == NdisMedium802_5) {
  1437. //
  1438. // token-ring, copy the correct fields.
  1439. //
  1440. FindNameBuffer->access_control = Packet[0];
  1441. FindNameBuffer->frame_control = Packet[1];
  1442. if (SourceRouting != NULL) {
  1443. RtlCopyMemory (FindNameBuffer->routing_info, SourceRouting, SourceRoutingLength);
  1444. FindNameBuffer->length += (UCHAR) SourceRoutingLength;
  1445. }
  1446. } else {
  1447. //
  1448. // non-token-ring, nothing else is significant.
  1449. //
  1450. FindNameBuffer->access_control = 0x0;
  1451. FindNameBuffer->frame_control = 0x0;
  1452. }
  1453. //
  1454. // If this is a unique name, complete the request now.
  1455. //
  1456. if (UiFrame->Data2High == NETBIOS_NAME_TYPE_UNIQUE) {
  1457. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql);
  1458. RemoveEntryList (&Request->Linkage);
  1459. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1460. NbfCompleteRequest(Request, STATUS_SUCCESS, Request->BytesWritten);
  1461. }
  1462. NbfDereferenceRequest ("NR processed", Request, RREF_FIND_NAME);
  1463. return STATUS_SUCCESS;
  1464. } /* NbfProcessQueryNameRecognized */
  1465. VOID
  1466. NbfSendStatusQuery(
  1467. IN PDEVICE_CONTEXT DeviceContext,
  1468. IN PTP_REQUEST Request,
  1469. IN PHARDWARE_ADDRESS DestinationAddress,
  1470. IN PUCHAR SourceRouting,
  1471. IN UINT SourceRoutingLength
  1472. )
  1473. /*++
  1474. Routine Description:
  1475. This routine will send a STATUS.NAME packet for the specified
  1476. find name request, and start the request timer.
  1477. Arguments:
  1478. DeviceContext - a pointer to the device context to send the status query on.
  1479. Request - The find name request.
  1480. DestinationAddress - The hardware destination address of the frame.
  1481. SourceRouting - Optional source routing information in the frame.
  1482. SourceRoutingLength - The length of SourceRouting.
  1483. Return Value:
  1484. NTSTATUS - status of operation.
  1485. --*/
  1486. {
  1487. TDI_ADDRESS_NETBIOS * remoteAddress;
  1488. PIO_STACK_LOCATION irpSp;
  1489. NTSTATUS Status;
  1490. PTP_UI_FRAME RawFrame;
  1491. PUCHAR SingleSR;
  1492. UINT SingleSRLength;
  1493. UINT HeaderLength;
  1494. LARGE_INTEGER Timeout;
  1495. UCHAR RequestType;
  1496. irpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket);
  1497. remoteAddress = NbfParseTdiAddress(
  1498. ((PTDI_REQUEST_KERNEL_QUERY_INFORMATION)(&irpSp->Parameters))->
  1499. RequestConnectionInformation->RemoteAddress, FALSE);
  1500. //
  1501. // Start the timer for this request.
  1502. //
  1503. Request->Flags |= REQUEST_FLAGS_TIMER; // there is a timeout on this request.
  1504. KeInitializeTimer (&Request->Timer); // set to not-signaled state.
  1505. NbfReferenceRequest ("Find Name: timer", Request, RREF_TIMER); // one for the timer
  1506. Timeout.LowPart = (ULONG)(-(LONG)DeviceContext->GeneralTimeout);
  1507. Timeout.HighPart = -1;
  1508. KeSetTimer (&Request->Timer, Timeout, &Request->Dpc);
  1509. //
  1510. // Allocate a UI frame from the pool.
  1511. //
  1512. Status = NbfCreateConnectionlessFrame (DeviceContext, &RawFrame);
  1513. if (!NT_SUCCESS (Status)) { // couldn't make frame.
  1514. return;
  1515. }
  1516. IF_NBFDBG (NBF_DEBUG_DEVCTX) {
  1517. NbfPrint2 ("NbfSendFindNames: Sending Frame: %lx, NdisPacket: %lx\n",
  1518. RawFrame, RawFrame->NdisPacket);
  1519. }
  1520. //
  1521. // Build the MAC header. STATUS_QUERY frames go out as
  1522. // single-route source routing.
  1523. //
  1524. MacReturnSingleRouteSR(
  1525. &DeviceContext->MacInfo,
  1526. &SingleSR,
  1527. &SingleSRLength);
  1528. MacConstructHeader (
  1529. &DeviceContext->MacInfo,
  1530. RawFrame->Header,
  1531. DeviceContext->NetBIOSAddress.Address,
  1532. DeviceContext->LocalAddress.Address,
  1533. sizeof (DLC_FRAME) + sizeof (NBF_HDR_CONNECTIONLESS),
  1534. SingleSR,
  1535. SingleSRLength,
  1536. &HeaderLength);
  1537. //
  1538. // Build the DLC UI frame header.
  1539. //
  1540. NbfBuildUIFrameHeader(&RawFrame->Header[HeaderLength]);
  1541. HeaderLength += sizeof(DLC_FRAME);
  1542. //
  1543. // Build the Netbios header.
  1544. //
  1545. //
  1546. // Determine what RequestType should be.
  1547. //
  1548. if (Request->BytesWritten == 0) {
  1549. //
  1550. // No way to know if he is 2.1 or not, so we put a 1 here
  1551. // instead of 0.
  1552. //
  1553. RequestType = 1;
  1554. } else {
  1555. RequestType = (UCHAR)((Request->BytesWritten - sizeof(ADAPTER_STATUS)) / sizeof(NAME_BUFFER));
  1556. }
  1557. ConstructStatusQuery (
  1558. (PNBF_HDR_CONNECTIONLESS)&(RawFrame->Header[HeaderLength]),
  1559. RequestType, // request status type.
  1560. (USHORT)Request->Buffer2Length, // user's buffer length
  1561. Request->FrameContext, // corr. in 1st NAME_RECOGNIZED.
  1562. (PNAME)remoteAddress->NetbiosName,
  1563. DeviceContext->ReservedNetBIOSAddress);
  1564. HeaderLength += sizeof(NBF_HDR_CONNECTIONLESS);
  1565. //
  1566. // Munge the packet length.
  1567. //
  1568. NbfSetNdisPacketLength(RawFrame->NdisPacket, HeaderLength);
  1569. NbfSendUIFrame (
  1570. DeviceContext,
  1571. RawFrame,
  1572. FALSE); // no loopback (MC frame)
  1573. } /* NbfSendStatusQuery */
  1574. NTSTATUS
  1575. NbfProcessStatusResponse(
  1576. IN PDEVICE_CONTEXT DeviceContext,
  1577. IN NDIS_HANDLE ReceiveContext,
  1578. IN PNBF_HDR_CONNECTIONLESS UiFrame,
  1579. IN PHARDWARE_ADDRESS SourceAddress,
  1580. IN PUCHAR SourceRouting,
  1581. IN UINT SourceRoutingLength
  1582. )
  1583. /*++
  1584. Routine Description:
  1585. This routine processes a STATUS.RESPONSE packet.
  1586. Arguments:
  1587. DeviceContext - a pointer to the device context the frame was received on.
  1588. ReceiveContext - The context for calling NdisTransferData.
  1589. UiFrame - The packet in question, starting at the Netbios header.
  1590. SourceAddress - The source hardware address of the packet.
  1591. SourceRouting - Source routing data in the query.
  1592. SourceRoutingLength - The length of SourceRouting.
  1593. Return Value:
  1594. NTSTATUS - status of operation.
  1595. --*/
  1596. {
  1597. KIRQL oldirql;
  1598. PTP_REQUEST Request;
  1599. PUCHAR TargetBuffer;
  1600. USHORT FrameContext;
  1601. USHORT NamesReceived;
  1602. USHORT ResponseLength, ResponseBytesToCopy;
  1603. PLIST_ENTRY p;
  1604. PSINGLE_LIST_ENTRY linkage;
  1605. NDIS_STATUS ndisStatus;
  1606. PNDIS_BUFFER NdisBuffer;
  1607. PNDIS_PACKET ndisPacket;
  1608. ULONG ndisBytesTransferred;
  1609. PRECEIVE_PACKET_TAG receiveTag;
  1610. NDIS_STATUS NdisStatus;
  1611. //
  1612. // Find the request that this is for, using the frame context.
  1613. //
  1614. FrameContext = TRANSMIT_CORR(UiFrame);
  1615. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  1616. for (p=DeviceContext->StatusQueryQueue.Flink;
  1617. p != &DeviceContext->StatusQueryQueue;
  1618. p=p->Flink) {
  1619. Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
  1620. if (Request->FrameContext == FrameContext) {
  1621. break;
  1622. }
  1623. }
  1624. if (p == &DeviceContext->StatusQueryQueue) {
  1625. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1626. return STATUS_SUCCESS;
  1627. }
  1628. NbfReferenceRequest ("Status Response", Request, RREF_STATUS);
  1629. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1630. ACQUIRE_SPIN_LOCK (&Request->SpinLock, &oldirql);
  1631. //
  1632. // Make sure this request is not stopping.
  1633. //
  1634. if ((Request->Flags & REQUEST_FLAGS_STOPPING) != 0) {
  1635. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1636. NbfDereferenceRequest ("Stopping", Request, RREF_STATUS);
  1637. return STATUS_SUCCESS;
  1638. }
  1639. //
  1640. // See if this is packet has new data.
  1641. //
  1642. if (Request->BytesWritten == 0) {
  1643. NamesReceived = 0;
  1644. } else {
  1645. NamesReceived = (USHORT)(Request->BytesWritten - sizeof(ADAPTER_STATUS)) / sizeof(NAME_BUFFER);
  1646. }
  1647. if ((UiFrame->Data1 > 0) && (UiFrame->Data1 <= NamesReceived)) {
  1648. //
  1649. // If it is a post-2.1 response, but we already got
  1650. // this data, ignore it.
  1651. //
  1652. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1653. NbfDereferenceRequest ("Duplicate SR", Request, RREF_STATUS);
  1654. return STATUS_SUCCESS;
  1655. }
  1656. //
  1657. // This is new data, append if there is room.
  1658. //
  1659. ResponseLength = ((UiFrame->Data2High & 0x3f) * 256) + UiFrame->Data2Low;
  1660. if ((ULONG)(Request->BytesWritten + ResponseLength) >
  1661. Request->Buffer2Length) {
  1662. ResponseBytesToCopy = (USHORT)(Request->Buffer2Length - Request->BytesWritten);
  1663. } else {
  1664. ResponseBytesToCopy = ResponseLength;
  1665. }
  1666. //
  1667. // Allocate a receive packer for this operation.
  1668. //
  1669. linkage = ExInterlockedPopEntryList(
  1670. &DeviceContext->ReceivePacketPool,
  1671. &DeviceContext->Interlock);
  1672. if (linkage != NULL) {
  1673. ndisPacket = CONTAINING_RECORD( linkage, NDIS_PACKET, ProtocolReserved[0] );
  1674. } else {
  1675. //
  1676. // Could not get a packet, oh well, it is connectionless.
  1677. //
  1678. DeviceContext->ReceivePacketExhausted++;
  1679. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1680. return STATUS_SUCCESS;
  1681. }
  1682. receiveTag = (PRECEIVE_PACKET_TAG)(ndisPacket->ProtocolReserved);
  1683. receiveTag->PacketType = TYPE_STATUS_RESPONSE;
  1684. receiveTag->Connection = (PTP_CONNECTION)Request;
  1685. TargetBuffer = (PUCHAR)Request->ResponseBuffer + Request->BytesWritten;
  1686. //
  1687. // Allocate an MDL to describe the part of the buffer we
  1688. // want transferred.
  1689. //
  1690. NdisAllocateBuffer(
  1691. &NdisStatus,
  1692. &NdisBuffer,
  1693. DeviceContext->NdisBufferPool,
  1694. TargetBuffer,
  1695. ResponseBytesToCopy);
  1696. if (NdisStatus != NDIS_STATUS_SUCCESS) {
  1697. ExInterlockedPushEntryList(
  1698. &DeviceContext->ReceivePacketPool,
  1699. linkage,
  1700. &DeviceContext->Interlock);
  1701. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1702. return STATUS_SUCCESS;
  1703. }
  1704. //
  1705. // Assume success, if not we fail the request.
  1706. //
  1707. Request->BytesWritten += ResponseBytesToCopy;
  1708. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1709. NdisChainBufferAtFront(ndisPacket, NdisBuffer);
  1710. //
  1711. // See if the response was too big (we can complete the
  1712. // request here since we still reference it).
  1713. //
  1714. if ((ResponseLength > ResponseBytesToCopy) ||
  1715. (UiFrame->Data2High & 0x40)) {
  1716. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql);
  1717. RemoveEntryList (&Request->Linkage);
  1718. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1719. receiveTag->CompleteReceive = TRUE;
  1720. receiveTag->EndOfMessage = FALSE;
  1721. } else {
  1722. //
  1723. // If we are done, complete the packet, otherwise send off
  1724. // the next request (unless it is a pre-2.1 response).
  1725. //
  1726. if ((UiFrame->Data1 > 0) && (UiFrame->Data2High & 0x80)) {
  1727. UCHAR TempSR[MAX_SOURCE_ROUTING];
  1728. PUCHAR ResponseSR;
  1729. receiveTag->CompleteReceive = FALSE;
  1730. //
  1731. // Try to cancel the timer, no harm if we fail.
  1732. //
  1733. ACQUIRE_SPIN_LOCK (&Request->SpinLock, &oldirql);
  1734. if ((Request->Flags & REQUEST_FLAGS_TIMER) != 0) {
  1735. Request->Flags &= ~REQUEST_FLAGS_TIMER;
  1736. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1737. if (KeCancelTimer (&Request->Timer)) {
  1738. NbfDereferenceRequest ("Status Response: stop timer", Request, RREF_TIMER);
  1739. }
  1740. } else {
  1741. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  1742. }
  1743. Request->Retries = DeviceContext->GeneralRetries;
  1744. //
  1745. // Send a STATUS_QUERY directed.
  1746. //
  1747. if (SourceRouting != NULL) {
  1748. RtlCopyMemory(
  1749. TempSR,
  1750. SourceRouting,
  1751. SourceRoutingLength);
  1752. MacCreateNonBroadcastReplySR(
  1753. &DeviceContext->MacInfo,
  1754. TempSR,
  1755. SourceRoutingLength,
  1756. &ResponseSR);
  1757. } else {
  1758. ResponseSR = NULL;
  1759. }
  1760. NbfSendStatusQuery(
  1761. DeviceContext,
  1762. Request,
  1763. SourceAddress,
  1764. ResponseSR,
  1765. SourceRoutingLength);
  1766. } else {
  1767. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql);
  1768. RemoveEntryList (&Request->Linkage);
  1769. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  1770. receiveTag->CompleteReceive = TRUE;
  1771. receiveTag->EndOfMessage = TRUE;
  1772. }
  1773. }
  1774. //
  1775. // Now do the actual data transfer.
  1776. //
  1777. if (DeviceContext->NdisBindingHandle) {
  1778. NdisTransferData (
  1779. &ndisStatus,
  1780. DeviceContext->NdisBindingHandle,
  1781. ReceiveContext,
  1782. DeviceContext->MacInfo.TransferDataOffset +
  1783. 3 + sizeof(NBF_HDR_CONNECTIONLESS),
  1784. ResponseBytesToCopy,
  1785. ndisPacket,
  1786. (PUINT)&ndisBytesTransferred);
  1787. }
  1788. else {
  1789. ndisStatus = STATUS_INVALID_DEVICE_STATE;
  1790. }
  1791. if (ndisStatus != NDIS_STATUS_PENDING) {
  1792. NbfTransferDataComplete(
  1793. (NDIS_HANDLE)DeviceContext,
  1794. ndisPacket,
  1795. ndisStatus,
  1796. ndisBytesTransferred);
  1797. }
  1798. return STATUS_SUCCESS;
  1799. } /* NbfProcessStatusResponse */
  1800. NTSTATUS
  1801. NbfTdiSetInformation(
  1802. IN PIRP Irp
  1803. )
  1804. /*++
  1805. Routine Description:
  1806. This routine performs the TdiSetInformation request for the transport
  1807. provider.
  1808. Arguments:
  1809. Irp - the Irp for the requested operation.
  1810. Return Value:
  1811. NTSTATUS - status of operation.
  1812. --*/
  1813. {
  1814. UNREFERENCED_PARAMETER (Irp); // prevent compiler warnings
  1815. return STATUS_NOT_IMPLEMENTED;
  1816. } /* NbfTdiQueryInformation */
  1817. #if 0
  1818. NTSTATUS
  1819. NbfQueryInfoEndpoint(
  1820. IN PTP_ENDPOINT Endpoint,
  1821. IN PTDI_REQ_QUERY_INFORMATION TdiRequest,
  1822. IN ULONG TdiRequestLength,
  1823. OUT PTDI_ENDPOINT_INFO InfoBuffer,
  1824. IN ULONG InfoBufferLength,
  1825. OUT PULONG InformationSize
  1826. )
  1827. /*++
  1828. Routine Description:
  1829. This routine returns information for the specified endpoint.
  1830. Arguments:
  1831. Endpoint - Pointer to transport endpoint context.
  1832. TdiRequest - Pointer to request buffer.
  1833. TdiRequestLength - Length of request buffer.
  1834. InfoBuffer - Pointer to output buffer to return information into.
  1835. InfoBufferLength - Length of output buffer.
  1836. InformationSize - Pointer to ulong where actual size of returned
  1837. information is to be stored.
  1838. Return Value:
  1839. NTSTATUS - status of operation.
  1840. --*/
  1841. {
  1842. KIRQL oldirql;
  1843. TdiRequest, TdiRequestLength; // prevent compiler warnings
  1844. if (InfoBufferLength < sizeof (TDI_ENDPOINT_INFO)) {
  1845. return STATUS_BUFFER_TOO_SMALL;
  1846. }
  1847. ACQUIRE_SPIN_LOCK (&Endpoint->SpinLock, &oldirql);
  1848. *InfoBuffer = Endpoint->Information; // structure copy.
  1849. RELEASE_SPIN_LOCK (&Endpoint->SpinLock, oldirql);
  1850. *InformationSize = sizeof (Endpoint->Information);
  1851. return STATUS_SUCCESS;
  1852. } /* NbfQueryInfoEndpoint */
  1853. NTSTATUS
  1854. NbfQueryInfoConnection(
  1855. IN PTP_CONNECTION Connection,
  1856. IN PTDI_REQUEST_KERNEL TdiRequest,
  1857. IN ULONG TdiRequestLength,
  1858. OUT PTDI_CONNECTION_INFO InfoBuffer,
  1859. IN ULONG InfoBufferLength,
  1860. OUT PULONG InformationSize
  1861. )
  1862. /*++
  1863. Routine Description:
  1864. This routine returns information for the specified connection.
  1865. Arguments:
  1866. Connection - Pointer to transport connection object.
  1867. TdiRequest - Pointer to request buffer.
  1868. TdiRequestLength - Length of request buffer.
  1869. InfoBuffer - Pointer to output buffer to return information into.
  1870. InfoBufferLength - Length of output buffer.
  1871. InformationSize - Pointer to ulong where actual size of returned
  1872. information is to be stored.
  1873. Return Value:
  1874. NTSTATUS - status of operation.
  1875. --*/
  1876. {
  1877. KIRQL oldirql;
  1878. TdiRequest, TdiRequestLength; // prevent compiler warnings
  1879. if (InfoBufferLength < sizeof (TDI_CONNECTION_INFO)) {
  1880. return STATUS_BUFFER_TOO_SMALL;
  1881. }
  1882. ACQUIRE_C_SPIN_LOCK (&Connection->SpinLock, &oldirql);
  1883. *InfoBuffer = Connection->Information; // structure copy.
  1884. RELEASE_C_SPIN_LOCK (&Connection->SpinLock, oldirql);
  1885. *InformationSize = sizeof (Connection->Information);
  1886. return STATUS_SUCCESS;
  1887. } /* NbfQueryInfoConnection */
  1888. NTSTATUS
  1889. NbfQueryInfoAddress(
  1890. IN PTP_ADDRESS Address,
  1891. IN PTDI_REQUEST_KERNEL TdiRequest,
  1892. IN ULONG TdiRequestLength,
  1893. OUT PTDI_ADDRESS_INFO InfoBuffer,
  1894. IN ULONG InfoBufferLength,
  1895. OUT PULONG InformationSize
  1896. )
  1897. /*++
  1898. Routine Description:
  1899. This routine returns information for the specified address. We
  1900. don't acquire a spinlock in this routine because there are no statistics
  1901. which must be read atomically.
  1902. Arguments:
  1903. Address - Pointer to transport address object.
  1904. TdiRequest - Pointer to request buffer.
  1905. TdiRequestLength - Length of request buffer.
  1906. InfoBuffer - Pointer to output buffer to return information into.
  1907. InfoBufferLength - Length of output buffer.
  1908. InformationSize - Pointer to ulong where actual size of returned
  1909. information is to be stored.
  1910. Return Value:
  1911. NTSTATUS - status of operation.
  1912. --*/
  1913. {
  1914. SHORT i;
  1915. PSZ p, q;
  1916. TdiRequest, TdiRequestLength; // prevent compiler warnings
  1917. //
  1918. // Calculate whether his buffer is big enough to return the entire
  1919. // information. The total size of the address information is the
  1920. // size of the fixed part, plus the size of the variable-length flat
  1921. // string in the NETWORK_NAME component of the TRANSPORT_ADDRESS
  1922. // component.
  1923. //
  1924. if (InfoBufferLength <
  1925. sizeof (TDI_ADDRESS_INFO) +
  1926. Address->NetworkName.Length)
  1927. {
  1928. return STATUS_BUFFER_TOO_SMALL;
  1929. }
  1930. //
  1931. // Copy both the fixed part of the address information, and the variable
  1932. // part. The variable part comes from the NETWORK_NAME component of the
  1933. // TRANSPORT_ADDRESS structure. This component contains a FLAT_STRING,
  1934. // which is of variable length.
  1935. //
  1936. InfoBuffer->Address.AddressComponents = Address->AddressComponents;
  1937. InfoBuffer->Address.Tsap = Address->Tsap;
  1938. InfoBuffer->Address.NetworkName.Name.Length =
  1939. Address->NetworkName.Length;
  1940. p = Address->NetworkName.Buffer; // p = ptr, source string.
  1941. q = InfoBuffer->Address.NetworkName.Name.Buffer; // q = ptr, dest string.
  1942. for (i=0; i<InfoBuffer->Address.NetworkName.Name.Length; i++) {
  1943. *(q++) = *(p++);
  1944. }
  1945. *InformationSize = sizeof (TDI_ADDRESS_INFO) +
  1946. Address->NetworkName.Length;
  1947. return STATUS_SUCCESS;
  1948. } /* NbfQueryInfoAddress */
  1949. NTSTATUS
  1950. NbfQueryInfoProvider(
  1951. IN PDEVICE_CONTEXT Provider,
  1952. IN PTDI_REQUEST_KERNEL TdiRequest,
  1953. IN ULONG TdiRequestLength,
  1954. OUT PTDI_PROVIDER_INFO InfoBuffer,
  1955. IN ULONG InfoBufferLength,
  1956. OUT PULONG InformationSize
  1957. )
  1958. /*++
  1959. Routine Description:
  1960. This routine returns information for the transport provider.
  1961. Arguments:
  1962. Provider - Pointer to device context for provider.
  1963. TdiRequest - Pointer to request buffer.
  1964. TdiRequestLength - Length of request buffer.
  1965. InfoBuffer - Pointer to output buffer to return information into.
  1966. InfoBufferLength - Length of output buffer.
  1967. InformationSize - Pointer to ulong where actual size of returned
  1968. information is to be stored.
  1969. Return Value:
  1970. NTSTATUS - status of operation.
  1971. --*/
  1972. {
  1973. KIRQL oldirql;
  1974. TdiRequest, TdiRequestLength; // prevent compiler warnings
  1975. if (InfoBufferLength < sizeof (TDI_PROVIDER_INFO)) {
  1976. return STATUS_BUFFER_TOO_SMALL;
  1977. }
  1978. ACQUIRE_SPIN_LOCK (&Provider->SpinLock, &oldirql);
  1979. *InfoBuffer = Provider->Information; // structure copy.
  1980. RELEASE_SPIN_LOCK (&Provider->SpinLock, oldirql);
  1981. *InformationSize = sizeof (Provider->Information);
  1982. return STATUS_SUCCESS;
  1983. } /* NbfQueryInfoProvider */
  1984. NTSTATUS
  1985. NbfQueryInfoNetman(
  1986. IN PDEVICE_CONTEXT Provider,
  1987. IN PTDI_REQUEST_KERNEL TdiRequest,
  1988. IN ULONG TdiRequestLength,
  1989. OUT PTDI_NETMAN_INFO InfoBuffer,
  1990. IN ULONG InfoBufferLength,
  1991. OUT PULONG InformationSize
  1992. )
  1993. /*++
  1994. Routine Description:
  1995. This routine returns information for the specified network-managable
  1996. variable managed by the transport provider.
  1997. Arguments:
  1998. Provider - Pointer to device context for provider.
  1999. TdiRequest - Pointer to request buffer.
  2000. TdiRequestLength - Length of request buffer.
  2001. InfoBuffer - Pointer to output buffer to return information into.
  2002. InfoBufferLength - Length of output buffer.
  2003. InformationSize - Pointer to ulong where actual size of returned
  2004. information is to be stored.
  2005. Return Value:
  2006. NTSTATUS - status of operation.
  2007. --*/
  2008. {
  2009. KIRQL oldirql;
  2010. PFLAT_STRING p;
  2011. PTP_VARIABLE v;
  2012. PTDI_NETMAN_VARIABLE n;
  2013. USHORT i;
  2014. ULONG NameOffset, ValueOffset;
  2015. TdiRequest, TdiRequestLength; // prevent compiler warnings
  2016. InfoBufferLength, InformationSize;
  2017. //
  2018. // check param lengths here.
  2019. //
  2020. ACQUIRE_SPIN_LOCK (&Provider->SpinLock, &oldirql);
  2021. NbfReferenceDeviceContext ("Query InfoNetMan", Provider, DCREF_QUERY_INFO);
  2022. for (v=Provider->NetmanVariables; v != NULL; v=v->Fwdlink) {
  2023. if (TdiRequest->Identification == v->VariableSerialNumber) {
  2024. //
  2025. // Return the variable information here.
  2026. //
  2027. NameOffset = sizeof (TDI_NETMAN_INFO);
  2028. ValueOffset = NameOffset + (sizeof (FLAT_STRING)-1) +
  2029. v->VariableName.Length;
  2030. InfoBuffer->VariableName = NameOffset;
  2031. InfoBuffer->VariableValue = ValueOffset;
  2032. //
  2033. // Copy the variable name to the user's buffer.
  2034. //
  2035. p = (PFLAT_STRING)((PUCHAR)InfoBuffer + NameOffset);
  2036. p->MaximumLength = v->VariableName.Length;
  2037. p->Length = v->VariableName.Length;
  2038. for (i=0; i<v->VariableName.Length; i++) {
  2039. p->Buffer [i] = v->VariableName.Buffer [i];
  2040. }
  2041. //
  2042. // Now copy the variable's contents to the user's buffer.
  2043. //
  2044. n = (PTDI_NETMAN_VARIABLE)((PUCHAR)InfoBuffer + ValueOffset);
  2045. n->VariableType = v->VariableType;
  2046. switch (v->VariableType) {
  2047. case NETMAN_VARTYPE_ULONG:
  2048. n->Value.LongValue = v->Value.LongValue;
  2049. break;
  2050. case NETMAN_VARTYPE_HARDWARE_ADDRESS:
  2051. n->Value.HardwareAddressValue =
  2052. v->Value.HardwareAddressValue;
  2053. break;
  2054. case NETMAN_VARTYPE_STRING:
  2055. p = &n->Value.StringValue;
  2056. p->MaximumLength = v->Value.StringValue.Length;
  2057. p->Length = v->Value.StringValue.Length;
  2058. for (i=0; i<v->Value.StringValue.Length; i++) {
  2059. p->Buffer [i] = v->Value.StringValue.Buffer [i];
  2060. }
  2061. } /* switch */
  2062. RELEASE_SPIN_LOCK (&Provider->SpinLock, oldirql);
  2063. NbfDereferenceDeviceContext ("Query InfoNetMan success", Provider, DCREF_QUERY_INFO);
  2064. return STATUS_SUCCESS;
  2065. } /* if */
  2066. } /* for */
  2067. RELEASE_SPIN_LOCK (&Provider->SpinLock, oldirql);
  2068. NbfDereferenceDeviceContext ("Query InfoNetMan no exist", Provider, DCREF_QUERY_INFO);
  2069. return STATUS_INVALID_INFO_CLASS; // variable does not exist.
  2070. } /* NbfQueryInfoNetman */
  2071. NTSTATUS
  2072. NbfSetInfoEndpoint(
  2073. IN PTP_ENDPOINT Endpoint,
  2074. IN PTDI_REQUEST_KERNEL TdiRequest,
  2075. IN ULONG TdiRequestLength
  2076. )
  2077. /*++
  2078. Routine Description:
  2079. This routine sets information for the specified endpoint.
  2080. Arguments:
  2081. Endpoint - Pointer to transport endpoint context.
  2082. TdiRequest - Pointer to request buffer.
  2083. TdiRequestLength - Length of request buffer.
  2084. Return Value:
  2085. NTSTATUS - status of operation.
  2086. --*/
  2087. {
  2088. KIRQL oldirql;
  2089. PTDI_ENDPOINT_INFO InfoBuffer;
  2090. if (TdiRequestLength !=
  2091. sizeof (TDI_ENDPOINT_INFO) + sizeof (TDI_REQ_SET_INFORMATION) -
  2092. sizeof (TDI_INFO_BUFFER)) {
  2093. return STATUS_BUFFER_TOO_SMALL; // buffer sizes must match.
  2094. }
  2095. InfoBuffer = (PTDI_ENDPOINT_INFO)&TdiRequest->InfoBuffer;
  2096. if ((InfoBuffer->MinimumLookaheadData <= NBF_MAX_LOOKAHEAD_DATA) ||
  2097. (InfoBuffer->MaximumLookaheadData <= NBF_MAX_LOOKAHEAD_DATA) ||
  2098. (InfoBuffer->MinimumLookaheadData > InfoBuffer->MaximumLookaheadData)) {
  2099. return STATUS_INVALID_PARAMETER;
  2100. }
  2101. ACQUIRE_SPIN_LOCK (&Endpoint->SpinLock, &oldirql);
  2102. //
  2103. // Set minimum lookahead data size. This is the number of bytes of
  2104. // contiguous data that will be supplied to TDI_IND_RECEIVE and
  2105. // TDI_IND_RECEIVE_DATAGRAM event handlers at indication time.
  2106. //
  2107. Endpoint->Information.MinimumLookaheadData = InfoBuffer->MinimumLookaheadData;
  2108. //
  2109. // Set maximum lookahead data size. This is the number of bytes of
  2110. // contiguous data that will be supplied to TDI_IND_RECEIVE and
  2111. // TDI_IND_RECEIVE_DATAGRAM event handlers at indication time.
  2112. //
  2113. Endpoint->Information.MaximumLookaheadData = InfoBuffer->MaximumLookaheadData;
  2114. //
  2115. // Reset all the statistics to his new values.
  2116. //
  2117. Endpoint->Information.TransmittedTsdus = InfoBuffer->TransmittedTsdus;
  2118. Endpoint->Information.ReceivedTsdus = InfoBuffer->ReceivedTsdus;
  2119. Endpoint->Information.TransmissionErrors = InfoBuffer->TransmissionErrors;
  2120. Endpoint->Information.ReceiveErrors = InfoBuffer->ReceiveErrors;
  2121. Endpoint->Information.PriorityLevel = InfoBuffer->PriorityLevel;
  2122. Endpoint->Information.SecurityLevel = InfoBuffer->SecurityLevel;
  2123. Endpoint->Information.SecurityCompartment = InfoBuffer->SecurityCompartment;
  2124. //
  2125. // The State and Event fields are read-only, so we DON'T set them here.
  2126. //
  2127. RELEASE_SPIN_LOCK (&Endpoint->SpinLock, oldirql);
  2128. return STATUS_SUCCESS;
  2129. } /* NbfSetInfoEndpoint */
  2130. NTSTATUS
  2131. NbfSetInfoAddress(
  2132. IN PTP_ADDRESS Address,
  2133. IN PTDI_REQUEST_KERNEL TdiRequest,
  2134. IN ULONG TdiRequestLength
  2135. )
  2136. /*++
  2137. Routine Description:
  2138. This routine sets information for the specified address. Currently,
  2139. all the user-visible fields in the transport address object are read-only.
  2140. Arguments:
  2141. Address - Pointer to transport address object.
  2142. TdiRequest - Pointer to request buffer.
  2143. TdiRequestLength - Length of request buffer.
  2144. Return Value:
  2145. NTSTATUS - status of operation.
  2146. --*/
  2147. {
  2148. Address, TdiRequest, TdiRequestLength; // prevent compiler warnings
  2149. return STATUS_SUCCESS;
  2150. } /* NbfSetInfoAddress */
  2151. NTSTATUS
  2152. NbfSetInfoConnection(
  2153. IN PTP_CONNECTION Connection,
  2154. IN PTDI_REQUEST_KERNEL TdiRequest,
  2155. IN ULONG TdiRequestLength
  2156. )
  2157. /*++
  2158. Routine Description:
  2159. This routine sets information for the specified connection.
  2160. Arguments:
  2161. Connection - Pointer to transport connection object.
  2162. TdiRequest - Pointer to request buffer.
  2163. TdiRequestLength - Length of request buffer.
  2164. Return Value:
  2165. NTSTATUS - status of operation.
  2166. --*/
  2167. {
  2168. KIRQL oldirql;
  2169. PTDI_CONNECTION_INFO InfoBuffer;
  2170. if (TdiRequestLength !=
  2171. sizeof (TDI_CONNECTION_INFO) + sizeof (TDI_REQ_SET_INFORMATION) -
  2172. sizeof (TDI_INFO_BUFFER)) {
  2173. return STATUS_BUFFER_TOO_SMALL; // buffer sizes must match.
  2174. }
  2175. InfoBuffer = (PTDI_CONNECTION_INFO)&TdiRequest->InfoBuffer;
  2176. ACQUIRE_C_SPIN_LOCK (&Connection->SpinLock, &oldirql);
  2177. //
  2178. // Reset all the statistics to his new values.
  2179. //
  2180. Connection->Information.TransmittedTsdus = InfoBuffer->TransmittedTsdus;
  2181. Connection->Information.ReceivedTsdus = InfoBuffer->ReceivedTsdus;
  2182. Connection->Information.TransmissionErrors = InfoBuffer->TransmissionErrors;
  2183. Connection->Information.ReceiveErrors = InfoBuffer->ReceiveErrors;
  2184. //
  2185. // The State and Event fields are read-only, so we DON'T set them here.
  2186. //
  2187. RELEASE_C_SPIN_LOCK (&Connection->SpinLock, oldirql);
  2188. return STATUS_SUCCESS;
  2189. } /* NbfSetInfoConnection */
  2190. NTSTATUS
  2191. NbfSetInfoProvider(
  2192. IN PDEVICE_CONTEXT Provider,
  2193. IN PTDI_REQUEST_KERNEL TdiRequest,
  2194. IN ULONG TdiRequestLength
  2195. )
  2196. /*++
  2197. Routine Description:
  2198. This routine sets information for the specified transport provider.
  2199. Arguments:
  2200. Provider - Pointer to device context.
  2201. TdiRequest - Pointer to request buffer.
  2202. TdiRequestLength - Length of request buffer.
  2203. Return Value:
  2204. NTSTATUS - status of operation.
  2205. --*/
  2206. {
  2207. KIRQL oldirql;
  2208. PTDI_PROVIDER_INFO InfoBuffer;
  2209. if (TdiRequestLength !=
  2210. sizeof (TDI_PROVIDER_INFO) + sizeof (TDI_REQ_SET_INFORMATION) -
  2211. sizeof (TDI_INFO_BUFFER)) {
  2212. return STATUS_BUFFER_TOO_SMALL; // buffer sizes must match.
  2213. }
  2214. InfoBuffer = (PTDI_PROVIDER_INFO)&TdiRequest->InfoBuffer;
  2215. //
  2216. // By changing the service flags the caller can request additional
  2217. // or fewer services on the fly. Make sure that he is requesting
  2218. // services we can provide, or else fail the request.
  2219. //
  2220. if (InfoBuffer->ServiceFlags & ~NBF_SERVICE_FLAGS) {
  2221. return STATUS_NOT_SUPPORTED;
  2222. }
  2223. ACQUIRE_SPIN_LOCK (&Provider->SpinLock, &oldirql);
  2224. //
  2225. // Reset all the statistics to his new values.
  2226. //
  2227. Provider->Information.TransmittedTsdus = InfoBuffer->TransmittedTsdus;
  2228. Provider->Information.ReceivedTsdus = InfoBuffer->ReceivedTsdus;
  2229. Provider->Information.TransmissionErrors = InfoBuffer->TransmissionErrors;
  2230. Provider->Information.ReceiveErrors = InfoBuffer->ReceiveErrors;
  2231. Provider->Information.DiscardedFrames = InfoBuffer->DiscardedFrames;
  2232. Provider->Information.ReceiveErrors = InfoBuffer->ReceiveErrors;
  2233. Provider->Information.OversizeTsdusReceived = InfoBuffer->OversizeTsdusReceived;
  2234. Provider->Information.UndersizeTsdusReceived = InfoBuffer->UndersizeTsdusReceived;
  2235. Provider->Information.MulticastTsdusReceived = InfoBuffer->MulticastTsdusReceived;
  2236. Provider->Information.BroadcastTsdusReceived = InfoBuffer->BroadcastTsdusReceived;
  2237. Provider->Information.MulticastTsdusTransmitted = InfoBuffer->MulticastTsdusTransmitted;
  2238. Provider->Information.BroadcastTsdusTransmitted = InfoBuffer->BroadcastTsdusTransmitted;
  2239. Provider->Information.SendTimeouts = InfoBuffer->SendTimeouts;
  2240. Provider->Information.ReceiveTimeouts = InfoBuffer->ReceiveTimeouts;
  2241. Provider->Information.ConnectionIndicationsReceived = InfoBuffer->ConnectionIndicationsReceived;
  2242. Provider->Information.ConnectionIndicationsAccepted = InfoBuffer->ConnectionIndicationsAccepted;
  2243. Provider->Information.ConnectionsInitiated = InfoBuffer->ConnectionsInitiated;
  2244. Provider->Information.ConnectionsAccepted = InfoBuffer->ConnectionsAccepted;
  2245. //
  2246. // The following fields are read-only, so we DON'T set them here:
  2247. // Version, MaxTsduSize, MaxConnectionUserData, MinimumLookaheadData,
  2248. // MaximumLookaheadData.
  2249. //
  2250. RELEASE_SPIN_LOCK (&Provider->SpinLock, oldirql);
  2251. return STATUS_SUCCESS;
  2252. } /* NbfSetInfoProvider */
  2253. NTSTATUS
  2254. NbfSetInfoNetman(
  2255. IN PDEVICE_CONTEXT Provider,
  2256. IN PTDI_REQ_SET_INFORMATION TdiRequest,
  2257. IN ULONG TdiRequestLength
  2258. )
  2259. /*++
  2260. Routine Description:
  2261. This routine sets information for the specified transport provider's
  2262. network-managable variable.
  2263. Arguments:
  2264. Provider - Pointer to device context.
  2265. TdiRequest - Pointer to request buffer.
  2266. TdiRequestLength - Length of request buffer.
  2267. Return Value:
  2268. NTSTATUS - status of operation.
  2269. --*/
  2270. {
  2271. PTDI_NETMAN_INFO InfoBuffer;
  2272. Provider; // prevent compiler warnings
  2273. if (TdiRequestLength !=
  2274. sizeof (TDI_NETMAN_INFO) + sizeof (TDI_REQ_SET_INFORMATION) -
  2275. sizeof (TDI_INFO_BUFFER)) {
  2276. return STATUS_BUFFER_TOO_SMALL; // buffer sizes must match.
  2277. }
  2278. InfoBuffer = (PTDI_NETMAN_INFO)&TdiRequest->InfoBuffer;
  2279. //
  2280. // set the network-managable variable here.
  2281. //
  2282. return STATUS_SUCCESS;
  2283. } /* NbfSetInfoNetman */
  2284. NTSTATUS
  2285. NbfTdiQueryInformation(
  2286. IN PTP_ENDPOINT Endpoint,
  2287. IN PTDI_REQ_QUERY_INFORMATION TdiRequest,
  2288. IN ULONG TdiRequestLength,
  2289. OUT PTDI_INFO_BUFFER InfoBuffer,
  2290. IN ULONG InfoBufferLength,
  2291. OUT PULONG InformationSize
  2292. )
  2293. /*++
  2294. Routine Description:
  2295. This routine performs the TdiQueryInformation request for the transport
  2296. provider.
  2297. Arguments:
  2298. Endpoint - Pointer to transport endpoint context.
  2299. TdiRequest - Pointer to request buffer.
  2300. TdiRequestLength - Length of request buffer.
  2301. InfoBuffer - Pointer to output buffer to return information into.
  2302. InfoBufferLength - Length of output buffer.
  2303. InformationSize - Pointer to ulong where actual size of returned
  2304. information is to be stored.
  2305. Return Value:
  2306. NTSTATUS - status of operation.
  2307. --*/
  2308. {
  2309. NTSTATUS Status;
  2310. PTP_CONNECTION Connection;
  2311. switch (TdiRequest->InformationClass) {
  2312. //
  2313. // ENDPOINT information: return information about the endpoint
  2314. // to which this request was submitted.
  2315. //
  2316. case TDI_INFO_CLASS_ENDPOINT:
  2317. Status = NbfQueryInfoEndpoint (
  2318. Endpoint,
  2319. TdiRequest,
  2320. TdiRequestLength,
  2321. (PTDI_ENDPOINT_INFO)InfoBuffer,
  2322. InfoBufferLength,
  2323. InformationSize);
  2324. break;
  2325. //
  2326. // CONNECTION information: return information about a connection
  2327. // that is associated with the endpoint on which this request was
  2328. // submitted.
  2329. //
  2330. case TDI_INFO_CLASS_CONNECTION:
  2331. // This causes a connection reference which is removed below.
  2332. Connection = NbfLookupConnectionById (
  2333. Endpoint,
  2334. TdiRequest->Identification);
  2335. if (Connection == NULL) {
  2336. Status = STATUS_INVALID_HANDLE;
  2337. break;
  2338. }
  2339. Status = NbfQueryInfoConnection (
  2340. Connection,
  2341. TdiRequest,
  2342. TdiRequestLength,
  2343. (PTDI_CONNECTION_INFO)InfoBuffer,
  2344. InfoBufferLength,
  2345. InformationSize);
  2346. NbfDereferenceConnection("Query Connection Info", Connection, CREF_BY_ID);
  2347. break;
  2348. //
  2349. // ADDRESS information: return information about the address object
  2350. // that is associated with the endpoint on which this request was
  2351. // submitted.
  2352. //
  2353. case TDI_INFO_CLASS_ADDRESS:
  2354. Status = NbfQueryInfoAddress (
  2355. Endpoint->BoundAddress,
  2356. TdiRequest,
  2357. TdiRequestLength,
  2358. (PTDI_ADDRESS_INFO)InfoBuffer,
  2359. InfoBufferLength,
  2360. InformationSize);
  2361. break;
  2362. //
  2363. // PROVIDER information: return information about the transport
  2364. // provider itself.
  2365. //
  2366. case TDI_INFO_CLASS_PROVIDER:
  2367. Status = NbfQueryInfoProvider (
  2368. Endpoint->BoundAddress->Provider,
  2369. TdiRequest,
  2370. TdiRequestLength,
  2371. (PTDI_PROVIDER_INFO)InfoBuffer,
  2372. InfoBufferLength,
  2373. InformationSize);
  2374. break;
  2375. //
  2376. // NETMAN information: return information about the network-managable
  2377. // variables managed by the provider itself.
  2378. //
  2379. case TDI_INFO_CLASS_NETMAN:
  2380. Status = NbfQueryInfoNetman (
  2381. Endpoint->BoundAddress->Provider,
  2382. TdiRequest,
  2383. TdiRequestLength,
  2384. (PTDI_NETMAN_INFO)InfoBuffer,
  2385. InfoBufferLength,
  2386. InformationSize);
  2387. break;
  2388. default:
  2389. Status = STATUS_INVALID_INFO_CLASS;
  2390. } /* switch */
  2391. return Status;
  2392. } /* TdiQueryInformation */
  2393. NTSTATUS
  2394. TdiSetInformation(
  2395. IN PTP_ENDPOINT Endpoint,
  2396. IN PTDI_REQ_SET_INFORMATION TdiRequest,
  2397. IN ULONG TdiRequestLength
  2398. )
  2399. /*++
  2400. Routine Description:
  2401. This routine performs the TdiSetInformation request for the transport
  2402. provider.
  2403. Arguments:
  2404. Endpoint - Pointer to transport endpoint context.
  2405. TdiRequest - Pointer to request buffer.
  2406. TdiRequestLength - Length of request buffer.
  2407. Return Value:
  2408. NTSTATUS - status of operation.
  2409. --*/
  2410. {
  2411. NTSTATUS Status;
  2412. PTP_CONNECTION Connection;
  2413. switch (TdiRequest->InformationClass) {
  2414. //
  2415. // ENDPOINT information: set information on the endpoint
  2416. // to which this request was submitted.
  2417. //
  2418. case TDI_INFO_CLASS_ENDPOINT:
  2419. Status = NbfSetInfoEndpoint (
  2420. Endpoint,
  2421. TdiRequest,
  2422. TdiRequestLength);
  2423. break;
  2424. //
  2425. // CONNECTION information: set information for a connection
  2426. // that is associated with the endpoint on which this request
  2427. // was submitted.
  2428. //
  2429. case TDI_INFO_CLASS_CONNECTION:
  2430. // This causes a connection reference which is removed below.
  2431. Connection = NbfLookupConnectionById (
  2432. Endpoint,
  2433. TdiRequest->Identification);
  2434. if (Connection == NULL) {
  2435. Status = STATUS_INVALID_HANDLE;
  2436. break;
  2437. }
  2438. Status = NbfSetInfoConnection (
  2439. Connection,
  2440. TdiRequest,
  2441. TdiRequestLength);
  2442. NbfDereferenceConnection("Set Connection Info", Connection, CREF_BY_ID);
  2443. break;
  2444. //
  2445. // ADDRESS information: set information for the address object
  2446. // that is associated with the endpoint on which this request
  2447. // was submitted.
  2448. //
  2449. case TDI_INFO_CLASS_ADDRESS:
  2450. Status = NbfSetInfoAddress (
  2451. Endpoint->BoundAddress,
  2452. TdiRequest,
  2453. TdiRequestLength);
  2454. break;
  2455. //
  2456. // PROVIDER information: set information for the transport
  2457. // provider itself.
  2458. //
  2459. case TDI_INFO_CLASS_PROVIDER:
  2460. Status = NbfSetInfoProvider (
  2461. Endpoint->BoundAddress->Provider,
  2462. TdiRequest,
  2463. TdiRequestLength);
  2464. break;
  2465. //
  2466. // NETMAN information: set information for the network-managable
  2467. // variables managed by the provider itself.
  2468. //
  2469. case TDI_INFO_CLASS_NETMAN:
  2470. Status = NbfSetInfoNetman (
  2471. Endpoint->BoundAddress->Provider,
  2472. TdiRequest,
  2473. TdiRequestLength);
  2474. break;
  2475. default:
  2476. Status = STATUS_INVALID_INFO_CLASS;
  2477. } /* switch */
  2478. return Status;
  2479. } /* TdiSetInformation */
  2480. #endif