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.

2051 lines
59 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. ndisreq.c
  5. Abstract:
  6. routines for passing NdisRequests up and down
  7. Author:
  8. Charlie Wickham (charlwi) 01-May-1996.
  9. Rajesh Sundaram (rajeshsu) 01-Aug-1998.
  10. Environment:
  11. Kernel Mode
  12. Revision History:
  13. --*/
  14. #include "psched.h"
  15. #pragma hdrstop
  16. /* External */
  17. /* Static */
  18. const UCHAR gDriverDescription[] = " (Microsoft's Packet Scheduler) ";
  19. /* Forward */ /* Generated by Emacs 19.17.0 on Mon May 06 15:54:11 1996 */
  20. VOID
  21. MpQueryPnPCapabilities(
  22. IN OUT PPS_NDIS_REQUEST PsReqBuffer,
  23. IN OUT PADAPTER pAdapt,
  24. OUT PNDIS_STATUS pStatus
  25. );
  26. NDIS_STATUS
  27. MakeNdisRequest(
  28. IN PADAPTER Adapter,
  29. IN NDIS_HANDLE VcHandle,
  30. IN NDIS_REQUEST_TYPE RequestType,
  31. IN NDIS_OID Oid,
  32. IN PVOID InformationBuffer,
  33. IN ULONG InformationBufferLength,
  34. OUT PULONG BytesReadOrWritten,
  35. OUT PULONG BytesNeeded,
  36. LOCAL_NDISREQUEST_COMPLETION_FUNCTION CompletionFunc
  37. );
  38. VOID
  39. ClRequestComplete(
  40. IN NDIS_HANDLE ProtocolBindingContext,
  41. IN PNDIS_REQUEST NdisRequest,
  42. IN NDIS_STATUS Status
  43. );
  44. NDIS_STATUS
  45. MakeLocalNdisRequest(
  46. PADAPTER Adapter,
  47. NDIS_HANDLE VcHandle,
  48. NDIS_REQUEST_TYPE RequestType,
  49. NDIS_OID Oid,
  50. PVOID Buffer,
  51. ULONG BufferSize,
  52. LOCAL_NDISREQUEST_COMPLETION_FUNCTION CompletionFunc OPTIONAL
  53. );
  54. NDIS_STATUS
  55. RecordNetworkAddressList(
  56. IN PADAPTER Adapter,
  57. IN PPS_NDIS_REQUEST PsRequestBuffer
  58. );
  59. ULONG
  60. GetSizeAddrList(
  61. IN NETWORK_ADDRESS_LIST UNALIGNED *AddrList
  62. );
  63. /* End Forward */
  64. NTSTATUS
  65. DoIpIoctl(
  66. IN PWCHAR DriverName,
  67. IN DWORD Ioctl,
  68. IN PVOID pvInArg,
  69. IN DWORD dwInSize,
  70. IN PVOID pvOutArg,
  71. IN DWORD dwOutSize)
  72. /*++
  73. Routine Description:
  74. Do an IOCTL to the stack. Used for a varity of purposes
  75. --*/
  76. {
  77. NTSTATUS status;
  78. UNICODE_STRING nameString;
  79. OBJECT_ATTRIBUTES Atts;
  80. IO_STATUS_BLOCK ioStatusBlock;
  81. HANDLE Handle;
  82. PAGED_CODE();
  83. RtlInitUnicodeString(&nameString, DriverName);
  84. InitializeObjectAttributes(&Atts,
  85. &nameString,
  86. OBJ_CASE_INSENSITIVE,
  87. NULL,
  88. NULL);
  89. status = ZwCreateFile(&Handle,
  90. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  91. &Atts,
  92. &ioStatusBlock,
  93. NULL,
  94. FILE_ATTRIBUTE_NORMAL,
  95. FILE_SHARE_READ | FILE_SHARE_WRITE,
  96. FILE_OPEN_IF,
  97. 0,
  98. NULL,
  99. 0);
  100. if (!NT_SUCCESS(status))
  101. {
  102. return STATUS_UNSUCCESSFUL;
  103. }
  104. //
  105. // Submit the request to the forwarder
  106. //
  107. status = ZwDeviceIoControlFile(
  108. Handle,
  109. NULL,
  110. NULL,
  111. NULL,
  112. &ioStatusBlock,
  113. Ioctl,
  114. pvInArg,
  115. dwInSize,
  116. pvOutArg,
  117. dwOutSize);
  118. //
  119. // Close the device.
  120. //
  121. ZwClose(Handle);
  122. return status;
  123. }
  124. //
  125. // This function uses one of the IP Addresses on the adapter to get the Interface Index of the
  126. // adapter. This function is called when IP updates the addresses on the interface. It uses this
  127. // address and the IpHlpAPI and obtains the InterfaceID.
  128. //
  129. // For WanLinks, the InterfaceID is a set of 2 ULONGS - One identifies the InterfaceIndex as above
  130. // and the other ULONG is the remote address of the server.
  131. //
  132. //
  133. VOID SetInterfaceIndex(PNDIS_WORK_ITEM pWorkItem, PVOID pWorkItemContext)
  134. {
  135. PPS_INTERFACE_INDEX_CONTEXT pInterfaceContext = (PPS_INTERFACE_INDEX_CONTEXT) pWorkItemContext;
  136. PTC_INTERFACE_ID pInterfaceID;
  137. IO_STATUS_BLOCK IoStatus;
  138. KEVENT LocalEvent;
  139. PIRP Irp;
  140. IPAddrEntry *pIpAddrTbl;
  141. ULONG k, OutBufferSize;
  142. TCP_REQUEST_QUERY_INFORMATION_EX trqiInBuf;
  143. TDIObjectID *ID;
  144. DWORD Status, dwInBufLen, dwOutBufLen;
  145. BYTE *Context;
  146. ULONG IpAddr, IpAddrCount;
  147. INT n;
  148. NETWORK_ADDRESS UNALIGNED *pAddr;
  149. IPSNMPInfo IPSnmpInfo;
  150. PS_LOCK(&pInterfaceContext->Adapter->Lock);
  151. if(pInterfaceContext->Adapter->MediaType == NdisMediumWan)
  152. {
  153. pInterfaceID = &pInterfaceContext->WanLink->InterfaceID;
  154. pInterfaceID->LinkId = 0;
  155. IpAddr = pInterfaceContext->WanLink->LocalIpAddress;
  156. if(pInterfaceContext->WanLink->DialUsage != DU_CALLOUT)
  157. pInterfaceID->LinkId = pInterfaceContext->WanLink->RemoteIpAddress;
  158. }
  159. else
  160. {
  161. pInterfaceID = &pInterfaceContext->Adapter->InterfaceID;
  162. pInterfaceID->LinkId = 0;
  163. pAddr = (NETWORK_ADDRESS UNALIGNED *)&pInterfaceContext->Adapter->IpNetAddressList->Address[0];
  164. for(n=0; n<pInterfaceContext->Adapter->IpNetAddressList->AddressCount; n++)
  165. {
  166. NETWORK_ADDRESS_IP UNALIGNED *pIpNetAddr;
  167. if(pAddr->AddressType == NDIS_PROTOCOL_ID_TCP_IP)
  168. {
  169. pIpNetAddr = (NETWORK_ADDRESS_IP UNALIGNED *)&pAddr->Address[0];
  170. IpAddr = pIpNetAddr->in_addr;
  171. break;
  172. }
  173. pAddr = (NETWORK_ADDRESS UNALIGNED *)(((PUCHAR)pAddr)
  174. + pAddr->AddressLength
  175. + FIELD_OFFSET(NETWORK_ADDRESS, Address));
  176. }
  177. if(n == pInterfaceContext->Adapter->IpNetAddressList->AddressCount)
  178. {
  179. PsDbgOut(DBG_FAILURE,
  180. DBG_PROTOCOL,
  181. ("[SetInterfaceIndex]: No Ip Addresses \n"));
  182. PS_UNLOCK(&pInterfaceContext->Adapter->Lock);
  183. goto Done;
  184. }
  185. }
  186. PS_UNLOCK(&pInterfaceContext->Adapter->Lock);
  187. //
  188. // Initialize parameters for sending the IO Request
  189. //
  190. ID = &(trqiInBuf.ID);
  191. ID->toi_entity.tei_entity = CL_NL_ENTITY;
  192. ID->toi_entity.tei_instance = 0;
  193. ID->toi_class = INFO_CLASS_PROTOCOL;
  194. ID->toi_type = INFO_TYPE_PROVIDER;
  195. ID->toi_id = IP_MIB_STATS_ID;
  196. Context = (BYTE *) &(trqiInBuf.Context[0]);
  197. NdisZeroMemory(Context,CONTEXT_SIZE);
  198. dwInBufLen = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  199. dwOutBufLen = sizeof(IPSNMPInfo);
  200. Status = DoIpIoctl(DD_TCP_DEVICE_NAME,
  201. IOCTL_TCP_QUERY_INFORMATION_EX,
  202. (PVOID) &trqiInBuf,
  203. sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
  204. (PVOID)&IPSnmpInfo,
  205. dwOutBufLen);
  206. if(NT_SUCCESS(Status))
  207. {
  208. //
  209. // Allocate the output buffer and send the I/O request.
  210. //
  211. IpAddrCount = IPSnmpInfo.ipsi_numaddr + 10;
  212. dwOutBufLen = IpAddrCount * sizeof(IPAddrEntry);
  213. PsAllocatePool(pIpAddrTbl, dwOutBufLen, PsMiscTag);
  214. if(!pIpAddrTbl)
  215. {
  216. PsDbgOut(DBG_FAILURE,
  217. DBG_PROTOCOL,
  218. ("[SetInterfaceIndex]: Could not allocate memory for %d addresses \n",
  219. IPSnmpInfo.ipsi_numaddr + 10));
  220. goto Done;
  221. }
  222. NdisZeroMemory(pIpAddrTbl, dwOutBufLen);
  223. ID->toi_type = INFO_TYPE_PROVIDER;
  224. ID->toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
  225. RtlZeroMemory(Context, CONTEXT_SIZE);
  226. Status = DoIpIoctl(DD_TCP_DEVICE_NAME,
  227. IOCTL_TCP_QUERY_INFORMATION_EX,
  228. (PVOID) &trqiInBuf,
  229. sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
  230. (PVOID)pIpAddrTbl,
  231. dwOutBufLen);
  232. if(!NT_SUCCESS(Status))
  233. {
  234. PsDbgOut(DBG_FAILURE,
  235. DBG_PROTOCOL,
  236. ("[SetInterfaceIndex]: IOCTL_TCP_QUERY_INFORMATION_EX failed with 0x%x \n", Status));
  237. PsFreePool(pIpAddrTbl);
  238. goto Done;
  239. }
  240. }
  241. else
  242. {
  243. PsDbgOut(DBG_FAILURE,
  244. DBG_PROTOCOL,
  245. ("[SetInterfaceIndex]: DoIpIoctl failed with 0x%x \n", Status));
  246. goto Done;
  247. }
  248. //
  249. // search for the matching IP address to IpAddr
  250. // in the table we got back from the stack
  251. //
  252. for (k = 0; k < IpAddrCount; k++) {
  253. if (pIpAddrTbl[k].iae_addr == IpAddr) {
  254. //
  255. // found one, get the index
  256. //
  257. PS_LOCK(&pInterfaceContext->Adapter->Lock);
  258. pInterfaceID->InterfaceId = pIpAddrTbl[k].iae_index;
  259. PS_UNLOCK(&pInterfaceContext->Adapter->Lock);
  260. break;
  261. }
  262. }
  263. PsDbgOut(DBG_INFO,
  264. DBG_PROTOCOL,
  265. ("[SetInterfaceIndex]: InterfaceID (0x%x:0x%x) \n", pInterfaceID->InterfaceId, pInterfaceID->LinkId));
  266. PsFreePool(pIpAddrTbl);
  267. Done:
  268. if(pInterfaceContext->Adapter->MediaType == NdisMediumWan)
  269. REFDEL(&pInterfaceContext->WanLink->RefCount, FALSE, 'IOTL');
  270. REFDEL(&pInterfaceContext->Adapter->RefCount, FALSE, 'IOTL');
  271. PsFreePool(pWorkItem);
  272. PsFreePool(pWorkItemContext);
  273. return;
  274. }
  275. VOID PsScheduleInterfaceIdWorkItem(PADAPTER Adapter, PPS_WAN_LINK WanLink)
  276. {
  277. PPS_INTERFACE_INDEX_CONTEXT pContext;
  278. NDIS_STATUS WorkItemStatus;
  279. PNDIS_WORK_ITEM pWorkItem;
  280. PsAllocatePool(pContext, sizeof(PS_INTERFACE_INDEX_CONTEXT), PsMiscTag);
  281. if(pContext)
  282. {
  283. PsAllocatePool(pWorkItem, sizeof(NDIS_WORK_ITEM), PsMiscTag);
  284. if(pWorkItem)
  285. {
  286. NdisInitializeWorkItem(pWorkItem, SetInterfaceIndex, pContext);
  287. pContext->Adapter = Adapter;
  288. pContext->WanLink = WanLink;
  289. //
  290. // We have to make sure that the adapter and the wanlink are around when the WorkItem fires.
  291. // The adapter and wanlink are valid at this point (see below), but there are no guarantees that
  292. // they will be around when the work item fires.
  293. //
  294. // 1. For LAN bindings, this function is called from the ClRequestComplete thread. The NDIS
  295. // request has not yet been completed. Hence we can never have an invalid Adapter context here.
  296. //
  297. // 2. For WAN links, this function is called from the WAN_LINE_UP thread. Again, the WanLink
  298. // cannot be invalid because it is called from the context of the line-up thread.
  299. //
  300. if(Adapter)
  301. {
  302. REFADD(&Adapter->RefCount, 'IOTL');
  303. }
  304. if(WanLink)
  305. {
  306. REFADD(&WanLink->RefCount, 'IOTL');
  307. }
  308. if((WorkItemStatus = NdisScheduleWorkItem(pWorkItem)) != NDIS_STATUS_SUCCESS)
  309. {
  310. PsDbgOut(DBG_TRACE,
  311. DBG_PROTOCOL,
  312. ("[PsScheduleInterfaceIdWorkItem]: Adapter %08X, NdisScheduleWorkItem failed 0x%x\n",
  313. Adapter, WorkItemStatus));
  314. if(WanLink)
  315. REFDEL(&WanLink->RefCount, FALSE, 'IOTL');
  316. if(Adapter)
  317. REFDEL(&Adapter->RefCount, FALSE, 'IOTL');
  318. PsFreePool(pContext);
  319. PsFreePool(pWorkItem);
  320. }
  321. }
  322. else
  323. {
  324. PsDbgOut(DBG_TRACE,
  325. DBG_PROTOCOL,
  326. ("[PsScheduleInterfaceIdWorkItem]: Adapter %08X, No memory to allocate Work Item \n", Adapter));
  327. PsFreePool(pContext);
  328. }
  329. }
  330. else
  331. {
  332. PsDbgOut(DBG_TRACE,
  333. DBG_PROTOCOL,
  334. ("[PsScheduleInterfaceIdWorkItem]: Adapter %08X, No memory to allocate Work Item context \n", Adapter));
  335. }
  336. }
  337. NDIS_STATUS
  338. MakeNdisRequest(
  339. IN PADAPTER Adapter,
  340. IN NDIS_HANDLE VcHandle,
  341. IN NDIS_REQUEST_TYPE RequestType,
  342. IN NDIS_OID Oid,
  343. IN PVOID InformationBuffer,
  344. IN ULONG InformationBufferLength,
  345. OUT PULONG BytesReadOrWritten,
  346. OUT PULONG BytesNeeded,
  347. IN LOCAL_NDISREQUEST_COMPLETION_FUNCTION CompletionFunc
  348. )
  349. /*++
  350. Routine Description:
  351. common handler for set and query information, local ndis request, and
  352. corequest routines. An NDIS_REQUEST is built and issued to the underlying MP
  353. Arguments:
  354. See the DDK...
  355. CompletionFunc - pointer to a function that gets called when the request
  356. completion handler has been called. Only used for local requests.
  357. RequestType also includes NdisRequestLocal{Set,Query}Info which is used
  358. to indicate a local request meaning the request is originated by the
  359. packet scheduler and needs no further completion
  360. Return Values:
  361. return the value returned to us by the underlying adapter
  362. --*/
  363. {
  364. PPS_NDIS_REQUEST PsReqBuffer;
  365. NDIS_STATUS Status;
  366. PsAllocFromLL(&PsReqBuffer, &NdisRequestLL, NdisRequest);
  367. if(PsReqBuffer == NULL){
  368. if(RequestType == NdisRequestLocalQueryInfo || RequestType == NdisRequestLocalSetInfo)
  369. {
  370. PsFreePool(BytesReadOrWritten);
  371. PsFreePool(BytesNeeded);
  372. }
  373. return NDIS_STATUS_RESOURCES;
  374. }
  375. else
  376. NdisZeroMemory(&PsReqBuffer->ReqBuffer, sizeof(NDIS_REQUEST));
  377. if(RequestType == NdisRequestSetInformation ||
  378. RequestType == NdisRequestLocalSetInfo){
  379. PsReqBuffer->ReqBuffer.RequestType = NdisRequestSetInformation;
  380. PsReqBuffer->LocalRequest = ( RequestType == NdisRequestLocalSetInfo );
  381. PsReqBuffer->ReqBuffer.DATA.SET_INFORMATION.Oid = Oid;
  382. PsReqBuffer->ReqBuffer.DATA.SET_INFORMATION.InformationBuffer =
  383. InformationBuffer;
  384. PsReqBuffer->ReqBuffer.DATA.SET_INFORMATION.InformationBufferLength =
  385. InformationBufferLength;
  386. }
  387. else{
  388. PsAssert(RequestType == NdisRequestQueryInformation ||
  389. RequestType == NdisRequestLocalQueryInfo ||
  390. RequestType == NdisRequestQueryStatistics);
  391. if(RequestType != NdisRequestQueryStatistics){
  392. PsReqBuffer->ReqBuffer.RequestType = NdisRequestQueryInformation;
  393. PsReqBuffer->LocalRequest =
  394. (RequestType == NdisRequestLocalQueryInfo);
  395. }
  396. else
  397. {
  398. PsReqBuffer->ReqBuffer.RequestType = NdisRequestQueryStatistics;
  399. PsReqBuffer->LocalRequest = 0;
  400. }
  401. PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.Oid = Oid;
  402. PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.InformationBuffer =
  403. InformationBuffer;
  404. PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.InformationBufferLength =
  405. InformationBufferLength;
  406. }
  407. //
  408. // store the pointers to BytesReadOrWritten and BytesNeeded so they can be
  409. // updated in the completion routine if necessary. Save the completion func
  410. //
  411. PsReqBuffer->BytesReadOrWritten = BytesReadOrWritten;
  412. PsReqBuffer->BytesNeeded = BytesNeeded;
  413. PsReqBuffer->LocalCompletionFunc = CompletionFunc;
  414. InterlockedIncrement(&Adapter->OutstandingNdisRequests);
  415. if(!PsReqBuffer->LocalRequest && Adapter->PTDeviceState != NdisDeviceStateD0)
  416. {
  417. // It's not a local request, and the device is off. So, we pend this request.
  418. PsAssert(!VcHandle);
  419. PsAssert(Adapter->PendedNdisRequest == 0);
  420. Adapter->PendedNdisRequest = PsReqBuffer;
  421. return NDIS_STATUS_PENDING;
  422. }
  423. if(VcHandle)
  424. {
  425. Status = NdisCoRequest(
  426. Adapter->LowerMpHandle,
  427. NULL,
  428. VcHandle,
  429. NULL,
  430. (PNDIS_REQUEST) PsReqBuffer);
  431. if(Status != NDIS_STATUS_PENDING) {
  432. WanCoRequestComplete(Status, Adapter, NULL, NULL, (PNDIS_REQUEST)PsReqBuffer);
  433. }
  434. }
  435. else
  436. {
  437. NdisRequest(&Status, Adapter->LowerMpHandle, (PNDIS_REQUEST)PsReqBuffer);
  438. if(Status != NDIS_STATUS_PENDING){
  439. ClRequestComplete((NDIS_HANDLE)Adapter,
  440. (PNDIS_REQUEST)PsReqBuffer,
  441. Status);
  442. }
  443. }
  444. return NDIS_STATUS_PENDING;
  445. } // MakeNdisRequest
  446. VOID
  447. ClRequestComplete(
  448. IN NDIS_HANDLE ProtocolBindingContext,
  449. IN PNDIS_REQUEST NdisRequest,
  450. IN NDIS_STATUS Status
  451. )
  452. /*++
  453. Routine Description:
  454. Completion routine for NdisRequest. Stuff our block back on the lookaside
  455. list and call the appropriate completion routine
  456. Arguments:
  457. See the DDK...
  458. Return Values:
  459. None
  460. --*/
  461. {
  462. PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
  463. PPS_NDIS_REQUEST PsReqBuffer;
  464. NDIS_OID Oid;
  465. ULONG SpaceAvailable;
  466. PUCHAR DataStart;
  467. ULONG Len;
  468. ULONG i;
  469. PVOID Data;
  470. NDIS_STATUS OriStatus = Status;
  471. PsReqBuffer = CONTAINING_RECORD( NdisRequest, PS_NDIS_REQUEST, ReqBuffer );
  472. PsStructAssert(Adapter);
  473. switch(NdisRequest->RequestType)
  474. {
  475. case NdisRequestQueryInformation:
  476. *PsReqBuffer->BytesReadOrWritten = PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.BytesWritten;
  477. *PsReqBuffer->BytesNeeded = PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.BytesNeeded;
  478. Oid = PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.Oid;
  479. Len = PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.InformationBufferLength;
  480. Data = PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.InformationBuffer;
  481. //
  482. // Process the Query only OIDs here
  483. //
  484. switch(Oid)
  485. {
  486. case OID_GEN_MAXIMUM_SEND_PACKETS:
  487. //
  488. // see if the underlying MP supports NdisSendPackets.
  489. // if not, fake it by saying we support one.
  490. //
  491. if(Status != NDIS_STATUS_SUCCESS)
  492. {
  493. if(Status == NDIS_STATUS_BUFFER_TOO_SHORT ||
  494. Status == NDIS_STATUS_INVALID_LENGTH)
  495. {
  496. //
  497. // The underlying MP has indicated that the buffer
  498. // is too short. We can assume that it supports this
  499. // OID.
  500. }
  501. else
  502. {
  503. if(Len >= 1)
  504. {
  505. //
  506. // The underlying MP does not support NdisSendPackets
  507. // We fake it here.
  508. //
  509. *((PULONG)PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.InformationBuffer)= 1;
  510. *PsReqBuffer->BytesNeeded = 0;
  511. *PsReqBuffer->BytesReadOrWritten = 1;
  512. Status = NDIS_STATUS_SUCCESS;
  513. }
  514. else
  515. {
  516. //
  517. // Buffer too short even to fake!
  518. //
  519. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  520. *PsReqBuffer->BytesNeeded = 1;
  521. *PsReqBuffer->BytesReadOrWritten = 0;
  522. }
  523. }
  524. }
  525. break;
  526. case OID_GEN_MAC_OPTIONS:
  527. //
  528. // if querying mac options, add full dux option.
  529. //
  530. if(Status == NDIS_STATUS_SUCCESS)
  531. {
  532. *((PULONG)PsReqBuffer->
  533. ReqBuffer.DATA.QUERY_INFORMATION.InformationBuffer) |=
  534. NDIS_MAC_OPTION_FULL_DUPLEX;
  535. //
  536. // Remove the no-loopback bit from mac-options. In essence we are telling NDIS that we can handle loopback.
  537. // We don't, but the interface below us does. If we do not do this, then the loopback processing happens below
  538. // us and above us. This is wasteful at best and if netmon is running multiple packets are seen below us.
  539. //
  540. *(PULONG)Data &= ~NDIS_MAC_OPTION_NO_LOOPBACK;
  541. }
  542. break;
  543. case OID_GEN_CO_VENDOR_DESCRIPTION:
  544. //
  545. // We append some keyword to the end of the Driver
  546. // Description to indicate that packet scheduler is
  547. // installed on this interface.
  548. //
  549. // Assume that the Data is a string followed by a 0
  550. // character, and the 0 is accounted for in the
  551. // len.
  552. //
  553. if(Status == NDIS_STATUS_BUFFER_TOO_SHORT ||
  554. Status == NDIS_STATUS_INVALID_LENGTH)
  555. {
  556. *PsReqBuffer->BytesReadOrWritten = 0;
  557. *PsReqBuffer->BytesNeeded +=
  558. sizeof(gDriverDescription);
  559. }
  560. else
  561. {
  562. if(Status == NDIS_STATUS_SUCCESS)
  563. {
  564. //
  565. // Setup the data pointer and length to copy the
  566. // descrption into the information buffer
  567. // passed to us.
  568. //
  569. if(Len >=
  570. NdisRequest->DATA.QUERY_INFORMATION.BytesWritten +
  571. sizeof(gDriverDescription))
  572. {
  573. PCHAR DescStr;
  574. LONG Written = (LONG)
  575. NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
  576. int i;
  577. //
  578. // Copy the original string, excluding the '0'
  579. // character
  580. //
  581. for(i=0, DescStr = (PCHAR) Data;
  582. (*DescStr != 0) && (i < Written); DescStr++, i++)
  583. ;
  584. *PsReqBuffer->BytesReadOrWritten = i;
  585. //
  586. // Append the new string
  587. //
  588. for(i=0; i < sizeof(gDriverDescription); i++)
  589. {
  590. *DescStr++ = gDriverDescription[i];
  591. }
  592. *PsReqBuffer->BytesReadOrWritten +=
  593. sizeof(gDriverDescription);
  594. *PsReqBuffer->BytesNeeded = 0;
  595. }
  596. else
  597. {
  598. *PsReqBuffer->BytesNeeded =
  599. NdisRequest->DATA.QUERY_INFORMATION.BytesWritten +
  600. sizeof(gDriverDescription);
  601. *PsReqBuffer->BytesReadOrWritten = 0;
  602. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  603. }
  604. }
  605. else {
  606. //
  607. // Upper layer failed for some reason.
  608. // We can still proceed to write the data
  609. //
  610. if(Len >= sizeof(gDriverDescription))
  611. {
  612. PCHAR DescStr = (PCHAR) Data;
  613. int i;
  614. for(i=0; i < sizeof(gDriverDescription); i++)
  615. {
  616. *DescStr++ = gDriverDescription[i];
  617. }
  618. *PsReqBuffer->BytesReadOrWritten =
  619. sizeof(gDriverDescription);
  620. *PsReqBuffer->BytesNeeded = 0;
  621. Status = NDIS_STATUS_SUCCESS;
  622. }
  623. else {
  624. *PsReqBuffer->BytesNeeded =
  625. sizeof(gDriverDescription);
  626. *PsReqBuffer->BytesReadOrWritten = 0;
  627. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  628. }
  629. }
  630. }
  631. break;
  632. case OID_PNP_CAPABILITIES:
  633. if(Status == NDIS_STATUS_SUCCESS)
  634. {
  635. MpQueryPnPCapabilities(PsReqBuffer, Adapter, &Status);
  636. }
  637. break;
  638. case OID_PNP_QUERY_POWER:
  639. PsAssert(0);
  640. break;
  641. default:
  642. break;
  643. }
  644. break;
  645. case NdisRequestSetInformation:
  646. *PsReqBuffer->BytesReadOrWritten = PsReqBuffer->ReqBuffer.DATA.SET_INFORMATION.BytesRead;
  647. *PsReqBuffer->BytesNeeded = PsReqBuffer->ReqBuffer.DATA.SET_INFORMATION.BytesNeeded;
  648. Oid = PsReqBuffer->ReqBuffer.DATA.SET_INFORMATION.Oid;
  649. Len = PsReqBuffer->ReqBuffer.DATA.SET_INFORMATION.InformationBufferLength;
  650. Data = PsReqBuffer->ReqBuffer.DATA.SET_INFORMATION.InformationBuffer;
  651. //
  652. // Process the "Set Only" OIDs here
  653. //
  654. switch(Oid)
  655. {
  656. case OID_WAN_PROTOCOL_TYPE:
  657. {
  658. if(Adapter->MediaType == NdisMediumWan)
  659. {
  660. if (Len > 5)
  661. {
  662. Adapter->ProtocolType =
  663. (((PUCHAR)Data)[4] << 8) |
  664. ((PUCHAR)Data)[5];
  665. }
  666. }
  667. break;
  668. }
  669. case OID_GEN_TRANSPORT_HEADER_OFFSET:
  670. {
  671. if(Len >= sizeof(TRANSPORT_HEADER_OFFSET) )
  672. {
  673. PTRANSPORT_HEADER_OFFSET pTh = (PTRANSPORT_HEADER_OFFSET) Data;
  674. if(pTh->ProtocolType == NDIS_PROTOCOL_ID_TCP_IP)
  675. {
  676. Adapter->IPHeaderOffset = pTh->HeaderOffset;
  677. }
  678. }
  679. else
  680. {
  681. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  682. *PsReqBuffer->BytesReadOrWritten = 0;
  683. *PsReqBuffer->BytesNeeded = sizeof(TRANSPORT_HEADER_OFFSET);
  684. }
  685. break;
  686. }
  687. case OID_GEN_NETWORK_LAYER_ADDRESSES:
  688. //
  689. // Updated network addresses from a transport.
  690. //
  691. Status = RecordNetworkAddressList(Adapter, PsReqBuffer);
  692. //
  693. // Queue a work item to update the Interface ID
  694. //
  695. PsScheduleInterfaceIdWorkItem(Adapter, 0);
  696. //
  697. // Do a status indication to show that the list has
  698. // changed.
  699. //
  700. TcIndicateInterfaceChange(Adapter, 0, NDIS_STATUS_INTERFACE_CHANGE);
  701. break;
  702. case OID_PNP_SET_POWER:
  703. PsAssert(0);
  704. break;
  705. default:
  706. break;
  707. }
  708. break;
  709. case NdisRequestLocalQueryInfo:
  710. break;
  711. default:
  712. PsAssert(0);
  713. break;
  714. }
  715. #if DBG
  716. switch(Oid)
  717. {
  718. case OID_GEN_MEDIA_CONNECT_STATUS:
  719. PsDbgOid(DBG_TRACE,
  720. DBG_ROUTINEOIDS,
  721. (PsReqBuffer->ReqBuffer.RequestType == NdisRequestSetInformation)
  722. ? TRACE_OID_SET_REQUEST_COMPLETE: TRACE_OID_QUERY_REQUEST_COMPLETE,
  723. PsReqBuffer->LocalRequest ? 1:0,
  724. Adapter->PTDeviceState,
  725. Adapter->MPDeviceState,
  726. Adapter,
  727. Oid,
  728. OriStatus);
  729. break;
  730. default:
  731. PsDbgOid(DBG_TRACE,
  732. DBG_PROTOCOL,
  733. (PsReqBuffer->ReqBuffer.RequestType == NdisRequestSetInformation)
  734. ? TRACE_OID_SET_REQUEST_COMPLETE: TRACE_OID_QUERY_REQUEST_COMPLETE,
  735. PsReqBuffer->LocalRequest ? 1:0,
  736. Adapter->PTDeviceState,
  737. Adapter->MPDeviceState,
  738. Adapter,
  739. Oid,
  740. OriStatus);
  741. break;
  742. }
  743. #endif
  744. //
  745. // if the caller specified a local completion function, then call it now.
  746. // this function is responsible for completing the original request
  747. //
  748. if(PsReqBuffer->LocalCompletionFunc){
  749. (*PsReqBuffer->LocalCompletionFunc)(Adapter, Status);
  750. PsFreePool(PsReqBuffer->BytesReadOrWritten);
  751. PsFreePool(PsReqBuffer->BytesNeeded);
  752. }
  753. else{
  754. //
  755. // if this was a PS originated request and no local completion
  756. // function was specified, then set the event to indicate that
  757. // the request completed. Note that the event can only be used
  758. // at lowered IRQL.
  759. //
  760. if(PsReqBuffer->LocalRequest)
  761. {
  762. Adapter->FinalStatus = Status;
  763. NdisSetEvent( &Adapter->LocalRequestEvent);
  764. PsFreePool(PsReqBuffer->BytesReadOrWritten);
  765. PsFreePool(PsReqBuffer->BytesNeeded);
  766. }
  767. else{
  768. Adapter->PendedNdisRequest = 0;
  769. //
  770. // if this is not a local request, call the
  771. // appropriate NDIS completion routine
  772. //
  773. if(NdisRequest->RequestType == NdisRequestSetInformation)
  774. {
  775. NdisMSetInformationComplete(Adapter->PsNdisHandle, Status);
  776. }
  777. else
  778. {
  779. NdisMQueryInformationComplete(Adapter->PsNdisHandle, Status);
  780. }
  781. }
  782. }
  783. InterlockedDecrement(&Adapter->OutstandingNdisRequests);
  784. //
  785. // give back our ndis request buffer
  786. //
  787. PsFreeToLL(PsReqBuffer, &NdisRequestLL, NdisRequest);
  788. } // ClRequestComplete
  789. NDIS_STATUS
  790. MakeLocalNdisRequest(
  791. PADAPTER Adapter,
  792. NDIS_HANDLE VcHandle,
  793. NDIS_REQUEST_TYPE RequestType,
  794. NDIS_OID Oid,
  795. PVOID Buffer,
  796. ULONG BufferSize,
  797. LOCAL_NDISREQUEST_COMPLETION_FUNCTION CompletionFunc OPTIONAL
  798. )
  799. /*++
  800. Routine Description:
  801. Make an NdisRequest to the underlying adapter on behalf of the packet scheduler
  802. Arguments:
  803. Adapter and Oid should be obvious
  804. Buffer, BufferSize - pointer to and size of location that receives the info
  805. CompletionFunc - if non-null, then don't wait on the adapter's event. Used when we're
  806. running at dispatch level
  807. Return Value:
  808. Standard NDIS_STATUS from an NdisRequest
  809. --*/
  810. {
  811. NDIS_STATUS Status;
  812. PULONG BytesRead, BytesNeeded;
  813. PsAssert(RequestType == NdisRequestLocalQueryInfo || RequestType == NdisRequestLocalSetInfo);
  814. //
  815. // Need to allocate space for BytesWritten & BytesNeeded because
  816. // we wait only for requests that do not have a Completion Function
  817. // Hence the Completion function could be writing to a stale stack
  818. // variable
  819. //
  820. PsAllocatePool(BytesNeeded, sizeof(ULONG), PsMiscTag);
  821. if(!BytesNeeded)
  822. {
  823. return NDIS_STATUS_RESOURCES;
  824. }
  825. PsAllocatePool(BytesRead, sizeof(ULONG), PsMiscTag);
  826. if(!BytesRead)
  827. {
  828. PsFreePool(BytesNeeded);
  829. return NDIS_STATUS_RESOURCES;
  830. }
  831. Status = MakeNdisRequest(Adapter,
  832. VcHandle,
  833. RequestType,
  834. Oid,
  835. Buffer,
  836. BufferSize,
  837. BytesRead,
  838. BytesNeeded,
  839. CompletionFunc);
  840. //
  841. // only wait if no completion function has been specified
  842. //
  843. if ( !ARGUMENT_PRESENT( CompletionFunc ) &&
  844. Status == NDIS_STATUS_PENDING ) {
  845. NdisWaitEvent( &Adapter->LocalRequestEvent, 0 );
  846. NdisResetEvent( &Adapter->LocalRequestEvent );
  847. Status = Adapter->FinalStatus;
  848. }
  849. return Status;
  850. } // MakeLocalNdisRequest
  851. NDIS_STATUS
  852. MpQueryInformation(
  853. IN NDIS_HANDLE MiniportAdapterContext,
  854. IN NDIS_OID Oid,
  855. IN PVOID InformationBuffer,
  856. IN ULONG InformationBufferLength,
  857. OUT PULONG BytesWritten,
  858. OUT PULONG BytesNeeded
  859. )
  860. {
  861. PADAPTER Adapter = (PADAPTER) MiniportAdapterContext;
  862. PVOID Data = InformationBuffer;
  863. ULONG Len = InformationBufferLength;
  864. PsStructAssert(Adapter);
  865. PsAssert(Adapter->PsMpState != AdapterStateWaiting);
  866. #if DBG
  867. switch(Oid)
  868. {
  869. case OID_GEN_MEDIA_CONNECT_STATUS:
  870. PsDbgOid(DBG_TRACE,
  871. DBG_ROUTINEOIDS,
  872. TRACE_OID_MP_QUERYINFORMATION,
  873. 0,
  874. Adapter->PTDeviceState,
  875. Adapter->MPDeviceState,
  876. Adapter,
  877. Oid,
  878. 0);
  879. break;
  880. default:
  881. PsDbgOid(DBG_TRACE,
  882. DBG_MINIPORT,
  883. TRACE_OID_MP_QUERYINFORMATION,
  884. 0,
  885. Adapter->PTDeviceState,
  886. Adapter->MPDeviceState,
  887. Adapter,
  888. Oid,
  889. 0);
  890. break;
  891. }
  892. #endif
  893. if(Oid == OID_PNP_QUERY_POWER)
  894. {
  895. return NDIS_STATUS_SUCCESS;
  896. }
  897. if (Oid == OID_GEN_SUPPORTED_GUIDS)
  898. {
  899. //
  900. // Do not forward this OID, otherwise we will end up with multiple
  901. // WMI instances of private GUIDs that the underlying miniport
  902. // supports.
  903. //
  904. return NDIS_STATUS_NOT_SUPPORTED;
  905. }
  906. if(Adapter->StandingBy == TRUE ||
  907. Adapter->PsMpState != AdapterStateRunning ||
  908. Adapter->MPDeviceState != NdisDeviceStateD0)
  909. {
  910. return NDIS_STATUS_FAILURE;
  911. }
  912. switch(Oid)
  913. {
  914. case OID_GEN_CO_DRIVER_VERSION:
  915. //
  916. // The NDIS version in use by the NIC driver. The high byte is
  917. // the major version number and the low byte is the minor
  918. // version number. We don't need to pass this down -
  919. // Irrespective of what version the driver below uses, we
  920. // need to return the version that we support.
  921. //
  922. if(Len < sizeof(USHORT))
  923. {
  924. *BytesNeeded = sizeof(USHORT);
  925. return NDIS_STATUS_BUFFER_TOO_SHORT;
  926. }
  927. else
  928. {
  929. PUSHORT pData = (PUSHORT) Data;
  930. *pData = 0x0500;
  931. *BytesWritten = sizeof(USHORT);
  932. return NDIS_STATUS_SUCCESS;
  933. }
  934. break;
  935. /*
  936. case OID_GEN_MAC_OPTIONS:
  937. //
  938. // This is to indicate to NDIS that PSched always indicates recv-up in the same context
  939. // of its recv-from or at DPC
  940. //
  941. if(Len < sizeof(ULONG))
  942. {
  943. *BytesNeeded = sizeof(ULONG);
  944. return NDIS_STATUS_BUFFER_TOO_SHORT;
  945. }
  946. else
  947. {
  948. PULONG pData = (PULONG) Data;
  949. *pData |= NDIS_MAC_OPTION_RECEIVE_AT_DPC;
  950. *BytesWritten = sizeof(ULONG);
  951. return NDIS_STATUS_SUCCESS;
  952. }
  953. break;
  954. case OID_GEN_PROTOCOL_OPTIONS:
  955. //
  956. // This is to indicate to NDIS that PSched always sends-down packets in the same context as the
  957. // send-from-above came from or at IRQL = DPC
  958. //
  959. if(Len < sizeof(ULONG))
  960. {
  961. *BytesNeeded = sizeof(ULONG);
  962. return NDIS_STATUS_BUFFER_TOO_SHORT;
  963. }
  964. else
  965. {
  966. PULONG pData = (PULONG) Data;
  967. *pData |= NDIS_PROT_OPTION_SEND_RESTRICTED;
  968. *BytesWritten = sizeof(ULONG);
  969. return NDIS_STATUS_SUCCESS;
  970. }
  971. break;
  972. */
  973. }
  974. //
  975. // By default, send other requests down.
  976. //
  977. return MakeNdisRequest(Adapter,
  978. NULL,
  979. NdisRequestQueryInformation,
  980. Oid,
  981. Data,
  982. Len,
  983. BytesWritten,
  984. BytesNeeded,
  985. NULL);
  986. }
  987. NDIS_STATUS
  988. MpSetInformation(
  989. IN NDIS_HANDLE MiniportAdapterContext,
  990. IN NDIS_OID Oid,
  991. IN PVOID InformationBuffer,
  992. IN ULONG InformationBufferLength,
  993. OUT PULONG BytesRead,
  994. OUT PULONG BytesNeeded
  995. )
  996. {
  997. PADAPTER Adapter = (PADAPTER) MiniportAdapterContext;
  998. NDIS_STATUS Status;
  999. PsStructAssert(Adapter);
  1000. PsAssert(Adapter->PsMpState != AdapterStateWaiting);
  1001. #if DBG
  1002. switch(Oid)
  1003. {
  1004. case OID_GEN_MEDIA_CONNECT_STATUS:
  1005. PsDbgOid(DBG_TRACE,
  1006. DBG_ROUTINEOIDS,
  1007. TRACE_OID_MP_SETINFORMATION,
  1008. 0,
  1009. Adapter->PTDeviceState,
  1010. Adapter->MPDeviceState,
  1011. Adapter,
  1012. Oid,
  1013. 0);
  1014. break;
  1015. default:
  1016. PsDbgOid(DBG_TRACE,
  1017. DBG_MINIPORT,
  1018. TRACE_OID_MP_SETINFORMATION,
  1019. 0,
  1020. Adapter->PTDeviceState,
  1021. Adapter->MPDeviceState,
  1022. Adapter,
  1023. Oid,
  1024. 0);
  1025. break;
  1026. }
  1027. #endif
  1028. switch(Oid)
  1029. {
  1030. case OID_PNP_SET_POWER:
  1031. //
  1032. // This is not transparent to us - We cannot send it down.
  1033. // Just succeed it!
  1034. //
  1035. if(InformationBufferLength >= sizeof(NDIS_DEVICE_POWER_STATE))
  1036. {
  1037. NDIS_DEVICE_POWER_STATE NewDeviceState =
  1038. (*(PNDIS_DEVICE_POWER_STATE) InformationBuffer);
  1039. //
  1040. // If the miniport is transitioning from a low power state to ON (D0), then clear the StandingBy flag
  1041. // All incoming requests will be pended until the physical miniport turns ON.
  1042. //
  1043. if(Adapter->MPDeviceState > NdisDeviceStateD0 && NewDeviceState == NdisDeviceStateD0)
  1044. {
  1045. Adapter->StandingBy = FALSE;
  1046. }
  1047. //
  1048. // Is the miniport transitioning from an On (D0) state to an Low Power State (>D0)
  1049. // If so, then set the StandingBy Flag - (Block all incoming requests)
  1050. //
  1051. if(Adapter->MPDeviceState == NdisDeviceStateD0 && NewDeviceState > NdisDeviceStateD0)
  1052. {
  1053. Adapter->StandingBy = TRUE;
  1054. }
  1055. // update the new device state.
  1056. Adapter->MPDeviceState = NewDeviceState;
  1057. Status = NDIS_STATUS_SUCCESS;
  1058. *BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
  1059. *BytesNeeded = 0;
  1060. if(IsDeviceStateOn(Adapter) == TRUE)
  1061. {
  1062. PsGetLinkSpeed(Adapter);
  1063. }
  1064. }
  1065. else
  1066. {
  1067. Status = NDIS_STATUS_INVALID_LENGTH;
  1068. *BytesRead = 0;
  1069. *BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
  1070. }
  1071. return Status;
  1072. }
  1073. if(Adapter->StandingBy == TRUE ||
  1074. Adapter->PsMpState != AdapterStateRunning ||
  1075. Adapter->MPDeviceState != NdisDeviceStateD0)
  1076. {
  1077. return NDIS_STATUS_FAILURE;
  1078. }
  1079. Status = MakeNdisRequest(Adapter,
  1080. NULL,
  1081. NdisRequestSetInformation,
  1082. Oid,
  1083. InformationBuffer,
  1084. InformationBufferLength,
  1085. BytesRead,
  1086. BytesNeeded,
  1087. NULL);
  1088. return Status;
  1089. }
  1090. NDIS_STATUS
  1091. CollectNetworkAddresses(
  1092. IN PADAPTER Adapter,
  1093. IN OUT ULONG *Len,
  1094. IN PVOID Data
  1095. )
  1096. {
  1097. ULONG RequiredBufferSize = 0;
  1098. ULONG RequiredIpBufferSize;
  1099. ULONG RequiredIpxBufferSize;
  1100. NETWORK_ADDRESS_LIST UNALIGNED *NetworkAddressList;
  1101. PTC_SUPPORTED_INFO_BUFFER TcQueryBuffer;
  1102. PADDRESS_LIST_DESCRIPTOR AddressDescriptorList;
  1103. PUCHAR AddressListIndex;
  1104. NDIS_STATUS Status;
  1105. NDIS_STRING Prefix = NDIS_STRING_CONST("\\Device\\");
  1106. //
  1107. // Ip address list
  1108. //
  1109. PS_LOCK(&Adapter->Lock);
  1110. if(Adapter->IpNetAddressList){
  1111. RequiredIpBufferSize = GetSizeAddrList(Adapter->IpNetAddressList);
  1112. //
  1113. // Returned buffer size actually includes extra bytes for
  1114. // address count and type. But - when we merge the lists,
  1115. // we'll replace the separate fields. So - subtract them out.
  1116. //
  1117. RequiredIpBufferSize -= FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);
  1118. }
  1119. else{
  1120. RequiredIpBufferSize = 0;
  1121. }
  1122. RequiredBufferSize += RequiredIpBufferSize;
  1123. //
  1124. // Add space for the Ipx address list
  1125. //
  1126. if(Adapter->IpxNetAddressList){
  1127. RequiredIpxBufferSize = GetSizeAddrList(Adapter->IpxNetAddressList);
  1128. //
  1129. // Returned buffer size actually includes extra bytes for
  1130. // address count and type. But - when we merge the lists,
  1131. // we'll replace the separate fields. So - subtract them out.
  1132. //
  1133. RequiredIpxBufferSize -= FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);
  1134. }
  1135. else{
  1136. RequiredIpxBufferSize = 0;
  1137. }
  1138. RequiredBufferSize += RequiredIpxBufferSize;
  1139. //
  1140. // Add space for the address list fields
  1141. //
  1142. RequiredBufferSize += FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);
  1143. //
  1144. // Add space for TC_SUPPORTED_INFO_BUFFER
  1145. //
  1146. RequiredBufferSize = RequiredBufferSize +
  1147. FIELD_OFFSET(TC_SUPPORTED_INFO_BUFFER, AddrListDesc) +
  1148. FIELD_OFFSET(ADDRESS_LIST_DESCRIPTOR, AddressList);
  1149. if(*Len > 0){
  1150. NdisZeroMemory(Data, *Len);
  1151. }
  1152. if(*Len >= RequiredBufferSize){
  1153. TcQueryBuffer = (PTC_SUPPORTED_INFO_BUFFER) Data;
  1154. //
  1155. // Fill in the upper binding, after striping the device
  1156. //
  1157. NdisMoveMemory(TcQueryBuffer->InstanceID,
  1158. (PUCHAR) Adapter->MpDeviceName.Buffer +
  1159. Prefix.Length,
  1160. Adapter->MpDeviceName.Length - Prefix.Length);
  1161. TcQueryBuffer->InstanceIDLength = Adapter->MpDeviceName.Length - Prefix.Length;
  1162. //
  1163. // Fill in the AddressListDescriptor
  1164. //
  1165. AddressDescriptorList = &TcQueryBuffer->AddrListDesc;
  1166. AddressDescriptorList->MediaType = Adapter->MediaType;
  1167. NetworkAddressList = (NETWORK_ADDRESS_LIST UNALIGNED *)
  1168. &AddressDescriptorList->AddressList;
  1169. AddressListIndex = (PUCHAR)&NetworkAddressList->Address;
  1170. if(RequiredIpBufferSize){
  1171. NdisMoveMemory(
  1172. AddressListIndex,
  1173. (PUCHAR)(&Adapter->IpNetAddressList->Address),
  1174. RequiredIpBufferSize
  1175. );
  1176. }
  1177. AddressListIndex += RequiredIpBufferSize;
  1178. if(RequiredIpxBufferSize){
  1179. NdisMoveMemory(
  1180. AddressListIndex,
  1181. (PUCHAR)(&Adapter->IpxNetAddressList->Address),
  1182. RequiredIpxBufferSize
  1183. );
  1184. }
  1185. AddressListIndex += RequiredIpxBufferSize;
  1186. if(RequiredIpBufferSize){
  1187. NetworkAddressList->AddressCount =
  1188. Adapter->IpNetAddressList->AddressCount;
  1189. }
  1190. if(RequiredIpxBufferSize){
  1191. NetworkAddressList->AddressCount +=
  1192. Adapter->IpxNetAddressList->AddressCount;
  1193. }
  1194. NetworkAddressList->AddressType = 0;
  1195. *Len = RequiredBufferSize;
  1196. Status = NDIS_STATUS_SUCCESS;
  1197. }
  1198. else{
  1199. *Len = RequiredBufferSize;
  1200. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  1201. }
  1202. PS_UNLOCK(&Adapter->Lock);
  1203. return(Status);
  1204. }
  1205. NDIS_STATUS
  1206. CollectWanNetworkAddresses(
  1207. IN PADAPTER Adapter,
  1208. IN PPS_WAN_LINK WanLink,
  1209. IN OUT ULONG *Len,
  1210. IN PVOID Data
  1211. )
  1212. {
  1213. ULONG RequiredBufferSize = 0;
  1214. NETWORK_ADDRESS_LIST UNALIGNED *NetworkAddressList;
  1215. NETWORK_ADDRESS UNALIGNED *NetworkAddress;
  1216. PTC_SUPPORTED_INFO_BUFFER TcQueryBuffer;
  1217. PADDRESS_LIST_DESCRIPTOR AddressDescriptorList;
  1218. NETWORK_ADDRESS_IP UNALIGNED *pIp;
  1219. NDIS_STATUS Status;
  1220. NDIS_STRING Prefix = NDIS_STRING_CONST("\\Device\\");
  1221. PsAssert(Adapter->MediaType == NdisMediumWan);
  1222. //
  1223. // Ip address list
  1224. //
  1225. switch(WanLink->ProtocolType)
  1226. {
  1227. case PROTOCOL_IP:
  1228. if(WanLink->DialUsage == DU_CALLOUT) {
  1229. RequiredBufferSize = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +
  1230. (FIELD_OFFSET(NETWORK_ADDRESS, Address) + NETWORK_ADDRESS_LENGTH_IP);
  1231. }
  1232. else {
  1233. //
  1234. // Include room for a pair of addresses (one local, one remote). Only for Dial in
  1235. // or router-router links.
  1236. //
  1237. RequiredBufferSize = FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +
  1238. 2 * (FIELD_OFFSET(NETWORK_ADDRESS, Address) +
  1239. NETWORK_ADDRESS_LENGTH_IP);
  1240. }
  1241. break;
  1242. case PROTOCOL_IPX:
  1243. //
  1244. // Not yet supported.
  1245. //
  1246. default:
  1247. RequiredBufferSize = 0;
  1248. }
  1249. //
  1250. // Add space for TC_SUPPORTED_INFO_BUFFER
  1251. //
  1252. RequiredBufferSize = RequiredBufferSize +
  1253. FIELD_OFFSET(TC_SUPPORTED_INFO_BUFFER, AddrListDesc) +
  1254. FIELD_OFFSET(ADDRESS_LIST_DESCRIPTOR, AddressList);
  1255. if(*Len >= RequiredBufferSize)
  1256. {
  1257. TcQueryBuffer = (PTC_SUPPORTED_INFO_BUFFER) Data;
  1258. //
  1259. // Fill in the device name
  1260. //
  1261. if(WanLink->MpDeviceName.Length > Prefix.Length)
  1262. {
  1263. NdisMoveMemory(TcQueryBuffer->InstanceID,
  1264. (PUCHAR) WanLink->MpDeviceName.Buffer + Prefix.Length,
  1265. WanLink->MpDeviceName.MaximumLength - Prefix.Length);
  1266. TcQueryBuffer->InstanceIDLength = WanLink->MpDeviceName.Length - Prefix.Length;
  1267. }
  1268. else
  1269. {
  1270. //
  1271. // We have got a MpDevice name that is less than \Device. What is the point in
  1272. // stripping the \Device from this ??
  1273. //
  1274. PsDbgOut(DBG_FAILURE,
  1275. DBG_WAN,
  1276. ("[CollectWanNetworkAddresses]: WanLink %08X, MpDeviceName is too small to strip \\Device \n",
  1277. WanLink));
  1278. NdisMoveMemory(TcQueryBuffer->InstanceID,
  1279. WanLink->MpDeviceName.Buffer,
  1280. WanLink->MpDeviceName.MaximumLength);
  1281. TcQueryBuffer->InstanceIDLength = WanLink->MpDeviceName.Length;
  1282. }
  1283. //
  1284. // Fill in the AddressListDescriptor
  1285. //
  1286. AddressDescriptorList = &TcQueryBuffer->AddrListDesc;
  1287. AddressDescriptorList->MediaType = NdisMediumWan;
  1288. NetworkAddressList = (NETWORK_ADDRESS_LIST UNALIGNED *)
  1289. &AddressDescriptorList->AddressList;
  1290. NetworkAddress = (NETWORK_ADDRESS UNALIGNED *)&NetworkAddressList->Address;
  1291. switch(WanLink->ProtocolType){
  1292. case PROTOCOL_IP:
  1293. NetworkAddressList->AddressType = NDIS_PROTOCOL_ID_TCP_IP;
  1294. //
  1295. // Fill in the local address
  1296. //
  1297. NetworkAddressList->AddressCount = 1;
  1298. NetworkAddress->AddressType = NDIS_PROTOCOL_ID_TCP_IP;
  1299. NetworkAddress->AddressLength = NETWORK_ADDRESS_LENGTH_IP;
  1300. pIp = (NETWORK_ADDRESS_IP UNALIGNED *)NetworkAddress->Address;
  1301. pIp->in_addr = WanLink->LocalIpAddress;
  1302. //
  1303. // Fill in the remote address only for non callout
  1304. //
  1305. if(WanLink->DialUsage != DU_CALLOUT) {
  1306. NetworkAddressList->AddressCount ++;
  1307. NetworkAddress = (NETWORK_ADDRESS UNALIGNED *)
  1308. ((PCHAR)NetworkAddress +
  1309. (FIELD_OFFSET(NETWORK_ADDRESS,Address)+ NETWORK_ADDRESS_LENGTH_IP));
  1310. NetworkAddress->AddressLength = NETWORK_ADDRESS_LENGTH_IP;
  1311. NetworkAddress->AddressType = NDIS_PROTOCOL_ID_TCP_IP;
  1312. pIp = (NETWORK_ADDRESS_IP UNALIGNED *)NetworkAddress->Address;
  1313. pIp->in_addr = WanLink->RemoteIpAddress;
  1314. }
  1315. break;
  1316. case PROTOCOL_IPX:
  1317. default:
  1318. //
  1319. // Not supported, return zero addresses.
  1320. //
  1321. NetworkAddressList->AddressCount = 0;
  1322. }
  1323. *Len = RequiredBufferSize;
  1324. Status = NDIS_STATUS_SUCCESS;
  1325. }
  1326. else{
  1327. *Len = RequiredBufferSize;
  1328. Status = NDIS_STATUS_BUFFER_TOO_SHORT;
  1329. }
  1330. return(Status);
  1331. }
  1332. NDIS_STATUS
  1333. RecordNetworkAddressList(
  1334. IN PADAPTER Adapter,
  1335. IN PPS_NDIS_REQUEST PsReqBuffer
  1336. )
  1337. {
  1338. NETWORK_ADDRESS_LIST UNALIGNED *AddressList, **pListDestination;
  1339. ULONG NewListSize;
  1340. ULONG OldListSize;
  1341. PS_LOCK(&Adapter->Lock);
  1342. AddressList = (NETWORK_ADDRESS_LIST UNALIGNED *)(PsReqBuffer->ReqBuffer.
  1343. DATA.SET_INFORMATION.InformationBuffer);
  1344. //
  1345. // Handle special case of a zero count address list. This means
  1346. // that the protocol is clearing the address list.
  1347. //
  1348. if(!AddressList->AddressCount){
  1349. //
  1350. // In this case, we use the top level AddressType to
  1351. // indicate the protocol.
  1352. //
  1353. switch(AddressList->AddressType){
  1354. case NDIS_PROTOCOL_ID_TCP_IP:
  1355. pListDestination = &Adapter->IpNetAddressList;
  1356. break;
  1357. case NDIS_PROTOCOL_ID_IPX:
  1358. pListDestination = &Adapter->IpxNetAddressList;
  1359. break;
  1360. default:
  1361. //
  1362. // Only maintain IP and IPX addresses for now
  1363. //
  1364. PS_UNLOCK(&Adapter->Lock);
  1365. return NDIS_STATUS_NOT_SUPPORTED;
  1366. }
  1367. (*pListDestination)->AddressType = AddressList->AddressType;
  1368. (*pListDestination)->AddressCount = 0;
  1369. PS_UNLOCK(&Adapter->Lock);
  1370. return(NDIS_STATUS_SUCCESS);
  1371. }
  1372. //
  1373. // We can tell from the first address type ifdentifier, whether
  1374. // this buffer carries addresses from the IP transport or the
  1375. // IPX transport.
  1376. //
  1377. switch(AddressList->Address[0].AddressType){
  1378. case NDIS_PROTOCOL_ID_TCP_IP:
  1379. pListDestination = &Adapter->IpNetAddressList;
  1380. break;
  1381. case NDIS_PROTOCOL_ID_IPX:
  1382. pListDestination = &Adapter->IpxNetAddressList;
  1383. break;
  1384. default:
  1385. //
  1386. // Only maintain IP and IPX addresses for now
  1387. //
  1388. PS_UNLOCK(&Adapter->Lock);
  1389. return NDIS_STATUS_NOT_SUPPORTED;
  1390. }
  1391. NewListSize = GetSizeAddrList(AddressList);
  1392. OldListSize = GetSizeAddrList(*pListDestination);
  1393. if(NewListSize > OldListSize){
  1394. //
  1395. // Then we need a new buffer. Free the old one.
  1396. //
  1397. PsFreePool(*pListDestination);
  1398. PsAllocatePool(*pListDestination,
  1399. NewListSize,
  1400. PsMiscTag);
  1401. if(0 == *pListDestination)
  1402. {
  1403. PsDbgOut(DBG_CRITICAL_ERROR,
  1404. DBG_PROTOCOL,
  1405. ("[RecordNetworkAddressList]: Adapter %08X, "
  1406. "No room for Network addresses list, failed to allocate %d bytes \n",
  1407. Adapter, NewListSize));
  1408. PS_UNLOCK(&Adapter->Lock);
  1409. PsAdapterWriteEventLog(
  1410. (ULONG)EVENT_PS_NETWORK_ADDRESS_FAIL,
  1411. 0,
  1412. &Adapter->MpDeviceName,
  1413. 0,
  1414. NULL);
  1415. return NDIS_STATUS_RESOURCES;
  1416. }
  1417. }
  1418. NdisMoveMemory(*pListDestination,
  1419. AddressList,
  1420. NewListSize);
  1421. PS_UNLOCK(&Adapter->Lock);
  1422. return NDIS_STATUS_SUCCESS;
  1423. }
  1424. ULONG
  1425. GetSizeAddrList(
  1426. IN NETWORK_ADDRESS_LIST UNALIGNED *AddrList
  1427. )
  1428. {
  1429. NETWORK_ADDRESS UNALIGNED *NextAddress;
  1430. LONG i;
  1431. ULONG ListSize = 0;
  1432. ULONG ElementSize = 0;
  1433. if(!AddrList->AddressCount){
  1434. return(FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address));
  1435. }
  1436. NextAddress = &(AddrList->Address[0]);
  1437. for(i = 0;i < AddrList->AddressCount; i++){
  1438. //
  1439. // Each address element is the number of bytes
  1440. // indicated by AddressLength plus the size of
  1441. // a NETWORK_ADDRESS structure, minus the one
  1442. // byte used for the adress array (see struct).
  1443. //
  1444. ElementSize = FIELD_OFFSET(NETWORK_ADDRESS, Address);
  1445. ElementSize += NextAddress->AddressLength;
  1446. ListSize += ElementSize;
  1447. NextAddress = (NETWORK_ADDRESS UNALIGNED *)
  1448. ((PUCHAR)NextAddress + ElementSize);
  1449. ElementSize = 0;
  1450. }
  1451. //
  1452. // Add the AddressCount size
  1453. //
  1454. ListSize += FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address);
  1455. return(ListSize);
  1456. }
  1457. VOID
  1458. TcIndicateInterfaceChange(
  1459. IN PADAPTER Adapter,
  1460. IN PPS_WAN_LINK WanLink,
  1461. IN NDIS_STATUS Status
  1462. )
  1463. {
  1464. ULONG AddrLen = 0;
  1465. ULONG DataLen;
  1466. PTC_INDICATION_BUFFER Data;
  1467. PsAssert((Status == NDIS_STATUS_INTERFACE_UP) || (Status == NDIS_STATUS_INTERFACE_DOWN) ||
  1468. (Status == NDIS_STATUS_INTERFACE_CHANGE));
  1469. if(Adapter->MediaType == NdisMediumWan)
  1470. {
  1471. if(WanLink) {
  1472. CollectWanNetworkAddresses(Adapter, WanLink, &AddrLen, NULL);
  1473. DataLen = AddrLen + FIELD_OFFSET(TC_INDICATION_BUFFER, InfoBuffer);
  1474. PsAllocatePool(Data, DataLen, PsMiscTag);
  1475. if(Data){
  1476. Data->SubCode = 0;
  1477. CollectWanNetworkAddresses(Adapter, WanLink, &AddrLen, &Data->InfoBuffer);
  1478. PsTcNotify(Adapter, WanLink, Status, Data, DataLen);
  1479. PsFreePool(Data);
  1480. }
  1481. }
  1482. }
  1483. else {
  1484. CollectNetworkAddresses(Adapter, &AddrLen, NULL);
  1485. DataLen = AddrLen + FIELD_OFFSET(TC_INDICATION_BUFFER, InfoBuffer);
  1486. PsAllocatePool(Data, DataLen, PsMiscTag);
  1487. if(Data){
  1488. Data->SubCode = 0;
  1489. CollectNetworkAddresses(Adapter, &AddrLen, &Data->InfoBuffer);
  1490. PsTcNotify(Adapter, 0, Status, Data, DataLen);
  1491. PsFreePool(Data);
  1492. }
  1493. }
  1494. return;
  1495. }
  1496. VOID
  1497. MpQueryPnPCapabilities(
  1498. IN OUT PPS_NDIS_REQUEST PsReqBuffer,
  1499. IN OUT PADAPTER pAdapt,
  1500. OUT PNDIS_STATUS pStatus
  1501. )
  1502. /*++
  1503. Routine Description:
  1504. Miniport QueryInfo OID_PNP_CAPAIBILITIES:
  1505. If the Oid == Oid_PNP_CAPABILITIES, InformationBuffer is returned with all the fields
  1506. assigned NdisDeviceStateUnspecified in the NDIS_PM_WAKE_UP_CAPABILITIES structure
  1507. OID_QUERY_POWER_STATE is returned with NDIS_STATUS_SUCCESS and should never be passed below.
  1508. Arguments:
  1509. MiniportAdapterContext Pointer to the adapter structure
  1510. Oid Oid for this query
  1511. InformationBuffer Buffer for information
  1512. InformationBufferLength Size of this buffer
  1513. BytesWritten Specifies how much info is written
  1514. BytesNeeded In case the buffer is smaller than what we need, tell them how much is needed
  1515. Return Value:
  1516. Return code from the NdisRequest below.
  1517. --*/
  1518. {
  1519. PNDIS_PNP_CAPABILITIES pPNPCapabilities;
  1520. PNDIS_PM_WAKE_UP_CAPABILITIES pPMstruct;
  1521. if (PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.InformationBufferLength
  1522. >= sizeof(NDIS_PNP_CAPABILITIES) )
  1523. {
  1524. pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)
  1525. (PsReqBuffer->ReqBuffer.DATA.QUERY_INFORMATION.InformationBuffer );
  1526. //
  1527. // Setting up the buffer to be returned to the Protocol above the SampleIM
  1528. //
  1529. pPMstruct= &pPNPCapabilities->WakeUpCapabilities;
  1530. pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
  1531. pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;
  1532. pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;
  1533. *PsReqBuffer->BytesReadOrWritten = sizeof(NDIS_PNP_CAPABILITIES );
  1534. *PsReqBuffer->BytesNeeded = 0;
  1535. //
  1536. // Setting our internal flags
  1537. // Default, device is ON
  1538. //
  1539. pAdapt->PTDeviceState = NdisDeviceStateD0;
  1540. pAdapt->MPDeviceState = NdisDeviceStateD0;
  1541. *pStatus = NDIS_STATUS_SUCCESS;
  1542. //
  1543. // We could have received some status indications when we were in DeviceState > D0.
  1544. // Now is the time to look at them again.
  1545. //
  1546. PsGetLinkSpeed(pAdapt);
  1547. }
  1548. else
  1549. {
  1550. *PsReqBuffer->BytesNeeded = sizeof(NDIS_PNP_CAPABILITIES);
  1551. *pStatus = NDIS_STATUS_RESOURCES;
  1552. }
  1553. }
  1554. #if DBG
  1555. VOID
  1556. IndicateLogThreshold(
  1557. IN PVOID Context
  1558. )
  1559. {
  1560. PADAPTER Adapter = (PADAPTER)Context;
  1561. ULONG BytesUnread = SchedtGetBytesUnread();
  1562. NdisMCoIndicateStatus(Adapter->PsNdisHandle,
  1563. NULL,
  1564. QOS_STATUS_LOG_THRESHOLD,
  1565. &BytesUnread,
  1566. sizeof(ULONG));
  1567. }
  1568. #endif
  1569. /* end ndisreq.c */