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.

2224 lines
47 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. arpwmi.c
  5. Abstract:
  6. WMI Support for ATMARP Client. One Device Object is created for each
  7. IP Interface, and a bunch of GUIDs are supported on each. The static
  8. instance name for each interface is derived from the friendly name
  9. of the adapter below.
  10. Revision History:
  11. Who When What
  12. -------- -------- ----------------------------------------------
  13. arvindm 12-16-97 Created
  14. Notes:
  15. --*/
  16. #undef BINARY_COMPATIBLE
  17. #define BINARY_COMPATIBLE 0
  18. #include <precomp.h>
  19. #define _FILENUMBER 'IMWA'
  20. #define NEWQOS 1
  21. #ifdef ATMARP_WMI
  22. //
  23. // Private macros
  24. //
  25. #define AA_WMI_BUFFER_TOO_SMALL(_BufferSize, _Wnode, _WnodeSize, _pStatus) \
  26. { \
  27. if ((_BufferSize) < sizeof(WNODE_TOO_SMALL)) \
  28. { \
  29. *(_pStatus) = STATUS_BUFFER_TOO_SMALL; \
  30. } \
  31. else \
  32. { \
  33. (_Wnode)->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL); \
  34. (_Wnode)->WnodeHeader.Flags |= WNODE_FLAG_TOO_SMALL; \
  35. ((PWNODE_TOO_SMALL)(_Wnode))->SizeNeeded = (_WnodeSize); \
  36. \
  37. *(_pStatus) = STATUS_SUCCESS; \
  38. } \
  39. }
  40. //
  41. // Provider Id in WMI structures
  42. //
  43. typedef ULONG_PTR PROV_ID_TYPE;
  44. PATMARP_WMI_GUID
  45. AtmArpWmiFindGuid(
  46. IN PATMARP_INTERFACE pInterface,
  47. IN LPGUID pGuid,
  48. OUT PULONG pGuidDataSize
  49. )
  50. /*++
  51. Routine Description:
  52. Locate and return a pointer to the GUID info structure
  53. for the specified GUID. The caller is assumed to have
  54. locked the IF structure. Also return the data size for
  55. the GUID instance.
  56. Arguments:
  57. pInterface - Pointer to our Interface structure
  58. pGuid - Pointer to GUID being searched for
  59. pGuidDataSize - Place to return data size for GUID instance
  60. Return Value:
  61. Pointer to GUID info structure if found, else NULL.
  62. --*/
  63. {
  64. PATMARP_IF_WMI_INFO pIfWmiInfo;
  65. PATMARP_WMI_GUID pArpGuid;
  66. ULONG i;
  67. UCHAR OutputBuffer[1];
  68. ULONG BytesReturned;
  69. NTSTATUS NtStatus;
  70. do
  71. {
  72. pIfWmiInfo = pInterface->pIfWmiInfo;
  73. AA_ASSERT(pIfWmiInfo != NULL);
  74. for (i = 0, pArpGuid = &pIfWmiInfo->GuidInfo[0];
  75. i < pIfWmiInfo->GuidCount;
  76. i++, pArpGuid++)
  77. {
  78. if (AA_MEM_CMP(&pArpGuid->Guid, pGuid, sizeof(GUID)) == 0)
  79. {
  80. break;
  81. }
  82. }
  83. if (i == pIfWmiInfo->GuidCount)
  84. {
  85. pArpGuid = NULL;
  86. break;
  87. }
  88. //
  89. // Found the GUID. Do a dummy query of its value to get
  90. // the value size.
  91. //
  92. if (pArpGuid->QueryHandler == NULL)
  93. {
  94. //
  95. // No query handler!
  96. //
  97. AA_ASSERT(!"No query handler!");
  98. pArpGuid = NULL;
  99. break;
  100. }
  101. NtStatus = (*pArpGuid->QueryHandler)(
  102. pInterface,
  103. pArpGuid->MyId,
  104. &OutputBuffer,
  105. 0, // output BufferLength
  106. &BytesReturned,
  107. pGuidDataSize
  108. );
  109. AA_ASSERT(NtStatus == STATUS_INSUFFICIENT_RESOURCES);
  110. break;
  111. }
  112. while (FALSE);
  113. return (pArpGuid);
  114. }
  115. NTSTATUS
  116. AtmArpWmiRegister(
  117. IN PATMARP_INTERFACE pInterface,
  118. IN ULONG RegistrationType,
  119. IN PWMIREGINFO pWmiRegInfo,
  120. IN ULONG WmiRegInfoSize,
  121. OUT PULONG pReturnSize
  122. )
  123. /*++
  124. Routine Description:
  125. This is called to process an IRP_MN_REGINFO. If the registration type
  126. is WMIREGISTER, we return a list of GUIDs supported on this interface.
  127. Arguments:
  128. pInterface - Pointer to our Interface structure
  129. RegistrationType- WMIREGISTER or WMIUPDATE. We only handle WMIREGISTER.
  130. pWmiRegInfo - Points to structure to be filled in with info about
  131. supported GUIDs on this interface.
  132. WmiRegInfoSize - Length of the above
  133. pReturnSize - What we filled up.
  134. Return Value:
  135. STATUS_SUCCESS if successful, STATUS_XXX error code otherwise.
  136. --*/
  137. {
  138. NTSTATUS Status;
  139. ULONG BytesNeeded;
  140. PATMARP_IF_WMI_INFO pIfWmiInfo;
  141. PATMARP_WMI_GUID pArpWmiGuid;
  142. PWMIREGGUID pWmiRegGuid;
  143. ULONG InstanceOffset;
  144. PUCHAR pDst;
  145. ULONG c;
  146. Status = STATUS_SUCCESS;
  147. do
  148. {
  149. if (RegistrationType != WMIREGISTER)
  150. {
  151. Status = STATUS_INVALID_PARAMETER;
  152. break;
  153. }
  154. pIfWmiInfo = pInterface->pIfWmiInfo;
  155. if ((pIfWmiInfo == NULL) ||
  156. (pIfWmiInfo->GuidCount == 0))
  157. {
  158. //
  159. // No GUIDs on this Interface.
  160. //
  161. Status = STATUS_UNSUCCESSFUL;
  162. break;
  163. }
  164. BytesNeeded = sizeof(WMIREGINFO)
  165. +
  166. //
  167. // One WMIREGGUID structure for each supported GUID.
  168. //
  169. (pIfWmiInfo->GuidCount * sizeof(WMIREGGUID))
  170. +
  171. //
  172. // Counted unicode string containing the instance name
  173. // for all GUIDs on this interface. Looks like:
  174. // <USHORT Length> <String of WCHAR>
  175. //
  176. (sizeof(USHORT) + pIfWmiInfo->InstanceName.Length)
  177. #ifdef PATHS_REQD
  178. +
  179. //
  180. // Counted unicode string containing the driver registry
  181. // path. Looks like: <USHORT Length> <String of WCHAR>
  182. //
  183. (sizeof(USHORT) + sizeof(ATMARP_REGISTRY_PATH) - sizeof(WCHAR))
  184. +
  185. //
  186. // Counted unicode string containing the MOF resource
  187. // name: <USHORT length> <String of WCHAR>
  188. //
  189. (sizeof(USHORT) + sizeof(ATMARP_MOF_RESOURCE_NAME) - sizeof(WCHAR))
  190. #endif // PATHS_REQD
  191. ;
  192. if (WmiRegInfoSize < BytesNeeded)
  193. {
  194. //
  195. // Insufficient space for GUID info.
  196. //
  197. *((ULONG UNALIGNED *)pWmiRegInfo) = BytesNeeded;
  198. *pReturnSize = sizeof(ULONG);
  199. Status = STATUS_SUCCESS;
  200. AADEBUGP(AAD_INFO, ("WmiRegister: Bytes needed %d, Reginfo size %d\n",
  201. BytesNeeded, WmiRegInfoSize));
  202. break;
  203. }
  204. //
  205. // Done with all validations.
  206. //
  207. *pReturnSize = BytesNeeded;
  208. AA_SET_MEM(pWmiRegInfo, 0, BytesNeeded);
  209. pWmiRegInfo->BufferSize = BytesNeeded;
  210. pWmiRegInfo->NextWmiRegInfo = 0;
  211. pWmiRegInfo->GuidCount = pIfWmiInfo->GuidCount;
  212. //
  213. // Calculate the offset at which we place the instance name.
  214. //
  215. InstanceOffset = sizeof(WMIREGINFO) + (pIfWmiInfo->GuidCount * sizeof(WMIREGGUID));
  216. //
  217. // Fill in the GUID list. All GUIDs for this interface refer to
  218. // the same Instance name.
  219. //
  220. pWmiRegGuid = &pWmiRegInfo->WmiRegGuid[0];
  221. pArpWmiGuid = &pIfWmiInfo->GuidInfo[0];
  222. for (c = 0;
  223. c < pIfWmiInfo->GuidCount;
  224. c++, pWmiRegGuid++, pArpWmiGuid++)
  225. {
  226. AA_COPY_MEM(&pWmiRegGuid->Guid, &pArpWmiGuid->Guid, sizeof(GUID));
  227. pWmiRegGuid->Flags = WMIREG_FLAG_INSTANCE_LIST;
  228. pWmiRegGuid->InstanceCount = 1;
  229. pWmiRegGuid->InstanceInfo = InstanceOffset;
  230. }
  231. //
  232. // Fill in the instance name.
  233. //
  234. pDst = (PUCHAR)pWmiRegGuid;
  235. *((USHORT UNALIGNED *)pDst) = pIfWmiInfo->InstanceName.Length;
  236. pDst += sizeof(USHORT);
  237. AA_COPY_MEM(pDst,
  238. pIfWmiInfo->InstanceName.Buffer,
  239. pIfWmiInfo->InstanceName.Length);
  240. pDst += pIfWmiInfo->InstanceName.Length;
  241. #ifdef PATHS_REQD
  242. //
  243. // Fill in the Driver registry path.
  244. //
  245. pWmiRegInfo->RegistryPath = (ULONG)(pDst - (PUCHAR)pWmiRegInfo);
  246. *((USHORT UNALIGNED *)pDst) = sizeof(ATMARP_REGISTRY_PATH) - sizeof(WCHAR);
  247. pDst += sizeof(USHORT);
  248. AA_COPY_MEM(pDst,
  249. (PUCHAR)ATMARP_REGISTRY_PATH,
  250. sizeof(ATMARP_REGISTRY_PATH) - sizeof(WCHAR));
  251. pDst += sizeof(ATMARP_REGISTRY_PATH) - sizeof(WCHAR);
  252. //
  253. // Fill in the MOF resource name.
  254. //
  255. pWmiRegInfo->MofResourceName = (ULONG)(pDst - (PUCHAR)pWmiRegInfo);
  256. *((USHORT UNALIGNED *)pDst) = sizeof(ATMARP_MOF_RESOURCE_NAME) - sizeof(WCHAR);
  257. pDst += sizeof(USHORT);
  258. AA_COPY_MEM(pDst,
  259. (PUCHAR)ATMARP_MOF_RESOURCE_NAME,
  260. sizeof(ATMARP_MOF_RESOURCE_NAME) - sizeof(WCHAR));
  261. #endif // PATHS_REQD
  262. break;
  263. }
  264. while (FALSE);
  265. AADEBUGP(AAD_INFO,
  266. ("WmiRegister: IF x%x, pWmiRegInfo x%x, Size %d, Ret size %d, status x%x\n",
  267. pInterface, pWmiRegInfo, WmiRegInfoSize, *pReturnSize, Status));
  268. return (Status);
  269. }
  270. NTSTATUS
  271. AtmArpWmiQueryAllData(
  272. IN PATMARP_INTERFACE pInterface,
  273. IN LPGUID pGuid,
  274. IN PWNODE_ALL_DATA pWnode,
  275. IN ULONG BufferSize,
  276. OUT PULONG pReturnSize
  277. )
  278. /*++
  279. Routine Description:
  280. This is called to process an IRP_MN_QUERY_ALL_DATA, which is used
  281. to query all instances of a GUID on this interface.
  282. For now, we only have single instances of any GUID on an interface.
  283. Arguments:
  284. pInterface - Pointer to our Interface structure
  285. pGuid - GUID of data block being queried.
  286. pWnode - The structure to be filled up.
  287. BufferSize - Total space for the WNODE_ALL_DATA, beginning at pWnode.
  288. pReturnSize - What we filled up.
  289. Return Value:
  290. STATUS_SUCCESS if we know this GUID and successfully filled up the
  291. WNODE_ALL_DATA, STATUS_XXX error code otherwise.
  292. --*/
  293. {
  294. NTSTATUS Status;
  295. ULONG BytesNeeded;
  296. ULONG WnodeSize;
  297. PATMARP_IF_WMI_INFO pIfWmiInfo;
  298. PATMARP_WMI_GUID pArpGuid;
  299. ULONG GuidDataSize;
  300. ULONG GuidDataBytesReturned;
  301. ULONG GuidDataBytesNeeded;
  302. PUCHAR pDst;
  303. BOOLEAN bIfLockAcquired = FALSE;
  304. do
  305. {
  306. pIfWmiInfo = pInterface->pIfWmiInfo;
  307. if ((pIfWmiInfo == NULL) ||
  308. (pIfWmiInfo->GuidCount == 0))
  309. {
  310. //
  311. // No GUIDs on this Interface.
  312. //
  313. Status = STATUS_UNSUCCESSFUL;
  314. break;
  315. }
  316. //
  317. // Locate the GUID.
  318. //
  319. bIfLockAcquired = TRUE;
  320. AA_ACQUIRE_IF_WMI_LOCK(pInterface);
  321. pArpGuid = AtmArpWmiFindGuid(pInterface, pGuid, &GuidDataSize);
  322. if (pArpGuid == NULL)
  323. {
  324. Status = STATUS_WMI_GUID_NOT_FOUND;
  325. break;
  326. }
  327. WnodeSize = ROUND_TO_8_BYTES(sizeof(WNODE_ALL_DATA));
  328. //
  329. // Compute the total size of the reply WNODE_ALL_DATA. Since
  330. // we only have a single instance of each GUID on an interface,
  331. // we use the "Fixed Instance Size" format.
  332. //
  333. BytesNeeded = WnodeSize +
  334. //
  335. // The data itself
  336. //
  337. GuidDataSize +
  338. //
  339. // A ULONG to store the instance name offset
  340. //
  341. sizeof(ULONG) +
  342. //
  343. // A USHORT to store the length of the instance name
  344. // (Counted Unicode string)
  345. //
  346. sizeof(USHORT) +
  347. //
  348. // The instance name
  349. //
  350. pIfWmiInfo->InstanceName.Length;
  351. //
  352. // Is there sufficient space in the buffer handed down to us?
  353. //
  354. if (BufferSize < BytesNeeded)
  355. {
  356. AA_WMI_BUFFER_TOO_SMALL(BufferSize, pWnode, WnodeSize, &Status);
  357. break;
  358. }
  359. //
  360. // Initialize the WNODE_ALL_DATA.
  361. //
  362. pWnode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(pIfWmiInfo->pDeviceObject);
  363. pWnode->WnodeHeader.Version = ATMARP_WMI_VERSION;
  364. NdisGetCurrentSystemTime(&pWnode->WnodeHeader.TimeStamp);
  365. pWnode->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE;
  366. pWnode->WnodeHeader.BufferSize = BytesNeeded;
  367. pWnode->InstanceCount = 1;
  368. //
  369. // The data follows the WNODE_ALL_DATA.
  370. //
  371. pWnode->DataBlockOffset = WnodeSize;
  372. //
  373. // The instance name ensemble follows the data.
  374. //
  375. pWnode->OffsetInstanceNameOffsets = WnodeSize + GuidDataSize;
  376. pWnode->FixedInstanceSize = GuidDataSize;
  377. //
  378. // Get the data.
  379. //
  380. Status = (*pArpGuid->QueryHandler)(
  381. pInterface,
  382. pArpGuid->MyId,
  383. (PVOID)((PUCHAR)pWnode + pWnode->DataBlockOffset),
  384. GuidDataSize,
  385. &GuidDataBytesReturned,
  386. &GuidDataBytesNeeded);
  387. if (!NT_SUCCESS(Status))
  388. {
  389. break;
  390. }
  391. //
  392. // Jump to the location where we must fill in the instance name
  393. // ensemble, which consists of:
  394. //
  395. // ULONG Offset from start of WNODE to counted Unicode string
  396. // representing Instance name (below).
  397. // USHORT Number of WCHARs in instance name.
  398. // WCHAR[] Array of WCHARs making up the instance name.
  399. //
  400. pDst = (PUCHAR)((PUCHAR)pWnode + pWnode->OffsetInstanceNameOffsets);
  401. //
  402. // Fill in the offset to the instance name at this spot, and move on.
  403. //
  404. *(ULONG UNALIGNED *)pDst = pWnode->OffsetInstanceNameOffsets + sizeof(ULONG);
  405. pDst += sizeof(ULONG);
  406. //
  407. // Fill in the instance name as a counted Unicode string.
  408. //
  409. *(PUSHORT)pDst = (USHORT)pIfWmiInfo->InstanceName.Length;
  410. pDst += sizeof(USHORT);
  411. AA_COPY_MEM(pDst,
  412. pIfWmiInfo->InstanceName.Buffer,
  413. pIfWmiInfo->InstanceName.Length);
  414. AA_ASSERT(NT_SUCCESS(Status));
  415. break;
  416. }
  417. while (FALSE);
  418. if (bIfLockAcquired)
  419. {
  420. AA_RELEASE_IF_WMI_LOCK(pInterface);
  421. }
  422. if (NT_SUCCESS(Status))
  423. {
  424. *pReturnSize = pWnode->WnodeHeader.BufferSize;
  425. }
  426. AADEBUGP(AAD_INFO,
  427. ("WmiQueryAllData: IF x%x, pWnode x%x, Size %d, Ret size %d, status x%x\n",
  428. pInterface, pWnode, BufferSize, *pReturnSize, Status));
  429. return (Status);
  430. }
  431. NTSTATUS
  432. AtmArpWmiQuerySingleInstance(
  433. IN PATMARP_INTERFACE pInterface,
  434. IN PWNODE_SINGLE_INSTANCE pWnode,
  435. IN ULONG BufferSize,
  436. OUT PULONG pReturnSize
  437. )
  438. /*++
  439. Routine Description:
  440. This is called to process an IRP_MN_QUERY_SINGLE_INSTANCE, which is used
  441. to query a single instance of a GUID on this interface.
  442. Arguments:
  443. pInterface - Pointer to our Interface structure
  444. pWnode - The structure to be filled up.
  445. BufferSize - Total space for the WNODE_SINGLE_INSTANCE, beginning at pWnode.
  446. pReturnSize - What we filled up.
  447. Return Value:
  448. STATUS_SUCCESS if we know this GUID and successfully filled up the
  449. WNODE_SINGLE_INSTANCE, STATUS_XXX error code otherwise.
  450. --*/
  451. {
  452. NTSTATUS Status;
  453. ULONG BytesNeeded;
  454. ULONG WnodeSize;
  455. LPGUID pGuid;
  456. PATMARP_IF_WMI_INFO pIfWmiInfo;
  457. PATMARP_WMI_GUID pArpGuid;
  458. PUCHAR pDst;
  459. ULONG GuidDataSize;
  460. ULONG GuidDataBytesNeeded;
  461. BOOLEAN bIfLockAcquired = FALSE;
  462. do
  463. {
  464. AA_ASSERT((pWnode->WnodeHeader.Flags & WNODE_FLAG_STATIC_INSTANCE_NAMES) != 0);
  465. {
  466. NDIS_STRING InstanceName;
  467. InstanceName.Length = *(PUSHORT)((PUCHAR)pWnode
  468. + pWnode-> OffsetInstanceName);
  469. InstanceName.Buffer = (PWSTR)((PUCHAR)pWnode + pWnode->OffsetInstanceName
  470. + sizeof(USHORT));
  471. AADEBUGP(AAD_INFO,
  472. ("QuerySingleInstance: InstanceName=%Z\n", &InstanceName));
  473. }
  474. pIfWmiInfo = pInterface->pIfWmiInfo;
  475. if ((pIfWmiInfo == NULL) ||
  476. (pIfWmiInfo->GuidCount == 0))
  477. {
  478. //
  479. // No GUIDs on this Interface.
  480. //
  481. Status = STATUS_UNSUCCESSFUL;
  482. break;
  483. }
  484. //
  485. // Locate the GUID.
  486. //
  487. pGuid = &pWnode->WnodeHeader.Guid;
  488. bIfLockAcquired = TRUE;
  489. AA_ACQUIRE_IF_WMI_LOCK(pInterface);
  490. pArpGuid = AtmArpWmiFindGuid(pInterface, pGuid, &GuidDataSize);
  491. if (pArpGuid == NULL)
  492. {
  493. Status = STATUS_WMI_GUID_NOT_FOUND;
  494. break;
  495. }
  496. WnodeSize = ROUND_TO_8_BYTES(sizeof(WNODE_SINGLE_INSTANCE));
  497. //
  498. // Compute the total size of the reply WNODE_SINGLE_INSTANCE.
  499. //
  500. BytesNeeded = pWnode->DataBlockOffset + GuidDataSize;
  501. if (BufferSize < BytesNeeded)
  502. {
  503. AA_WMI_BUFFER_TOO_SMALL(BufferSize, pWnode, WnodeSize, &Status);
  504. break;
  505. }
  506. //
  507. // Fill in the WNODE_SINGLE_INSTANCE.
  508. //
  509. pWnode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(pIfWmiInfo->pDeviceObject);
  510. pWnode->WnodeHeader.Version = ATMARP_WMI_VERSION;
  511. NdisGetCurrentSystemTime(&pWnode->WnodeHeader.TimeStamp);
  512. pWnode->WnodeHeader.BufferSize = BytesNeeded;
  513. pWnode->SizeDataBlock = GuidDataSize;
  514. //
  515. // Get the GUID Data.
  516. //
  517. Status = (*pArpGuid->QueryHandler)(
  518. pInterface,
  519. pArpGuid->MyId,
  520. (PUCHAR)pWnode + pWnode->DataBlockOffset, // start of output buf
  521. BufferSize - pWnode->DataBlockOffset, // total length available
  522. &pWnode->SizeDataBlock, // bytes written
  523. &GuidDataBytesNeeded
  524. );
  525. if (!NT_SUCCESS(Status))
  526. {
  527. break;
  528. }
  529. *pReturnSize = BytesNeeded;
  530. Status = STATUS_SUCCESS;
  531. break;
  532. }
  533. while (FALSE);
  534. if (bIfLockAcquired)
  535. {
  536. AA_RELEASE_IF_WMI_LOCK(pInterface);
  537. }
  538. AADEBUGP(AAD_INFO,
  539. ("WmiQuerySingleInst: IF x%x, pWnode x%x, Size %d, Ret size %d, status x%x\n",
  540. pInterface, pWnode, BufferSize, *pReturnSize, Status));
  541. return (Status);
  542. }
  543. NTSTATUS
  544. AtmArpWmiChangeSingleInstance(
  545. IN PATMARP_INTERFACE pInterface,
  546. IN PWNODE_SINGLE_INSTANCE pWnode,
  547. IN ULONG BufferSize,
  548. OUT PULONG pReturnSize
  549. )
  550. /*++
  551. Routine Description:
  552. This is called to process an IRP_MN_CHANGE_SINGLE_INSTANCE, which is used
  553. to change the value of a single instance of a GUID on this interface.
  554. Arguments:
  555. pInterface - Pointer to our Interface structure
  556. pWnode - The structure containing the new value for the GUID instance.
  557. BufferSize - Total space for the WNODE_SINGLE_INSTANCE, beginning at pWnode.
  558. pReturnSize - Not used.
  559. Return Value:
  560. STATUS_SUCCESS if we know this GUID and successfully changed its value,
  561. STATUS_XXX error code otherwise.
  562. --*/
  563. {
  564. NTSTATUS Status;
  565. ULONG BytesNeeded;
  566. ULONG WnodeSize;
  567. LPGUID pGuid;
  568. PATMARP_IF_WMI_INFO pIfWmiInfo;
  569. PATMARP_WMI_GUID pArpGuid;
  570. PUCHAR pGuidData;
  571. ULONG GuidDataSize;
  572. ULONG GuidDataBytesWritten;
  573. ULONG GuidDataBytesNeeded;
  574. BOOLEAN bIfLockAcquired = FALSE;
  575. do
  576. {
  577. AA_ASSERT((pWnode->WnodeHeader.Flags & WNODE_FLAG_STATIC_INSTANCE_NAMES) != 0);
  578. pIfWmiInfo = pInterface->pIfWmiInfo;
  579. if ((pIfWmiInfo == NULL) ||
  580. (pIfWmiInfo->GuidCount == 0))
  581. {
  582. //
  583. // No GUIDs on this Interface.
  584. //
  585. Status = STATUS_UNSUCCESSFUL;
  586. break;
  587. }
  588. //
  589. // Locate the GUID.
  590. //
  591. pGuid = &pWnode->WnodeHeader.Guid;
  592. bIfLockAcquired = TRUE;
  593. AA_ACQUIRE_IF_WMI_LOCK(pInterface);
  594. pArpGuid = AtmArpWmiFindGuid(pInterface, pGuid, &GuidDataSize);
  595. if (pArpGuid == NULL)
  596. {
  597. Status = STATUS_WMI_GUID_NOT_FOUND;
  598. break;
  599. }
  600. //
  601. // Check if the GUID can be set.
  602. //
  603. if (pArpGuid->SetHandler == NULL)
  604. {
  605. Status = STATUS_NOT_SUPPORTED;
  606. break;
  607. }
  608. //
  609. // Get the start and size of the data block.
  610. //
  611. pGuidData = (PUCHAR)pWnode + pWnode->DataBlockOffset;
  612. GuidDataSize = pWnode->SizeDataBlock;
  613. if (GuidDataSize == 0)
  614. {
  615. Status = STATUS_INVALID_PARAMETER;
  616. break;
  617. }
  618. //
  619. // Try to set the value of the GUID instance.
  620. //
  621. Status = (*pArpGuid->SetHandler)(
  622. pInterface,
  623. pArpGuid->MyId,
  624. pGuidData,
  625. GuidDataSize,
  626. &GuidDataBytesWritten,
  627. &GuidDataBytesNeeded
  628. );
  629. break;
  630. }
  631. while (FALSE);
  632. if (bIfLockAcquired)
  633. {
  634. AA_RELEASE_IF_WMI_LOCK(pInterface);
  635. }
  636. return (Status);
  637. }
  638. NTSTATUS
  639. AtmArpWmiChangeSingleItem(
  640. IN PATMARP_INTERFACE pInterface,
  641. IN PWNODE_SINGLE_ITEM pWnode,
  642. IN ULONG BufferSize,
  643. OUT PULONG pReturnSize
  644. )
  645. /*++
  646. Routine Description:
  647. This is called to change a single item within the data block for a GUID
  648. instance (e.g. field in a struct). We don't need this for now.
  649. Arguments:
  650. Return Value:
  651. STATUS_NOT_SUPPORTED
  652. --*/
  653. {
  654. return (STATUS_NOT_SUPPORTED);
  655. }
  656. NTSTATUS
  657. AtmArpWmiSetEventStatus(
  658. IN PATMARP_INTERFACE pInterface,
  659. IN LPGUID pGuid,
  660. IN BOOLEAN bEnabled
  661. )
  662. /*++
  663. Routine Description:
  664. This is called to enable/disable event generation on the specified GUID.
  665. Arguments:
  666. pInterface - Pointer to our Interface structure
  667. pGuid - affected GUID
  668. bEnabled - TRUE iff events are to be enabled.
  669. Return Value:
  670. STATUS_SUCCESS if we successfully enabled/disabled event generation,
  671. STATUS_XXX error code otherwise.
  672. --*/
  673. {
  674. NTSTATUS Status;
  675. PATMARP_IF_WMI_INFO pIfWmiInfo;
  676. PATMARP_WMI_GUID pArpGuid;
  677. ULONG GuidDataSize;
  678. BOOLEAN bIfLockAcquired = FALSE;
  679. do
  680. {
  681. pIfWmiInfo = pInterface->pIfWmiInfo;
  682. if ((pIfWmiInfo == NULL) ||
  683. (pIfWmiInfo->GuidCount == 0))
  684. {
  685. //
  686. // No GUIDs on this Interface.
  687. //
  688. Status = STATUS_UNSUCCESSFUL;
  689. break;
  690. }
  691. bIfLockAcquired = TRUE;
  692. AA_ACQUIRE_IF_WMI_LOCK(pInterface);
  693. pArpGuid = AtmArpWmiFindGuid(pInterface, pGuid, &GuidDataSize);
  694. if (pArpGuid == NULL)
  695. {
  696. Status = STATUS_WMI_GUID_NOT_FOUND;
  697. break;
  698. }
  699. AADEBUGP(AAD_INFO, ("WmiSetEventStatus: IF x%x, pArpGuid x%x, MyId %d, enable: %d\n",
  700. pInterface, pArpGuid, pArpGuid->MyId, bEnabled));
  701. //
  702. // Check if we generate events on this GUID.
  703. //
  704. if (pArpGuid->EnableEventHandler == NULL)
  705. {
  706. Status = STATUS_NOT_SUPPORTED;
  707. break;
  708. }
  709. //
  710. // Go ahead and enable events.
  711. //
  712. if (bEnabled)
  713. {
  714. AA_SET_FLAG(pArpGuid->Flags, AWGF_EVENT_MASK, AWGF_EVENT_ENABLED);
  715. }
  716. else
  717. {
  718. AA_SET_FLAG(pArpGuid->Flags, AWGF_EVENT_MASK, AWGF_EVENT_DISABLED);
  719. }
  720. (*pArpGuid->EnableEventHandler)(
  721. pInterface,
  722. pArpGuid->MyId,
  723. bEnabled
  724. );
  725. Status = STATUS_SUCCESS;
  726. break;
  727. }
  728. while (FALSE);
  729. if (bIfLockAcquired)
  730. {
  731. AA_RELEASE_IF_WMI_LOCK(pInterface);
  732. }
  733. return (Status);
  734. }
  735. NTSTATUS
  736. AtmArpWmiDispatch(
  737. IN PDEVICE_OBJECT pDeviceObject,
  738. IN PIRP pIrp
  739. )
  740. /*++
  741. Routine Description:
  742. System dispatch function for handling IRP_MJ_SYSTEM_CONTROL IRPs from WMI.
  743. Arguments:
  744. pDeviceObject - Pointer to device object. The device extension field
  745. contains a pointer to the Interface
  746. pIrp - Pointer to IRP.
  747. Return Value:
  748. NT status code.
  749. --*/
  750. {
  751. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  752. PVOID DataPath = pIrpSp->Parameters.WMI.DataPath;
  753. ULONG BufferSize = pIrpSp->Parameters.WMI.BufferSize;
  754. PVOID pBuffer = pIrpSp->Parameters.WMI.Buffer;
  755. NTSTATUS Status;
  756. ULONG ReturnSize;
  757. PATMARP_INTERFACE pInterface;
  758. pInterface = AA_PDO_TO_INTERFACE(pDeviceObject);
  759. AA_STRUCT_ASSERT(pInterface, aai);
  760. ReturnSize = 0;
  761. switch (pIrpSp->MinorFunction)
  762. {
  763. case IRP_MN_REGINFO:
  764. Status = AtmArpWmiRegister(
  765. pInterface,
  766. PtrToUlong(DataPath),
  767. pBuffer,
  768. BufferSize,
  769. &ReturnSize
  770. );
  771. break;
  772. case IRP_MN_QUERY_ALL_DATA:
  773. Status = AtmArpWmiQueryAllData(
  774. pInterface,
  775. (LPGUID)DataPath,
  776. (PWNODE_ALL_DATA)pBuffer,
  777. BufferSize,
  778. &ReturnSize
  779. );
  780. break;
  781. case IRP_MN_QUERY_SINGLE_INSTANCE:
  782. Status = AtmArpWmiQuerySingleInstance(
  783. pInterface,
  784. pBuffer,
  785. BufferSize,
  786. &ReturnSize
  787. );
  788. break;
  789. case IRP_MN_CHANGE_SINGLE_INSTANCE:
  790. Status = AtmArpWmiChangeSingleInstance(
  791. pInterface,
  792. pBuffer,
  793. BufferSize,
  794. &ReturnSize
  795. );
  796. break;
  797. case IRP_MN_CHANGE_SINGLE_ITEM:
  798. Status = AtmArpWmiChangeSingleItem(
  799. pInterface,
  800. pBuffer,
  801. BufferSize,
  802. &ReturnSize
  803. );
  804. break;
  805. case IRP_MN_ENABLE_EVENTS:
  806. Status = AtmArpWmiSetEventStatus(
  807. pInterface,
  808. (LPGUID)DataPath,
  809. TRUE // Enable
  810. );
  811. break;
  812. case IRP_MN_DISABLE_EVENTS:
  813. Status = AtmArpWmiSetEventStatus(
  814. pInterface,
  815. (LPGUID)DataPath,
  816. FALSE // Disable
  817. );
  818. break;
  819. case IRP_MN_ENABLE_COLLECTION:
  820. case IRP_MN_DISABLE_COLLECTION:
  821. default:
  822. Status = STATUS_INVALID_DEVICE_REQUEST;
  823. break;
  824. }
  825. pIrp->IoStatus.Status = Status;
  826. pIrp->IoStatus.Information = (NT_SUCCESS(Status) ? ReturnSize: 0);
  827. AADEBUGP(AAD_INFO,
  828. ("WmiDispatch done: IF x%x, MinorFn %d, Status x%x, ReturnInfo %d\n",
  829. pInterface, pIrpSp->MinorFunction, Status, pIrp->IoStatus.Information));
  830. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  831. return (Status);
  832. }
  833. VOID
  834. AtmArpWmiInitInterface(
  835. IN PATMARP_INTERFACE pInterface,
  836. IN PATMARP_WMI_GUID GuidList,
  837. IN ULONG NumberOfGuids
  838. )
  839. /*++
  840. Routine Description:
  841. Set up the given IP Interface as a WMI provider.
  842. Arguments:
  843. pInterface - Pointer to our Interface structure
  844. GuidList - List of GUIDs
  845. NumberOfGuids - Size of above list
  846. Return Value:
  847. None. If the interface is successfully set up, we reference it.
  848. --*/
  849. {
  850. PATMARP_IF_WMI_INFO pIfWmiInfo;
  851. NDIS_STRING DeviceName;
  852. NDIS_STRING AdapterName;
  853. NDIS_STRING HyphenString = NDIS_STRING_CONST(" - ");
  854. #define MAX_IF_NUMBER_STRING_LEN 6 // 5 Digits plus terminator
  855. NDIS_STRING IfNumberString;
  856. ULONG TotalIfWmiLength;
  857. USHORT NameLength;
  858. NDIS_STATUS Status;
  859. NTSTATUS NtStatus;
  860. AA_ASSERT(NumberOfGuids > 0);
  861. AA_ASSERT(GuidList != NULL);
  862. //
  863. // Initialize.
  864. //
  865. AdapterName.Buffer = NULL;
  866. IfNumberString.Buffer = NULL;
  867. pIfWmiInfo = NULL;
  868. Status = NDIS_STATUS_SUCCESS;
  869. do
  870. {
  871. AA_INIT_IF_WMI_LOCK(pInterface);
  872. //
  873. // Query the friendly name for the adapter beneath
  874. // this Interface.
  875. //
  876. Status = NdisQueryAdapterInstanceName(
  877. &AdapterName,
  878. pInterface->NdisAdapterHandle
  879. );
  880. if (Status != NDIS_STATUS_SUCCESS)
  881. {
  882. AdapterName.Buffer = NULL;
  883. break;
  884. }
  885. AADEBUGP(AAD_INFO,
  886. ("WmiInitIF: IF x%x, Adapter Name: <%Z>\n", pInterface, &AdapterName));
  887. //
  888. // Prepare an instance name for all GUIDs on this Interface.
  889. //
  890. // This is constructed by appending a string of the form "- <Num>"
  891. // to the adapter's friendly name. <Num> is the value of the SEL
  892. // byte used to identify this interface.
  893. //
  894. //
  895. // Allocate space for the IF Number string - 5 digits should
  896. // be more than enough.
  897. //
  898. AA_ASSERT(pInterface->SapSelector <= 99999);
  899. AA_ALLOC_MEM(IfNumberString.Buffer, WCHAR, MAX_IF_NUMBER_STRING_LEN * sizeof(WCHAR));
  900. if (IfNumberString.Buffer == NULL)
  901. {
  902. Status = NDIS_STATUS_RESOURCES;
  903. break;
  904. }
  905. IfNumberString.MaximumLength = MAX_IF_NUMBER_STRING_LEN;
  906. IfNumberString.Length = 0;
  907. //
  908. // Prepare the IF Number string.
  909. //
  910. Status = RtlIntegerToUnicodeString(
  911. pInterface->SapSelector,
  912. 10, // Decimal
  913. &IfNumberString
  914. );
  915. AA_ASSERT(NT_SUCCESS(Status));
  916. //
  917. // Compute the total length of the Interface instance name.
  918. //
  919. NameLength = AdapterName.Length + HyphenString.Length + IfNumberString.Length + sizeof(WCHAR);
  920. //
  921. // Allocate space for WMI Info for this interface. We allocate one
  922. // chunk of memory for all the following:
  923. //
  924. // 1. IF WMI Info structure
  925. // 2. IF Instance name string
  926. // 3. GUID list
  927. //
  928. TotalIfWmiLength = sizeof(ATMARP_IF_WMI_INFO) +
  929. //
  930. // IF Instance name:
  931. //
  932. NameLength +
  933. //
  934. // GUID list (-1 because ATMARP_IF_WMI_INFO
  935. // has space for one of these).
  936. //
  937. ((NumberOfGuids - 1) * sizeof(ATMARP_WMI_GUID));
  938. AA_ALLOC_MEM(pIfWmiInfo, ATMARP_IF_WMI_INFO, TotalIfWmiLength);
  939. if (pIfWmiInfo == NULL)
  940. {
  941. Status = NDIS_STATUS_RESOURCES;
  942. break;
  943. }
  944. AA_SET_MEM(pIfWmiInfo, 0, TotalIfWmiLength);
  945. pIfWmiInfo->GuidCount = NumberOfGuids;
  946. AA_COPY_MEM(&pIfWmiInfo->GuidInfo[0],
  947. GuidList,
  948. NumberOfGuids * sizeof(ATMARP_WMI_GUID));
  949. pIfWmiInfo->InstanceName.Buffer = (PWCHAR)
  950. ((PUCHAR)pIfWmiInfo +
  951. FIELD_OFFSET(ATMARP_IF_WMI_INFO, GuidInfo) +
  952. (NumberOfGuids * sizeof(ATMARP_WMI_GUID)));
  953. pIfWmiInfo->InstanceName.MaximumLength = NameLength;
  954. //
  955. // Concatenate the three parts of the IF Instance name.
  956. //
  957. RtlCopyUnicodeString(&pIfWmiInfo->InstanceName, &AdapterName);
  958. NtStatus = RtlAppendUnicodeStringToString(&pIfWmiInfo->InstanceName, &HyphenString);
  959. AA_ASSERT(NT_SUCCESS(NtStatus));
  960. NtStatus = RtlAppendUnicodeStringToString(&pIfWmiInfo->InstanceName, &IfNumberString);
  961. AA_ASSERT(NT_SUCCESS(NtStatus));
  962. AADEBUGP(AAD_INFO,
  963. ("WmiInitIF: IF x%x, InstanceName: <%Z>\n", pInterface, &pIfWmiInfo->InstanceName));
  964. //
  965. // Create a device object for this interface. A pointer's worth
  966. // of space is required in the device extension.
  967. //
  968. #define ATMARP_DEVICE_NAME1 L"\\Device\\ATMARPC1"
  969. NdisInitUnicodeString(&DeviceName, ATMARP_DEVICE_NAME1);
  970. NtStatus = IoCreateDevice(
  971. pAtmArpGlobalInfo->pDriverObject,
  972. sizeof(PATMARP_INTERFACE),
  973. NULL, // &DeviceName
  974. FILE_DEVICE_NETWORK,
  975. 0, // Device Characteristics
  976. FALSE, // Exclusive?
  977. &pIfWmiInfo->pDeviceObject
  978. );
  979. if (!NT_SUCCESS(NtStatus))
  980. {
  981. AADEBUGP(AAD_INFO,
  982. ("WmiInitIF: IoCreateDevice (%Z) failed: x%x\n", &DeviceName, NtStatus));
  983. Status = NDIS_STATUS_FAILURE;
  984. break;
  985. }
  986. //
  987. // Set up the device extension.
  988. //
  989. *((PATMARP_INTERFACE *)pIfWmiInfo->pDeviceObject->DeviceExtension) = pInterface;
  990. //
  991. // Prepare to register with WMI.
  992. //
  993. pInterface->pIfWmiInfo = pIfWmiInfo;
  994. NtStatus = IoWMIRegistrationControl(
  995. pIfWmiInfo->pDeviceObject,
  996. WMIREG_ACTION_REGISTER);
  997. if (!NT_SUCCESS(NtStatus))
  998. {
  999. pInterface->pIfWmiInfo = NULL;
  1000. IoDeleteDevice(pIfWmiInfo->pDeviceObject);
  1001. Status = NDIS_STATUS_FAILURE;
  1002. break;
  1003. }
  1004. AA_ASSERT(Status == NDIS_STATUS_SUCCESS);
  1005. break;
  1006. }
  1007. while (FALSE);
  1008. //
  1009. // Clean up.
  1010. //
  1011. if (IfNumberString.Buffer != NULL)
  1012. {
  1013. AA_FREE_MEM(IfNumberString.Buffer);
  1014. }
  1015. if (AdapterName.Buffer != NULL)
  1016. {
  1017. //
  1018. // This was allocated by NDIS.
  1019. //
  1020. NdisFreeString(AdapterName);
  1021. }
  1022. if (Status != NDIS_STATUS_SUCCESS)
  1023. {
  1024. AA_ASSERT(pInterface->pIfWmiInfo == NULL);
  1025. if (pIfWmiInfo != NULL)
  1026. {
  1027. AA_FREE_MEM(pIfWmiInfo);
  1028. }
  1029. }
  1030. AADEBUGP(AAD_INFO, ("WmiInitIF: IF x%x, WMI Info x%x, Status x%x\n",
  1031. pInterface, pIfWmiInfo, Status));
  1032. return;
  1033. }
  1034. VOID
  1035. AtmArpWmiShutdownInterface(
  1036. IN PATMARP_INTERFACE pInterface
  1037. )
  1038. /*++
  1039. Routine Description:
  1040. Shuts down the given IP Interface as a WMI provider.
  1041. Arguments:
  1042. pInterface - Pointer to our Interface structure
  1043. Return Value:
  1044. None. If the interface was originally set up and we shut it down
  1045. successfully, we dereference it.
  1046. --*/
  1047. {
  1048. PATMARP_IF_WMI_INFO pIfWmiInfo;
  1049. do
  1050. {
  1051. //
  1052. // Check if we had successfully set up this interface for WMI.
  1053. //
  1054. pIfWmiInfo = pInterface->pIfWmiInfo;
  1055. if (pIfWmiInfo == NULL)
  1056. {
  1057. break;
  1058. }
  1059. pInterface->pIfWmiInfo = NULL;
  1060. //
  1061. // Deregister this device object with WMI.
  1062. //
  1063. IoWMIRegistrationControl(pIfWmiInfo->pDeviceObject, WMIREG_ACTION_DEREGISTER);
  1064. //
  1065. // Delete the device object.
  1066. //
  1067. IoDeleteDevice(pIfWmiInfo->pDeviceObject);
  1068. AA_FREE_IF_WMI_LOCK(pInterface);
  1069. break;
  1070. }
  1071. while (FALSE);
  1072. if (pIfWmiInfo)
  1073. {
  1074. AA_FREE_MEM(pIfWmiInfo);
  1075. }
  1076. return;
  1077. }
  1078. NTSTATUS
  1079. AtmArpWmiSetTCSupported(
  1080. IN PATMARP_INTERFACE pInterface,
  1081. IN ATMARP_GUID_ID MyId,
  1082. IN PVOID pInputBuffer,
  1083. IN ULONG BufferLength,
  1084. OUT PULONG pBytesWritten,
  1085. OUT PULONG pBytesNeeded
  1086. )
  1087. /*++
  1088. Routine Description:
  1089. Set function for the TC_SUPPORTED GUID.
  1090. Arguments:
  1091. pInterface - Pointer to our Interface structure
  1092. MyId - Local ID for this GUID
  1093. pInputBuffer - Points to data value
  1094. BufferLength - Length of the above
  1095. pBytesWritten - Place to return how much was written
  1096. pBytesNeeded - If insufficient data, place to return expected data size
  1097. Return Value:
  1098. STATUS_NOT_SUPPORTED. We don't allow setting the value of this GUID.
  1099. --*/
  1100. {
  1101. *pBytesWritten = 0;
  1102. return (STATUS_NOT_SUPPORTED);
  1103. }
  1104. NTSTATUS
  1105. AtmArpWmiQueryTCSupported(
  1106. IN PATMARP_INTERFACE pInterface,
  1107. IN ATMARP_GUID_ID MyId,
  1108. OUT PVOID pOutputBuffer,
  1109. IN ULONG BufferLength,
  1110. OUT PULONG pBytesReturned,
  1111. OUT PULONG pBytesNeeded
  1112. )
  1113. /*++
  1114. Routine Description:
  1115. Query function for the TC_SUPPORTED GUID. The value of this GUID is
  1116. the list of IP Addresses assigned to this interface. This is returned
  1117. using an ADDRESS_LIST_DESCRIPTOR data structure.
  1118. Arguments:
  1119. pInterface - Pointer to our Interface structure
  1120. MyId - Local ID for this GUID
  1121. pOutputBuffer - Start of Buffer to be filled up
  1122. BufferLength - Length of the above
  1123. pBytesReturned - Place to return how much was returned
  1124. pBytesNeeded - If insufficient space, place to return expected data size
  1125. Return Value:
  1126. STATUS_SUCCESS if we successfully filled in the address list,
  1127. STATUS_XXX error code otherwise.
  1128. --*/
  1129. {
  1130. NTSTATUS NtStatus;
  1131. #if NEWQOS
  1132. PTC_SUPPORTED_INFO_BUFFER
  1133. pInfo = (PTC_SUPPORTED_INFO_BUFFER)pOutputBuffer;
  1134. UINT HeaderSize = FIELD_OFFSET(
  1135. TC_SUPPORTED_INFO_BUFFER,
  1136. AddrListDesc
  1137. );
  1138. BOOLEAN CopiedHeader= FALSE;
  1139. #endif // NEWQOS
  1140. do
  1141. {
  1142. #if NEWQOS
  1143. // address list
  1144. if (BufferLength >= HeaderSize)
  1145. {
  1146. NDIS_STRING DeviceGUID;
  1147. //
  1148. // Reserve space for the portion of SUPPORTED_INFO_BUFFER before
  1149. // AddrListDesc, and fill it out
  1150. //
  1151. AA_ACQUIRE_IF_LOCK(pInterface);
  1152. pOutputBuffer = &pInfo->AddrListDesc;
  1153. BufferLength -= HeaderSize;
  1154. DeviceGUID = pInterface->pAdapter->DeviceName; // struct copy.
  1155. //
  1156. // Need to skip past the "\\DEVICE\\" part of name.
  1157. //
  1158. if (DeviceGUID.Length > sizeof(L"\\DEVICE\\"))
  1159. {
  1160. DeviceGUID.Length -= sizeof(L"\\DEVICE\\");
  1161. DeviceGUID.Buffer += sizeof(L"\\DEVICE\\")/sizeof(WCHAR);
  1162. }
  1163. if (sizeof(pInfo->InstanceID) < DeviceGUID.Length)
  1164. {
  1165. AA_ASSERT(FALSE);
  1166. NtStatus = STATUS_INVALID_PARAMETER;
  1167. AA_RELEASE_IF_LOCK(pInterface);
  1168. break;
  1169. }
  1170. pInfo->InstanceIDLength = DeviceGUID.Length;
  1171. AA_COPY_MEM(pInfo->InstanceID, DeviceGUID.Buffer, DeviceGUID.Length);
  1172. CopiedHeader = TRUE;
  1173. AA_RELEASE_IF_LOCK(pInterface);
  1174. }
  1175. else
  1176. {
  1177. BufferLength = 0;
  1178. }
  1179. #endif // NEWQOS
  1180. NtStatus = AtmArpWmiGetAddressList(
  1181. pInterface,
  1182. pOutputBuffer,
  1183. BufferLength,
  1184. pBytesReturned,
  1185. pBytesNeeded);
  1186. #if NEWQOS
  1187. *pBytesNeeded += HeaderSize;
  1188. if (CopiedHeader)
  1189. {
  1190. *pBytesReturned += HeaderSize;
  1191. }
  1192. #endif // NEWQOS
  1193. } while(FALSE);
  1194. return (NtStatus);
  1195. }
  1196. NTSTATUS
  1197. AtmArpWmiGetAddressList(
  1198. IN PATMARP_INTERFACE pInterface,
  1199. OUT PVOID pOutputBuffer,
  1200. IN ULONG BufferLength,
  1201. OUT PULONG pBytesReturned,
  1202. OUT PULONG pBytesNeeded
  1203. )
  1204. /*++
  1205. Routine Description:
  1206. Prepare an address descriptor list out of the IP Addresses assigned
  1207. to the specified interface. Use the buffer supplied for this.
  1208. Arguments:
  1209. pInterface - Pointer to our Interface structure
  1210. pOutputBuffer - Start of Buffer to be filled up
  1211. BufferLength - Length of the above
  1212. pBytesReturned - Place to return how much was returned
  1213. pBytesNeeded - If insufficient space, place to return expected data size
  1214. Return Value:
  1215. STATUS_SUCCESS if we successfully filled in the address list,
  1216. STATUS_XXX error code otherwise.
  1217. --*/
  1218. {
  1219. NTSTATUS NtStatus;
  1220. ULONG BytesNeeded;
  1221. ULONG NumberOfIPAddresses;
  1222. ADDRESS_LIST_DESCRIPTOR UNALIGNED * pAddrListDescr;
  1223. NETWORK_ADDRESS UNALIGNED * pNwAddr;
  1224. PIP_ADDRESS_ENTRY pIPAddrEntry;
  1225. NtStatus = STATUS_SUCCESS;
  1226. AA_ACQUIRE_IF_LOCK(pInterface);
  1227. do
  1228. {
  1229. *pBytesReturned = 0;
  1230. NumberOfIPAddresses = pInterface->NumOfIPAddresses;
  1231. //
  1232. // Compute the space needed.
  1233. //
  1234. BytesNeeded = (sizeof(ADDRESS_LIST_DESCRIPTOR) - sizeof(NETWORK_ADDRESS)) +
  1235. (NumberOfIPAddresses *
  1236. (FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(NETWORK_ADDRESS_IP)));
  1237. *pBytesNeeded = BytesNeeded;
  1238. if (BytesNeeded > BufferLength)
  1239. {
  1240. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  1241. break;
  1242. }
  1243. pAddrListDescr = (PADDRESS_LIST_DESCRIPTOR)pOutputBuffer;
  1244. pAddrListDescr->MediaType = NdisMediumAtm;
  1245. pAddrListDescr->AddressList.AddressCount = NumberOfIPAddresses;
  1246. pAddrListDescr->AddressList.AddressType = NDIS_PROTOCOL_ID_TCP_IP;
  1247. //
  1248. // Copy in the IP addresses assigned to this Interface.
  1249. //
  1250. pIPAddrEntry = &pInterface->LocalIPAddress;
  1251. pNwAddr = &pAddrListDescr->AddressList.Address[0];
  1252. while (NumberOfIPAddresses--)
  1253. {
  1254. UNALIGNED NETWORK_ADDRESS_IP *pNetIPAddr =
  1255. (NETWORK_ADDRESS_IP UNALIGNED *)&pNwAddr->Address[0];
  1256. pNwAddr->AddressLength = sizeof(NETWORK_ADDRESS_IP);
  1257. pNwAddr->AddressType = NDIS_PROTOCOL_ID_TCP_IP;
  1258. //
  1259. // Each *pNetIPAddr struct has the following fields, of which
  1260. // only in_addr is used. We set the rest to zero.
  1261. //
  1262. // USHORT sin_port;
  1263. // ULONG in_addr;
  1264. // UCHAR sin_zero[8];
  1265. //
  1266. AA_SET_MEM(pNetIPAddr, sizeof(*pNetIPAddr), 0);
  1267. pNetIPAddr->in_addr = pIPAddrEntry->IPAddress;
  1268. pIPAddrEntry = pIPAddrEntry->pNext;
  1269. pNwAddr = (NETWORK_ADDRESS UNALIGNED *)
  1270. ((PUCHAR)pNwAddr + FIELD_OFFSET(NETWORK_ADDRESS, Address) + sizeof(IP_ADDRESS));
  1271. }
  1272. *pBytesReturned = BytesNeeded;
  1273. AA_ASSERT(NT_SUCCESS(NtStatus));
  1274. break;
  1275. }
  1276. while (FALSE);
  1277. AA_RELEASE_IF_LOCK(pInterface);
  1278. AADEBUGP(AAD_INFO,
  1279. ("WmiGetAddrList: IF x%x, OutBuf x%x, Len x%x, BytesRet %d, Needed %d, Sts x%x\n",
  1280. pInterface, pOutputBuffer, BufferLength, *pBytesReturned, *pBytesNeeded, NtStatus));
  1281. return (NtStatus);
  1282. }
  1283. VOID
  1284. AtmArpWmiEnableEventTCSupported(
  1285. IN PATMARP_INTERFACE pInterface,
  1286. IN ATMARP_GUID_ID MyId,
  1287. IN BOOLEAN bEnable
  1288. )
  1289. /*++
  1290. Routine Description:
  1291. Turns on/off event generation on the TC_SUPPORTED GUID. Since we don't
  1292. generate events on this GUID, this is ignored.
  1293. Arguments:
  1294. pInterface - Pointer to our Interface structure
  1295. MyId - Local ID for this GUID
  1296. bEnable - if true, enable events on this GUID, else disable.
  1297. Return Value:
  1298. None
  1299. --*/
  1300. {
  1301. return;
  1302. }
  1303. NTSTATUS
  1304. AtmArpWmiSetTCIfIndication(
  1305. IN PATMARP_INTERFACE pInterface,
  1306. IN ATMARP_GUID_ID MyId,
  1307. IN PVOID pInputBuffer,
  1308. IN ULONG BufferLength,
  1309. OUT PULONG pBytesWritten,
  1310. OUT PULONG pBytesNeeded
  1311. )
  1312. /*++
  1313. Routine Description:
  1314. Set function for the TC_INTERFACE_INDICATION GUID.
  1315. Arguments:
  1316. pInterface - Pointer to our Interface structure
  1317. MyId - Local ID for this GUID
  1318. pInputBuffer - Points to data value
  1319. BufferLength - Length of the above
  1320. pBytesWritten - Place to return how much was written
  1321. pBytesNeeded - If insufficient data, place to return expected data size
  1322. Return Value:
  1323. STATUS_NOT_SUPPORTED. We don't allow setting the value of this GUID.
  1324. --*/
  1325. {
  1326. *pBytesWritten = 0;
  1327. return (STATUS_NOT_SUPPORTED);
  1328. }
  1329. NTSTATUS
  1330. AtmArpWmiQueryTCIfIndication(
  1331. IN PATMARP_INTERFACE pInterface,
  1332. IN ATMARP_GUID_ID MyId,
  1333. OUT PVOID pOutputBuffer,
  1334. IN ULONG BufferLength,
  1335. OUT PULONG pBytesReturned,
  1336. OUT PULONG pBytesNeeded
  1337. )
  1338. /*++
  1339. Routine Description:
  1340. Query function for the TC_INTERFACE_INDICATION GUID. The
  1341. value of this GUID is the list of IP Addresses assigned to
  1342. this interface. This is returned using a TC_INDICATION_BUFFER
  1343. data structure.
  1344. Arguments:
  1345. pInterface - Pointer to our Interface structure
  1346. MyId - Local ID for this GUID
  1347. pOutputBuffer - Start of Buffer to be filled up
  1348. BufferLength - Length of the above
  1349. pBytesReturned - Place to return how much was returned
  1350. pBytesNeeded - If insufficient space, place to return expected data size
  1351. Return Value:
  1352. STATUS_SUCCESS if we successfully filled in the address list,
  1353. STATUS_XXX error code otherwise.
  1354. --*/
  1355. {
  1356. PTC_INDICATION_BUFFER pTcIndicationBuffer;
  1357. NTSTATUS NtStatus;
  1358. ULONG BytesReturned, BytesNeeded;
  1359. PVOID pAddrListBuffer;
  1360. ULONG AddrListBufferSize;
  1361. ULONG AddrListDescriptorOffset;
  1362. pTcIndicationBuffer = (PTC_INDICATION_BUFFER)pOutputBuffer;
  1363. pAddrListBuffer = (PVOID) &(pTcIndicationBuffer->InfoBuffer.AddrListDesc);
  1364. AddrListDescriptorOffset = (ULONG)
  1365. ((PUCHAR) pAddrListBuffer - (PUCHAR) pOutputBuffer);
  1366. AddrListBufferSize = ((BufferLength >= AddrListDescriptorOffset) ?
  1367. (BufferLength - AddrListDescriptorOffset): 0);
  1368. NtStatus = AtmArpWmiGetAddressList(
  1369. pInterface,
  1370. pAddrListBuffer,
  1371. AddrListBufferSize,
  1372. &BytesReturned,
  1373. &BytesNeeded);
  1374. if (NT_SUCCESS(NtStatus))
  1375. {
  1376. pTcIndicationBuffer->SubCode = 0;
  1377. *pBytesReturned = BytesReturned + AddrListDescriptorOffset;
  1378. }
  1379. else
  1380. {
  1381. *pBytesReturned = 0;
  1382. }
  1383. *pBytesNeeded = BytesNeeded + AddrListDescriptorOffset;
  1384. return (NtStatus);
  1385. }
  1386. VOID
  1387. AtmArpWmiEnableEventTCIfIndication(
  1388. IN PATMARP_INTERFACE pInterface,
  1389. IN ATMARP_GUID_ID MyId,
  1390. IN BOOLEAN bEnable
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. Turns on/off event generation on the TC_INTERFACE_INDICATION GUID.
  1395. Arguments:
  1396. pInterface - Pointer to our Interface structure
  1397. MyId - Local ID for this GUID
  1398. bEnable - if true, enable events on this GUID, else disable.
  1399. Return Value:
  1400. None
  1401. --*/
  1402. {
  1403. // CODE EnableEventTCIfIndication
  1404. return;
  1405. }
  1406. VOID
  1407. AtmArpWmiSendTCIfIndication(
  1408. IN PATMARP_INTERFACE pInterface,
  1409. IN ULONG IndicationCode,
  1410. IN ULONG IndicationSubCode
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. If event generation is allowed on TC_INTERFACE_INDICATION, send
  1415. a WMI event now.
  1416. Arguments:
  1417. pInterface - Pointer to our Interface structure
  1418. IndicationCode - To be used in the event
  1419. Return Value:
  1420. None
  1421. --*/
  1422. {
  1423. PATMARP_IF_WMI_INFO pIfWmiInfo;
  1424. PATMARP_WMI_GUID pArpGuid;
  1425. ULONG AddrBufferLength;
  1426. ULONG BytesReturned;
  1427. UCHAR DummyBuffer;
  1428. PUCHAR pOutputBuffer;
  1429. #ifndef NEWQOS
  1430. PUCHAR pDst;
  1431. #endif // !NEWQOS
  1432. PWNODE_SINGLE_INSTANCE pWnode;
  1433. ULONG WnodeSize;
  1434. ULONG TotalSize;
  1435. NTSTATUS NtStatus;
  1436. pWnode = NULL;
  1437. AA_ACQUIRE_IF_WMI_LOCK(pInterface);
  1438. do
  1439. {
  1440. pIfWmiInfo = pInterface->pIfWmiInfo;
  1441. if (pInterface->pIfWmiInfo == NULL)
  1442. {
  1443. //
  1444. // Haven't registered this interface with WMI.
  1445. //
  1446. break;
  1447. }
  1448. pArpGuid = &pIfWmiInfo->GuidInfo[IndicationCode];
  1449. //
  1450. // Are we allowed to generate events on this GUID instance?
  1451. //
  1452. if (AA_IS_FLAG_SET(pArpGuid->Flags,
  1453. AWGF_EVENT_MASK,
  1454. AWGF_EVENT_DISABLED))
  1455. {
  1456. break;
  1457. }
  1458. #if NEWQOS
  1459. //
  1460. // Check if our instance name will fit into INFO_BUFFER.InstanceID
  1461. //
  1462. if ( pIfWmiInfo->InstanceName.Length
  1463. > sizeof ((TC_SUPPORTED_INFO_BUFFER*)NULL)->InstanceID)
  1464. {
  1465. AA_ASSERT(FALSE);
  1466. break;
  1467. }
  1468. #endif // NEWQOS
  1469. //
  1470. // Find out how much space is needed for the data block.
  1471. //
  1472. pOutputBuffer = &DummyBuffer;
  1473. AddrBufferLength = 0;
  1474. NtStatus = AtmArpWmiGetAddressList(
  1475. pInterface,
  1476. pOutputBuffer,
  1477. AddrBufferLength,
  1478. &BytesReturned,
  1479. &AddrBufferLength);
  1480. AA_ASSERT(NtStatus == STATUS_INSUFFICIENT_RESOURCES);
  1481. //
  1482. // Compute the total space for the WMI Event.
  1483. //
  1484. WnodeSize = ROUND_TO_8_BYTES(sizeof(WNODE_SINGLE_INSTANCE));
  1485. #if NEWQOS
  1486. TotalSize = WnodeSize +
  1487. FIELD_OFFSET( // Indication upto info buf.
  1488. TC_INDICATION_BUFFER,
  1489. InfoBuffer) +
  1490. FIELD_OFFSET( // info-buf upto AddrListDesc
  1491. TC_SUPPORTED_INFO_BUFFER,
  1492. AddrListDesc) +
  1493. AddrBufferLength; // AddrListDesc plus data.
  1494. #else // !NEWQOS
  1495. TotalSize = WnodeSize +
  1496. //
  1497. // Counted Unicode string for the instance name:
  1498. //
  1499. sizeof(USHORT) +
  1500. pIfWmiInfo->InstanceName.Length +
  1501. //
  1502. // The actual data
  1503. //
  1504. AddrBufferLength;
  1505. #endif // !NEWQOS
  1506. //
  1507. // Allocate space for the entire lot. Since WMI will free
  1508. // it back to pool later, we don't use the usual allocation
  1509. // routine.
  1510. //
  1511. AA_ALLOC_FROM_POOL(pWnode, WNODE_SINGLE_INSTANCE, TotalSize);
  1512. if (pWnode == NULL)
  1513. {
  1514. break;
  1515. }
  1516. AA_SET_MEM(pWnode, 0, TotalSize);
  1517. pWnode->WnodeHeader.BufferSize = TotalSize;
  1518. pWnode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(pIfWmiInfo->pDeviceObject);
  1519. pWnode->WnodeHeader.Version = ATMARP_WMI_VERSION;
  1520. NdisGetCurrentSystemTime(&pWnode->WnodeHeader.TimeStamp);
  1521. pWnode->WnodeHeader.Flags = WNODE_FLAG_EVENT_ITEM |
  1522. WNODE_FLAG_SINGLE_INSTANCE;
  1523. #if NEWQOS
  1524. {
  1525. PTC_INDICATION_BUFFER pIndication
  1526. = (PTC_INDICATION_BUFFER) ((PUCHAR)pWnode + WnodeSize);
  1527. pIndication->SubCode = 0; // Unused, must be 0.
  1528. pIndication->InfoBuffer.InstanceIDLength
  1529. = pIfWmiInfo->InstanceName.Length;
  1530. //
  1531. // We checked earlier if InstanceName will fit into InstanceID, so
  1532. // the copy is safe.
  1533. //
  1534. AA_COPY_MEM(
  1535. pIndication->InfoBuffer.InstanceID,
  1536. pIfWmiInfo->InstanceName.Buffer,
  1537. pIfWmiInfo->InstanceName.Length
  1538. );
  1539. //
  1540. // Get the address list.
  1541. //
  1542. NtStatus = AtmArpWmiGetAddressList(
  1543. pInterface,
  1544. &(pIndication->InfoBuffer.AddrListDesc),
  1545. AddrBufferLength,
  1546. &BytesReturned,
  1547. &AddrBufferLength
  1548. );
  1549. }
  1550. #else
  1551. pDst = (PUCHAR)pWnode + WnodeSize;
  1552. //
  1553. // Copy in the instance name.
  1554. //
  1555. *((PUSHORT)pDst) = pIfWmiInfo->InstanceName.Length;
  1556. pDst += sizeof(USHORT);
  1557. AA_COPY_MEM(pDst, pIfWmiInfo->InstanceName.Buffer, pIfWmiInfo->InstanceName.Length);
  1558. pDst += pIfWmiInfo->InstanceName.Length;
  1559. //
  1560. // Get the data.
  1561. //
  1562. NtStatus = AtmArpWmiGetAddressList(
  1563. pInterface,
  1564. pDst,
  1565. AddrBufferLength,
  1566. &BytesReturned,
  1567. &AddrBufferLength);
  1568. #endif // !NEWQOS
  1569. AA_ASSERT(NtStatus == STATUS_SUCCESS);
  1570. break;
  1571. }
  1572. while (FALSE);
  1573. AA_RELEASE_IF_WMI_LOCK(pInterface);
  1574. //
  1575. // Send off the event if OK. WMI will take care of freeing the
  1576. // entire structure back to pool.
  1577. //
  1578. if (pWnode)
  1579. {
  1580. NtStatus = IoWMIWriteEvent(pWnode);
  1581. AADEBUGP(AAD_INFO, ("WmiSendTCIFInd: IF x%x, WMIWriteEv status x%x\n",
  1582. pInterface, NtStatus));
  1583. if (NtStatus!= STATUS_SUCCESS)
  1584. {
  1585. // Docs don't list pending as a possible return value.
  1586. //
  1587. ASSERT(NtStatus != STATUS_PENDING);
  1588. AA_FREE_TO_POOL(pWnode);
  1589. }
  1590. }
  1591. return;
  1592. }
  1593. NTSTATUS
  1594. AtmArpWmiQueryStatisticsBuffer(
  1595. IN PATMARP_INTERFACE pInterface,
  1596. IN ATMARP_GUID_ID MyId,
  1597. OUT PVOID pOutputBuffer,
  1598. IN ULONG BufferLength,
  1599. OUT PULONG pBytesReturned,
  1600. OUT PULONG pBytesNeeded
  1601. )
  1602. /*++
  1603. Routine Description:
  1604. Query function for the STATISTICS_BUFFER GUID.
  1605. This function is unimplemented.
  1606. Arguments:
  1607. pInterface - Pointer to our Interface structure
  1608. MyId - Local ID for this GUID
  1609. pOutputBuffer - Start of Buffer to be filled up
  1610. BufferLength - Length of the above
  1611. pBytesReturned - Place to return how much was returned
  1612. pBytesNeeded - If insufficient space, place to return expected data size
  1613. Return Value:
  1614. STATUS_SUCCESS if we successfully filled in the address list,
  1615. STATUS_XXX error code otherwise.
  1616. --*/
  1617. {
  1618. return GPC_STATUS_RESOURCES;
  1619. }
  1620. NTSTATUS
  1621. AtmArpWmiSetStatisticsBuffer(
  1622. IN PATMARP_INTERFACE pInterface,
  1623. IN ATMARP_GUID_ID MyId,
  1624. IN PVOID pInputBuffer,
  1625. IN ULONG BufferLength,
  1626. OUT PULONG pBytesWritten,
  1627. OUT PULONG pBytesNeeded
  1628. )
  1629. /*++
  1630. Routine Description:
  1631. Set function for the STATISTICS_BUFFER GUID.
  1632. Arguments:
  1633. pInterface - Pointer to our Interface structure
  1634. MyId - Local ID for this GUID
  1635. pInputBuffer - Points to data value
  1636. BufferLength - Length of the above
  1637. pBytesWritten - Place to return how much was written
  1638. pBytesNeeded - If insufficient data, place to return expected data size
  1639. Return Value:
  1640. STATUS_NOT_SUPPORTED. We don't allow setting the value of this GUID.
  1641. --*/
  1642. {
  1643. *pBytesWritten = 0;
  1644. return (STATUS_NOT_SUPPORTED);
  1645. }
  1646. PATMARP_INTERFACE
  1647. AtmArpWmiGetIfByName(
  1648. IN PWSTR pIfName,
  1649. IN USHORT IfNameLength
  1650. )
  1651. /*++
  1652. Routine Description:
  1653. Given a name, locate and return the Interface whose instance name
  1654. matches it. A temporary reference to the interface is added -- the caller
  1655. is expected to deref the interface when done with it.
  1656. Arguments:
  1657. pIfName - Points to name to be searched for
  1658. IfNameLength - length of above
  1659. Return Value:
  1660. Pointer to ATMARP interface if found, NULL otherwise.
  1661. --*/
  1662. {
  1663. PATMARP_ADAPTER pAdapter;
  1664. PATMARP_INTERFACE pInterface;
  1665. pInterface = NULL_PATMARP_INTERFACE;
  1666. //
  1667. // Knock off the terminating NULL WCHAR.
  1668. //
  1669. if (IfNameLength > sizeof(WCHAR))
  1670. {
  1671. IfNameLength -= sizeof(WCHAR);
  1672. }
  1673. AA_ACQUIRE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  1674. for (pAdapter = pAtmArpGlobalInfo->pAdapterList;
  1675. pAdapter != NULL_PATMARP_ADAPTER;
  1676. pAdapter = pAdapter->pNextAdapter)
  1677. {
  1678. for (pInterface = pAdapter->pInterfaceList;
  1679. pInterface != NULL_PATMARP_INTERFACE;
  1680. pInterface = pInterface->pNextInterface)
  1681. {
  1682. #if DBG
  1683. AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  1684. if (pInterface->pIfWmiInfo)
  1685. {
  1686. AADEBUGP(AAD_WARNING,
  1687. ("Given len %d, string %ws\n", IfNameLength, pIfName));
  1688. AADEBUGP(AAD_WARNING,
  1689. (" IF len %d, string %ws\n",
  1690. pInterface->pIfWmiInfo->InstanceName.Length,
  1691. pInterface->pIfWmiInfo->InstanceName.Buffer));
  1692. }
  1693. AA_ACQUIRE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  1694. #endif // DBG
  1695. if ((pInterface->pIfWmiInfo != NULL) &&
  1696. (pInterface->pIfWmiInfo->InstanceName.Length == IfNameLength) &&
  1697. (AA_MEM_CMP(pInterface->pIfWmiInfo->InstanceName.Buffer,
  1698. pIfName,
  1699. IfNameLength) == 0))
  1700. {
  1701. //
  1702. // Found it.
  1703. //
  1704. AA_ACQUIRE_IF_LOCK(pInterface);
  1705. AtmArpReferenceInterface(pInterface); // WMI: Tmp ref.
  1706. AA_RELEASE_IF_LOCK(pInterface);
  1707. break;
  1708. }
  1709. }
  1710. if (pInterface != NULL_PATMARP_INTERFACE)
  1711. {
  1712. break;
  1713. }
  1714. }
  1715. AA_RELEASE_GLOBAL_LOCK(pAtmArpGlobalInfo);
  1716. return (pInterface);
  1717. }
  1718. #endif // ATMARP_WMI